Haproxy+Nginx+Tproxy实现流量透明代理

haproxy+nginx+tproxy实现透明代理

1.tproxy的原理

内核实现的一个透明代理,该模块允许监听一个非本机ip的socket(listen阶段),并可以send到远端服务器。

1.haproxy与nginx通信

haproxy与nginx同时对proxy protocol进行了支持,所以两者之间可以透传真实的用户ip(非tcp报文直接透传)

proxy protocol代理协议的原理:

该协议的本质是在三次握手结束后由代理在连接中插入了一个携带了原始连接四元组信息的数据包。携带的数据包示例内容如下:

1
PROXY TCP4 202.112.144.236 10.210.12.10 5678 80\r\nPROXY TCP6 2001:da8:205::100 2400:89c0:2110:1::21 6324 80\r\n

proxy protocol的接收端必须在接收到完整有效的 proxy protocol 头部后才能开始处理连接数据。如果服务器接收到的第一个数据包不符合proxy protocol的格式,那么服务器会直接终止连接。

haproxy代理节点的示例配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
global
log 127.0.0.1 local0
# log /dev/log local1 notice
# chroot /var/lib/haproxy
# pidfile /var/run/haproxy.pid
daemon

defaults
log global
mode tcp
option tcplog
option dontlognull
maxconn 2000
timeout connect 5000
timeout client 500000
timeout server 500000

frontend 3389_srv
mode tcp
bind 0.0.0.0:3389
default_backend nginx-3389

backend nginx-3389
mode tcp
server ngxserver 10.0.0.99:3389 send-proxy #send-proxy参数实现真实ip的传递

2.nginx与后端服务通信的

nginx对proxy protocol的支持,可以从haproxy处拿到的真实用户ip,高版本(暂未确定具体版本)nginx自身就支持tproxy,因此可以通过配置,将源ip通过指令bind绑定为源ip(tproxy服务的本质就是绑定一个非本机ip),并向后端服务转发封装好的tcp包。

nginx实现代理协议支持及透明代理的示例配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
stream {
log_format proxy '$proxy_protocol_addr [$time_local] '
'$protocol $status $bytes_sent $bytes_received '
'$session_time "$upstream_addr" '
'"$upstream_bytes_sent" "$upstream_bytes_received" "$upstream_connect_time"';

upstream up_server1 {
server 10.0.0.75:3389;
}

server {
error_log logs/error.log;
access_log logs/access.log proxy;
proxy_bind $proxy_protocol_addr transparent; #实现代理与真实来源ip的绑定

listen 3389 proxy_protocol; #proxy_protocol参数用于解析haproxy的代理协议,获取传递的真实ip
proxy_connect_timeout 10s;
proxy_timeout 30s;
proxy_pass up_server1;
}
}

此外,还需要设置tproxy相关的路由规则以正常回报给haproxy,设置命令示例如下:

1
2
3
iptables -t mangle -A PREROUTING -p tcp -s 10.0.0.100 -m multiport --sport 3389,80 -j MARK --set-xmark 0x1/0xffffffff #将来源ip为10.0.0.100(上游服务器),且来源端口为3389或80的流量在路由前设置一个标记值1
ip rule add fwmark 1 lookup 100 #监控标记值为1的数据包
ip route add local 0.0.0.0/0 dev lo table 100 #将标记数据转发至本地回环端口

4.后端(上游)服务器响应回包

在上游服务器上也须设置网关,将所有相关的响应包发送至nginx服务器

1
2
3
iptables -t mangle -A OUTPUT -p tcp -m multiport --sport 3389,80 -j MARK --set-xmark 0x1/0xffffffff #将来源ip为10.0.0.100(上游服务器),且来源端口为3389的流量在OUTPUT链设置一个标记值1
ip rule add fwmark 1 lookup 100 #监控标记值为1的数据包
ip route add 0.0.0.0/0 10.0.0.99 dev eth0 table 100 # 10.0.0.99为nginx的ip
-------------本文结束感谢您的阅读-------------
0%