浏览代码

Added support domain name address type for SOCKS5.
Fixes issue #98.

drieseng 9 年之前
父节点
当前提交
13fff36135
共有 1 个文件被更改,包括 72 次插入60 次删除
  1. 72 60
      src/Renci.SshNet/ForwardedPortDynamic.NET.cs

+ 72 - 60
src/Renci.SshNet/ForwardedPortDynamic.NET.cs

@@ -435,106 +435,118 @@ namespace Renci.SshNet
                 return false;
                 return false;
             }
             }
 
 
-            IPAddress ipAddress;
-            byte[] addressBuffer;
+            var host = GetSocks5Host(addressType, socket, timeout);
+            if (host == null)
+            {
+                // SOCKS client closed connection
+                return false;
+            }
+
+            var portBuffer = new byte[2];
+            if (SocketAbstraction.Read(socket, portBuffer, 0, portBuffer.Length, timeout) == 0)
+            {
+                // SOCKS client closed connection
+                return false;
+            }
+
+            var port = (uint)(portBuffer[0] * 256 + portBuffer[1]);
+
+            RaiseRequestReceived(host, port);
+
+            channel.Open(host, port, this, socket);
+
+            var socksReply = CreateSocks5Reply(channel.IsOpen);
+
+            SocketAbstraction.Send(socket, socksReply, 0, socksReply.Length);
+
+            return true;
+        }
+
+        private static string GetSocks5Host(int addressType, Socket socket, TimeSpan timeout)
+        {
             switch (addressType)
             switch (addressType)
             {
             {
-                case 0x01:
+                case 0x01: // IPv4
                     {
                     {
-                        addressBuffer = new byte[4];
+                        var addressBuffer = new byte[4];
                         if (SocketAbstraction.Read(socket, addressBuffer, 0, 4, timeout) == 0)
                         if (SocketAbstraction.Read(socket, addressBuffer, 0, 4, timeout) == 0)
                         {
                         {
                             // SOCKS client closed connection
                             // SOCKS client closed connection
-                            return false;
+                            return null;
                         }
                         }
 
 
-                        ipAddress = new IPAddress(addressBuffer);
+                        var ipv4 = new IPAddress(addressBuffer);
+                        return ipv4.ToString();
                     }
                     }
-                    break;
-                case 0x03:
+                case 0x03: // Domain name
                     {
                     {
                         var length = SocketAbstraction.ReadByte(socket, timeout);
                         var length = SocketAbstraction.ReadByte(socket, timeout);
                         if (length == -1)
                         if (length == -1)
                         {
                         {
                             // SOCKS client closed connection
                             // SOCKS client closed connection
-                            return false;
+                            return null;
                         }
                         }
-                        addressBuffer = new byte[length];
+                        var addressBuffer = new byte[length];
                         if (SocketAbstraction.Read(socket, addressBuffer, 0, addressBuffer.Length, timeout) == 0)
                         if (SocketAbstraction.Read(socket, addressBuffer, 0, addressBuffer.Length, timeout) == 0)
                         {
                         {
                             // SOCKS client closed connection
                             // SOCKS client closed connection
-                            return false;
+                            return null;
                         }
                         }
 
 
-                        ipAddress = IPAddress.Parse(SshData.Ascii.GetString(addressBuffer, 0, addressBuffer.Length));
-
-                        //var hostName = new Common.ASCIIEncoding().GetString(addressBuffer);
-
-                        //ipAddress = Dns.GetHostEntry(hostName).AddressList[0];
+                        var hostName = SshData.Ascii.GetString(addressBuffer);
+                        return hostName;
                     }
                     }
-                    break;
-                case 0x04:
+                case 0x04: // IPv6
                     {
                     {
-                        addressBuffer = new byte[16];
+                        var addressBuffer = new byte[16];
                         if (SocketAbstraction.Read(socket, addressBuffer, 0, 16, timeout) == 0)
                         if (SocketAbstraction.Read(socket, addressBuffer, 0, 16, timeout) == 0)
                         {
                         {
                             // SOCKS client closed connection
                             // SOCKS client closed connection
-                            return false;
+                            return null;
                         }
                         }
 
 
-                        ipAddress = new IPAddress(addressBuffer);
+                        var ipv6 = new IPAddress(addressBuffer);
+                        return ipv6.ToString();
                     }
                     }
-                    break;
                 default:
                 default:
                     throw new ProxyException(string.Format("SOCKS5: Address type '{0}' is not supported.", addressType));
                     throw new ProxyException(string.Format("SOCKS5: Address type '{0}' is not supported.", addressType));
             }
             }
+        }
 
 
-            var portBuffer = new byte[2];
-            if (SocketAbstraction.Read(socket, portBuffer, 0, portBuffer.Length, timeout) == 0)
-            {
-                // SOCKS client closed connection
-                return false;
-            }
-
-            var port = (uint)(portBuffer[0] * 256 + portBuffer[1]);
-            var host = ipAddress.ToString();
-
-            RaiseRequestReceived(host, port);
-
-            channel.Open(host, port, this, socket);
-
-            SocketAbstraction.SendByte(socket, 0x05);
-
-            if (channel.IsOpen)
-            {
-                SocketAbstraction.SendByte(socket, 0x00);
+        private static byte[] CreateSocks5Reply(bool channelOpen)
+        {
+            var socksReply = new byte[
+                // SOCKS version
+                1 +
+                // Reply field
+                1 +
+                // Reserved; fixed: 0x00
+                1 +
+                // Address type; fixed: 0x01
+                1 +
+                // IPv4 server bound address; fixed: {0x00, 0x00, 0x00, 0x00}
+                4 +
+                // server bound port; fixed: {0x00, 0x00}
+                2];
+
+            socksReply[0] = 0x05;
+
+            if (channelOpen)
+            {
+                socksReply[1] = 0x00; // succeeded
             }
             }
             else
             else
             {
             {
-                SocketAbstraction.SendByte(socket, 0x01);
+                socksReply[1] = 0x01; // general SOCKS server failure
             }
             }
 
 
             // reserved
             // reserved
-            SocketAbstraction.SendByte(socket, 0x00);
-
-            if (ipAddress.AddressFamily == AddressFamily.InterNetwork)
-            {
-                SocketAbstraction.SendByte(socket, 0x01);
-            }
-            else if (ipAddress.AddressFamily == AddressFamily.InterNetworkV6)
-            {
-                SocketAbstraction.SendByte(socket, 0x04);
-            }
-            else
-            {
-                throw new NotSupportedException("Not supported address family.");
-            }
+            socksReply[2] = 0x00;
 
 
-            var addressBytes = ipAddress.GetAddressBytes();
-            SocketAbstraction.Send(socket, addressBytes, 0, addressBytes.Length);
-            SocketAbstraction.Send(socket, portBuffer, 0, portBuffer.Length);
+            // IPv4 address type
+            socksReply[3] = 0x01;
 
 
-            return true;
+            return socksReply;
         }
         }
 
 
         /// <summary>
         /// <summary>