How to connect through the proxy with .Net/Mono TCP/UDP Socket?


We are using C# Socket in Unity to connect to our server. Using proxy is crucial for our use case, unfortunately there is no direct support for proxy in Socket. We are using both TCP and UDP sockets at the same time to exchange data between our app and the server.

Based on this question I'm able to connect through the proxy with first TCP socket, but when I try to connect through the same proxy with second UDP socket, I receive this exception on line socket.Receive(receiveBuffer):

System.Net.Sockets.SocketException (0x80004005): An existing connection was forcibly closed by the remote host.
ErrorCode = 10054
SocketErrorCode = ConnectionReset

Does it means that the first TCP ws closed because ther can be only one connection at the same time?

I'm using Fiddler to test this scenario. I do not see the second UDP connection in its log.

Is it possible to connect through single proxy with more than one socket from the same app (process)? Is there some settings in Fiddler that should be changed? Am I missing something?

My simplified code:

class ConnectorExample
    public class ProxyConfig
        public string server; //
        public string username;
        public string password;

        public Uri serverUri => new Uri(server);

    void Connect(IPAddress ipAddress, int tcpPort, int udpPort, ProxyConfig proxyConfig)
        IPEndPoint remoteTcpEndPoint = new IPEndPoint(ipAddress, tcpPort);
        IPEndPoint remoteUdpEndPoint = new IPEndPoint(ipAddress, udpPort);

        Socket tcpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        Socket udpSocket = new Socket(tcpSocket.AddressFamily, SocketType.Dgram, ProtocolType.Udp);

        // TCP socket
        ConnectThroughProxy(proxyConfig, tcpSocket, remoteTcpEndPoint);

        // UDP Socket
        // Bind UDP to a free port
        udpSocket.Bind(new IPEndPoint(((IPEndPoint) tcpSocket.LocalEndPoint).Address, 0));
        ConnectThroughProxy(proxyConfig, udpSocket, remoteUdpEndPoint);

    // Returns true if connection through the proxy succeeded
    private bool ConnectThroughProxy(ProxyConfig proxyConfig, Socket socket, IPEndPoint destination)
        Uri proxyUri = proxyConfig.serverUri;
        string username = proxyConfig.username;
        string password = proxyConfig.password;

        // Connect to the proxy
        socket.Connect(proxyUri.Host, proxyUri.Port);

        // Authentication
        string auth = string.Empty;
        if (!string.IsNullOrEmpty(username) && !string.IsNullOrEmpty(password))
            string credentials = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{username}:{password}"));
            auth = $"Proxy-Authorization: Basic {credentials}";

        // Connect to the destination
        // string connectString = $"CONNECT {destination.Address}:{destination.Port} HTTP/1.1{Environment.NewLine}{auth}{Environment.NewLine}{Environment.NewLine}";
        string hostAddress = $"{destination.Address}:{destination.Port}";
        string connectString = $"CONNECT {destination.Address}:{destination.Port} HTTP/1.1{Environment.NewLine}Host: {hostAddress}{Environment.NewLine}{auth}{Environment.NewLine}{Environment.NewLine}";
        byte[] connectMessage = Encoding.UTF8.GetBytes(connectString);

        byte[] receiveBuffer = new byte[1024];
        int received = socket.Receive(receiveBuffer); // Exception for second UDP socket

        string response = ASCIIEncoding.ASCII.GetString(receiveBuffer, 0, received);
        // Response content sample:
        // HTTP/1.1 200 Connection Established

        // TODO: Should we check for string: "HTTP/1.1 200" ? Checking just "200" seems to be quite weak check.
        bool connected = response.Contains("200");
        return connected;

EDIT: Perhaps the correct question is: Is it possible to use proxy for UDP connections?

asked on Stack Overflow Apr 14, 2021 by David Rysanek • edited Apr 14, 2021 by David Rysanek

0 Answers

Nobody has answered this question yet.

User contributions licensed under CC BY-SA 3.0