我有一个设置,希望在某些 HTTPS 服务前使用透明 TCP 代理。这些服务本身处理证书,因此我尝试避免使用 HTTP 代理。我还需要这些服务来获取客户端的原始 IP。
设置如下:
- 192.168.86.33:HAProxy
- 192.168.86.31:服务1
- 192.168.86.36:Service2 这三个都运行 Raspberry Pi OS。
根据文档,HAProxy 似乎是一个很好的工具,但我无法让它工作。在我添加之前它可以工作,source 0.0.0.0 usesrc clientip
但服务看到的是代理的 IP,而不是客户端的 IP。
当我添加时,source 0.0.0.0 usesrc clientip
我在客户端得到了这个:Error: Client network socket disconnected before secure TLS connection was established
使用 strace 运行时,HAProxy 日志中会出现这个:
[{EPOLLIN, {u32=15, u64=15}}], 200, 60000, NULL, 8) = 1
clock_gettime(CLOCK_THREAD_CPUTIME_ID, {tv_sec=0, tv_nsec=304312352}) = 0
read(15, "c", 1024) = 1
read(15, 0x7fe9410d50, 1024) = -1 EAGAIN (Resource temporarily unavailable)
setsockopt(17, SOL_TCP, TCP_NODELAY, [1], 4) = 0
recvfrom(17, 0x55a7d68c80, 15360, 0, NULL, NULL) = -1 EAGAIN (Resource temporarily unavailable)
socket(AF_INET, SOCK_STREAM, IPPROTO_IP) = 18
fcntl(18, F_SETFL, O_RDONLY|O_NONBLOCK) = 0
setsockopt(18, SOL_TCP, TCP_NODELAY, [1], 4) = 0
setsockopt(18, SOL_IP, IP_BIND_ADDRESS_NO_PORT, [1], 4) = 0
setsockopt(18, SOL_IP, IP_TRANSPARENT, [1], 4) = 0
setsockopt(18, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
bind(18, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("192.168.86.161")}, 16) = 0
connect(18, {sa_family=AF_INET, sin_port=htons(30989), sin_addr=inet_addr("192.168.86.36")}, 16) = -1 EINPROGRESS (Operation now in progress)
epoll_ctl(4, EPOLL_CTL_ADD, 17, {EPOLLIN|EPOLLRDHUP, {u32=17, u64=17}}) = 0
epoll_ctl(4, EPOLL_CTL_ADD, 18, {EPOLLIN|EPOLLOUT|EPOLLRDHUP, {u32=18, u64=18}}) = 0
clock_gettime(CLOCK_THREAD_CPUTIME_ID, {tv_sec=0, tv_nsec=307519852}) = 0
epoll_pwait(4, [{EPOLLIN, {u32=17, u64=17}}], 200, 5001, NULL, 8) = 1
clock_gettime(CLOCK_THREAD_CPUTIME_ID, {tv_sec=0, tv_nsec=307766259}) = 0
recvfrom(17, "\26\3\1\2\0\1\0\1\374\3\3\277\357D\241\236\245Gw\361\16\6\273\234\212D\245\305\241.\10o"..., 15360, 0, NULL, NULL) = 517
下面是我的完整 haproxy.cfg。我暂时删除了其中一个后端:
defaults
mode tcp
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
frontend db
bind 192.168.86.33:30989 transparent
default_backend databases
backend databases
source 0.0.0.0 usesrc clientip
server db2 192.168.86.36:30989
直接连接到 192.168.86.36 即可。如果我删除“源”行,则通过代理连接可以正常工作,但我的服务看到的 IP 是错误的。
我相信我已经加载了正确的内核模块:
lsmod | grep proxy
nft_tproxy 16384 0
nf_tproxy_ipv6 16384 1 nft_tproxy
nf_tproxy_ipv4 16384 1 nft_tproxy
nf_defrag_ipv6 20480 3 nf_conntrack,xt_socket,nft_tproxy
nf_defrag_ipv4 16384 3 nf_conntrack,xt_socket,nft_tproxy
nf_tables 237568 212 nft_compat,nft_tproxy,nft_chain_nat,nft_socket
ipv6 557056 50 nf_tproxy_ipv6,bridge,br_netfilter,nf_socket_ipv6
这些是在代理上设置的 iptables 和路由:
#!/bin/bash
iptables -t mangle -N DIVERT
iptables -t mangle -A PREROUTING -p tcp -m socket -j DIVERT
iptables -t mangle -A DIVERT -j MARK --set-mark 111
iptables -t mangle -A DIVERT -j ACCEPT
ip rule add fwmark 111 lookup 100
ip route add local 0.0.0.0/0 dev lo table 100
根据回应这里我还将代理设置为服务机器上的默认网关:
ip route show
default via 192.168.86.33 dev wlan0 src 192.168.86.36 metric 303
我最后尝试过的方法:
- 使用USE_LINUX_TPROXY = 1重新编译haproxy:
OPTIONS = USE_LINUX_TPROXY=1
- 我已将 net.ipv4.ip_forward 和 net.ipv4.ipnonlocalbind 设置为 1
任何能帮助我解决错误地方的帮助都将非常感激!