diff --git a/DearFTP/Connection/Commands/PassiveCommand.cs b/DearFTP/Connection/Commands/PassiveCommand.cs index e353952..c57e57a 100644 --- a/DearFTP/Connection/Commands/PassiveCommand.cs +++ b/DearFTP/Connection/Commands/PassiveCommand.cs @@ -1,5 +1,6 @@ using System; using System.Linq; +using System.Net; namespace DearFTP.Connection.Commands { @@ -16,11 +17,43 @@ namespace DearFTP.Connection.Commands int port = session.DataConnection.Port; var portBytes = BitConverter.GetBytes((ushort)port).Reverse().Select(x => x.ToString()); - string remote = string.Join(',', session.Configuration.Server.Host.Split('.').Concat(portBytes)); + + string remote; + + if (IsInternal(session.RemoteIP)) + { + remote = string.Join(',', session.LocalIP.ToString().Split('.').Concat(portBytes)); + } + else + { + remote = string.Join(',', session.Configuration.Server.Host.Split('.').Concat(portBytes)); + } stream.Send(ResponseCode.PassiveMode, $"Entering Passive Mode ({remote})"); session.DataConnection.AcceptClient(); } + + // Source: https://stackoverflow.com/a/39120248 + /// + /// An extension method to determine if an IP address is internal, as specified in RFC1918 + /// + /// The IP address that will be tested + /// Returns true if the IP is internal, false if it is external + public bool IsInternal(IPAddress toTest) + { + byte[] bytes = toTest.GetAddressBytes(); + switch (bytes[0]) + { + case 10: + return true; + case 172: + return bytes[1] < 32 && bytes[1] >= 16; + case 192: + return bytes[1] == 168; + default: + return false; + } + } } } diff --git a/DearFTP/Connection/Session.cs b/DearFTP/Connection/Session.cs index 8183045..8ec20d6 100644 --- a/DearFTP/Connection/Session.cs +++ b/DearFTP/Connection/Session.cs @@ -23,10 +23,11 @@ namespace DearFTP.Connection public bool IsTlsProtected { get; private set; } public string CurrentWorkingDirectory => NavigablePath.CurrentDirectory; - public string IP => ((IPEndPoint)_client.Client.LocalEndPoint).Address.ToString(); + public IPAddress LocalIP => ((IPEndPoint)_client.Client.LocalEndPoint).Address; + public IPAddress RemoteIP => ((IPEndPoint)_client.Client.RemoteEndPoint).Address; - private TcpClient _client; - private NetworkStream _networkStream; + private readonly TcpClient _client; + private readonly NetworkStream _networkStream; private SslStream _sslStream; private bool _isRunning = true;