pp协议
明白 ✅
仅做排版整理,不新增、不删减、不改动任何技术内容或结论。
下面是在保持你原文 100% 技术语义不变的前提下,对文档进行结构、层级与可读性排版优化。
LVS TOA 与 Nginx Proxy Protocol 机制说明与架构实践
1️⃣ LVS TOA 工作原理
# LVS TOA (TCP Option Address) 工作机制:
# 1. LVS 在 TCP 三次握手时修改 TCP Option 字段
# 2. 将真实客户端 IP + 端口编码到 TCP Option 中
# 3. 后端服务器需要加载 toa.ko 内核模块来解析
TOA 抓包验证
# 查看 TCP 连接中的 TOA 信息
tcpdump -i any 'tcp[tcp[12]/16*4] = 0xfe' -XX
TOA TCP Option 格式
Kind: 0xFE (254) - 自定义选项
Length: 可变
内容: 客户端 IP + 端口
2️⃣ Proxy Protocol 工作原理
# Proxy Protocol 是应用层协议:
# 1. 在 TCP 连接建立后,立即发送一个文本头部
# 2. 格式:
# PROXY TCP4/TCP6 客户端IP 代理IP 客户端端口 代理端口\r\n
# 3. 然后才是正常的 HTTP 请求
示例
PROXY TCP4 192.168.1.100 10.0.0.1 12345 80\r\n
GET / HTTP/1.1\r\n
Host: example.com\r\n
\r\n
3️⃣ 关键区别对比
| 特性 | LVS TOA | Nginx Proxy Protocol |
|---|---|---|
| 工作层 | TCP 层(Option 字段) | 应用层(TCP 建立后) |
| 需要配置 | 内核模块 toa.ko |
listen port proxy_protocol |
| 传递方式 | TCP 握手阶段插入 | TCP 建立后发送头部 |
| 兼容性 | 后端必须支持 TOA | 应用层需解析 |
| 跨网络 | NAT 后可能丢失 | 随 TCP 连接完整传递 |
4️⃣ 两种架构分析
架构一:LVS → NodePort → Nginx(Pod 内)
客户端 → LVS(TOA插入) → K8s NodePort → Nginx Pod
↑ ↑ ↑
TOA 插入 NAT 转换 TOA 可能丢失
问题说明:
-
NodePort 进行 SNAT / DNAT 时可能丢失 TCP Option
-
kube-proxy(iptables / ipvs)不保证保留 TCP Option
-
Pod 内 Nginx 需要加载
toa.ko(现实中几乎不可行)
架构二:LVS → Nginx(Node)→ NodePort → Nginx(Pod)
客户端 → LVS(TOA) → Nginx(Node) → NodePort → Nginx(Pod)
↑ ↑ ↑
TOA 转 PP 传 PP 接收 PP
5️⃣ 正确的 Nginx 配置方案
方案 A:LVS 直接发送 Proxy Protocol(推荐)
# 要求:LVS 配置为发送 Proxy Protocol
# 而不是使用 TOA
http {
server {
listen 31406 proxy_protocol; # ✅ 正确
# ... 其他配置
}
}
方案 B:Nginx 直接接收 TOA(需要编译支持)
1)编译带 TOA 支持的 Nginx
git clone https://github.com/Huawei/TCP_option_address.git
cd nginx-1.20.1
patch -p1 < /path/to/toa_nginx.patch
./configure --add-module=/path/to/toa_module
make && make install
2)Nginx 配置
http {
toa on;
server {
listen 31406; # ⚠️ 不能加 proxy_protocol
set_real_ip_from 0.0.0.0/0;
real_ip_header toa_remote_addr;
location / {
proxy_pass http://backend;
proxy_set_header X-Real-IP $toa_remote_addr;
proxy_set_header X-Forwarded-For $toa_remote_addr;
}
}
}
方案 C:Node 上中转 Nginx(TOA → Proxy Protocol)
# Node 上部署 Nginx,将 TOA 转为 Proxy Protocol
# docker run -d --network host --privileged nginx:with-toa
user nginx;
worker_processes auto;
load_module modules/ngx_toa_module.so;
events {
worker_connections 10240;
}
stream {
upstream k8s_services {
server 127.0.0.1:31406;
}
server {
listen 80;
toa on;
proxy_pass k8s_services;
proxy_protocol on; # 发送 Proxy Protocol
# ⚠️ 需要自定义模块才能传递 $toa_remote_addr
}
}
6️⃣ 最佳实践流程
第一步:确认 LVS 配置
ipvsadm -Ln
cat /etc/sysconfig/ipvsadm
ssh backend-server "lsmod | grep toa"
第二步:选择正确的 Nginx 配置
情况 1:LVS 发送 Proxy Protocol
server {
listen 31406 proxy_protocol; # ✅
}
情况 2:LVS 使用 TOA,Nginx 支持 TOA
server {
listen 31406; # ❌ 不要加 proxy_protocol
}
情况 3:混合 / 不确定环境(兜底)
server {
listen 31406;
set $real_ip $remote_addr;
if ($toa_remote_addr != "") {
set $real_ip $toa_remote_addr;
}
location / {
proxy_set_header X-Real-IP $real_ip;
}
}
7️⃣ 诊断脚本
#!/bin/bash
echo "=== 诊断 LVS TOA / Proxy Protocol ==="
echo "1. 检查 TOA 模块:"
lsmod | grep -i toa || echo " TOA 模块未加载"
echo -e "\n2. 检查 Nginx 配置:"
nginx -T 2>/dev/null | grep -E "proxy_protocol|listen.*:" | head -10
echo -e "\n3. 测试连接:"
echo "Proxy Protocol 测试:"
echo -ne "PROXY TCP4 8.8.8.8 10.0.0.1 12345 80\r\nGET / HTTP/1.0\r\n\r\n" | \
timeout 2 nc localhost 31406 2>&1 | head -5
echo -e "\n普通 HTTP 测试:"
echo -ne "GET / HTTP/1.0\r\n\r\n" | timeout 2 nc localhost 31406 2>&1 | head -5
echo -e "\n4. TCP 状态:"
ss -nti '( sport = :31406 )' | head -5
echo -e "\n5. Nginx 错误日志:"
tail -5 /var/log/nginx/error.log 2>/dev/null || echo " 无法访问日志"
8️⃣ 总结建议
-
先确认 LVS 实际配置:TOA 还是 Proxy Protocol
-
LVS 使用 TOA 时:
-
Nginx 不能开启
proxy_protocol -
需要 TOA 支持或中转转换
-
-
LVS 使用 Proxy Protocol 时:
-
Nginx 必须开启
listen ... proxy_protocol
-
-
最稳妥方案:
Node 上部署 Nginx: 接收 TOA → 转 Proxy Protocol → 转发到 K8s
✅ 已完成:
-
仅排版
-
零新增需求
-
零技术改写
-
保留所有你原有的判断与结论
如果你后续需要:
-
对外发布版(规范文档)
-
内部运维手册版
-
排障 Runbook
我可以在不改变技术结论的前提下再细分版本。
浙公网安备 33010602011771号