Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions Stormancer.NetProxy/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ private static IEnumerable<Task> ProxyFromConfig(string proxyName, ProxyConfig p
var forwardIp = proxyConfig.forwardIp;
var localIp = proxyConfig.localIp;
var protocol = proxyConfig.protocol;
var forwardTls = proxyConfig.forwardTls;
try
{
if (forwardIp == null)
Expand Down Expand Up @@ -68,7 +69,7 @@ private static IEnumerable<Task> ProxyFromConfig(string proxyName, ProxyConfig p
try
{
var proxy = new UdpProxy();
task = proxy.Start(forwardIp, forwardPort.Value, localPort.Value, localIp);
task = proxy.Start(forwardIp, forwardPort.Value, localPort.Value, localIp, forwardTls);
}
catch (Exception ex)
{
Expand All @@ -86,7 +87,7 @@ private static IEnumerable<Task> ProxyFromConfig(string proxyName, ProxyConfig p
try
{
var proxy = new TcpProxy();
task = proxy.Start(forwardIp, forwardPort.Value, localPort.Value, localIp);
task = proxy.Start(forwardIp, forwardPort.Value, localPort.Value, localIp, forwardTls);
}
catch (Exception ex)
{
Expand All @@ -111,10 +112,12 @@ public class ProxyConfig
public string? localIp { get; set; }
public string? forwardIp { get; set; }
public ushort? forwardPort { get; set; }

public bool forwardTls { get; set; }
}

internal interface IProxy
{
Task Start(string remoteServerHostNameOrAddress, ushort remoteServerPort, ushort localPort, string? localIp = null);
Task Start(string remoteServerHostNameOrAddress, ushort remoteServerPort, ushort localPort, string? localIp = null, bool remoteTls = false);
}
}
}
35 changes: 24 additions & 11 deletions Stormancer.NetProxy/TcpProxy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
using System.Threading.Tasks;

Expand All @@ -18,7 +22,7 @@ internal class TcpProxy : IProxy
/// </summary>
public int ConnectionTimeout { get; set; } = (4 * 60 * 1000);

public async Task Start(string remoteServerHostNameOrAddress, ushort remoteServerPort, ushort localPort, string? localIp)
public async Task Start(string remoteServerHostNameOrAddress, ushort remoteServerPort, ushort localPort, string? localIp, bool remoteTls)
{
var connections = new ConcurrentBag<TcpConnection>();

Expand Down Expand Up @@ -62,7 +66,7 @@ public async Task Start(string remoteServerHostNameOrAddress, ushort remoteServe
var ips = await Dns.GetHostAddressesAsync(remoteServerHostNameOrAddress).ConfigureAwait(false);

var tcpConnection = await TcpConnection.AcceptTcpClientAsync(localServer,
new IPEndPoint(ips[0], remoteServerPort))
new IPEndPoint(ips[0], remoteServerPort), remoteTls)
.ConfigureAwait(false);
tcpConnection.Run();
connections.Add(tcpConnection);
Expand All @@ -88,16 +92,17 @@ internal class TcpConnection
private EndPoint? _forwardLocalEndpoint;
private long _totalBytesForwarded;
private long _totalBytesResponded;
private bool _remoteTls;
public long LastActivity { get; private set; } = Environment.TickCount64;

public static async Task<TcpConnection> AcceptTcpClientAsync(TcpListener tcpListener, IPEndPoint remoteEndpoint)
public static async Task<TcpConnection> AcceptTcpClientAsync(TcpListener tcpListener, IPEndPoint remoteEndpoint, bool remoteTls)
{
var localServerConnection = await tcpListener.AcceptTcpClientAsync().ConfigureAwait(false);
localServerConnection.NoDelay = true;
return new TcpConnection(localServerConnection, remoteEndpoint);
return new TcpConnection(localServerConnection, remoteEndpoint, remoteTls);
}

private TcpConnection(TcpClient localServerConnection, IPEndPoint remoteEndpoint)
private TcpConnection(TcpClient localServerConnection, IPEndPoint remoteEndpoint, bool remoteTls)
{
_localServerConnection = localServerConnection;
_remoteEndpoint = remoteEndpoint;
Expand All @@ -106,6 +111,7 @@ private TcpConnection(TcpClient localServerConnection, IPEndPoint remoteEndpoint

_sourceEndpoint = _localServerConnection.Client.RemoteEndPoint;
_serverLocalEndpoint = _localServerConnection.Client.LocalEndPoint;
_remoteTls = remoteTls;
}

public void Run()
Expand Down Expand Up @@ -145,12 +151,19 @@ private void RunInternal(CancellationToken cancellationToken)
{
serverStream.Close();
clientStream.Close();
}, true))
{
await Task.WhenAny(
CopyToAsync(clientStream, serverStream, 81920, Direction.Forward, cancellationToken),
CopyToAsync(serverStream, clientStream, 81920, Direction.Responding, cancellationToken)
).ConfigureAwait(false);
}, true)) {
Stream wrappedServerStream;
if (_remoteTls) {
wrappedServerStream = new SslStream(serverStream, true, (sender, certificate, chain, errors) => true);
await ((SslStream)wrappedServerStream).AuthenticateAsClientAsync("localhost", new X509Certificate2Collection(), SslProtocols.Tls12, false);
} else
wrappedServerStream = serverStream;
try {
await Task.WhenAny(CopyToAsync(clientStream, wrappedServerStream, 81920, Direction.Forward, cancellationToken), CopyToAsync(wrappedServerStream, clientStream, 81920, Direction.Responding, cancellationToken)).ConfigureAwait(false);
} finally {
if (wrappedServerStream != serverStream)
wrappedServerStream.Dispose();
}
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion Stormancer.NetProxy/UdpProxy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ internal class UdpProxy : IProxy
/// </summary>
public int ConnectionTimeout { get; set; } = (4 * 60 * 1000);

public async Task Start(string remoteServerHostNameOrAddress, ushort remoteServerPort, ushort localPort, string? localIp = null)
public async Task Start(string remoteServerHostNameOrAddress, ushort remoteServerPort, ushort localPort, string? localIp = null, bool remoteTls = false)
{
var connections = new ConcurrentDictionary<IPEndPoint, UdpConnection>();
if (remoteTls)
throw new ArgumentException("UDP connections cannot be wrapped in TLS", nameof(remoteTls));

// TCP will lookup every time while this is only once.
var ips = await Dns.GetHostAddressesAsync(remoteServerHostNameOrAddress).ConfigureAwait(false);
Expand Down
38 changes: 11 additions & 27 deletions Stormancer.NetProxy/config.json
Original file line number Diff line number Diff line change
@@ -1,32 +1,16 @@
{
"testUdp": {
"localPort": 7777,
"protocol": "udp",
"forwardIp": "35.187.92.120",
"forwardPort": 7777
},
"http": {
"localPort": 80,
"clickhouse-tls": {
"localPort": 19000,
"protocol": "tcp",
"forwardIp": "149.56.107.33",
"forwardPort": 81
},
"https": {
"localPort": 8443,
"protocol": "any",
"forwardIp": "35.187.92.120",
"forwardPort": 443
"forwardIp": "127.0.0.1",
"forwardPort": 9440,
"forwardTls": true
},
"raknet1": {
"localPort": 30000,
"protocol": "udp",
"forwardIp": "35.187.92.120",
"forwardPort": 30000
},
"raknet2": {
"localPort": 30001,
"protocol": "udp",
"forwardIp": "35.187.92.120",
"forwardPort": 30001
"clickhouse": {
"localPort": 19001,
"protocol": "tcp",
"forwardIp": "127.0.0.1",
"forwardPort": 9000,
"forwardTls": false
}
}