public static void Handle(byte[] firstResponse, ProxyClient client) { if (!client.Controller.IsSocksSupported || !IsSocks(firstResponse)) { client.Close(); return; } // Responding with socks protocol byte clientVersion = firstResponse[0]; if (clientVersion == 5) { byte[] clientSupportedAuths = new byte[firstResponse[1]]; Array.Copy(firstResponse, 2, clientSupportedAuths, 0, firstResponse[1]); byte[] serverResponse = new byte[2]; if (clientSupportedAuths.Length == 0) { client.Close( "No authentication method found.", null, ErrorRenderer.HttpHeaderCode.C417ExpectationFailed); return; } serverResponse[0] = clientVersion; // -------------Selecting authentication type byte serverSelectedAuth = 255; foreach (byte item in clientSupportedAuths) { if (item == 0) { serverSelectedAuth = 0; } } serverResponse[1] = serverSelectedAuth; client.Write(serverResponse); client.IsReceivingStarted = false; // -------------Doing authentication if (serverSelectedAuth == 255) { client.Close( "SOCKS Connection only accept clients with no authentication information.", null, ErrorRenderer.HttpHeaderCode.C417ExpectationFailed); return; } // -------------Establishing connection byte[] response = new byte[client.UnderlyingSocket.ReceiveBufferSize]; client.UnderlyingSocket.ReceiveTimeout = client.NoDataTimeOut; client.UnderlyingSocket.BeginReceive( response, 0, response.Length, SocketFlags.None, delegate(IAsyncResult ar) { try { int bytes = client.UnderlyingSocket.EndReceive(ar); Array.Resize(ref response, bytes); if (response == null || response.Length == 0) { client.Close( "No request received. Connection Timeout.", null, ErrorRenderer.HttpHeaderCode.C417ExpectationFailed); return; } if (response[0] != clientVersion) { client.Close( "Unknown SOCKS version, Expected " + clientVersion, null, ErrorRenderer.HttpHeaderCode.C417ExpectationFailed); return; } byte clientConnectionType = response[1]; byte clientAddressType = response[3]; string clientConnectionAddress = null; byte[] clientUnformatedConnectionAddress; ushort clientConnectionPort = 0; byte serverAresponse = 0; if (clientConnectionType != 1) { serverAresponse = 7; } switch (clientAddressType) { case 1: clientUnformatedConnectionAddress = new byte[4]; Array.Copy(response, 4, clientUnformatedConnectionAddress, 0, 4); clientConnectionAddress = new IPAddress(clientUnformatedConnectionAddress).ToString(); clientConnectionPort = (ushort)((ushort)(response[8] * 256) + response[9]); break; case 3: clientUnformatedConnectionAddress = new byte[response[4]]; Array.Copy(response, 5, clientUnformatedConnectionAddress, 0, response[4]); clientConnectionAddress = Encoding.ASCII.GetString(clientUnformatedConnectionAddress); clientConnectionPort = (ushort) ((ushort)(response[5 + response[4]] * 256) + response[5 + response[4] + 1]); break; case 4: clientUnformatedConnectionAddress = new byte[16]; Array.Copy(response, 4, clientUnformatedConnectionAddress, 0, 16); clientConnectionAddress = new IPAddress(clientUnformatedConnectionAddress).ToString(); clientConnectionPort = (ushort)((ushort)(response[20] * 256) + response[21]); break; default: serverAresponse = 8; break; } serverResponse = new byte[3 + (response.Length - 3)]; serverResponse[0] = clientVersion; serverResponse[1] = serverAresponse; serverResponse[2] = 0; serverResponse[3] = 3; Array.Copy(response, 3, serverResponse, 3, response.Length - 3); client.RequestAddress = "socks://" + clientConnectionAddress + ":" + clientConnectionPort; client.Write(serverResponse); client.IsReceivingStarted = false; if (serverAresponse != 0) { client.Close( "Response Error, Code: " + serverAresponse, null, ErrorRenderer.HttpHeaderCode.C417ExpectationFailed, true); return; } firstResponse = new byte[0]; DirectHandle(client, clientConnectionAddress, clientConnectionPort, firstResponse); } catch (Exception e) { client.Close(e.Message, e.StackTrace); } }, response); } else if (clientVersion == 4) { try { byte clientConnectionType = firstResponse[1]; byte serverAresponse = 90; if (clientConnectionType != 1) { serverAresponse = 91; } ushort clientConnectionPort = (ushort)((ushort)(firstResponse[2] * 256) + firstResponse[3]); byte[] clientUnformatedConnectionAddress = new byte[4]; Array.Copy(firstResponse, 4, clientUnformatedConnectionAddress, 0, 4); string clientConnectionAddress = new IPAddress(clientUnformatedConnectionAddress).ToString(); if (clientConnectionAddress.StartsWith("0.0.0.") && !clientConnectionAddress.EndsWith(".0")) { int domainStart = 0, domainEnd = 0; for (int i = 8; i < firstResponse.Length; i++) { if (firstResponse[i] == 0) { if (domainStart == 0) { domainStart = i + 1; } else if (domainEnd == 0) { domainEnd = i; } } } if (domainEnd != 0 && domainStart != 0) { clientConnectionAddress = Encoding.ASCII.GetString( firstResponse, domainStart, domainEnd - domainStart); } else { serverAresponse = 91; } } byte[] serverResponse = new byte[8]; serverResponse[0] = 0; serverResponse[1] = serverAresponse; Array.Copy(firstResponse, 2, serverResponse, 2, 2); // PORT Array.Copy(firstResponse, 4, serverResponse, 4, 4); // IP client.RequestAddress = "socks://" + clientConnectionAddress + ":" + clientConnectionPort; client.Write(serverResponse); client.IsReceivingStarted = false; if (serverAresponse != 90) { client.Close( "Response Error, Code: " + serverAresponse, null, ErrorRenderer.HttpHeaderCode.C417ExpectationFailed, true); return; } firstResponse = new byte[0]; DirectHandle(client, clientConnectionAddress, clientConnectionPort, firstResponse); } catch (Exception e) { client.Close(e.Message, e.StackTrace); } } }