/* # shadowsocks UDP Request (before encrypted) # +------+----------+----------+----------+ # | ATYP | DST.ADDR | DST.PORT | DATA | # +------+----------+----------+----------+ # | 1 | Variable | 2 | Variable | # +------+----------+----------+----------+ # # shadowsocks UDP Response (before encrypted) # +------+----------+----------+----------+ # | ATYP | DST.ADDR | DST.PORT | DATA | # +------+----------+----------+----------+ # | 1 | Variable | 2 | Variable | # +------+----------+----------+----------+ */ public async Task HandleUdp(IClient client, CancellationToken cancellationToken) { if (null == client) { return; } await HandleClient(client, 1500, (pipe) => { var cipher = _remoteServerConfig.CreateCipher(_logger); IClientFilter cipherFilter = new Cipher.UdpCipherFilter(cipher, _logger); pipe.AddFilter(client, cipherFilter); }, async (targetIPEndPoint) => { return(await UdpClient1.ConnectAsync(targetIPEndPoint, _logger)); }, async (request, pipe, targetClient, targetSsAddr) => { pipe.ClientB = targetClient; IClientFilter filterTarget1 = new UdpRelayEncapsulationFilter(_logger); pipe.AddFilter(targetClient, filterTarget1); _logger?.LogInformation($"Writing payload before piping..."); await pipe.GetWriter(targetClient).Write(request.SignificantMemory, cancellationToken); request.Dispose(); }, cancellationToken); await Task.CompletedTask; }
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; } DuplexPipe pipe = new DuplexPipe(client, relayClient, 1500, _logger); IClientFilter filter = new Cipher.UdpCipherFilter(server.CreateCipher(_logger), _logger); IClientFilter filter2 = new UdpEncapsulationFilter(_logger); pipe.AddFilter(relayClient, filter) .AddFilter(relayClient, filter2); PipeClient(pipe, cancellationToken); }
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; } PipeUdp(client, relayClient, server.CreateCipher(_logger), cancellationToken); }
/* * # shadowsocks UDP Request (before encrypted) # +------+----------+----------+----------+ # | ATYP | DST.ADDR | DST.PORT | DATA | # +------+----------+----------+----------+ # | 1 | Variable | 2 | Variable | # +------+----------+----------+----------+ # # shadowsocks UDP Response (before encrypted) # +------+----------+----------+----------+ # | ATYP | DST.ADDR | DST.PORT | DATA | # +------+----------+----------+----------+ # | 1 | Variable | 2 | Variable | # +------+----------+----------+----------+ */ public async Task HandleUdp(IClient client, CancellationToken cancellationToken = default) { if (null == client) { return; } using (SmartBuffer localRequestCipher = SmartBuffer.Rent(1500)) { localRequestCipher.SignificantLength = await client.ReadAsync(localRequestCipher.Memory, cancellationToken);//A. read a packet if (0 == localRequestCipher.SignificantLength) { _logger?.LogWarning($"HandleUdp an empty udp packet received, client=[{client.EndPoint.ToString()}]"); client.Close(); return; } var cipher = _remoteServerConfig.CreateCipher(_logger); using (var localReqest = cipher.DecryptUdp(localRequestCipher.SignificanMemory)) //B. decrypt { if (null == localReqest || 0 == localReqest.SignificantLength) //decrypt failed, available options: 1.leave it. 2.close connection. 3.add to blocklist. { _logger?.LogWarning($"HandleUdp decrypt failed, client=[{client.EndPoint.ToString()}]"); client.Close();//->local pipe broken-> local pipe close. return; } IPAddress targetIP = IPAddress.Any; //TODO target address check if (ShadowsocksAddress.TryResolve(localReqest.SignificanMemory, out ShadowsocksAddress ssaddr)) //C. resolve target address { if (0x3 == ssaddr.ATYP) //a domain name { var ips = await _dnsCache.ResolveHost(Encoding.UTF8.GetString(ssaddr.Address.ToArray())); if (ips != null && ips.Length > 0) { targetIP = ips[0]; } } else { targetIP = new IPAddress(ssaddr.Address.Span); } if (IPAddress.Any != targetIP)//D. target addr resolved. { IPEndPoint targetEndPoint = new IPEndPoint(targetIP, ssaddr.Port); var targetClient = await UdpClient1.ConnectAsync(targetEndPoint, _logger);//E. connect to target if (null == targetClient) { _logger?.LogInformation($"HandleUdp unable to connect target [{targetEndPoint.ToString()}]. client=[{client.EndPoint.ToString()}]"); client.Close(); return; } await targetClient.WriteAsync(localReqest.Memory.Slice(ssaddr.RawMemory.Length), cancellationToken); //F. send payload . PipeUdp(client, targetClient, cipher, cancellationToken); //G. piping } else//resolve target address failed. { _logger?.LogWarning($"HandleUdp invalid target addr. client=[{client.EndPoint.ToString()}]"); client.Close(); return; } } else { _logger?.LogWarning($"HandleUdp resolve target addr failed. client=[{client.EndPoint.ToString()}]"); client.Close(); return; } } }//end using }