|
|
@@ -435,106 +435,118 @@ namespace Renci.SshNet
|
|
|
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)
|
|
|
{
|
|
|
- case 0x01:
|
|
|
+ case 0x01: // IPv4
|
|
|
{
|
|
|
- addressBuffer = new byte[4];
|
|
|
+ var addressBuffer = new byte[4];
|
|
|
if (SocketAbstraction.Read(socket, addressBuffer, 0, 4, timeout) == 0)
|
|
|
{
|
|
|
// 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);
|
|
|
if (length == -1)
|
|
|
{
|
|
|
// 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)
|
|
|
{
|
|
|
// 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)
|
|
|
{
|
|
|
// SOCKS client closed connection
|
|
|
- return false;
|
|
|
+ return null;
|
|
|
}
|
|
|
|
|
|
- ipAddress = new IPAddress(addressBuffer);
|
|
|
+ var ipv6 = new IPAddress(addressBuffer);
|
|
|
+ return ipv6.ToString();
|
|
|
}
|
|
|
- break;
|
|
|
default:
|
|
|
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
|
|
|
{
|
|
|
- SocketAbstraction.SendByte(socket, 0x01);
|
|
|
+ socksReply[1] = 0x01; // general SOCKS server failure
|
|
|
}
|
|
|
|
|
|
// 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>
|