# tcp-tunnel-client **Repository Path**: jf_linux/tcp-tunnel-client ## Basic Information - **Project Name**: tcp-tunnel-client - **Description**: 将远程防火墙内的客户端端口转发到服务器,实现远程访问。 例如将远程客户端的22端口映射到服务器的一个端口,就可以用ssh客户端连接服务器这个端口进行远程操作。 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2026-01-09 - **Last Updated**: 2026-01-09 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # ITCat-LightTunnel 一个轻量级的 TCP 隧道/端口转发工具,用 Go 语言实现。可以在客户端和服务器之间建立隧道,实现类似 NAT 转发的功能。比传统 VPN 更轻量、更简单。 **ITCat-LightTunnel** - 轻量级 TCP 隧道解决方案 ## 功能特性 - ✅ TCP 端口转发(通过访问服务器端口访问客户端本地端口) - ✅ 心跳保持连接 - ✅ 自动重连机制 - ✅ 支持多个客户端连接 - ✅ 双向数据转发 - ✅ 接收端功能(Windows 客户端接收远程端口映射,本地访问) - ✅ 多端口映射(单个客户端可映射多个端口) - ✅ 管理端口自动映射(接收端自动映射服务端管理端口) ## 架构说明 程序分为三部分: 1. **服务器端(server)**:监听多个端口 - **控制端口**(默认 9100):客户端连接,用于心跳和控制消息 - **数据端口**(默认 9101):客户端建立数据连接 - **管理端口**(默认 9102):**仅监听 127.0.0.1**,可通过 HTTP 查询客户端列表 - **映射端口范围**(默认 9103-9200):分配给各个客户端,**仅监听 127.0.0.1**,用于接收本地连接 2. **提供端客户端(client)**:连接到服务器,将本地端口转发到服务器(如 SSH 的 22 端口) 3. **接收端客户端(receiver)**:Windows 客户端,连接到服务器,接收远程提供端的端口映射,在本地监听相同端口,实现本地访问远程服务 ### 防火墙配置 **重要**:服务端需要在防火墙中开放以下两个端口,供客户端连接: 1. **控制端口**(默认 9100):客户端通过此端口建立控制连接 2. **数据端口**(默认 9101):客户端通过此端口建立数据连接 **不需要开放**: - 管理端口(仅监听 127.0.0.1,本地访问) - 映射端口范围(仅监听 127.0.0.1,本地访问) **防火墙配置示例**(Linux iptables): ```bash # 开放控制端口 sudo iptables -A INPUT -p tcp --dport 9100 -j ACCEPT # 开放数据端口 sudo iptables -A INPUT -p tcp --dport 9101 -j ACCEPT # 保存规则(根据系统不同) sudo iptables-save > /etc/iptables/rules.v4 # 或 sudo service iptables save ``` **防火墙配置示例**(firewalld): ```bash # 开放控制端口 sudo firewall-cmd --permanent --add-port=9100/tcp # 开放数据端口 sudo firewall-cmd --permanent --add-port=9101/tcp # 重新加载防火墙规则 sudo firewall-cmd --reload ``` ## 系统要求 - **服务器**:通常运行在 x86_64 Linux/Windows 服务器上 - **客户端**:通常运行在 ARMv7 设备上(如树莓派、嵌入式设备等) - **Go 版本**:Go 1.16 或更高版本(支持交叉编译) ## 使用场景 - **管理远端采集器**:服务器端通过本地端口访问客户端服务(如 SSH) - **穿透 NAT 访问内网服务**:通过服务器中转访问内网设备 - **服务器本地访问客户端服务**:安全限制,外部端口仅监听 127.0.0.1 - **Windows 本地访问远程服务**:使用接收端客户端,在 Windows 本地访问远程提供端的服务(如远程 SSH、Redis 等) ## 编译 ### 本地编译(Windows/Linux) ```bash # 编译服务器 go build -o server.exe ./server # 编译提供端客户端 go build -o client.exe ./client # 编译接收端客户端(Windows) go build -o receiver.exe ./receiver ``` ### ARMv7 交叉编译(客户端) 客户端通常运行在 ARMv7 设备上,需要交叉编译: **Linux/Mac:** ```bash # 使用编译脚本 chmod +x build_arm.sh ./build_arm.sh # 或手动编译 export GOOS=linux export GOARCH=arm export GOARM=7 go build -o client_armv7 ./client ``` **Windows:** ```bash # 使用编译脚本 build_arm.bat # 或手动编译 set GOOS=linux set GOARCH=arm set GOARM=7 go build -o client_armv7 ./client ``` **编译后:** 1. 将 `client_armv7` 复制到 ARM 设备 2. 在 ARM 设备上执行:`chmod +x client_armv7` 3. 运行:`./client_armv7 -config=client_config.json` **注意:** - 服务器通常运行在 x86_64 架构上,使用本地编译即可 - 客户端需要根据目标设备架构选择编译方式 - ARMv7 编译需要 Go 1.16+ 支持 ## 快速开始 1. **生成密钥对**(如果还没有): ```bash # 生成RSA密钥对 go run generate_keys.go # 或 ./generate_keys.exe ``` 这会生成: - `client_private_key.pem` - 客户端私钥(复制到客户端) - `server_public_key.pem` - 服务端公钥(放在服务端) 2. **配置防火墙**(重要): 在服务端防火墙中开放两个端口: - 控制端口(默认 9100) - 数据端口(默认 9101) 3. **启动服务器**: ```bash ./server.exe -config=server_config.json ``` 4. **启动客户端**: ```bash ./client.exe -config=client_config.json ``` ## 配置文件支持 除了命令行参数,程序也支持通过JSON配置文件设置参数。配置文件参数优先级低于命令行参数(命令行参数会覆盖配置文件)。 ### 服务器配置文件示例 创建 `server_config.json`: ```json { "control_port": 9100, "data_port": 9101, "admin_port": 9102, "mapping_ports": [9103, 9200], "heartbeat": "30s", "public_key": "server_public_key.pem", "test_mode": false, "allow_receiver": false } ``` **配置说明**: - `allow_receiver`: 是否允许接收端连接(默认 `false`,需要显式启用) ### 提供端客户端配置文件示例 创建 `client_config.json`: ```json { "server": "192.168.1.100:9100", "port_mappings": [ { "name": "SSH", "target": "localhost:22" }, { "name": "Redis", "target": "localhost:6379" } ], "client_id": "", "client_name": "采集器1", "heartbeat": "30s", "reconnect": "5s", "private_key": "client_private_key.pem", "test_mode": false } ``` ### 接收端客户端配置文件示例 创建 `receiver_config.json`: ```json { "server": "192.168.1.100:9100", "server_data": "192.168.1.100:9101", "client_id": "", "client_name": "Windows接收端", "heartbeat": "30s", "reconnect": "5s", "private_key": "client_private_key.pem", "test_mode": false } ``` **注意**: - 接收端会自动接收所有提供端的端口映射信息 - 接收端会在本地监听相同的端口,实现本地访问远程服务 - 接收端会自动映射服务端的管理端口(默认 9102),可通过 `http://127.0.0.1:9102` 查看端口映射信息 - 服务端需要启用 `allow_receiver: true` 才能允许接收端连接 **注意**: - 配置文件中的时间格式使用Go的duration格式(如 "30s", "5m", "1h") - 命令行参数会覆盖配置文件中的对应参数 - 如果配置文件不存在或格式错误,程序会报错 ## 使用方法 ### 1. 启动服务器 **使用命令行参数:** ```bash # 使用默认端口配置 ./server.exe # 自定义端口配置 ./server.exe -control-port=9100 -data-port=9101 -admin-port=9102 -port-range-start=9103 -port-range-end=9200 -public-key=server_public_key.pem ``` **使用配置文件:** ```bash # 使用配置文件(推荐,便于管理) ./server.exe -config=server_config.json # 配置文件 + 命令行参数覆盖 ./server.exe -config=server_config.json -control-port=9200 ``` **参数说明:** - `-config`: 配置文件路径(可选) - `-control-port`: 控制端口(客户端连接),默认 9100 - `-data-port`: 数据端口(客户端数据连接),默认 9101 - `-admin-port`: 管理端口(HTTP管理界面),默认 9102 - `-port-range-start`: 映射端口范围起始,默认 9103 - `-port-range-end`: 映射端口范围结束,默认 9200 - `-public-key`: 服务端公钥文件路径(PEM格式),可通过配置文件设置 - `-heartbeat`: 心跳间隔(如 "30s"),默认 30s **注意**: - **防火墙配置**:必须在防火墙中开放 `control_port` 和 `data_port` 两个端口,供客户端连接 - 管理端口支持多种格式: - JSON格式(默认):`curl http://127.0.0.1:9102` - 返回JSON数据 - 文本格式:`curl http://127.0.0.1:9102/text` - 返回纯文本 - HTML界面:浏览器访问 `http://127.0.0.1:9102/html` - 返回网页界面 - 映射端口范围(如 9103-9200)会自动分配给连接的客户端 - 管理端口和映射端口仅监听 127.0.0.1,确保只有服务器本地可以访问 - 命令行参数优先级高于配置文件参数 - 如需使用接收端功能,需要在配置文件中设置 `allow_receiver: true` ### 2. 启动提供端客户端 **使用命令行参数:** ```bash # 连接到服务器,转发到本地 22 端口(SSH) ./client.exe -server=服务器IP:9100 -target=localhost:22 -client-name=client1 -private-key=client_private_key.pem # 自定义参数 ./client.exe -server=192.168.1.100:9100 -target=localhost:22 -client-name=采集器1 -heartbeat=30s -reconnect=5s -private-key=client_private_key.pem ``` **使用配置文件:** ```bash # 使用配置文件(推荐,便于管理) ./client.exe -config=client_config.json # 配置文件 + 命令行参数覆盖(如覆盖客户端名称) ./client.exe -config=client_config.json -client-name=采集器2 ``` **参数说明:** - `-config`: 配置文件路径(可选) - `-private-key`: 客户端私钥文件路径(PEM格式),可通过配置文件设置 - `-client-name`: 客户端名称(用于显示),可通过配置文件设置 - `-server`: 服务器地址(控制端口),默认 localhost:9100 - `-target`: 目标地址(本地要转发的端口,向后兼容),默认 localhost:22 - `-heartbeat`: 心跳间隔(如 "30s"),默认 30s - `-reconnect`: 重连间隔(如 "5s"),默认 5s **注意**: - 客户端会自动生成唯一的 `client_id`(Windows生成GUID,Linux读取根分区UUID) - 服务器会为每个客户端分配多个映射端口(取决于配置的端口映射数量) - 客户端连接成功后会显示分配的映射端口号 - 命令行参数优先级高于配置文件参数 ### 3. 启动接收端客户端(Windows) **使用场景**:在 Windows 本地访问远程提供端的服务 **使用配置文件(推荐):** ```bash # 使用配置文件 receiver.exe -config=receiver_config.json ``` **使用命令行参数:** ```bash # 连接到服务器 receiver.exe -server=192.168.1.100:9100 -server-data=192.168.1.100:9101 -client-name=Windows接收端 -private-key=client_private_key.pem ``` **参数说明**: - `-config`: 配置文件路径(可选) - `-server`: 服务器控制端口地址,默认 localhost:9100 - `-server-data`: 服务器数据端口地址(可选,默认从 server 推导,端口+1) - `-client-id`: 客户端ID(GUID,自动生成),可通过配置文件设置 - `-client-name`: 客户端名称(用于显示),可通过配置文件设置 - `-heartbeat`: 心跳间隔(如 "30s"),默认 30s - `-reconnect`: 重连间隔(如 "5s"),默认 5s - `-private-key`: 客户端私钥文件路径(PEM格式),可通过配置文件设置 **功能说明**: - 接收端连接成功后,会自动接收所有提供端的端口映射信息 - 接收端会在本地监听相同的端口(如提供端的 9103 端口映射,接收端也会监听本地 9103 端口) - 接收端会自动映射服务端的管理端口(默认 9102),可通过 `http://127.0.0.1:9102` 查看端口映射信息 - 通过本地端口访问时,数据会通过服务器转发到对应的提供端 **使用示例**: ```bash # 1. 启动接收端 receiver.exe -config=receiver_config.json # 2. 查看端口映射(自动映射的管理端口) curl http://127.0.0.1:9102 # 3. 通过本地端口访问远程服务(假设提供端映射了 9103 端口用于 SSH) ssh -p 9103 user@127.0.0.1 ``` ### 4. 使用示例 假设: - 服务器 IP: `123.456.789.0` - 控制端口: `9100` - 数据端口: `9101` - 管理端口: `9102` - 映射端口范围: `9103-9200` - 客户端1名称: `采集器1` - 客户端2名称: `采集器2` 1. **配置防火墙**(在服务器上): ```bash # 开放控制端口和数据端口 sudo firewall-cmd --permanent --add-port=9100/tcp sudo firewall-cmd --permanent --add-port=9101/tcp sudo firewall-cmd --reload ``` 2. 在服务器上启动服务端: ```bash ./server.exe -config=server_config.json ``` 3. 在客户端1上启动: ```bash ./client.exe -config=client_config.json ``` 服务器会为客户端1分配映射端口(如 9103, 9104) 4. 在客户端2上启动: ```bash ./client.exe -config=client_config.json ``` 服务器会为客户端2分配映射端口(如 9105, 9106) 5. 查看客户端列表(在服务器上执行): **JSON格式(默认,便于程序处理):** ```bash curl http://127.0.0.1:9102 # 或 curl http://127.0.0.1:9102/ ``` **文本格式:** ```bash curl http://127.0.0.1:9102/text ``` **HTML界面(浏览器访问):** ```bash # 在浏览器中打开 http://127.0.0.1:9102/html ``` 管理端口支持三种格式: - **JSON**(默认):返回结构化JSON数据,便于程序处理 - **文本**:返回纯文本格式,便于命令行查看 - **HTML**:返回美观的网页界面,便于浏览器查看 6. 访问客户端(在服务器本地执行): ```bash # 访问客户端1的SSH(假设分配了端口9103) ssh -p 9103 user@127.0.0.1 # 访问客户端2的SSH(假设分配了端口9105) ssh -p 9105 user@127.0.0.1 ``` ## 工作流程 1. 客户端连接到服务器的控制端口,建立长连接 2. 客户端定期发送心跳包保持连接 3. 用户连接到服务器的外部端口 4. 服务器通过控制通道通知客户端有新连接 5. 客户端连接到本地目标端口(如 22) 6. 客户端连接到服务器的客户端数据端口 7. 服务器将外部连接和客户端数据连接桥接 8. 开始双向数据转发 ## 协议说明 ### 认证协议 客户端连接后,首先进行公钥签名认证: 1. 客户端发送:`client_id长度(1字节) + client_id + client_name长度(1字节) + client_name` 2. 客户端使用私钥对 `client_id` 进行 SHA256 哈希签名,发送:`签名长度(2字节) + 签名` 3. 服务器使用公钥验证签名后响应:`0x00`(成功)或 `0xFF`(失败) ### 控制消息格式 - `0x00`: 心跳包(1 字节) - `0x01 + connID(4字节) + port(2字节)`: 新连接请求(服务器 -> 客户端) - `0x03 + connID(4字节)`: 数据连接就绪(客户端 -> 服务器) ### 数据连接 客户端连接到数据端口后,先发送 4 字节的 connID(大端序),然后开始传输数据。 ## 安全特性 1. **公钥私钥认证**:客户端使用私钥对 client_id 进行签名,服务端使用公钥验证签名 2. **客户端白名单**:服务端可以配置 `allowed_clients.txt` 文件,只允许列表中的客户端连接 3. **端口访问限制**: - **控制端口和数据端口**:需要对外开放(供客户端连接),但受公钥签名保护 - **管理端口和映射端口**:仅监听 127.0.0.1,只有服务器本地可以访问,确保只有服务器端操作时才能访问客户端服务 4. **防火墙配置**:服务端需要在防火墙中开放控制端口和数据端口两个端口 ## 多客户端支持 系统支持多个客户端同时连接,每个客户端会分配一个独立的外部端口: 1. **客户端注册**:客户端连接时发送唯一的 `client-id`,服务器自动分配端口 2. **端口分配**:从端口范围的第二个端口开始依次分配(第一个端口为管理端口) 3. **查看客户端**:通过管理端口(如 9102)可以查看所有已连接的客户端及其分配的端口 4. **透明访问**:通过分配的端口访问对应客户端,完全透明穿透 **示例**: - 管理端口:9102(查看客户端列表) - 客户端1(名称: 采集器1)→ 映射端口 9103, 9104(SSH, Redis) - 客户端2(名称: 采集器2)→ 映射端口 9105, 9106(SSH, Redis) - 客户端3(名称: 采集器3)→ 映射端口 9107, 9108(SSH, Redis) - ... ## 注意事项 1. **防火墙配置**:服务端必须在防火墙中开放控制端口和数据端口两个端口,供客户端连接 2. **密钥配置**:建议使用公钥私钥认证,客户端使用私钥签名,服务端使用公钥验证 3. **客户端ID**:每个客户端会自动生成唯一的 `client_id`(Windows生成GUID,Linux读取根分区UUID) 4. **客户端名称**:可以设置 `client_name` 用于显示,便于识别不同客户端 5. **端口范围**:确保映射端口范围足够大,能够容纳所有客户端(每个客户端占用多个端口,取决于配置的端口映射数量) 6. **端口访问限制**: - 控制端口和数据端口需要对外开放(供客户端连接),但受公钥签名保护 - 管理端口和映射端口仅监听 127.0.0.1,确保只有服务器本地可以访问 7. **客户端白名单**:可以配置 `allowed_clients.txt` 文件,只允许列表中的客户端连接 8. 心跳间隔建议设置为 30 秒或更长,避免流量过大 9. 客户端会自动重连,无需手动重启 ## 流量消耗 使用默认心跳间隔(30秒)时,一个连接每月消耗约 **300-400 KB** 流量(仅心跳)。 ## 关于 **ITCat-LightTunnel** - 一个轻量级的 TCP 隧道/端口转发工具 - 比传统 VPN 更轻量、更简单 - 支持多端口映射 - 支持接收端功能(Windows 客户端接收远程端口映射) - 公钥私钥认证,安全可靠 ## 许可证 MIT License