private bool HandleSocks4(Socket socket, IChannelDirectTcpip channel, TimeSpan timeout) { var commandCode = SocketAbstraction.ReadByte(socket, timeout); if (commandCode == 0) { // SOCKS client closed connection return(false); } // TODO: See what need to be done depends on the code 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 ipBuffer = new byte[4]; if (SocketAbstraction.Read(socket, ipBuffer, 0, ipBuffer.Length, timeout) == 0) { // SOCKS client closed connection return(false); } var ipAddress = new IPAddress(ipBuffer); var username = ReadString(socket, timeout); if (username == null) { // SOCKS client closed connection return(false); } var host = ipAddress.ToString(); RaiseRequestReceived(host, port); channel.Open(host, port, this, socket); SocketAbstraction.SendByte(socket, 0x00); if (channel.IsOpen) { SocketAbstraction.SendByte(socket, 0x5a); SocketAbstraction.Send(socket, portBuffer, 0, portBuffer.Length); SocketAbstraction.Send(socket, ipBuffer, 0, ipBuffer.Length); return(true); } // signal that request was rejected or failed SocketAbstraction.SendByte(socket, 0x5b); return(false); }
private static string GetSocks5Host(int addressType, Socket socket, TimeSpan timeout) { switch (addressType) { case 0x01: // IPv4 { var addressBuffer = new byte[4]; if (SocketAbstraction.Read(socket, addressBuffer, 0, 4, timeout) == 0) { // SOCKS client closed connection return(null); } var ipv4 = new IPAddress(addressBuffer); return(ipv4.ToString()); } case 0x03: // Domain name { var length = SocketAbstraction.ReadByte(socket, timeout); if (length == -1) { // SOCKS client closed connection return(null); } var addressBuffer = new byte[length]; if (SocketAbstraction.Read(socket, addressBuffer, 0, addressBuffer.Length, timeout) == 0) { // SOCKS client closed connection return(null); } var hostName = SshData.Ascii.GetString(addressBuffer, 0, addressBuffer.Length); return(hostName); } case 0x04: // IPv6 { var addressBuffer = new byte[16]; if (SocketAbstraction.Read(socket, addressBuffer, 0, 16, timeout) == 0) { // SOCKS client closed connection return(null); } var ipv6 = new IPAddress(addressBuffer); return(ipv6.ToString()); } default: throw new ProxyException(string.Format("SOCKS5: Address type '{0}' is not supported.", addressType)); } }
private bool HandleSocks(IChannelDirectTcpip channel, Socket remoteSocket, TimeSpan timeout) { // create eventhandler which is to be invoked to interrupt a blocking receive // when we're closing the forwarded port EventHandler closeClientSocket = (_, args) => CloseSocket(remoteSocket); Closing += closeClientSocket; try { #if DEBUG_GERT Console.WriteLine("ID: " + Thread.CurrentThread.ManagedThreadId + " | Before ReadByte for version | " + DateTime.Now.ToString("hh:mm:ss.fff")); #endif // DEBUG_GERT var version = SocketAbstraction.ReadByte(remoteSocket, timeout); if (version == -1) { return(false); } #if DEBUG_GERT Console.WriteLine("ID: " + Thread.CurrentThread.ManagedThreadId + " | After ReadByte for version | " + DateTime.Now.ToString("hh:mm:ss.fff")); #endif // DEBUG_GERT if (version == 4) { return(HandleSocks4(remoteSocket, channel, timeout)); } else if (version == 5) { return(HandleSocks5(remoteSocket, channel, timeout)); } else { throw new NotSupportedException(string.Format("SOCKS version {0} is not supported.", version)); } } finally { // interrupt of blocking receive is now handled by channel (SOCKS4 and SOCKS5) // or no longer necessary Closing -= closeClientSocket; } }
private bool HandleSocks(IChannelDirectTcpip channel, Socket clientSocket, TimeSpan timeout) { // create eventhandler which is to be invoked to interrupt a blocking receive // when we're closing the forwarded port EventHandler closeClientSocket = (_, args) => CloseClientSocket(clientSocket); Closing += closeClientSocket; try { var version = SocketAbstraction.ReadByte(clientSocket, timeout); switch (version) { case -1: // SOCKS client closed connection return(false); case 4: return(HandleSocks4(clientSocket, channel, timeout)); case 5: return(HandleSocks5(clientSocket, channel, timeout)); default: throw new NotSupportedException(string.Format("SOCKS version {0} is not supported.", version)); } } catch (SocketException ex) { // ignore exception thrown by interrupting the blocking receive as part of closing // the forwarded port if (ex.SocketErrorCode != SocketError.Interrupted) { RaiseExceptionEvent(ex); } return(false); } finally { // interrupt of blocking receive is now handled by channel (SOCKS4 and SOCKS5) // or no longer necessary Closing -= closeClientSocket; } }
private bool HandleSocks5(Socket socket, IChannelDirectTcpip channel, TimeSpan timeout) { #if DEBUG_GERT Console.WriteLine("ID: " + Thread.CurrentThread.ManagedThreadId + " | Handling Socks5: " + socket.LocalEndPoint + " | " + socket.RemoteEndPoint + " | " + DateTime.Now.ToString("hh:mm:ss.fff")); #endif // DEBUG_GERT var authenticationMethodsCount = SocketAbstraction.ReadByte(socket, timeout); if (authenticationMethodsCount == -1) { // SOCKS client closed connection return(false); } #if DEBUG_GERT Console.WriteLine("ID: " + Thread.CurrentThread.ManagedThreadId + " | After ReadByte for authenticationMethodsCount | " + DateTime.Now.ToString("hh:mm:ss.fff")); #endif // DEBUG_GERT var authenticationMethods = new byte[authenticationMethodsCount]; if (SocketAbstraction.Read(socket, authenticationMethods, 0, authenticationMethods.Length, timeout) == 0) { // SOCKS client closed connection return(false); } #if DEBUG_GERT Console.WriteLine("ID: " + Thread.CurrentThread.ManagedThreadId + " | After Read for authenticationMethods | " + DateTime.Now.ToString("hh:mm:ss.fff")); #endif // DEBUG_GERT if (authenticationMethods.Min() == 0) { // no user authentication is one of the authentication methods supported // by the SOCKS client SocketAbstraction.Send(socket, new byte[] { 0x05, 0x00 }, 0, 2); #if DEBUG_GERT Console.WriteLine("ID: " + Thread.CurrentThread.ManagedThreadId + " | After Send for authenticationMethods 0 | " + DateTime.Now.ToString("hh:mm:ss.fff")); #endif // DEBUG_GERT } else { // the SOCKS client requires authentication, which we currently do not support SocketAbstraction.Send(socket, new byte[] { 0x05, 0xFF }, 0, 2); // we continue business as usual but expect the client to close the connection // so one of the subsequent reads should return -1 signaling that the client // has effectively closed the connection #if DEBUG_GERT Console.WriteLine("ID: " + Thread.CurrentThread.ManagedThreadId + " | After Send for authenticationMethods 2 | " + DateTime.Now.ToString("hh:mm:ss.fff")); #endif // DEBUG_GERT } var version = SocketAbstraction.ReadByte(socket, timeout); if (version == -1) { // SOCKS client closed connection return(false); } if (version != 5) { throw new ProxyException("SOCKS5: Version 5 is expected."); } var commandCode = SocketAbstraction.ReadByte(socket, timeout); if (commandCode == -1) { // SOCKS client closed connection return(false); } var reserved = SocketAbstraction.ReadByte(socket, timeout); if (reserved == -1) { // SOCKS client closed connection return(false); } if (reserved != 0) { throw new ProxyException("SOCKS5: 0 is expected for reserved byte."); } var addressType = SocketAbstraction.ReadByte(socket, timeout); if (addressType == -1) { // SOCKS client closed connection return(false); } IPAddress ipAddress; byte[] addressBuffer; switch (addressType) { case 0x01: { addressBuffer = new byte[4]; if (SocketAbstraction.Read(socket, addressBuffer, 0, 4, timeout) == 0) { // SOCKS client closed connection return(false); } ipAddress = new IPAddress(addressBuffer); } break; case 0x03: { var length = SocketAbstraction.ReadByte(socket, timeout); addressBuffer = new byte[length]; if (SocketAbstraction.Read(socket, addressBuffer, 0, addressBuffer.Length, timeout) == 0) { // SOCKS client closed connection return(false); } ipAddress = IPAddress.Parse(SshData.Ascii.GetString(addressBuffer)); //var hostName = new Common.ASCIIEncoding().GetString(addressBuffer); //ipAddress = Dns.GetHostEntry(hostName).AddressList[0]; } break; case 0x04: { addressBuffer = new byte[16]; if (SocketAbstraction.Read(socket, addressBuffer, 0, 16, timeout) == 0) { // SOCKS client closed connection return(false); } ipAddress = new IPAddress(addressBuffer); } 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); #if DEBUG_GERT Console.WriteLine("ID: " + Thread.CurrentThread.ManagedThreadId + " | Before channel open | " + DateTime.Now.ToString("hh:mm:ss.fff")); var stopWatch = new Stopwatch(); stopWatch.Start(); #endif // DEBUG_GERT channel.Open(host, port, this, socket); #if DEBUG_GERT stopWatch.Stop(); Console.WriteLine("ID: " + Thread.CurrentThread.ManagedThreadId + " | After channel open | " + DateTime.Now.ToString("hh:mm:ss.fff") + " => " + stopWatch.ElapsedMilliseconds); #endif // DEBUG_GERT SocketAbstraction.SendByte(socket, 0x05); if (channel.IsOpen) { SocketAbstraction.SendByte(socket, 0x00); } else { SocketAbstraction.SendByte(socket, 0x01); } // 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."); } var addressBytes = ipAddress.GetAddressBytes(); SocketAbstraction.Send(socket, addressBytes, 0, addressBytes.Length); SocketAbstraction.Send(socket, portBuffer, 0, portBuffer.Length); return(true); }
private bool HandleSocks5(Socket socket, IChannelDirectTcpip channel, TimeSpan timeout) { var authenticationMethodsCount = SocketAbstraction.ReadByte(socket, timeout); if (authenticationMethodsCount == -1) { // SOCKS client closed connection return(false); } var authenticationMethods = new byte[authenticationMethodsCount]; if (SocketAbstraction.Read(socket, authenticationMethods, 0, authenticationMethods.Length, timeout) == 0) { // SOCKS client closed connection return(false); } if (authenticationMethods.Min() == 0) { // no user authentication is one of the authentication methods supported // by the SOCKS client SocketAbstraction.Send(socket, new byte[] { 0x05, 0x00 }, 0, 2); } else { // the SOCKS client requires authentication, which we currently do not support SocketAbstraction.Send(socket, new byte[] { 0x05, 0xFF }, 0, 2); // we continue business as usual but expect the client to close the connection // so one of the subsequent reads should return -1 signaling that the client // has effectively closed the connection } var version = SocketAbstraction.ReadByte(socket, timeout); if (version == -1) { // SOCKS client closed connection return(false); } if (version != 5) { throw new ProxyException("SOCKS5: Version 5 is expected."); } var commandCode = SocketAbstraction.ReadByte(socket, timeout); if (commandCode == -1) { // SOCKS client closed connection return(false); } var reserved = SocketAbstraction.ReadByte(socket, timeout); if (reserved == -1) { // SOCKS client closed connection return(false); } if (reserved != 0) { throw new ProxyException("SOCKS5: 0 is expected for reserved byte."); } var addressType = SocketAbstraction.ReadByte(socket, timeout); if (addressType == -1) { // SOCKS client closed connection return(false); } IPAddress ipAddress; byte[] addressBuffer; switch (addressType) { case 0x01: { addressBuffer = new byte[4]; if (SocketAbstraction.Read(socket, addressBuffer, 0, 4, timeout) == 0) { // SOCKS client closed connection return(false); } ipAddress = new IPAddress(addressBuffer); } break; case 0x03: { var length = SocketAbstraction.ReadByte(socket, timeout); if (length == -1) { // SOCKS client closed connection return(false); } addressBuffer = new byte[length]; if (SocketAbstraction.Read(socket, addressBuffer, 0, addressBuffer.Length, timeout) == 0) { // SOCKS client closed connection return(false); } ipAddress = IPAddress.Parse(SshData.Ascii.GetString(addressBuffer, 0, addressBuffer.Length)); //var hostName = new Common.ASCIIEncoding().GetString(addressBuffer); //ipAddress = Dns.GetHostEntry(hostName).AddressList[0]; } break; case 0x04: { addressBuffer = new byte[16]; if (SocketAbstraction.Read(socket, addressBuffer, 0, 16, timeout) == 0) { // SOCKS client closed connection return(false); } ipAddress = new IPAddress(addressBuffer); } 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); } else { SocketAbstraction.SendByte(socket, 0x01); } // 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."); } var addressBytes = ipAddress.GetAddressBytes(); SocketAbstraction.Send(socket, addressBytes, 0, addressBytes.Length); SocketAbstraction.Send(socket, portBuffer, 0, portBuffer.Length); return(true); }
private bool HandleSocks5(Socket socket, IChannelDirectTcpip channel, TimeSpan timeout) { var authenticationMethodsCount = SocketAbstraction.ReadByte(socket, timeout); if (authenticationMethodsCount == -1) { // SOCKS client closed connection return(false); } var authenticationMethods = new byte[authenticationMethodsCount]; if (SocketAbstraction.Read(socket, authenticationMethods, 0, authenticationMethods.Length, timeout) == 0) { // SOCKS client closed connection return(false); } if (authenticationMethods.Min() == 0) { // no user authentication is one of the authentication methods supported // by the SOCKS client SocketAbstraction.Send(socket, new byte[] { 0x05, 0x00 }, 0, 2); } else { // the SOCKS client requires authentication, which we currently do not support SocketAbstraction.Send(socket, new byte[] { 0x05, 0xFF }, 0, 2); // we continue business as usual but expect the client to close the connection // so one of the subsequent reads should return -1 signaling that the client // has effectively closed the connection } var version = SocketAbstraction.ReadByte(socket, timeout); if (version == -1) { // SOCKS client closed connection return(false); } if (version != 5) { throw new ProxyException("SOCKS5: Version 5 is expected."); } var commandCode = SocketAbstraction.ReadByte(socket, timeout); if (commandCode == -1) { // SOCKS client closed connection return(false); } var reserved = SocketAbstraction.ReadByte(socket, timeout); if (reserved == -1) { // SOCKS client closed connection return(false); } if (reserved != 0) { throw new ProxyException("SOCKS5: 0 is expected for reserved byte."); } var addressType = SocketAbstraction.ReadByte(socket, timeout); if (addressType == -1) { // SOCKS client closed connection return(false); } 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 = Pack.BigEndianToUInt16(portBuffer); RaiseRequestReceived(host, port); channel.Open(host, port, this, socket); var socksReply = CreateSocks5Reply(channel.IsOpen); SocketAbstraction.Send(socket, socksReply, 0, socksReply.Length); return(true); }