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(); }
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(); }
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; }
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; } } }