Beispiel #1
0
        public override async Task <int> UdpQueryAsync(ArraySegment <byte> request, ArraySegment <byte> response, EndPoint remoteEP, int timeout = 10000, int retries = 1, bool expBackoffTimeout = false, CancellationToken cancellationToken = default)
        {
            if (IsBypassed(remoteEP))
            {
                IPEndPoint ep = await remoteEP.GetIPEndPointAsync();

                using (Socket socket = new Socket(ep.AddressFamily, SocketType.Dgram, ProtocolType.Udp))
                {
                    return(await socket.UdpQueryAsync(request, response, ep, timeout, retries, expBackoffTimeout, cancellationToken));
                }
            }

            if (_viaProxy != null)
            {
                throw new NotSupportedException("Cannot chain proxies for Udp protocol.");
            }

            using (SocksProxyUdpAssociateHandler proxyUdpRequestHandler = await UdpAssociateAsync())
            {
                return(await proxyUdpRequestHandler.UdpQueryAsync(request, response, remoteEP, timeout, retries, expBackoffTimeout, cancellationToken));
            }
        }
Beispiel #2
0
        public override async Task <bool> IsUdpAvailableAsync()
        {
            if (_isUdpAvailableChecked)
            {
                return(_isUdpAvailable);
            }

            SocksProxyUdpAssociateHandler udpHandler = null;

            try
            {
                udpHandler = await UdpAssociateAsync();

                _isUdpAvailable = true;
            }
            catch (SocksProxyException ex)
            {
                if (ex.ReplyCode == SocksProxyReplyCode.CommandNotSupported)
                {
                    _isUdpAvailable = false;
                }
                else
                {
                    throw;
                }
            }
            finally
            {
                if (udpHandler != null)
                {
                    udpHandler.Dispose();
                }
            }

            _isUdpAvailableChecked = true;

            return(_isUdpAvailable);
        }
Beispiel #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();
                    }
                }
            }