From 49595315f0ca06e950b9bd083e0635b006f61b13 Mon Sep 17 00:00:00 2001 From: Measurity Date: Sun, 2 Jul 2023 14:30:09 +0200 Subject: [PATCH 1/2] Added ipAddress.IsLocalhost() API This API tests that the IP address points to the same machine that is executing the code (localhost). --- Nitrox.Test/Model/Helper/NetHelperTest.cs | 44 +++++++++++++++++++---- NitroxModel/Helper/NetHelper.cs | 26 ++++++++++++++ 2 files changed, 64 insertions(+), 6 deletions(-) diff --git a/Nitrox.Test/Model/Helper/NetHelperTest.cs b/Nitrox.Test/Model/Helper/NetHelperTest.cs index affa337892..5a4d4a1547 100644 --- a/Nitrox.Test/Model/Helper/NetHelperTest.cs +++ b/Nitrox.Test/Model/Helper/NetHelperTest.cs @@ -1,4 +1,6 @@ -using System.Net; +using System; +using System.Net; +using System.Net.Sockets; using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -11,11 +13,11 @@ public class NetHelperTest public void ShouldMatchPrivateIps() { // Tested subnet ranges that are reserved for private networks: - // 10.0.0.0/8 - // 127.0.0.0/8 - // 172.16.0.0/12 - // 192.0.0.0/24 - // 192.168.0.0/16 + // 10.0.0.0/8 + // 127.0.0.0/8 + // 172.16.0.0/12 + // 192.0.0.0/24 + // 192.168.0.0/16 // 198.18.0.0/15 IPAddress.Parse("10.0.0.0").IsPrivate().Should().BeTrue(); @@ -36,4 +38,34 @@ public void ShouldMatchPrivateIps() IPAddress.Parse("198.17.255.255").IsPrivate().Should().BeFalse(); IPAddress.Parse("198.20.0.0").IsPrivate().Should().BeFalse(); } + + [TestMethod] + public void ShouldMatchLocalhostIps() + { + IPAddress GetSlightlyDifferentIp(IPAddress address) + { + if (address.AddressFamily != AddressFamily.InterNetwork) + { + throw new Exception("Only supports IPv4"); + } + byte[] bytes = address.GetAddressBytes(); + unchecked + { + while (bytes[3] is < 1 or > 253) + { + bytes[3]++; + } + bytes[3]++; + } + return new IPAddress(bytes); + } + + IPAddress.Parse("127.0.0.1").IsLocalhost().Should().BeTrue(); + IPAddress.Parse("127.0.0.2").IsLocalhost().Should().BeTrue(); + IPAddress.Parse("192.168.0.255").IsLocalhost().Should().BeFalse(); + NetHelper.GetLanIp().IsLocalhost().Should().BeTrue(); + IPAddress differentIp = GetSlightlyDifferentIp(NetHelper.GetLanIp()); + differentIp.Should().NotBeEquivalentTo(NetHelper.GetLanIp()); + differentIp.IsLocalhost().Should().BeFalse(); + } } diff --git a/NitroxModel/Helper/NetHelper.cs b/NitroxModel/Helper/NetHelper.cs index 6320fefba5..15c7e71f2f 100644 --- a/NitroxModel/Helper/NetHelper.cs +++ b/NitroxModel/Helper/NetHelper.cs @@ -161,5 +161,31 @@ static bool IsInRange(IPAddress ipAddress, string mask) } return false; } + + /// + /// Returns true if the IP address points to the executing machine. + /// + public static bool IsLocalhost(this IPAddress address) + { + if (address == null) + { + return false; + } + if (IPAddress.IsLoopback(address)) + { + return true; + } + foreach (NetworkInterface ni in GetInternetInterfaces()) + { + foreach (UnicastIPAddressInformation ip in ni.GetIPProperties().UnicastAddresses) + { + if (address.Equals(ip.Address)) + { + return true; + } + } + } + return false; + } } } From c2627f90b0558146f09c8a126f0a08ab9cd28efd Mon Sep 17 00:00:00 2001 From: Measurity Date: Sun, 2 Jul 2023 14:31:11 +0200 Subject: [PATCH 2/2] Used ipAddress.IsLocalhost API to grant admin to local player Previously this only worked for 127.x.x.x range IPs but now also works for LAN ipv4 and ipv6 IPs. --- .../Processors/PlayerJoiningMultiplayerSessionProcessor.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/NitroxServer/Communication/Packets/Processors/PlayerJoiningMultiplayerSessionProcessor.cs b/NitroxServer/Communication/Packets/Processors/PlayerJoiningMultiplayerSessionProcessor.cs index a9e23214aa..b004ccdf59 100644 --- a/NitroxServer/Communication/Packets/Processors/PlayerJoiningMultiplayerSessionProcessor.cs +++ b/NitroxServer/Communication/Packets/Processors/PlayerJoiningMultiplayerSessionProcessor.cs @@ -1,12 +1,11 @@ using System.Collections.Generic; using System.Linq; -using System.Net; -using System.Numerics; using NitroxModel.DataStructures; using NitroxModel.DataStructures.GameLogic; using NitroxModel.DataStructures.GameLogic.Entities; using NitroxModel.DataStructures.Unity; using NitroxModel.DataStructures.Util; +using NitroxModel.Helper; using NitroxModel.MultiplayerSession; using NitroxModel.Packets; using NitroxServer.Communication.Packets.Processors.Abstract; @@ -51,8 +50,9 @@ public override void Process(PlayerJoiningMultiplayerSession packet, NitroxConne playerManager.SendPacketToOtherPlayers(playerJoinedPacket, player); // Make players on localhost admin by default. - if (IPAddress.IsLoopback(connection.Endpoint.Address)) + if (connection.Endpoint.Address.IsLocalhost()) { + Log.Info($"Granted admin to '{player.Name}' because they're playing on the host machine"); player.Permissions = Perms.ADMIN; }