SNI 分流后获取客户端 IP 一般通过 proxy_protocol 来实现,但分流后的某些程序不能识别 proxy_protocol 怎么办?比如我的 DoH 服务器要 IP 地址,但某木头马并不支持,我开启 proxy_protocol 这马就死了。

我们看代码片段,注意注释。

nginx.conf 主配置文件片段:(From https://github.com/trojan-gfw/trojan/issues/433#issuecomment-692878138)

stream {
    log_format basic '$remote_addr - $remote_user [$time_local] '
                     '$protocol $status $bytes_sent $bytes_received '
                     '$session_time';
    map $ssl_preread_server_name $backend {
        trojan6.domain.com unix:/run/nginx-trojan-stream.sock;
        trojan.domain.com unix:/run/nginx-trojan-stream.sock;
        default 127.0.0.1:443;
    }
    server {
        listen unix:/run/nginx-trojan-stream.sock proxy_protocol;
        proxy_pass 127.0.0.1:8443;
    }
    server {
        listen 0.0.0.0:443;
        listen [::]:443;
        proxy_pass $backend;
        ssl_preread on;
        proxy_protocol on;
    }
}

http {
    log_format combined '$proxy_protocol_addr - $remote_user [$time_local] '
                        '"$request" $status $body_bytes_sent '
                        '"$http_referer" "$http_user_agent"';
    server {
        listen 127.0.0.1:80 proxy_protocol;
        listen [::1]:443 ssl proxy_protocol;
        ...
    }
}

http 的 log_format 中,原来的将原来的 $remote_addr 替换成 $proxy_protocol_addr 就成了。

stream 中的第一个 server 就是为了接收带 proxy_protocol 的 stream,然后发出不带 proxy_protocol 的 stream 给 trojan。