Beispiel #1
0
            private async Task DoConnectAsync(NetworkStream localStream, HttpRequest httpRequest)
            {
                string host;
                int    port;

                {
                    string[] parts = httpRequest.RequestPath.Split(':');

                    host = parts[0];

                    if (parts.Length > 1)
                    {
                        port = int.Parse(parts[1]);
                    }
                    else
                    {
                        port = 80;
                    }
                }

                //connect to remote server
                _remoteSocket = await _connectionManager.ConnectAsync(EndPointExtension.GetEndPoint(host, port));

                //signal client 200 OK
                await localStream.WriteAsync(Encoding.ASCII.GetBytes(httpRequest.Protocol + " 200 OK\r\nConnection: close\r\n\r\n"));

                //pipe sockets
                _ = _localSocket.CopyToAsync(_remoteSocket).ContinueWith(delegate(Task prevTask) { Dispose(); });
                _ = _remoteSocket.CopyToAsync(_localSocket).ContinueWith(delegate(Task prevTask) { Dispose(); });
            }
            public async Task StartAsync()
            {
                bool dontDispose = false;

                try
                {
                    IPEndPoint originalDestinationEP = GetOriginalDestination();
                    if (originalDestinationEP == null)
                    {
                        return;
                    }

                    _remoteSocket = await _connectionManager.ConnectAsync(originalDestinationEP);

                    //pipe sockets
                    _           = _localSocket.PipeToAsync(_remoteSocket).ContinueWith(delegate(Task prevTask) { Dispose(); });
                    dontDispose = true;
                }
                finally
                {
                    if (!dontDispose)
                    {
                        Dispose();
                    }
                }
            }
        private async Task <IProxyServerConnectionManager> CheckConnectivityAsync(IProxyServerConnectionManager connectionManager)
        {
            Exception lastException = null;

            foreach (EndPoint connectivityCheckEP in _connectivityCheckEPs)
            {
                try
                {
                    using (Socket socket = await connectionManager.ConnectAsync(connectivityCheckEP).WithTimeout(NETWORK_CHECK_CONNECTION_TIMEOUT))
                    { }

                    return(connectionManager);
                }
                catch (Exception ex)
                {
                    lastException = ex;
                }
            }

            Errors?.Invoke(this, lastException);
            return(null);
        }
Beispiel #4
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();
                    }
                }
            }