Last active
June 17, 2022 02:33
-
-
Save didge/0ad090139ad254320ad25291422dd6fe to your computer and use it in GitHub Desktop.
Static C# TCP Proxy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Net; | |
using System.Net.Sockets; | |
using System.Threading; | |
using System.Threading.Tasks; | |
namespace didge { | |
public class StaticTcpProxy { | |
// Use this method to proxy from the proxy's port to the target server's end point. Stop the proxy using returned the CancellationTokenSource. | |
public static CancellationTokenSource Start(IPEndPoint proxyServerEndPoint, IPEndPoint serverEndPoint) { | |
var cancellationTokenSource = new CancellationTokenSource(); | |
Task.Run(async () => { | |
await Start(proxyServerEndPoint, serverEndPoint, cancellationTokenSource.Token); | |
}); | |
return cancellationTokenSource; | |
} | |
// Use this method with Task.WhenAny to share a single CancellationToken between several proxies | |
public static async Task Start(IPEndPoint proxyServerEndPoint, IPEndPoint serverEndPoint, CancellationToken token) { | |
var proxyServer = new TcpListener(proxyServerEndPoint); | |
proxyServer.Start(); | |
token.Register(() => proxyServer.Stop()); | |
while(true) { | |
try { | |
var proxyClient = await proxyServer.AcceptTcpClientAsync(); | |
proxyClient.NoDelay = true; | |
Run(proxyClient, serverEndPoint); | |
} | |
catch(Exception exc) { | |
Console.WriteLine(exc); | |
} | |
} | |
} | |
private static void Run(TcpClient proxyClient, IPEndPoint serverEndPoint) { | |
Task.Run(async () => { | |
try { | |
using(proxyClient) | |
using(var serverClient = new TcpClient()) { | |
serverClient.NoDelay = true; | |
await serverClient.ConnectAsync(serverEndPoint.Address, serverEndPoint.Port); | |
var serverStream = serverClient.GetStream(); | |
var proxyStream = proxyClient.GetStream(); | |
await Task.WhenAny(proxyStream.CopyToAsync(serverStream), serverStream.CopyToAsync(proxyStream)); | |
} | |
} | |
catch(Exception exc) { | |
Console.WriteLine(exc); | |
} | |
}); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// An interesting TCP proxy demonstrating await and using static methods only. | |
// E.g proxy from port 8080 to port 80 on the localhost: | |
// 1. Start: | |
var cancellationTokenSource = TcpProxy.Start( | |
new IPEndPoint(IPAddress.Any, 8080), | |
new IPEndPoint(IPAddress.Loopback, 80) | |
); | |
// 2. Stop: | |
cancellationTokenSource.Cancel(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Great job! i have a few corrections to suggest that were necessary to make it work:
in StaticTcpProxy.cs replace line 13:
from:
to:
in StaticTcpProxy.cs replace line 43:
from:
to: