Skip to content

Commit

Permalink
add TunnelId
Browse files Browse the repository at this point in the history
  • Loading branch information
tqk2811 committed Jul 18, 2024
1 parent b125b44 commit cda7d67
Show file tree
Hide file tree
Showing 28 changed files with 102 additions and 85 deletions.
2 changes: 1 addition & 1 deletion src/ConsoleTest/Socks4SourceBindTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ internal static class Socks4SourceBindTest
public static async Task RunAsync()
{
IProxySource proxySource = new LocalProxySource();
using var bindSource = proxySource.GetBindSource();
using var bindSource = proxySource.GetBindSource(Guid.NewGuid());

await bindSource.BindAsync();
var endpoint = await bindSource.BindAsync();
Expand Down
2 changes: 1 addition & 1 deletion src/TestProxy/BaseBindTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public BaseBindTest() : base()
[TestMethod]
public async Task TestBindTransfer()
{
using IBindSource bindSource = _sockProxySource.GetBindSource();
using IBindSource bindSource = _sockProxySource.GetBindSource(Guid.NewGuid());
IPEndPoint iPEndPoint = await bindSource.BindAsync();

Task<string?> t_ping = ConnectBindAsync(iPEndPoint);
Expand Down
5 changes: 4 additions & 1 deletion src/TqkLibrary.Proxy/Authentications/BaseUserInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@ namespace TqkLibrary.Proxy.Authentications
{
public class BaseUserInfo : IUserInfo
{
public BaseUserInfo(IPEndPoint iPEndPoint)
public BaseUserInfo(IPEndPoint iPEndPoint, Guid tunnelId)
{
IPEndPoint = iPEndPoint;
TunnelId = tunnelId;
}
public Guid TunnelId { get; }
public IPEndPoint IPEndPoint { get; }

public virtual IAuthentication? Authentication { get; set; }

}
}
6 changes: 3 additions & 3 deletions src/TqkLibrary.Proxy/Handlers/BasePreProxyServerHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@ namespace TqkLibrary.Proxy.Handlers
{
public class BasePreProxyServerHandler : IPreProxyServerHandler
{
public virtual Task<bool> IsAcceptClientAsync(TcpClient tcpClient, CancellationToken cancellationToken = default)
public virtual Task<bool> IsAcceptClientAsync(TcpClient tcpClient, Guid tunnelId, CancellationToken cancellationToken = default)
{
return Task.FromResult(true);
}
public virtual Task<Stream> StreamHandlerAsync(Stream stream, IPEndPoint iPEndPoint, CancellationToken cancellationToken = default)
public virtual Task<Stream> StreamHandlerAsync(Stream stream, IPEndPoint iPEndPoint, Guid tunnelId, CancellationToken cancellationToken = default)
{
return Task.FromResult(stream);
}

public virtual async Task<IProxyServer> GetProxyServerAsync(PreReadStream preReadStream, IPEndPoint iPEndPoint, CancellationToken cancellationToken = default)
public virtual async Task<IProxyServer> GetProxyServerAsync(PreReadStream preReadStream, IPEndPoint iPEndPoint, Guid tunnelId, CancellationToken cancellationToken = default)
{
byte[] buffer = await preReadStream.PreReadAsync(1, cancellationToken).ConfigureAwait(false);
if (buffer.Length == 0)
Expand Down
6 changes: 3 additions & 3 deletions src/TqkLibrary.Proxy/Interfaces/IPreProxyServerHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public interface IPreProxyServerHandler
/// <param name="tcpClient"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<bool> IsAcceptClientAsync(TcpClient tcpClient, CancellationToken cancellationToken = default);
Task<bool> IsAcceptClientAsync(TcpClient tcpClient, Guid tunnelId, CancellationToken cancellationToken = default);

/// <summary>
/// SSL/Cert or limit/calc bandwidth
Expand All @@ -21,7 +21,7 @@ public interface IPreProxyServerHandler
/// <param name="iPEndPoint"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<Stream> StreamHandlerAsync(Stream stream, IPEndPoint iPEndPoint, CancellationToken cancellationToken = default);
Task<Stream> StreamHandlerAsync(Stream stream, IPEndPoint iPEndPoint, Guid tunnelId, CancellationToken cancellationToken = default);

/// <summary>
/// Handler allow http/socks4/socks5 base on IP
Expand All @@ -30,6 +30,6 @@ public interface IPreProxyServerHandler
/// <param name="iPEndPoint"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<IProxyServer> GetProxyServerAsync(PreReadStream preReadStream, IPEndPoint iPEndPoint, CancellationToken cancellationToken = default);
Task<IProxyServer> GetProxyServerAsync(PreReadStream preReadStream, IPEndPoint iPEndPoint, Guid tunnelId, CancellationToken cancellationToken = default);
}
}
2 changes: 1 addition & 1 deletion src/TqkLibrary.Proxy/Interfaces/IProxyServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ namespace TqkLibrary.Proxy.Interfaces
{
public interface IProxyServer
{
Task ProxyWorkAsync(Stream clientStream, IPEndPoint clientEndPoint, IProxyServerHandler proxyServerHandler, CancellationToken cancellationToken = default);
Task ProxyWorkAsync(Stream clientStream, IPEndPoint clientEndPoint, IProxyServerHandler proxyServerHandler, Guid tunnelId, CancellationToken cancellationToken = default);
}
}
6 changes: 3 additions & 3 deletions src/TqkLibrary.Proxy/Interfaces/IProxySource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,16 @@ public interface IProxySource
/// <summary>
///
/// </summary>
IConnectSource GetConnectSource();
IConnectSource GetConnectSource(Guid tunnelId);

/// <summary>
///
/// </summary>
IBindSource GetBindSource();
IBindSource GetBindSource(Guid tunnelId);

/// <summary>
///
/// </summary>
IUdpAssociateSource GetUdpAssociateSource();
IUdpAssociateSource GetUdpAssociateSource(Guid tunnelId);
}
}
1 change: 1 addition & 0 deletions src/TqkLibrary.Proxy/Interfaces/IUserInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ namespace TqkLibrary.Proxy.Interfaces
{
public interface IUserInfo
{
Guid TunnelId { get; }
IPEndPoint IPEndPoint { get; }
/// <summary>
/// <see cref="HttpProxyAuthentication"/> for http<br></br>
Expand Down
25 changes: 14 additions & 11 deletions src/TqkLibrary.Proxy/ProxyServers/HttpProxyServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public class HttpProxyServer : BaseLogger, IProxyServer, IHttpProxy
Stream? _clientStream;
IPEndPoint? _clientEndPoint;
IProxyServerHandler? _proxyServerHandler;
Guid _tunnelId;
CancellationToken _cancellationToken;


Expand All @@ -24,6 +25,7 @@ public async Task ProxyWorkAsync(
Stream clientStream,
IPEndPoint clientEndPoint,
IProxyServerHandler proxyServerHandler,
Guid tunnelId,
CancellationToken cancellationToken = default
)
{
Expand All @@ -33,6 +35,7 @@ public async Task ProxyWorkAsync(
_clientStream = clientStream;
_clientEndPoint = clientEndPoint;
_proxyServerHandler = proxyServerHandler;
_tunnelId = tunnelId;
_cancellationToken = cancellationToken;


Expand All @@ -48,11 +51,11 @@ public async Task ProxyWorkAsync(
if (_client_HeaderLines.Count == 0)
return;//client stream closed

_logger?.LogInformation($"{_clientEndPoint} -> \r\n{string.Join("\r\n", _client_HeaderLines)}");
_logger?.LogInformation($"{_tunnelId} {_clientEndPoint} -> \r\n{string.Join("\r\n", _client_HeaderLines)}");

_client_HeaderParse = HeaderRequestParse.ParseRequest(_client_HeaderLines);

BaseUserInfo userInfo = new BaseUserInfo(clientEndPoint);
BaseUserInfo userInfo = new BaseUserInfo(clientEndPoint, tunnelId);

if ("basic".Equals(_client_HeaderParse.ProxyAuthorization?.Scheme?.ToLower(), StringComparison.OrdinalIgnoreCase))
{
Expand Down Expand Up @@ -82,7 +85,7 @@ public async Task ProxyWorkAsync(
if (await proxyServerHandler.IsAcceptDomainAsync(_client_HeaderParse.Uri, userInfo, cancellationToken))
{
IProxySource proxySource = await proxyServerHandler.GetProxySourceAsync(_client_HeaderParse.Uri, userInfo, cancellationToken);
using IConnectSource connectSource = proxySource.GetConnectSource();
using IConnectSource connectSource = proxySource.GetConnectSource(tunnelId);
try
{
await connectSource.ConnectAsync(_client_HeaderParse.Uri, _cancellationToken);
Expand All @@ -98,7 +101,7 @@ public async Task ProxyWorkAsync(
}
catch (InitConnectSourceFailedException ex)
{
_logger?.LogInformation(ex, "InitConnectSourceFailedException");
_logger?.LogInformation(ex, $"InitConnectSourceFailedException({_tunnelId})");
await _WriteResponse((int)HttpStatusCode.ServiceUnavailable, "Service Unavailable", true);
}
}
Expand All @@ -121,7 +124,7 @@ async Task<bool> _HttpsTransfer(Stream source_stream, IUserInfo userInfo)

using Stream clientStream = await _proxyServerHandler!.StreamHandlerAsync(_clientStream!, userInfo!, _cancellationToken);

await new StreamTransferHelper(clientStream, source_stream)
await new StreamTransferHelper(clientStream, source_stream, _tunnelId)
.DebugName(_clientEndPoint, _client_HeaderParse?.Uri)
.WaitUntilDisconnect(_cancellationToken);
return false;
Expand All @@ -146,7 +149,7 @@ async Task<bool> _HttpTransfer(Stream source_stream, IUserInfo userInfo)
}

await source_stream.WriteLineAsync(string.Join("\r\n", headerLines), _cancellationToken);
_logger?.LogInformation($"{_client_HeaderParse.Uri.Host} <- \r\n{string.Join("\r\n", headerLines)}");
_logger?.LogInformation($"{_tunnelId} {_client_HeaderParse.Uri.Host} <- \r\n{string.Join("\r\n", headerLines)}");

await source_stream.WriteLineAsync(_cancellationToken);

Expand All @@ -155,7 +158,7 @@ async Task<bool> _HttpTransfer(Stream source_stream, IUserInfo userInfo)

//Transfer content from client to target if have
await clientStream.TransferAsync(source_stream, _client_HeaderParse.ContentLength, cancellationToken: _cancellationToken);
_logger?.LogInformation($"[{_clientEndPoint} -> {_client_HeaderParse.Uri.Host}] {_client_HeaderParse.ContentLength} bytes");
_logger?.LogInformation($"{_tunnelId} [{_clientEndPoint} -> {_client_HeaderParse.Uri.Host}] {_client_HeaderParse.ContentLength} bytes");

await source_stream.FlushAsync(_cancellationToken);

Expand All @@ -165,13 +168,13 @@ async Task<bool> _HttpTransfer(Stream source_stream, IUserInfo userInfo)
int ContentLength = target_response_HeaderLines.GetContentLength();

await clientStream.WriteLineAsync(string.Join("\r\n", target_response_HeaderLines), _cancellationToken);
_logger?.LogInformation($"{_client_HeaderParse.Uri.Host} ->\r\n{string.Join("\r\n", target_response_HeaderLines)}");
_logger?.LogInformation($"{_tunnelId} {_client_HeaderParse.Uri.Host} ->\r\n{string.Join("\r\n", target_response_HeaderLines)}");

await clientStream.WriteLineAsync(_cancellationToken);

//Transfer content from target to client if have
await source_stream.TransferAsync(_clientStream!, ContentLength, cancellationToken: _cancellationToken);
_logger?.LogInformation($"[{_clientEndPoint} <- {_client_HeaderParse.Uri.Host}] {ContentLength} bytes");
_logger?.LogInformation($"{_tunnelId} [{_clientEndPoint} <- {_client_HeaderParse.Uri.Host}] {ContentLength} bytes");

await clientStream.FlushAsync(_cancellationToken);

Expand Down Expand Up @@ -228,12 +231,12 @@ async Task<bool> _WriteResponse(IEnumerable<string> headers, byte[]? body = null
}

await _clientStream!.WriteHeadersAsync(headers, _cancellationToken);
_logger?.LogInformation($"{_clientEndPoint} <-\r\n{string.Join("\r\n", headers)}");
_logger?.LogInformation($"{_tunnelId} {_clientEndPoint} <-\r\n{string.Join("\r\n", headers)}");

if (body is not null)
{
await _clientStream!.WriteAsync(body, _cancellationToken);
_logger?.LogInformation($"{_clientEndPoint} <- bytes {body.Length}");
_logger?.LogInformation($"{_tunnelId} {_clientEndPoint} <- bytes {body.Length}");
}

await _clientStream!.FlushAsync(_cancellationToken);
Expand Down
15 changes: 8 additions & 7 deletions src/TqkLibrary.Proxy/ProxyServers/ProxyServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ async void _MainLoopListen()

private async Task _PreProxyWorkAsync(TcpClient tcpClient)
{
Guid tunnelId = Guid.NewGuid();
try
{
using (tcpClient)
Expand All @@ -177,35 +178,35 @@ private async Task _PreProxyWorkAsync(TcpClient tcpClient)
tcpClient.SendTimeout = SendTimeout;

IPEndPoint iPEndPoint = (IPEndPoint)tcpClient.Client.RemoteEndPoint!;
if (await PreProxyServerHandler.IsAcceptClientAsync(tcpClient, _CancellationToken))
if (await PreProxyServerHandler.IsAcceptClientAsync(tcpClient, tunnelId, _CancellationToken))
{
using Stream baseStream = tcpClient.GetStream();
using AsynchronousOnlyStream asynchronousOnlyStream = new AsynchronousOnlyStream(baseStream);

using Stream stream = await PreProxyServerHandler.StreamHandlerAsync(asynchronousOnlyStream, iPEndPoint, _CancellationToken);
using Stream stream = await PreProxyServerHandler.StreamHandlerAsync(asynchronousOnlyStream, iPEndPoint, tunnelId, _CancellationToken);
if (stream is null)
throw new InvalidOperationException($"{PreProxyServerHandler.GetType().FullName}.{nameof(IPreProxyServerHandler.StreamHandlerAsync)} was return null");

using PreReadStream preReadStream = new PreReadStream(stream);
IProxyServer proxyServer = await PreProxyServerHandler.GetProxyServerAsync(preReadStream, iPEndPoint, _CancellationToken);
IProxyServer proxyServer = await PreProxyServerHandler.GetProxyServerAsync(preReadStream, iPEndPoint, tunnelId, _CancellationToken);
if (proxyServer is null)
throw new InvalidOperationException($"{PreProxyServerHandler.GetType().FullName}.{nameof(IPreProxyServerHandler.GetProxyServerAsync)} was return null");

await proxyServer.ProxyWorkAsync(preReadStream, iPEndPoint, ProxyServerHandler, _CancellationToken);
await proxyServer.ProxyWorkAsync(preReadStream, iPEndPoint, ProxyServerHandler, tunnelId, _CancellationToken);
}
}
}
catch (ObjectDisposedException ode)
{
_logger?.LogInformation(ode, nameof(_PreProxyWorkAsync));
_logger?.LogInformation(ode, $"{nameof(_PreProxyWorkAsync)}({tunnelId})");
}
catch (OperationCanceledException oce)
{
_logger?.LogInformation(oce, nameof(_PreProxyWorkAsync));
_logger?.LogInformation(oce, $"{nameof(_PreProxyWorkAsync)}({tunnelId})");
}
catch (Exception ex)
{
_logger?.LogCritical(ex, nameof(_PreProxyWorkAsync));
_logger?.LogCritical(ex, $"{nameof(_PreProxyWorkAsync)}({tunnelId})");
}
}
}
Expand Down
15 changes: 9 additions & 6 deletions src/TqkLibrary.Proxy/ProxyServers/Socks4ProxyServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@ public class Socks4ProxyServer : BaseLogger, IProxyServer, ISocks4Proxy
Stream? _clientStream;
IPEndPoint? _clientEndPoint;
IProxyServerHandler? _proxyServerHandler;
Guid _tunnelId;
CancellationToken _cancellationToken;
BaseUserInfo? userInfo;

public async Task ProxyWorkAsync(
Stream clientStream,
IPEndPoint clientEndPoint,
IProxyServerHandler proxyServerHandler,
Guid tunnelId,
CancellationToken cancellationToken = default
)
{
Expand All @@ -33,6 +35,7 @@ public async Task ProxyWorkAsync(
_clientStream = clientStream;
_clientEndPoint = clientEndPoint;
_proxyServerHandler = proxyServerHandler;
_tunnelId = tunnelId;
_cancellationToken = cancellationToken;


Expand All @@ -43,7 +46,7 @@ public async Task ProxyWorkAsync(
return;
}

userInfo = new BaseUserInfo(clientEndPoint);
userInfo = new BaseUserInfo(clientEndPoint, _tunnelId);



Expand Down Expand Up @@ -113,7 +116,7 @@ async Task _HandleConnectAsync(Socks4_Request socks4_Request)
IProxySource proxySource = await _proxyServerHandler!.GetProxySourceAsync(uri, userInfo!, _cancellationToken);

Uri uri_connect = new Uri($"http://{target_ip}:{socks4_Request.DSTPORT}");
using IConnectSource connectSource = proxySource.GetConnectSource();
using IConnectSource connectSource = proxySource.GetConnectSource(_tunnelId);
await connectSource.ConnectAsync(uri_connect, _cancellationToken);

using Stream session_stream = await connectSource.GetStreamAsync();
Expand All @@ -123,7 +126,7 @@ async Task _HandleConnectAsync(Socks4_Request socks4_Request)

using Stream clientStream = await _proxyServerHandler.StreamHandlerAsync(_clientStream!, userInfo!, _cancellationToken);
//transfer until disconnect
await new StreamTransferHelper(clientStream, session_stream)
await new StreamTransferHelper(clientStream, session_stream, _tunnelId)
.DebugName(_clientEndPoint, uri_connect)
.WaitUntilDisconnect(_cancellationToken);
}
Expand All @@ -137,15 +140,15 @@ async Task _HandleBindAsync()
return;
}

using IBindSource bindSource = proxySource.GetBindSource();
using IBindSource bindSource = proxySource.GetBindSource(_tunnelId);
IPEndPoint iPEndPoint = await bindSource.BindAsync(_cancellationToken);

await _WriteReplyAsync(Socks4_REP.RequestGranted, iPEndPoint.Address, (UInt16)iPEndPoint.Port);
using Stream stream = await bindSource.GetStreamAsync(_cancellationToken);

using Stream clientStream = await _proxyServerHandler.StreamHandlerAsync(_clientStream!, userInfo!, _cancellationToken);
//transfer until disconnect
await new StreamTransferHelper(clientStream, stream)
await new StreamTransferHelper(clientStream, stream, _tunnelId)
.DebugName(_clientEndPoint, iPEndPoint)
.WaitUntilDisconnect(_cancellationToken);
}
Expand All @@ -163,7 +166,7 @@ async Task _WriteReplyAsync(
Socks4_RequestResponse response = new Socks4_RequestResponse(rep, listen_ip, listen_port);
byte[] rep_buffer = response.GetByteArray();

_logger?.LogInformation($"{_clientEndPoint} <- 0x{BitConverter.ToString(rep_buffer).Replace("-", "")}");
_logger?.LogInformation($"{_tunnelId} {_clientEndPoint} <- 0x{BitConverter.ToString(rep_buffer).Replace("-", "")}");

await _clientStream!.WriteAsync(rep_buffer, _cancellationToken);
await _clientStream!.FlushAsync(_cancellationToken);
Expand Down
Loading

0 comments on commit cda7d67

Please sign in to comment.