跳到主要内容

Csharp Base Nat

C#实现基础内网穿透服务的分步骤解决方案:

  1. 创建控制台项目

  2. 服务端代码(部署在公网服务器):

using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;

public class Server
{
private TcpListener _controlListener;
private TcpListener _publicListener;
private TcpClient _clientBridge;

public void Start(int controlPort, int publicPort)
{
_controlListener = new TcpListener(IPAddress.Any, controlPort);
_publicListener = new TcpListener(IPAddress.Any, publicPort);

_controlListener.Start();
_publicListener.Start();

// 客户端连接线程
new Thread(() => {
while(true)
{
var client = _controlListener.AcceptTcpClient();
new Thread(() => HandleClient(client)).Start();
}
}).Start();

// 公网请求处理线程
new Thread(() => {
while(true)
{
var publicClient = _publicListener.AcceptTcpClient();
if(_clientBridge != null)
{
BridgeConnections(publicClient, _clientBridge);
}
}
}).Start();
}

private void HandleClient(TcpClient client)
{
_clientBridge = client;
// 保持连接心跳
while(client.Connected)
{
Thread.Sleep(1000);
}
_clientBridge = null;
}

private void BridgeConnections(TcpClient src, TcpClient dst)
{
new Thread(() => ForwardData(src.GetStream(), dst.GetStream())).Start();
new Thread(() => ForwardData(dst.GetStream(), src.GetStream())).Start();
}

private void ForwardData(NetworkStream src, NetworkStream dst)
{
byte[] buffer = new byte[4096];
while(true)
{
int bytesRead = src.Read(buffer, 0, buffer.Length);
dst.Write(buffer, 0, bytesRead);
}
}
}
  1. 客户端代码(运行在内网机器):
using System;
using System.Net.Sockets;
using System.Threading;

public class Client
{
public void Connect(string serverIp, int controlPort, string targetIp, int targetPort)
{
var client = new TcpClient();
client.Connect(serverIp, controlPort);

while(true)
{
if(client.GetStream().DataAvailable)
{
HandleServerRequest(client, targetIp, targetPort);
}
Thread.Sleep(100);
}
}

private void HandleServerRequest(TcpClient serverClient, string targetIp, int targetPort)
{
var targetClient = new TcpClient();
targetClient.Connect(targetIp, targetPort);

BridgeConnections(serverClient, targetClient);
}

private void BridgeConnections(TcpClient src, TcpClient dst)
{
new Thread(() => ForwardData(src.GetStream(), dst.GetStream())).Start();
new Thread(() => ForwardData(dst.GetStream(), src.GetStream())).Start();
}

private void ForwardData(NetworkStream src, NetworkStream dst)
{
byte[] buffer = new byte[4096];
while(true)
{
int bytesRead = src.Read(buffer, 0, buffer.Length);
dst.Write(buffer, 0, bytesRead);
}
}
}
  1. 使用方式:

服务端启动:

new Server().Start(8888, 8080); // 控制端口8888,公网端口8080

客户端连接:

new Client().Connect("公网IP", 8888, "127.0.0.1", 80); // 映射本地80端口
  1. 注意事项:

需要配置服务器防火墙放行端口支持TCP协议穿透基础版本不含身份验证需要保持客户端持续运行实际使用需添加异常处理该实现通过端口映射建立双向隧道,服务端监听两个端口分别处理客户端连接和公网请求,客户端负责建立到内网服务的连接。数据通过流复制实现双向转发。