Ejemplo n.º 1
0
 void PipeClient(DefaultPipe pipe, CancellationToken cancellationToken)
 {
     pipe.OnBroken += this.Pipe_OnBroken;
     lock (_pipesReadWriteLock)
     {
         this._pipes.Add(pipe);
     }
     pipe.Pipe(cancellationToken);
 }
 void PipeClient(DefaultPipe p, CancellationToken cancellationToken, params ClientFilter[] addFilters)
 {
     p.OnBroken += Pipe_OnBroken;
     p.ApplyClientFilter(addFilters);
     lock (_pipesReadWriteLock)
     {
         this._pipes.Add(p);
     }
     p.Pipe(cancellationToken);
 }
        void PipeTcp(IClient client, IClient relayClient, IShadowsocksStreamCipher cipher, CancellationToken cancellationToken)
        {
            DefaultPipe pipe   = new DefaultPipe(client, relayClient, Defaults.ReceiveBufferSize, _logger);
            PipeFilter  filter = new Cipher.CipherTcpFilter(relayClient, cipher, _logger);

            pipe.ApplyFilter(filter);

            pipe.OnBroken += this.Pipe_OnBroken;
            lock (_pipesReadWriteLock)
            {
                this._pipes.Add(pipe);
            }
            pipe.Pipe();
        }
Ejemplo n.º 4
0
        public async Task HandleUdp(IClient client, CancellationToken cancellationToken)
        {
            if (null == client)
            {
                return;
            }

            //authentication //TODO udp assoc

            var server = _serverLoader.Load(null);

            if (null == server)
            {
                _logger?.LogInformation($"proxy server not found.");
                client.Close();
                return;
            }
            var serverAddr = await server.GetIPEndPoint();

            if (null == serverAddr)
            {
                _logger?.LogInformation($"unable to get proxy server address.");
                client.Close();
                return;
            }


            var relayClient = await UdpClient1.ConnectAsync(serverAddr, _logger);

            if (null == relayClient)
            {
                _logger?.LogInformation($"unable to relay udp");
                client.Close();
                return;
            }

            DefaultPipe  pipe    = new DefaultPipe(client, relayClient, 1500, _logger);
            ClientFilter filter  = new Cipher.UdpCipherFilter(relayClient, server.CreateCipher(_logger), _logger);
            ClientFilter filter2 = new UdpEncapsulationFilter(relayClient, _logger);

            pipe.ApplyClientFilter(filter).ApplyClientFilter(filter2);

            PipeClient(pipe, cancellationToken);
        }
        void PipeUdp(IClient client, IClient relayClient, IShadowsocksStreamCipher cipher, CancellationToken cancellationToken)
        {
            //authentication //TODO udp assoc
            DefaultPipe pipe = new DefaultPipe(relayClient, client, Defaults.ReceiveBufferSize, _logger);

            PipeFilter filter  = new Cipher.CipherUdpFilter(relayClient, cipher, _logger);
            PipeFilter filter2 = new LocalUdpRelayPackingFilter(relayClient, _logger);

            pipe.ApplyFilter(filter)
            .ApplyFilter(filter2);

            pipe.OnBroken += this.Pipe_OnBroken;

            lock (_pipesReadWriteLock)
            {
                this._pipes.Add(pipe);
            }
            pipe.Pipe();
        }
        void PipeUdp(IClient localClient, IClient targetClient, Cipher.IShadowsocksStreamCipher cipher, CancellationToken cancellationToken, params PipeFilter[] addFilters)
        {
            DefaultPipe p = new DefaultPipe(targetClient, localClient, 1500, _logger);

            p.OnBroken += Pipe_OnBroken;

            Cipher.CipherUdpFilter      filterLocal1  = new Cipher.CipherUdpFilter(localClient, cipher, _logger);
            RemoteUdpRelayPackingFilter filterTarget1 = new RemoteUdpRelayPackingFilter(targetClient, _logger);

            p.ApplyFilter(filterLocal1).ApplyFilter(filterTarget1);
            if (addFilters.Length > 0)
            {
                p.ApplyFilter(addFilters);
            }

            lock (_pipesReadWriteLock)
            {
                this._pipes.Add(p);
            }
            p.Pipe();
        }
        void PipeTcp(IClient localClient, IClient targetClient, Cipher.IShadowsocksStreamCipher cipher, CancellationToken cancellationToken, params PipeFilter[] addFilters)
        {
            DefaultPipe p = new DefaultPipe(localClient, targetClient, Defaults.ReceiveBufferSize, _logger);

            p.OnBroken += Pipe_OnBroken;

            Cipher.CipherTcpFilter filter1 = new Cipher.CipherTcpFilter(localClient, cipher, _logger);

            p.ApplyFilter(filter1);

            //if (addFilters.Length > 0)
            //{
            //    foreach (var f in addFilters)
            //    {
            //        p.ApplyFilter(f);
            //    }
            //}
            lock (_pipesReadWriteLock)
            {
                this._pipes.Add(p);
            }
            p.Pipe();
        }
Ejemplo n.º 8
0
        public async Task HandleHttp(IClient client, CancellationToken cancellationToken)
        {
            if (null == client)
            {
                return;
            }
            using (SmartBuffer clientRequest = SmartBuffer.Rent(2048))
            {
                clientRequest.SignificantLength = await client.ReadAsync(clientRequest.Memory, cancellationToken);

                if (10 >= clientRequest.SignificantLength)
                {
                    goto GOODBYE503;
                }


                if (HttpProxyHeaderResolver.TryResolve(clientRequest.SignificantMemory,
                                                       out HttpProxyHeaderResolver.Verb httpVerb, out Uri targetHost, out byte[] normalHttpRequestHeader))
                {
                    //_logger?.LogInformation($"HttpRoxyServer Verb={httpVerb.ToString()}.");
                    var server = _serverLoader.Load(null);
                    if (null == server)
                    {
                        _logger?.LogInformation($"HttpRoxyServer Proxy server not found.");
                        goto GOODBYE503;
                    }
                    var serverAddr = await server.GetIPEndPoint();

                    if (null == serverAddr)
                    {
                        _logger?.LogInformation($"HttpRoxyServer Unable to get proxy server address.");
                        goto GOODBYE503;
                    }

                    var relayClient = await TcpClient1.ConnectAsync(serverAddr, _logger); //A. connect ss-remote

                    if (null == relayClient)                                              //unable to connect ss-remote
                    {
                        _logger?.LogInformation($"HttpRoxyServer Unable to connect ss-remote:[{serverAddr.ToString()}]");
                        goto GOODBYE503;
                    }

                    using (var relayRequst = SmartBuffer.Rent(HttpProxyHeaderResolver.Verb.CONNECT == httpVerb ? 300 : normalHttpRequestHeader.Length + 300))
                    {
                        if (ShadowsocksAddress.TryParse(targetHost, out Tuple <byte, ushort, byte[]> ssaddr))//B. construct sssaddr
                        {
                            //_logger?.LogInformation($"HttpRoxyServer ATYP={ssaddr.Item1}, port={ssaddr.Item2}");
                            ShadowsocksAddress.TrySerailizeTo(ssaddr.Item1, ssaddr.Item3, ssaddr.Item2, relayRequst.Memory, out int written);
                            relayRequst.SignificantLength = written;

                            if (HttpProxyHeaderResolver.Verb.CONNECT != httpVerb)
                            {
                                normalHttpRequestHeader.CopyTo(relayRequst.FreeMemory);
                                relayRequst.SignificantLength += normalHttpRequestHeader.Length;
                            }

                            var                    cipher       = server.CreateCipher(_logger);
                            DefaultPipe            pipe         = new DefaultPipe(client, relayClient, Defaults.ReceiveBufferSize, _logger);
                            Cipher.TcpCipherFilter cipherFilter = new Cipher.TcpCipherFilter(relayClient, cipher, _logger);
                            pipe.ApplyClientFilter(cipherFilter);

                            var writeResult = await pipe.Writer[relayClient].Write(relayRequst.SignificantMemory, cancellationToken);//C. send target addr (& http header) to ss-remote.
                            _logger?.LogInformation($"Send target addr {writeResult.Written} bytes. {writeResult.Result}.");

                            if (HttpProxyHeaderResolver.Verb.CONNECT == httpVerb)
                            {
                                await client.WriteAsync(RESPONSE_200_Connection_Established, cancellationToken);
                            }
                            PipeClient(pipe, cancellationToken);//D. start piping.

                            return;
                        }
                        else
                        {
                            _logger?.LogInformation($"HttpRoxyServer parse host URL failed."); goto GOODBYE503;
                        }
                    }
                }
        async Task HandleClient(IClient client, int pipeBufferSize,
                                Action <DefaultPipe> pipeCreatedAction,
                                Func <IPEndPoint, Task <IClient> > createTargetClientFunc,
                                Action <SmartBuffer, DefaultPipe, IClient, ShadowsocksAddress> targetClientConnectedAction,
                                CancellationToken cancellationToken)
        {
            DefaultPipe pipe = new DefaultPipe(pipeBufferSize, _logger);

            pipeCreatedAction(pipe);///////////////////


            var readClientResult = await pipe.Reader[client].Read(cancellationToken);//A. Read target addr (and payload).

            if (readClientResult.Result != ClientReadWriteResult.Succeeded)
            {
                client.Close(); return;
            }

            if (readClientResult.Read <= 0)
            {
                _logger?.LogWarning($"This should not happen. [{client.EndPoint.ToString()}]");
                ////decrypt failed? available options: 1.leave it. 2.close connection. 3.add to blocklist.
                client.Close();
                return;
            }
            var request = readClientResult.Memory;

            IPAddress targetIP = IPAddress.Any;                                                          //TODO target address check

            if (ShadowsocksAddress.TryResolve(request.SignificantMemory, out ShadowsocksAddress ssaddr)) //B. Resolve target addr.
            {
                _logger?.LogWarning($"Reading target addr. ATYP={ssaddr.ATYP}, client=[{client.EndPoint.ToString()}]");
                IPEndPoint ipeTarget = await ssaddr.ToIPEndPoint();

                if (IPAddress.Any == ipeTarget.Address || IPAddress.IPv6Any == ipeTarget.Address)//an empty IP.
                {
                    _logger?.LogWarning($"Invalid target addr. client=[{client.EndPoint.ToString()}]");
                    client.Close();
                    return;
                }

                _logger?.LogInformation($"Resolved target address:[{ipeTarget.ToString()}]. Connecting...");
                IClient targetClient = await createTargetClientFunc(ipeTarget); //C. Connect target ///////////////////////////////

                if (null == targetClient)                                       //connect target failed.
                {
                    _logger?.LogInformation($"Unable to connect target [{ipeTarget.ToString()}]. client=[{client.EndPoint.ToString()}]");
                    client.Close();
                    return;
                }
                _logger?.LogInformation($"Connected to [{ipeTarget.ToString()}]");
                targetClientConnectedAction(request, pipe, targetClient, ssaddr);////////////////////////////////

                _logger?.LogInformation($"Start piping...");
                PipeClient(pipe, cancellationToken);//D. start piping.
            }
            else//invalid socks5 addr
            {
                _logger?.LogWarning($"Resolve target addr failed. client=[{client.EndPoint.ToString()}]");
                client.Close();
                return;
            }

            await Task.CompletedTask;
        }
Ejemplo n.º 10
0
        public async Task HandleTcp(IClient client, CancellationToken cancellationToken)
        {
            if (null == client)
            {
                return;
            }
            if (!await Handshake(client, cancellationToken))
            {
                return;
            }                                                            //Handshake
            using (SmartBuffer request = SmartBuffer.Rent(300), response = SmartBuffer.Rent(300))
            {
                request.SignificantLength = await client.ReadAsync(request.Memory, cancellationToken);

                if (5 >= request.SignificantLength)
                {
                    client.Close(); return;
                }
                #region socks5

                /*
                 +----+-----+-------+------+----------+----------+
                 |VER | CMD |  RSV  | ATYP | DST.ADDR | DST.PORT |
                 +----+-----+-------+------+----------+----------+
                 | 1  |  1  | X'00' |  1   | Variable |    2     |
                 +----+-----+-------+------+----------+----------+
                 |
                 | Where:
                 |
                 |    o  VER    protocol version: X'05'
                 |    o  CMD
                 |       o  CONNECT X'01'
                 |       o  BIND X'02'
                 |       o  UDP ASSOCIATE X'03'
                 |    o  RSV    RESERVED
                 |    o  ATYP   address type of following address
                 |       o  IP V4 address: X'01'
                 |       o  DOMAINNAME: X'03'
                 |       o  IP V6 address: X'04'
                 |    o  DST.ADDR       desired destination address
                 |    o  DST.PORT desired destination port in network octet
                 |       order
                 |
                 |
                 +----+-----+-------+------+----------+----------+
                 |VER | REP |  RSV  | ATYP | BND.ADDR | BND.PORT |
                 +----+-----+-------+------+----------+----------+
                 | 1  |  1  | X'00' |  1   | Variable |    2     |
                 +----+-----+-------+------+----------+----------+
                 |
                 | Where:
                 |
                 |    o  VER    protocol version: X'05'
                 |    o  REP    Reply field:
                 |       o  X'00' succeeded
                 |       o  X'01' general SOCKS server failure
                 |       o  X'02' connection not allowed by ruleset
                 |       o  X'03' Network unreachable
                 |       o  X'04' Host unreachable
                 |       o  X'05' Connection refused
                 |       o  X'06' TTL expired
                 |       o  X'07' Command not supported
                 |       o  X'08' Address type not supported
                 |       o  X'09' to X'FF' unassigned
                 |    o  RSV    RESERVED
                 |    o  ATYP   address type of following address
                 |       o  IP V4 address: X'01'
                 |       o  DOMAINNAME: X'03'
                 |       o  IP V6 address: X'04'
                 |    o  BND.ADDR       server bound address
                 |    o  BND.PORT       server bound port in network octet order
                 */

                #endregion

                switch (request.Memory.Span[1])
                {
                case 0x1:    //connect //TODO validate addr
                {
                    var server = _serverLoader.Load(null);
                    if (null == server)
                    {
                        _logger?.LogInformation($"proxy server not found.");
                        client.Close();
                        break;
                    }
                    var serverAddr = await server.GetIPEndPoint();

                    if (null == serverAddr)
                    {
                        _logger?.LogInformation($"unable to get proxy server address.");
                        client.Close();
                        break;
                    }

                    var relayClient = await TcpClient1.ConnectAsync(serverAddr, _logger); //A. connect ss-remote

                    if (null == relayClient)                                              //unable to connect ss-remote
                    {
                        _logger?.LogInformation($"unable to connect ss-remote:[{serverAddr.ToString()}]");
                        await client.WriteAsync(NegotiationResponse.CommandConnectFailed, cancellationToken);

                        client.Close();
                        break;
                    }

                    var clientRequest = request;
                    if (ShadowsocksAddress.TryResolve(clientRequest.Memory.Slice(3), out ShadowsocksAddress ssaddr))        //B.resove target addr.
                    {
                        var cipher = server.CreateCipher(_logger);

                        DefaultPipe            pipe         = new DefaultPipe(client, relayClient, Defaults.ReceiveBufferSize, _logger);
                        Cipher.TcpCipherFilter cipherFilter = new Cipher.TcpCipherFilter(relayClient, cipher, _logger);
                        pipe.ApplyClientFilter(cipherFilter);

                        var writeResult = await pipe.Writer[relayClient].Write(ssaddr.RawMemory, cancellationToken);        //C. send target addr to ss-remote.
                        _logger?.LogInformation($"Send target addr {writeResult.Written} bytes. {writeResult.Result}.");

                        await client.WriteAsync(NegotiationResponse.CommandConnectOK, cancellationToken); //D. notify client to send data.

                        PipeClient(pipe, cancellationToken);                                              //E. start piping.
                    }
                    else
                    {
                        _logger?.LogWarning("resolve target addr failed.");
                        client.Close();
                    }
                }
                break;

                case 0x2:    //bind
                {
                    request.SignificantMemory.CopyTo(response.Memory);
                    response.Memory.Span[1] = 0x7;
                    await client.WriteAsync(response.Memory.Slice(0, request.SignificantLength), cancellationToken);

                    client.Close();
                }
                break;

                case 0x3:    //udp assoc
                {
                    if (ShadowsocksAddress.TrySerailizeTo(
                            (byte)(AddressFamily.InterNetworkV6 == client.LocalEndPoint.AddressFamily ? 0x4 : 0x1),
                            client.LocalEndPoint.Address.GetAddressBytes(),
                            (ushort)client.LocalEndPoint.Port,
                            response.Memory,
                            out int written))
                    {
                        response.SignificantLength = written;
                        await client.WriteAsync(response.SignificantMemory, cancellationToken);
                    }

                    //TODO
                    client.Closing += this.Client_Closing;
                }
                break;

                default:
                    break;
                }
            }
        }