You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SSH隧道问题:如何在远程ServerB获取客户端真实IP?

解决SSH本地端口转发无法获取客户端真实IP的问题

问题根源

你当前使用的-L本地端口转发模式中,ServerA接收的客户端流量会通过SSH连接转发到ServerB。此时ServerB上的服务接收到的连接源是ServerB自身的SSH客户端进程(通常是127.0.0.1或ServerB内网IP),而非客户端真实IP——因为SSH隧道默认不会传递源IP信息。

可行解决方案

1. 借助socat传递源IP(无需修改后端服务)

这是最简易的方案,通过socat作为中间层捕获并传递客户端真实IP:

  • 在ServerB上:停止原服务对30238端口的监听,启动socat监听该端口,捕获客户端IP后转发到实际服务端口(假设服务运行在30239):
    socat TCP-LISTEN:30238,fork,reuseaddr EXEC:"/bin/sh -c 'echo 客户端真实IP: \$SOCAT_PEERADDR >> /var/log/client_ip.log; nc 127.0.0.1 30239'"
    
    这里$SOCAT_PEERADDR就是客户端的真实IP,可写入日志或通过脚本传递给后端服务(比如HTTP服务可添加X-Forwarded-For请求头)。
  • 在ServerA上:替换原SSH命令为socat转发+SSH隧道,确保源IP被传递:
    socat TCP-LISTEN:30238,fork,reuseaddr EXEC:"ssh user@ServerB socat STDIO TCP-CONNECT:127.0.0.1:30238"
    

2. 启用代理协议(需后端服务支持)

如果你的后端服务支持Proxy Protocol(如Nginx、HAProxy、部分Java服务),可通过SSH配合代理协议传递源IP:

  • 在ServerA上:使用socat监听端口并通过SSH转发到ServerB,同时添加代理协议头:
    socat TCP-LISTEN:30238,fork,reuseaddr EXEC:"ssh user@ServerB socat STDIO TCP-CONNECT:127.0.0.1:30238,proxyprotocol"
    
  • 在ServerB上:开启后端服务的代理协议支持(比如Nginx需添加proxy_protocol on;到监听配置),即可直接获取客户端真实IP。

3. 使用HAProxy转发(适合生产环境)

对于生产环境,推荐用HAProxy做中间层处理代理协议:

  • ServerA的HAProxy配置:
    frontend tunnel_front
        bind *:30238
        mode tcp
        option tcplog
        default_backend serverb_backend
    
    backend serverb_backend
        mode tcp
        server serverb <ServerB_IP>:30238 send-proxy
    
  • ServerB的HAProxy配置:
    frontend service_front
        bind *:30238 accept-proxy
        mode tcp
        option tcplog
        default_backend actual_service
    
    backend actual_service
        mode tcp
        server service 127.0.0.1:<实际服务端口>
    
    配置完成后,ServerB的HAProxy会解析代理协议头,将客户端真实IP传递给后端服务。

内容的提问来源于stack exchange,提问作者Ali Nazari

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 16:25:27