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 == SocketServer.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("SOCKS5 Bytestream connection for: {0}", reqmsg.DestinationDomain); RemoteHost = reqmsg.DestinationDomain; bConnected = true; this.ServerSessionState = SocketServer.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 }
protected override void OnRecvData(byte[] bData, int nLen) { if (nLen == 0) { OnDisconnect("Normal closing"); return; } //Console.WriteLine(string.Format("<-- {0}", ByteSize.ByteUtils.HexStringFromByte(bData, true))); if (ServerSessionState == ServerSessionState.Forwarding) { try { 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 { 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 /// this.ServerSessionState = ServerSessionState.Forwarding; /// Let's try to connect /// /// Don't connect to a remote host in this version, just check the hash here, if it matches, send back success bool bHashMatched = false; //if (reqmsg.AddressType == AddressType.DomainName) // bConnected = ConnectClient.Connect(reqmsg.DestinationDomain, reqmsg.DestinationPort, true); //else // bConnected = ConnectClient.Connect(reqmsg.DestinationAddress.ToString(), reqmsg.DestinationPort, true); SocksReplyMessage reply = new SocksReplyMessage(); if (bHashMatched == 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 }