protected override void OnRecvData(byte[] bData, int nLen) { if (nLen == 0) { OnDisconnect("Normal closing"); return; } if (ServerSessionState == ServerSessionState.Forwarding) { try { if (ConnectClient != null) /// connected client may be null if we are acting as a socks5 bytestream proxy, where we don't actually forward anything { ConnectClient.Send(bData, nLen); } DoAsyncRead(); } catch (Exception) { } return; } ReceiveBuffer.AppendData(bData, 0, nLen); if (ServerSessionState == ServerSessionState.JustExisting) { DoAsyncRead(); // go read some more return; } byte[] bCurData = ReceiveBuffer.PeekAllSamples(); if (bCurData.Length <= 0) { DoAsyncRead(); return; } if (ServerSessionState == ServerSessionState.WaitingForMethodSelections) { int nVersion = bCurData[0]; if (nVersion == 5) { MethodSelectionsMessage msg = new MethodSelectionsMessage(); int nRead = msg.ReadFromBytes(bData, 0); if (nRead > 0) { ReceiveBuffer.GetNSamples(nRead); /// Determine which method we support /// bool bCanDoNoAuth = false; foreach (SockMethod method in msg.Methods) { if (method == SockMethod.NoAuthenticationRequired) { bCanDoNoAuth = true; break; } } if (bCanDoNoAuth == false) { MethodSelectedMessage retmsg = new MethodSelectedMessage(); retmsg.Version = 5; retmsg.SockMethod = SockMethod.NoAcceptableMethods; this.Send(retmsg.GetBytes()); this.Disconnect(); return; } else { ServerSessionState = ServerSessionState.WaitingForSocksRequestMessage; MethodSelectedMessage retmsg = new MethodSelectedMessage(); retmsg.Version = msg.Version; retmsg.SockMethod = SockMethod.NoAuthenticationRequired; this.Send(retmsg.GetBytes()); } } } else if (nVersion == 4) { MethodSelectionsVersionFourMessage msg = new MethodSelectionsVersionFourMessage(); int nRead = msg.ReadFromBytes(bData, 0); if (nRead > 0) { ReceiveBuffer.GetNSamples(nRead); MethodSelectedVersionFourMessage reply = new MethodSelectedVersionFourMessage(); /// See what the man wants. It appears that mozilla immediately starts sending data if we return success here, so let's do it /// this.ServerSessionState = ServerSessionState.Forwarding; /// Let's try to connect /// bool bConnected = false; if (msg.DomainName != null) { bConnected = ConnectClient.Connect(msg.DomainName, msg.DestinationPort, true); } else { bConnected = ConnectClient.Connect(msg.DestIPAddress.ToString(), msg.DestinationPort, true); } if (bConnected == false) { reply.SOCKS4Status = SOCKS4Status.RequestRejected; Send(reply.GetBytes()); Disconnect(); } else { reply.SOCKS4Status = SOCKS4Status.RequestGranted; Send(reply.GetBytes()); } } } else { Console.WriteLine("Version {0} not supported", nVersion); MethodSelectedMessage retmsg = new MethodSelectedMessage(); retmsg.Version = 5; retmsg.SockMethod = SockMethod.NoAcceptableMethods; this.Send(retmsg.GetBytes()); this.Disconnect(); return; } } else if (ServerSessionState == ServerSessionState.WaitingForSocksRequestMessage) { /// Read in our SocksRequestMessage /// SocksRequestMessage reqmsg = new SocksRequestMessage(); int nRead = reqmsg.ReadFromBytes(bData, 0); if (nRead > 0) { ReceiveBuffer.GetNSamples(nRead); if (reqmsg.Version != 0x05) { Console.WriteLine("No version 5, client wants version: {0}", reqmsg.Version); } //Parent.HandleRequest(reqmsg, this); if (reqmsg.SOCKSCommand == SOCKSCommand.Connect) { /// See what the man wants. It appears that mozilla immediately starts sending data if we return success here, so let's do it /// bool bConnected = false; if (SOCKSServerMode == SOCKSServerMode.NormalSOCKS5Server) { this.ServerSessionState = ServerSessionState.Forwarding; /// Let's try to connect /// if (reqmsg.AddressType == AddressType.DomainName) { bConnected = ConnectClient.Connect(reqmsg.DestinationDomain, reqmsg.DestinationPort, true); } else { bConnected = ConnectClient.Connect(reqmsg.DestinationAddress.ToString(), reqmsg.DestinationPort, true); } } else { Console.WriteLine("Incoming SOCKS5 Bytestream Connect command to domain: {0}, remote endppoint is: {1}", reqmsg.DestinationDomain, this.socket.RemoteEndPoint); RemoteHost = reqmsg.DestinationDomain; bConnected = true; this.ServerSessionState = ServerSessionState.JustExisting; } SocksReplyMessage reply = new SocksReplyMessage(); if (bConnected == false) { reply.SOCKSReply = SOCKSReply.ConnectionRefused; } else { reply.SOCKSReply = SOCKSReply.Succeeded; } Send(reply.GetBytes()); } else { SocksReplyMessage reply = new SocksReplyMessage(); reply.SOCKSReply = SOCKSReply.CommandNotSupported; reply.AddressType = AddressType.IPV4; Send(reply.GetBytes()); } } } DoAsyncRead(); // go read some more }
public bool HandleReceiveData(byte[] bRecv) { ReceiveBuffer.AppendData(bRecv); byte[] bAllData = ReceiveBuffer.PeekAllSamples(); /// Recieve our response /// if (SocksVersion == 4) { MethodSelectedVersionFourMessage msg = new MethodSelectedVersionFourMessage(); int nRead = msg.ReadFromBytes(bAllData, 0); if (nRead > 0) { ReceiveBuffer.GetNSamples(nRead); if (msg.SOCKS4Status == SOCKS4Status.RequestGranted) { return(true); } else { throw new Exception("Failed to negotiate a SOCKS4 session"); } } return(false); } else if (SocksVersion == 5) { if (SOCKS5ClientSessionState == SOCKS5ClientSessionState.WaitingForMethodSelected) { MethodSelectedMessage msg = new MethodSelectedMessage(); int nRead = msg.ReadFromBytes(bAllData, 0); if (nRead > 0) { ReceiveBuffer.GetNSamples(nRead); if (msg.SockMethod != SockMethod.NoAuthenticationRequired) { throw new Exception("Failed to negotiate a SOCKS5 session"); } SOCKS5ClientSessionState = SOCKS5ClientSessionState.WaitingForFinalResponse; /// We're happy, send our connect request SocksRequestMessage req = new SocksRequestMessage(); req.AddressType = AddressType.DomainName; req.DestinationDomain = RemoteHost; req.DestinationPort = (ushort)RemotePort; req.Version = 0x05; req.SOCKSCommand = SOCKSCommand.Connect; byte[] bMsg = req.GetBytes(); Send(bMsg); } return(false); } else if (SOCKS5ClientSessionState == SOCKS5ClientSessionState.WaitingForFinalResponse) { SocksReplyMessage msg = new SocksReplyMessage(); int nRead = msg.ReadFromBytes(bAllData, 0); if (nRead > 0) { ReceiveBuffer.GetNSamples(nRead); if (msg.SOCKSReply == SOCKSReply.Succeeded) { return(true); } else { throw new Exception(string.Format("Failed to negotiate a SOCKS5 session, error: {0}", msg.SOCKSReply)); } } return(false); } return(false); } else { throw new Exception("Unsupported Version"); } }