使用Putty与Socat实现防火墙后Windows Rust服务器公网访问的问题排查
首先,咱们先明确核心问题:Rust游戏服务器严重依赖UDP 28015端口进行游戏数据传输,只转发TCP 28015/28016是远远不够的——这就是你用客户端连接公网Linux机器超时的根本原因。接下来咱们一步步拆解你的配置问题,然后给出修正方案。
你当前配置的核心错误
你遇到的socat[954671] E bind(...) Address already in use,是因为你把Putty的反向隧道和Linux侧的Socat配置冲突了:
- 你在Putty里设置了
R50053 127.0.0.1:50053,这意味着Linux机器的50053 TCP端口已经被Putty监听,用于把流量转发到Windows本地的50053端口。 - 但你又在Linux上执行
socat tcp4-listen:50053...,试图让Socat监听同一个端口,自然会报端口占用。
另外,你Windows侧的Socat命令方向也搞反了,导致UDP流量无法正确双向转发。
修正后的完整配置流程
咱们重新梳理整个流量路径:外部Rust客户端 <-> Linux UDP 28015 <-> Linux Socat(UDP转TCP)<-> Putty SSH隧道(TCP)<-> Windows Socat(TCP转UDP)<-> Windows Rust服务器 UDP 28015
同时保留TCP 28015(备用通信)和TCP 28016(RCON)的转发。
步骤1:配置Putty反向隧道(Windows → Linux)
打开Putty的SSH隧道配置(Connection → SSH → Tunnels),添加以下三条转发规则:
- 规则1(TCP游戏端口):
- Source port:
28015 - Destination:
127.0.0.1:28015 - 选择
Remote(远程端口转发),点击Add
- Source port:
- 规则2(RCON端口):
- Source port:
28016 - Destination:
127.0.0.1:28016 - 选择
Remote,点击Add
- Source port:
- 规则3(UDP转TCP的通道端口):
- Source port:
50053 - Destination:
127.0.0.1:50053 - 选择
Remote,点击Add
- Source port:
配置完成后,连接到Linux机器,确保Putty保持在线(可以配置Putty的Keepalive防止断线)。
步骤2:Windows侧Socat配置(TCP转UDP)
在Windows机器上运行Socat,把Putty隧道传过来的TCP 50053流量,转换成UDP发送给本地Rust服务器的28015端口,同时双向转发响应:
socat TCP4-LISTEN:50053,reuseaddr,fork UDP4:127.0.0.1:28015
这个命令的作用是:监听Windows本地的50053 TCP端口,把每个进来的TCP连接转成UDP数据包发送到127.0.0.1:28015,同时把服务器返回的UDP响应转成TCP发回隧道。
步骤3:Linux侧Socat配置(UDP转TCP)
在Linux机器上运行Socat,把外部客户端发来的UDP 28015流量,转换成TCP发送到本地的50053端口(也就是Putty隧道的入口),双向转发响应:
socat UDP4-LISTEN:28015,reuseaddr,fork TCP4:127.0.0.1:50053
这里注意:Socat是连接到Linux的50053端口(由Putty监听),而不是监听这个端口,所以不会和Putty的隧道冲突,完美解决端口占用问题。
步骤4:验证与测试
- 先确认Windows上的Rust服务器正常运行,本地客户端
client.connect localhost 28015能正常连接。 - 在Linux上测试TCP隧道:执行
telnet localhost 28015,如果没有连接拒绝,说明TCP隧道正常。 - 在Linux上测试UDP转发:执行
nc -u localhost 28015,发送任意字符,同时查看Windows侧Socat的输出,确认流量能到达。 - 最后用外部客户端测试:
client.connect linuxhostname 28015,应该能正常连接了。
额外注意事项
- 确保Linux机器的防火墙/安全组对外开放以下端口:
- UDP 28015(游戏主端口)
- TCP 28015(备用通信)
- TCP 28016(RCON)
- 如果Putty经常断线,可以在Putty的
Connection设置里,把Seconds between keepalives设为30,防止SSH连接被防火墙断开。 - 可以把Socat命令做成开机自启脚本,避免每次手动启动。
备注:内容来源于stack exchange,提问作者weiss100

