private bool DispatchRequest(Request request) { bool bRet = false; switch (request.Command) { case ConnectCommand: var bind = new AddrSpec(); int bindPort = rnd.Next(65000, 65536); IPEndPoint localEndpoint = new IPEndPoint(localhostIPAddr, bindPort); bind.FQDN = ""; bind.IP = localhostIPAddr; bind.Port = bindPort; Socket target; try { if (request.DestAddr.IP.AddressFamily == AddressFamily.InterNetwork) { target = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); } else { target = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp); } } catch (Exception ex) { throw new SocksException("Failed to create socket for address.", SocksError.ConnectionRefused); } //target.Bind(localEndpoint); //TcpClient target = new TcpClient(localEndpoint); try { target.Connect(request.DestAddr.IP.ToString(), request.DestAddr.Port); } catch (Exception ex) { throw new SocksException($"Failed on client connect to {request.DestAddr.IP.ToString()}", SocksError.HostUnreachable, ex); } bRet = true; //DebugWriteLine($"Successfully connected to {request.DestAddr.IP.ToString()}"); ClientConnection = target; Bind = bind; //var msgToSend = CreateFormattedMessageWithLength(SocksError.SuccessReply, bind, conn); //AddMythicMessageToQueue(msgToSend); //new Thread(() => conn.StartRelay()).Start(); break; default: throw new SocksException($"Command not supported: {request.Command}", SocksError.CommandNotSupported); } return(bRet); }
private Request ParseAddrSpec(byte[] data) { int dataIndex = 0; int headerIndex = 0; byte[] header = new byte[3]; byte[] address = null; IPAddress targetIP = null; int targetPort; AddrSpec addrSpec = new AddrSpec() { FQDN = "", IP = null, Port = -1 }; SocksError errorResponse; if (data.Length <= 1) { throw new SocksException("Datagram was an invalid length.", SocksError.InvalidDatagram); } if (data.Length < 3) { throw new SocksException("Datagram was an invalid length.", SocksError.InvalidDatagram); } Array.Copy(data, header, 3); dataIndex += 3; // gonna assume this means fail to read header if (header[0] != socks5Version) { throw new SocksException($"Got header frame requesting invalid SOCKS version {header[0]}.", SocksError.CommandNotSupported); } AddressType ipType = (AddressType)data[dataIndex]; dataIndex += 1; switch (ipType) { case AddressType.IPv4Address: address = new byte[4]; Array.Copy(data, dataIndex, address, 0, 4); targetIP = new IPAddress(address); dataIndex += 4; addrSpec = new AddrSpec() { FQDN = "", IP = targetIP }; break; case AddressType.IPV6Address: address = new byte[16]; Array.Copy(data, dataIndex, address, 0, 16); targetIP = new IPAddress(address); dataIndex += 16; addrSpec = new AddrSpec() { FQDN = "", IP = targetIP, }; break; case AddressType.FQDNAddress: int addrLength = data[dataIndex]; dataIndex += 1; byte[] fqdnBytes = new byte[addrLength]; Array.Copy(data, dataIndex, fqdnBytes, 0, addrLength); dataIndex += addrLength; string fqdn = Encoding.UTF8.GetString(fqdnBytes); try { var ipEntry = Dns.GetHostEntry(fqdn); if (ipEntry.AddressList.Length == 0) { break; } foreach (var ipaddr in ipEntry.AddressList) { if (ipaddr.ToString().Contains(".")) { targetIP = ipaddr; break; } } if (targetIP == null) { targetIP = ipEntry.AddressList[0]; } addrSpec = new AddrSpec() { FQDN = fqdn, IP = targetIP }; break; } catch (Exception ex) { //DebugWriteLine($"Error while resolving FQDN: {ex.Message}"); //if (ByteSequenceEquals(data, new byte[] { 5, 1, 0, 5}) || ByteSequenceEquals(data, new byte[] { 5,2,0,2})) //{ // var msg = new SocksDatagram() // { // server_id = conn.ServerID, // data = Convert.ToBase64String(new byte[] { 5, 0 }) // }; // AddMythicMessageToQueue(msg); //} //new Thread(() => RemoveProxyConnection(conn)).Start(); break; } default: //DebugWriteLine("AddrType was not IPv4, IPv6, or FQDN!"); //if (ByteSequenceEquals(data, new byte[] { 5, 1, 0, 5 }) || ByteSequenceEquals(data, new byte[] { 5, 2, 0, 2 })) //{ // var msg = new SocksDatagram() // { // server_id = conn.ServerID, // data = Convert.ToBase64String(new byte[] { 5, 0 }) // }; // AddMythicMessageToQueue(msg); //} //new Thread(() => RemoveProxyConnection(conn)).Start(); break; } if (targetIP == null) { throw new SocksException(SocksError.AddrTypeNotSupported); } if (data.Length < (dataIndex + 2)) { throw new SocksException(SocksError.ServerFailure); } byte[] portBytes = new byte[2]; Array.Copy(data, dataIndex, portBytes, 0, 2); dataIndex += 2; targetPort = ((int)portBytes[0] << 8) | (int)portBytes[1]; addrSpec.Port = targetPort; Request request = new Request() { Version = socks5Version, Command = header[1], DestAddr = addrSpec, //BufCon = conn }; int clientPort = rnd.Next(60000, 65536); AddrSpec clientAddr = new AddrSpec() { FQDN = "", IP = System.Net.IPAddress.Parse("127.0.0.1"), Port = clientPort }; request.RemoteAddr = clientAddr; IPAddress destIPAddr; if (request.DestAddr.FQDN != "") { if (request.DestAddr.IP == null) { //DebugWriteLine("About to resolve FQDN"); var dnsEntry = Dns.GetHostEntry(request.DestAddr.FQDN); if (dnsEntry.AddressList.Length == 0) { throw new SocksException(SocksError.HostUnreachable); } request.DestAddr.IP = dnsEntry.AddressList[0]; } } return(request); }