如何在.net上创建软件路由器?
本文关键字:软件 路由器 创建 net | 更新日期: 2023-09-27 18:06:56
我怎么能创建一个程序透明地转发连接到新的IP地址/端口?
例如,如果一个客户端发起一个TCP连接,IP地址为111.111.111.111,TCP端口为111,那么该程序可以被配置为转发该数据包和后续数据包,IP/端口为222.222.222.222:222。
我说的透明是指:
- 最小性能损失
- 无需调整客户端或最终目的地软件/配置(就像透明Web代理不需要在浏览器中设置显式设置)
- 处理尽可能低层次的操作系统网络层
我想在。net, c#和Windows中这样做。但是我不想创建一个简单的TCP代理,原因有很多,但没有说明。如果无法做到这一点,在没有可能的解决方案的情况下,这可能是一个可以接受的答案。
这是我几周前为一个实验写的:
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Globalization;
using System.Threading;
namespace TcpTunnel {
public static class Program {
public static void Main(String[] args) {
if( args.Length != 3 ) {
Console.WriteLine("<remoteAddress> <remotePort> <listenPort>");
return;
}
ServerConfiguration config;
try {
config = new ServerConfiguration( args[0], args[1], args[2] );
} catch(ArgumentException aex) {
Console.WriteLine("<remoteAddress> <remotePort> <listenPort>");
Console.WriteLine( aex.Message );
return;
}
Thread serverThread = new Thread( ServerThread );
serverThread.Start( config );
Console.WriteLine("Enter '"q<enter>'" to stop program.");
String line;
while( (line = Console.ReadLine()).ToUpperInvariant() != "Q" );
config.ServerSocket.Shutdown(SocketShutdown.Both);
config.ServerSocket.Close();
}
private class ServerConfiguration {
public IPAddress RemoteAddress;
public UInt16 RemotePort;
public UInt16 ListenPort;
public ServerConfiguration(String remoteAddress, String remotePort, String listenPort) {
RemoteAddress = IPAddress.Parse( remoteAddress );
RemotePort = UInt16 .Parse( remotePort, NumberStyles.Integer, CultureInfo.InvariantCulture );
ListenPort = UInt16 .Parse( listenPort, NumberStyles.Integer, CultureInfo.InvariantCulture );
}
public Boolean RunServer = true;
public Socket ServerSocket;
}
private static void ServerThread(Object configObj) {
ServerConfiguration config = (ServerConfiguration)configObj;
///////////////////////////////////////
// Setup
///////////////////////////////////////
// Wait for client
Socket serverSocket = config.ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Unspecified);
serverSocket.Bind( new IPEndPoint( IPAddress.Any, config.ListenPort ) );
serverSocket.Listen(1);
Console.WriteLine("Now listening for port {0}, will forward to {1}.", config.ListenPort, config.RemotePort);
while( config.RunServer ) {
Socket client = serverSocket.Accept();
Thread clientThread = new Thread( ClientThread );
clientThread.Start( new ClientContext() { Config = config, Client = client } );
}
}
private class ClientContext {
public ServerConfiguration Config;
public Socket Client;
}
private static void ClientThread(Object contextObj) {
ClientContext context = (ClientContext)contextObj;
Socket client = context.Client;
ServerConfiguration config = context.Config;
///////////////////////////////////////
// Connect to remote server.
IPEndPoint remoteEndPoint = new IPEndPoint( config.RemoteAddress, config.RemotePort );
Socket remote = new Socket( remoteEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Unspecified);
remote.Connect( remoteEndPoint );
///////////////////////////////////////
// Run tunnel.
Console.WriteLine("Running tunnel.");
Byte[] buffer = new Byte[4096];
for(;;) {
if( client.Available > 0 ) {
Int32 count = client.Receive( buffer );
if( count == 0 ) return;
remote.Send( buffer, count, SocketFlags.None );
}
if( remote.Available > 0 ) {
Int32 count = remote.Receive( buffer );
if( count == 0 ) return;
client.Send( buffer, count, SocketFlags.None );
}
}
}
}
}