要实现完全透明的四层转发,需同时满足:1. 内核启用TPROXY模块并关闭rp_filter;2. NGINX stream块中配置proxy_bind $remote_addr transparent;3. iptables mangle表配合fwmark与local路由将流量导向lo;4. 后端开启accept_local且禁用rp_filter,确保直接接收客户端真实IP。

要实现完全透明的四层转发(即客户端真实 IP 透传到后端服务,且后端看到的源 IP 就是客户端 IP),仅靠 proxy_bind $remote_addr transparent 是不够的——它只是必要条件之一,还需内核、网络路由、权限与后端配合。下面分关键环节说明如何真正达成“完全透明”。
1. 必须启用 Linux 内核的 transparent proxy 支持
transparent 模式要求内核支持 TPROXY(Transparent Proxy),并开启对应模块:
- 确认内核已编译
CONFIG_IP_NF_TPROXY_CORE=m或=y(常见于 4.0+ 内核) - 加载必要模块:
modprobe ip_tables iptable_mangle iptable_nat nf_conntrack_ipv4 ipt_REDIR ipt_TPROXY_CORE - 启用 IP 转发:
sysctl -w net.ipv4.ip_forward=1 - 关闭反向路径过滤(否则会丢包):
sysctl -w net.ipv4.conf.all.rp_filter=0,同时对监听网卡(如 eth0)也设为 0
2. NGINX 配置需完整搭配 tproxy + set_real_ip_from
proxy_bind $remote_addr transparent 本身只让连接从客户端 IP 出去,但 NGINX 默认仍用本机 IP 建连;必须配合 proxy_bind 的完整上下文和 TPROXY 目标规则:
- 使用
stream块(非 http),因为透明代理在四层生效 - 监听时需绑定到通配地址(
0.0.0.0:80),并启用so_keepalive和proxy_protocol off - 关键配置示例:
stream {
upstream backend {
server 192.168.10.100:80;
}
<pre class='brush:php;toolbar:false;'>server {
listen 80 so_keepalive=on;
proxy_pass backend;
proxy_bind $remote_addr transparent;
# 注意:$remote_addr 在 stream 中实际是客户端 IP,但需确保 realip 已生效
# 若前端有 LVS/F5 等,需额外配置 set_real_ip_from + real_ip_header
}}
⚠️ 注意:$remote_addr 在 stream 上下文中默认就是原始客户端 IP(无中间代理时)。若上游有代理(如另一台 NGINX 或 LVS),必须用 set_real_ip_from + real_ip_header proxy_protocol 或自定义 header 提前还原真实 IP,否则 $remote_addr 会变成上一跳地址。
安全更新和维护 CLI Proxy API(CPA)部署与配置。用于 CPA 镜像升级、配置变更、认证目录兼容修复、上线验证与回滚。适用于用户提到“CPA 更新/升级/配置改了/容器重建/回滚”等场景。
3. 必须配置 iptables 规则将流量导向 TPROXY 目标
NGINX 的 transparent 模式依赖 iptables 的 TPROXY target 将连接重定向到本地 socket,而不是普通 DNAT:
- 假设 NGINX 监听
0.0.0.0:80,后端真实服务在192.168.10.100:80 - 添加 mangle 表规则,标记并重定向入向流量:
iptables -t mangle -N DIVERT iptables -t mangle -A PREROUTING -p tcp --dport 80 -j DIVERT iptables -t mangle -A DIVERT -j MARK --set-mark 1 iptables -t mangle -A DIVERT -j ACCEPT ip rule add fwmark 1 table 100 ip route add local 0.0.0.0/0 dev lo table 100
这样,所有目标为本机 80 端口的 TCP 包会被打标、路由到 loopback,并由 NGINX 的 transparent socket 接收——此时 proxy_bind $remote_addr transparent 才能真正以客户端 IP 发起 outbound 连接。
4. 后端服务必须支持接收非本机 IP 的连接(即 accept_local + rp_filter 宽松)
后端服务器(如另一台 nginx、Apache 或自研服务)收到连接时,源 IP 是客户端真实 IP,目的 IP 是自己的某个 IP(比如 VIP 或公网 IP)。若该目的 IP 不属于本机直连网卡,内核默认会拒绝(rp_filter=1):
- 设置
net.ipv4.conf.all.accept_local=1(允许接收目的 IP 是本机但非直连地址的包) - 确保
net.ipv4.conf.eth0.rp_filter=0(或对应网卡名) - 若后端用 nginx,还需配置
real_ip_header和set_real_ip_from来信任来自代理的 X-Real-IP,但注意:在纯四层 transparent 场景中,后端应直接看到客户端 IP,无需额外 header —— 这才是“完全透明”的体现
验证方式:在后端执行 ss -tn src <client_ip></client_ip>,应能看到 ESTABLISHED 连接,且五元组中源 IP 确实是客户端 IP。

















