public static async Task <SocksProxyRequest> ReadRequestAsync(Stream s)
        {
            SocksProxyRequest request = new SocksProxyRequest();

            byte[] buffer = new byte[3];
            await s.ReadBytesAsync(buffer, 0, 3);

            request._version = buffer[0];
            request._command = (SocksProxyRequestCommand)buffer[1];
            request._dstEP   = await SocksProxyServer.ReadEndPointAsync(s);

            return(request);
        }
Esempio n. 2
0
        private static async Task <EndPoint> RequestAsync(Stream s, SocksProxyRequest request)
        {
            await request.WriteToAsync(s);

            await s.FlushAsync();

            SocksProxyReply reply = await SocksProxyReply.ReadReplyAsync(s);

            if (!reply.IsVersionSupported)
            {
                throw new SocksProxyException("Socks version 5 is not supported by the proxy server.");
            }

            if (reply.ReplyCode != SocksProxyReplyCode.Succeeded)
            {
                throw new SocksProxyException("Socks proxy server request failed: " + reply.ReplyCode.ToString(), reply.ReplyCode);
            }

            return(reply.BindEndPoint);
        }
Esempio n. 3
0
            public async Task StartAsync()
            {
                bool dontDispose = false;

                try
                {
                    NetworkStream localNetworkStream = new NetworkStream(_localSocket);
                    Stream        localStream        = new WriteBufferedStream(localNetworkStream, 512);

                    #region authenticate

                    SocksProxyNegotiationRequest negotiationRequest = await SocksProxyNegotiationRequest.ReadRequestAsync(localStream).WithTimeout(CLIENT_WAIT_TIMEOUT);

                    if (!negotiationRequest.IsVersionSupported)
                    {
                        await new SocksProxyNegotiationReply(SocksProxyAuthenticationMethod.NoAcceptableMethods).WriteToAsync(localStream);
                        await localStream.FlushAsync();

                        return;
                    }

                    //match method and authenticate
                    bool methodMatched = false;
                    SocksProxyAuthenticationMethod serverMethod = _authenticationManager == null ? SocksProxyAuthenticationMethod.NoAuthenticationRequired : SocksProxyAuthenticationMethod.UsernamePassword;

                    foreach (SocksProxyAuthenticationMethod method in negotiationRequest.Methods)
                    {
                        if (method == serverMethod)
                        {
                            //method matches
                            await new SocksProxyNegotiationReply(method).WriteToAsync(localStream);
                            await localStream.FlushAsync();

                            switch (serverMethod)
                            {
                            case SocksProxyAuthenticationMethod.NoAuthenticationRequired:
                                methodMatched = true;
                                break;

                            case SocksProxyAuthenticationMethod.UsernamePassword:
                                //read method version

                                SocksProxyAuthenticationRequest authenticationRequest = await SocksProxyAuthenticationRequest.ReadRequestAsync(localStream).WithTimeout(CLIENT_WAIT_TIMEOUT);

                                if (!authenticationRequest.IsVersionSupported)
                                {
                                    await new SocksProxyAuthenticationReply(SocksProxyAuthenticationStatus.Failure).WriteToAsync(localStream);
                                    await localStream.FlushAsync();

                                    return;
                                }

                                if (!_authenticationManager.Authenticate(authenticationRequest.Username, authenticationRequest.Password))
                                {
                                    await new SocksProxyAuthenticationReply(SocksProxyAuthenticationStatus.Failure).WriteToAsync(localStream);
                                    await localStream.FlushAsync();

                                    return;
                                }

                                await new SocksProxyAuthenticationReply(SocksProxyAuthenticationStatus.Success).WriteToAsync(localStream);
                                await localStream.FlushAsync();

                                methodMatched = true;
                                break;
                            }

                            break;
                        }
                    }

                    if (!methodMatched)
                    {
                        //no method matched
                        await new SocksProxyNegotiationReply(SocksProxyAuthenticationMethod.NoAcceptableMethods).WriteToAsync(localStream);
                        await localStream.FlushAsync();

                        return;
                    }

                    #endregion

                    #region process request

                    //read request
                    SocksProxyRequest request = await SocksProxyRequest.ReadRequestAsync(localStream).WithTimeout(CLIENT_WAIT_TIMEOUT);

                    if (!request.IsVersionSupported)
                    {
                        await new SocksProxyReply(SocksProxyReplyCode.GeneralSocksServerFailure).WriteToAsync(localStream);
                        await localStream.FlushAsync();

                        return;
                    }

                    //process command
                    SocksProxyReplyCode reply;
                    EndPoint            bindEP;

                    switch (request.Command)
                    {
                    case SocksProxyRequestCommand.Connect:
                    {
                        try
                        {
                            _remoteSocket = await _connectionManager.ConnectAsync(request.DestinationEndPoint);

                            reply  = SocksProxyReplyCode.Succeeded;
                            bindEP = _remoteSocket.LocalEndPoint;
                        }
                        catch (SocketException ex)
                        {
                            switch (ex.SocketErrorCode)
                            {
                            case SocketError.NetworkUnreachable:
                                reply = SocksProxyReplyCode.NetworkUnreachable;
                                break;

                            case SocketError.HostUnreachable:
                                reply = SocksProxyReplyCode.HostUnreachable;
                                break;

                            case SocketError.ConnectionRefused:
                                reply = SocksProxyReplyCode.ConnectionRefused;
                                break;

                            default:
                                reply = SocksProxyReplyCode.GeneralSocksServerFailure;
                                break;
                            }

                            bindEP = new IPEndPoint(IPAddress.Any, 0);
                        }
                    }
                    break;

                    case SocksProxyRequestCommand.Bind:
                    {
                        _bindHandler = await _connectionManager.GetBindHandlerAsync(request.DestinationEndPoint.AddressFamily);

                        reply  = _bindHandler.ReplyCode;
                        bindEP = _bindHandler.ProxyLocalEndPoint;
                    }
                    break;

                    case SocksProxyRequestCommand.UdpAssociate:
                    {
                        switch (_localSocket.LocalEndPoint.AddressFamily)
                        {
                        case AddressFamily.InterNetwork:
                        case AddressFamily.InterNetworkV6:
                            EndPoint localEP = new IPEndPoint((_localSocket.LocalEndPoint as IPEndPoint).Address, 0);

                            _udpRelaySocket = new Socket(localEP.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
                            _udpRelaySocket.Bind(localEP);

                            reply  = SocksProxyReplyCode.Succeeded;
                            bindEP = _udpRelaySocket.LocalEndPoint as IPEndPoint;
                            break;

                        default:
                            reply  = SocksProxyReplyCode.AddressTypeNotSupported;
                            bindEP = new IPEndPoint(IPAddress.Any, 0);
                            break;
                        }
                    }
                    break;

                    default:
                        reply  = SocksProxyReplyCode.CommandNotSupported;
                        bindEP = new IPEndPoint(IPAddress.Any, 0);
                        break;
                    }

                    //send response
                    await new SocksProxyReply(reply, bindEP).WriteToAsync(localStream);
                    await localStream.FlushAsync();

                    if (reply != SocksProxyReplyCode.Succeeded)
                    {
                        return; //nothing to do further
                    }
                    //final command process
                    switch (request.Command)
                    {
                    case SocksProxyRequestCommand.Connect:
                    {
                        //pipe sockets
                        _           = _localSocket.CopyToAsync(_remoteSocket).ContinueWith(delegate(Task prevTask) { Dispose(); });
                        _           = _remoteSocket.CopyToAsync(_localSocket).ContinueWith(delegate(Task prevTask) { Dispose(); });
                        dontDispose = true;
                    }
                    break;

                    case SocksProxyRequestCommand.Bind:
                    {
                        try
                        {
                            _remoteSocket = await _bindHandler.AcceptAsync().WithTimeout(CLIENT_WAIT_TIMEOUT);
                        }
                        catch (SocksProxyException ex)
                        {
                            //send second reply
                            await new SocksProxyReply(ex.ReplyCode, _bindHandler.ProxyLocalEndPoint).WriteToAsync(localStream);
                            await localStream.FlushAsync();
                        }
                        catch
                        {
                            //send second reply
                            await new SocksProxyReply(SocksProxyReplyCode.GeneralSocksServerFailure, _bindHandler.ProxyLocalEndPoint).WriteToAsync(localStream);
                            await localStream.FlushAsync();
                        }

                        if (_remoteSocket != null)
                        {
                            _bindHandler.Dispose();

                            //send second reply
                            await new SocksProxyReply(SocksProxyReplyCode.Succeeded, _bindHandler.ProxyRemoteEndPoint).WriteToAsync(localStream);
                            await localStream.FlushAsync();

                            //pipe sockets
                            _           = _localSocket.CopyToAsync(_remoteSocket).ContinueWith(delegate(Task prevTask) { Dispose(); });
                            _           = _remoteSocket.CopyToAsync(_localSocket).ContinueWith(delegate(Task prevTask) { Dispose(); });
                            dontDispose = true;
                        }
                    }
                    break;

                    case SocksProxyRequestCommand.UdpAssociate:
                    {
                        EndPoint localEP = null;

                        switch (_localSocket.LocalEndPoint.AddressFamily)
                        {
                        case AddressFamily.InterNetwork:
                            localEP = new IPEndPoint(IPAddress.Any, 0);
                            break;

                        case AddressFamily.InterNetworkV6:
                            localEP = new IPEndPoint(IPAddress.IPv6Any, 0);
                            break;

                        default:
                            throw new NotSupportedException();
                        }

                        using (IProxyServerUdpAssociateHandler udpRemoteHandler = await _connectionManager.GetUdpAssociateHandlerAsync(localEP))
                        {
                            using (IProxyServerUdpAssociateHandler udpLocalHandler = new SocksProxyUdpAssociateHandler(_localSocket, _udpRelaySocket, new IPEndPoint((_localSocket.RemoteEndPoint as IPEndPoint).Address, (request.DestinationEndPoint as IPEndPoint).Port)))
                            {
                                _ = CopyToAsync(udpRemoteHandler, udpLocalHandler);
                                await CopyToAsync(udpLocalHandler, udpRemoteHandler);
                            }
                        }
                    }
                    break;
                    }

                    #endregion
                }
                finally
                {
                    if (!dontDispose)
                    {
                        Dispose();
                    }
                }
            }