send-proxy vs send-proxy-v2 vs send-proxy-v2-ssl --1

下面我严格按你的要求结构来,不跳步、不混概念:

  1. 先对比 send-proxy / send-proxy-v2 / send-proxy-v2-ssl(结合你的场景)

  2. 明确在 LVS TOA → HAProxy → Nginx 的正确选择

  3. 给出一套“能跑、不会踩坑、支持 TLS 透传 + HTTP/2”的完整配置

    • HAProxy

    • Nginx stream

    • Nginx http


一、先对比三种 send-proxy(放在你的架构里看)

你的架构前提:

  • LVS 使用 TOA(真实源 IP 已在 TCP option 中)

  • HAProxy / Nginx 不依赖 TOA

  • TLS 必须透传

  • HTTP/2 必须支持

  • TLS 在 Nginx 终止

1️⃣ 能力对比表(结合 TLS 透传 & HTTP/2)

项目send-proxysend-proxy-v2send-proxy-v2-ssl
PROXY 协议版本 v1 v2 v2
编码方式 明文 二进制 二进制
客户端 IP
IPv6 ⚠️ 有限
性能 一般
TLS 是否使用
TLS 版本
SNI
ALPN / HTTP2 判断
TLS 透传 ⚠️ 不完整
HTTP/2 ⚠️ 易异常
生产推荐 ⚠️

2️⃣ 在你这个场景里的结论(非常明确)

LVS TOA + HAProxy TCP + TLS 透传 + HTTP/2 + Nginx 终止 TLS

只能用:send-proxy-v2-ssl
❌ 另外两个都会在 TLS / HTTP2 / SNI 上出问题


二、为什么 TLS 透传 + HTTP/2 必须是 send-proxy-v2-ssl

一句话解释:

HTTP/2 是跑在 TLS 之上的,而 TLS 透传时,后端只能靠 SSL TLV 判断“这是 HTTPS + h2”

没有 SSL TLV 会发生什么

  • Nginx stream 层:

    • 不知道是不是 SSL

    • ssl_preread 信息不完整

  • Nginx http 层:

    • HTTP/2 协议判断异常

    • 日志 / real_ip 错乱

    • mTLS / 策略无法用


三、完整正确配置(可直接用)

下面是一整套标准生产写法


1️⃣ HAProxy 配置(RS 机器上)

特点

  • TCP 模式

  • 不解 TLS

  • 注入 PROXY v2 + SSL TLV

global
    log /dev/log local0
    maxconn 200000

defaults
    log global
    mode tcp
    timeout connect 5s
    timeout client  1m
    timeout server  1m

frontend ft_tls_passthrough
    bind *:443
    mode tcp
    default_backend bk_nginx_tls

backend bk_nginx_tls
    mode tcp
    server nginx 127.0.0.1:443 send-proxy-v2-ssl

2️⃣ Nginx:stream 层(TLS 透传 + PROXY)

职责

  • 接收 PROXY v2

  • 接收 TLS 原始流

  • 不解密 TLS

  • 读取 SNI / TLS 信息

  • 转交给 http 层

stream {

    log_format stream_log
        '$remote_addr:$remote_port '
        'sni=$ssl_preread_server_name '
        'protocol=$protocol';

    server {
        listen 443 proxy_protocol;
        proxy_protocol on;

        ssl_preread on;

        proxy_pass 127.0.0.1:8443;
    }
}

关键点解释

  • proxy_protocol on;
    → 接收 HAProxy 注入的 PROXY v2 / SSL TLV

  • ssl_preread on;
    → 读取 SNI / TLS 信息(不解密)


3️⃣ Nginx:http 层(TLS 终止 + HTTP/2)

职责

  • 终止 TLS

  • 提供 HTTP/2

  • 使用真实客户端 IP

http {
    real_ip_header proxy_protocol;
    set_real_ip_from 127.0.0.1;

    log_format main
        '$remote_addr - $host [$time_local] '
        '"$request" $status $body_bytes_sent';

    server {
        listen 8443 ssl http2 proxy_protocol;
        server_name example.com;

        ssl_certificate     /etc/nginx/ssl/example.crt;
        ssl_certificate_key /etc/nginx/ssl/example.key;

        location / {
            proxy_pass http://backend_app;
        }
    }
}

关键点解释

  • listen ... ssl http2 proxy_protocol;

  • HTTP/2 必须在 TLS 终止点

  • real_ip_header proxy_protocol;
    → 客户端真实 IP 生效


四、TOA 在这里的地位(避免误解)

LVS TOA 只影响 LVS → HAProxy

一旦 HAProxy 建立新连接到 Nginx:

  • TOA 已经不存在

  • 必须靠 PROXY protocol 继续传递客户端信息

所以你这个链路里:

Client IP
  ↓ (TOA)
HAProxy
  ↓ (PROXY v2 + SSL TLV)
Nginx

五、最终一句话总结(架构级)

  • send-proxy:历史遗留,不适合 TLS / HTTP2

  • send-proxy-v2:仅适合非 TLS 或 TLS 已终止

  • send-proxy-v2-ssl
    👉 TLS 透传 + HTTP/2 + SNI + 真实 IP 的唯一正确选择


如果你愿意,我可以下一步帮你做:

  • LVS TOA + HAProxy + Nginx 的抓包验证方法

  • HTTP/2 / ALPN / SNI 是否生效的检查清单

  • stream → http 的多域名 SNI 分流方案

你现在问的,已经是七层负载与传输层边界的高级问题了。

posted on 2026-01-22 21:07  吃草的青蛙  阅读(0)  评论(0)    收藏  举报

导航