一,需求来源

1,因历史原因需要在同一个端口实现http和https的同时支持

2,因安全需求需要对部分接口URL添加白名单IP限制,需要将真实客户端IP转发到后端服务上

二,实现原由

1,同一端口实现兼容http和https主要使用的是nginx的stream->map $ssl_preread_protocol->server转发。

2,IP透传主要使用的是proxy_bind $remote_addr transparent;和iptables+ip route规则实现。

三,实现过程

1,后端真实服务监听端口在: 192.168.0.101:9000

2,前端NGINX代理运行在: 192.168.0.100:9000

3,在NGINX服务上建两个分别为HTTP和HTTPS协议的服务使用不同的端口指向后端服务

server {

listen 20036; # http

listen 20037 ssl; # https

ssl_certificate /etc/nginx/cert.pem; #证书。

ssl_certificate_key /etc/nginx/cert.key; #证书。

ssl_session_timeout 5m;

ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; #使用此加密套件。

ssl_protocols TLSv1 TLSv1.1 TLSv1.2; #使用该协议进行配置。

ssl_prefer_server_ciphers on;

location / {

proxy_set_header Host $http_host;

proxy_set_header X-Real-IP $remote_addr;

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

proxy_set_header X-Forwarded-Proto $scheme;

client_body_buffer_size 100M;

client_max_body_size 100M;

proxy_buffer_size 512k;

proxy_buffers 64 512k;

proxy_busy_buffers_size 1m;

proxy_connect_timeout 300;

proxy_http_version 1.1;

proxy_set_header Connection "";

chunked_transfer_encoding off;

proxy_pass http://192.168.0.101:9000;

}

}

4,在NGINX服务上建立stream通过ssl_preread_protocol自适应客户端请求类型进行转发。此时用http和https均能正常访问到后端服务。但是在后端服务的访问日志中可以看到所有的来源IP地址都是192.168.0.100。

stream {

upstream http_gateway {

server 127.0.0.1:20036;

}

upstream https_gateway {

server 127.0.0.1:20037;

}

map $ssl_preread_protocol $upstream{

default http_gateway;

"TLSv1.0" https_gateway;

"TLSv1.1" https_gateway;

"TLSv1.2" https_gateway;

"TLSv1.3" https_gateway;

}

server {

listen 9000;

ssl_preread on;

#proxy_bind $remote_addr transparent; #这行先注释

proxy_pass $upstream;

}

}

5,使用以下方法将客户端地址和连接透传到后端服务上。

在NGINX服务器上stream的server中配置启用以下:

proxy_bind $remote_addr transparent;  

该行启用后客户端访问NGINX时会卡在连接状态无法连接成功,需要进后行续处理。

6,NGINX服务器上添加iptables规则和ip route路由

#1,添加路由到lo口,100

ip route add local 0.0.0.0/0 dev lo table 100

#2,mark标记为1的使用100路由规则

ip rule add fwmark 1 lookup 100

7,后端服务器上添加规则

#1,允许流量

iptables -I INPUT -i bond0 -j ACCEPT

#2,禁用101主机上的reverse path filter,避免无法回复非本地网段数据包

echo "net.ipv4.conf.all.rp_filter = 0" >> /etc/sysctl.conf

echo "net.ipv4.conf.bond0.rp_filter = 0" >> /etc/sysctl.conf

#3,对源地址和端口为本机服务的打mark为1

iptables -t mangle -A OUTPUT -p tcp --src 192.168.0.101 --sport 9000 -j MARK --set-xmark 0x1/0xffffffff

#4,添加路由到前端代理服务器,100

ip route add default via 192.168.0.100 table 100

#5,mark匹配的使用该100路由转发回前端代理主机

ip rule add fwmark 1 lookup 100

8,重启nginx(reload不生效)观察访问日志结果。

多次测试后成功。

四,参考资源和原理说明:

nginx的tcp透明代理设置 - 简书

IP Transparency and Direct Server Return with NGINX Plus

记玄妙莫测的透明代理_tproxy-CSDN博客

好文链接

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。