当设置源 0.0.0.0 usesrc clientip 时,HAProxy 透明 TCP 代理失败

当设置源 0.0.0.0 usesrc clientip 时,HAProxy 透明 TCP 代理失败

我有一个设置,希望在某些 HTTPS 服务前使用透明 TCP 代理。这些服务本身处理证书,因此我尝试避免使用 HTTP 代理。我还需要这些服务来获取客户端的原始 IP。

设置如下:

  1. 192.168.86.33:HAProxy
  2. 192.168.86.31:服务1
  3. 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

任何能帮助我解决错误地方的帮助都将非常感激!

相关内容