言成言成啊 | Kit Chen's Blog

手撕TCPMux单端口多路复用以及小记SSH隧道

发布于2025-07-26 03:37:31,更新于2025-07-28 01:10:04,标签:devops tcp  文章会持续修订,转载请注明来源地址:https://meethigher.top/blog

我的公网服务只有一个端口,我想让TCP连接也能实现类似Nginx的HTTP反向代理的功能,可以通过一个端口将内网的服务全部转发出来。

这就涉及到一个概念了—— TCP Port Service Multiplexer (TCPMux)。

一、手撕TCPMux

1.1 概念

本节参考RFC 1078 - TCP port service Multiplexer (TCPMUX)

RFC 1078 提出了一种机制:访问任何TCP服务,只要访问端口1即可。

工作流程(极简版)

1.) 客户端 → 服务器 1 号端口:发送SSH<CRLF>

2.) 服务器 检查本地有没有叫 “SSH” 的服务

  • ✅ 有:回 + 非必填的消息说明<CRLF>,然后直接把连接交给真正的 SSH 程序。
  • ❌ 无:回 - 非必填的消息说明<CRLF> 并断开连接。

3.) 特殊服务名

  • 发送 HELP:服务器列出它能转接的所有服务名,然后礼貌地挂电话。

这是理论定义上的TCPMux。

1.2 实现

我的需求就像最初提到的。

我的公网服务器只有一个端口可对外。我希望通过这一个端口,将公网服务器的所有TCP服务都转发出来。这就需要使用到类似TCPMux的工具了。

该功能使用SSH隧道即可实现,可以参照我下文记录。但是由于服务器的SSH隧道自身有限制,因此只得弃用,FRP也可以,但最后还是决定自己手撕一个。

源码

实现思路时序图

实际场景使用示例

二、SSH隧道

2.1 开启SSH隧道

cat /etc/ssh/sshd_config,修改如下参数

1
2
3
4
5
6
# 允许tcp转发,该项决定 -L / -R / -D 是否能使用转发。
AllowTcpForwarding yes
# 该项若为no,则只能监听127.0.0.1,配置为yes可监听0.0.0.0
GatewayPorts yes
# 允许隧道,默认为no。该功能大部分人用不到。-w tun/tap VPN
PermitTunnel no

systemctl restart sshd,重启服务即可生效

2.2 三种模式

2.2.1 本地端口转发(TCPMux)

场景

  • 公司内网服务器有 MySQL(10.0.0.20:3306),但是公司只有一台机器可通过 SSH (10.0.0.30:22)访问
  • 你笔记本在家,需要连接 MySQL 开发。

在你的笔记本上执行如下命令

1
2
3
4
5
# -p 22,指定10.0.0.30机器的ssh端口
# -N,只建立隧道,不打开远程 shell;
# -L 3306:10.0.0.20:3306,本地启用3306端口用来转发10.0.0.20:3306
# -f,认证完成后放到后台运行
ssh -p 22 -f -N -L 3306:10.0.0.20:3306 root@10.0.0.30

该模式对应meethigher/tcp-reverse-proxy的TCP单端口多路复用

2.2.2 远程端口转发(内网穿透)

场景

  • 你笔记本有 MySQL(127.0.0.1:3306),你有一台公网服务器 SSH (10.0.0.30:22)
  • 你要把你笔记本你的 MySQL,通过公网服务器穿透出去,通过公网服务器的 3306 端口即可访问你的 MySQL

在你的笔记本上执行如下命令

1
2
3
4
5
# -p 22,指定10.0.0.30机器的ssh端口
# -N,只建立隧道,不打开远程 shell;
# -R 3306:10.0.0.20:3306,远端启用3306端口用来转发127.0.0.1:3306
# -f,认证完成后放到后台运行
ssh -p 22 -f -N -R 3306:127.0.0.1:3306 root@10.0.0.30

该模式对应meethigher/tcp-reverse-proxy的TCP内网穿透。

2.2.3 动态端口转发(Socks5代理)

场景

  • 评论时,记录IP。
  • 你希望使用你的笔记本,通过你的另一个地区的服务器(10.0.0.30:22)进行访问,以便达到你评论的IP不是你的真实IP的目的。

在你的笔记本上执行如下命令

1
2
3
4
# -p 22,指定10.0.0.30机器的ssh端口
# -D 21080,在本地监听的端口
# -N,只建立隧道,不打开远程 shell;
ssh -p 22 -N -D 21080 root@10.0.0.30

在浏览器发起请求时,配置Socks5代理即可。此处我以curl为例。

1
2
3
4
5
# winddows使用set,linux使用export
set http_proxy=socks5://127.0.0.1:21080
set https_proxy=socks5://127.0.0.1:21080

curl https://meethigher.top/whoami
发布:2025-07-26 03:37:31
修改:2025-07-28 01:10:04
链接:https://meethigher.top/blog/2025/tcp-mux/
标签:devops tcp 
付款码 打赏 分享
Shift+Ctrl+1 可控制工具栏