中继 TCP 上传流量并使下载流量直接发往客户端

中继 TCP 上传流量并使下载流量直接发往客户端

这是iptables UDP 规则的 SNAT 仅适用于部分流量

事实上,我有三台机器:

  • 客户端
  • 目标服务器
  • 中继服务器

我这样做的动机是什么?

客户端到目标服务器的上传通道很不稳定,但是目标服务器到客户端的下载通道很好。

因此我希望中继服务器只中继客户端的上传流量到目标服务器,不中继目标服务器响应的下载流量到客户端,而由目标服务器直接响应客户端。

这是交通流量

我做什么

为了达到这个要求。

  • 在中继服务器上,我针对客户端的请求数据包设置了DNAT规则,将这些数据包的目的地址转换为目标服务器的地址,使得目标服务器认为这些请求数据包是客户端直接发送给它的。

  • 在目标服务器上,我为响应数据包添加 SNAT 规则,将响应数据包的源地址转换为中继服务器,以便让客户端认为响应数据包来自中继服务器。

配置:

  • IP 地址

    • 中继服务器:192.168.169.129
    • 客户:192.168.169.131
    • 目标服务器:192.168.169.132
  • 一般用途

    • Client将请求流量发送到RelayServer:10080
    • RelayServer:10080将请求流量从客户端中继到TargetServer:80通过中继服务器上的 DNAT 规则实现
    • TargetServer:80响应client就好像它是RelayServer:10080响应数据包未能在目标服务器上应用 SNAT 规则
    • Client接收来自的响应流量RelayServer:10080,实际上来自TargetServer:80
  • 中继服务器上的 iptables 规则

    # DNAT-RULES                     relay-server       protocol            relay-port                target-server:target:port 
    iptables -t nat -A PREROUTING -d 192.168.169.129/32 -p tcp -m tcp --dport 10080 -j DNAT --to-destination 192.168.169.132:80
    iptables -t nat -A PREROUTING -d 192.168.169.129/32 -p udp -m udp --dport 10080 -j DNAT --to-destination 192.168.169.132:80
    
  • 目标服务器上的 iptables 规则

    # NOTRACK-RULES                  target-server      protocol            target-port    
    iptables -t raw -A PREROUTING -d 192.168.169.132/32 -p udp -m udp --dport 80 -j NOTRACK
    iptables -t raw -A PREROUTING -d 192.168.169.132/32 -p tcp -m tcp --dport 80 -j NOTRACK
    
    # SNAT-RULES                      target-server      protocol            target-port            relay-server:relay:port 
    iptables -t nat -A POSTROUTING -s 192.168.169.132/32 -p udp -m udp --sport 80 -j SNAT --to-source 192.168.169.129:10080
    iptables -t nat -A POSTROUTING -s 192.168.169.132/32 -p tcp -m tcp --sport 80 -j SNAT --to-source 192.168.169.129:10080
    

与 UDP 协议完美兼容

TCP 协议问题

  • 请求数据包能够成功到达目标服务器,说明中继服务器上的DNAT规则确实起作用了。

  • 而目标服务器虽然可以对请求的数据包进行响应,但是响应数据包的源地址无法应用 SNAT 规则,也就是说客户端虽然收到了响应数据包,但是响应数据包的源地址是目标服务器而不是中继服务器,因此客户端会拒绝这些响应数据包。

  • 进一步的测试表明,从目标服务器直接发送到客户端的 TCP 数据包确实应用了 SNAT 规则,但 TCP 响应数据包却没有应用。

问题是什么?

  • 这仍然是个问题吗conntrack?我已根据 UDP 的配置为 TCP 添加了 NOTRACK 和 SNAT 规则。
  • 有解决方案可以满足我的要求吗?

更新

SNAT 在目标服务器上工作,但客户端重置了 TCP 连接

替换iptablesnftables 在目标服务器上,SNAT 对目标服务器上的请求和响应数据包都起作用。

但是客户端会回复一个RESET数据包给SYNC目标服务器,这个SYNC数据包是对客户端请求数据包的响应SYNC,经过目标服务器的 SNAT 规则转换,让客户端认为这个数据包是来自中继服务器的。

新问题

  • 为什么客户端收到SYNC目标的响应包后会重置连接?

  • 客户端是否可以通过中继服务器与目标服务器建立 TCP 连接?这边走

再次更新

在中继服务器上用 nftables 替换 iptables,它按我预期的方式工作

抓包之后发现问题出在中继服务器重置 TCP 连接一旦收到ACK 数据包来自客户端,这是TCP协议的第三个数据包。

根据 DNAT 规则,中继服务器应该将 ACK 数据包的地址转换为目标服务器,然后将其发送到目标服务器。我不知道为什么ACK 数据包未能应用 DNAT 规则

当我在中继服务器上用 nftables 替换 iptables 时,它按我预期的方式工作。也许 iptables 太难用了,我不知道 iptables 的问题是什么。

无论如何,我最终实现了我的需求nftables

答案1

通过将 iptables 替换为 nftables 来解决

注意:由于源地址验证

目的:

交通流量

  • Client将请求流量发送到RelayServer:10080
  • RelayServer:10080将请求流量从客户端中继到TargetServer:10080通过中继服务器上的 DNAT 规则实现
  • TargetServer:10080响应client就好像它是RelayServer:10080通过目标服务器上的 SNAT 规则实现
  • Client接收来自的响应流量RelayServer:10080,实际上来自TargetServer:10080
  • 它适用于 TCP 和 UDP 协议

环境

  • 设备:4 台 Vmware 机器,带桥接网络

    • 路由器
    • 客户
    • 中继服务器
    • 目标服务器
  • 操作系统:Alpine Linux 3.15.1

设备 IP 地址

  • 客户
    • IP地址:192.168.10.2/24
    • 閱讀:192.168.10.1
    • 苹果:00:0c:29:06:c7:7e
  • 中继服务器
    • IP地址:192.168.20.2/24
    • 閱讀:192.168.20.1
    • 苹果:00:0c:29:5b:89:3e
  • 目标服务器
    • IP地址:192.168.30.2/24
    • 閱讀:192.168.30.1
    • 苹果:00:0c:29:15:da:6a

路由器配置

网络接口

  • eth0
    • 苹果:00:0c:29:65:3c:a3
    • IP地址:192.168.10.1/24
  • eth1
    • 苹果:00:0c:29:65:3c:ad
    • IP地址:192.168.20.1/24
  • eth2
    • 苹果:00:0c:29:65:3c:b7
    • IP地址:192.168.30.1/24

启用 ipv4_forward

echo 1 > /proc/sys/net/ipv4/ip_forward

禁用所有接口的源地址验证

对于基于Linux的路由器,参考内核sysctl参数rp_filter

echo 0 > /proc/sys/net/ipv4/conf/eth0/rp_filter
echo 0 > /proc/sys/net/ipv4/conf/eth1/rp_filter
echo 0 > /proc/sys/net/ipv4/conf/eth2/rp_filter

中继/目标服务器配置

两个都

  • 卸载 iptables 并安装 nftables
  • 为内核启用 ipv4_forward 选项
    echo 1 > /proc/sys/net/ipv4/ip_forward
    

中继服务器的 nftables 规则

table ip route {
      chain prerouting {
              type filter hook prerouting priority dstnat + 1; policy accept;
              ip daddr 192.168.20.2 udp dport 10080 ip daddr set 192.168.30.2
              ip daddr 192.168.20.2 tcp dport 10080 ip daddr set 192.168.30.2
      }
}

目标服务器的 nftables 规则:

table ip raw {
      chain prerouting {
              type filter hook prerouting priority raw; policy accept;
              ip daddr 192.168.30.2 udp dport 10080 notrack return
              ip daddr 192.168.30.2 tcp dport 10080 notrack return
      }
}
table ip route {
      chain output {
              type filter hook postrouting priority srcnat + 1; policy accept;
              ip saddr 192.168.30.2 udp sport 10080 ip saddr set 192.168.20.2
              ip saddr 192.168.30.2 tcp sport 10080 ip saddr set 192.168.20.2
      }
}

如何测试

  • 在目标服务器上,启动 tcp/udp 服务器

    nc -s 192.168.30.2 -l -p 10080 # for tcp
    nc -s 192.168.30.2 -l -u -p 10080 # for udp
    
  • 在客户端上,启动一个 tcp/udp 客户端到服务器

    nc -s 192.168.10.2 -p 12345 192.168.20.2 10080 # for tcp
    nc -s 192.168.10.2 -u -p 12345 192.168.20.2 10080 # for udp
    

我的测试

脚步

  1. 客户端与服务器建立 TCP 连接
  2. 客户端向服务器发送“Hello”
  3. 服务器回复“World”给客户端
  4. 客户端终止 TCP 连接

路由器捕获的数据包流

router:~# tcpdump '(dst 192.168.10.2 && dst port 12345) || (src 192.168.10.2 && src port 12345)' -e
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
17:33:45.712751 00:0c:29:06:c7:7e (oui Unknown) > 00:0c:29:65:3c:a3 (oui Unknown), ethertype IPv4 (0x0800), length 74: 192.168.10.2.12345 > 192.168.20.2.10080: Flags [S], seq 4018363570, win 64240, options [mss 1460,sackOK,TS val 1510067563 ecr 0,nop,wscale 7], length 0
17:33:45.712870 00:0c:29:65:3c:ad (oui Unknown) > 00:0c:29:5b:89:3e (oui Unknown), ethertype IPv4 (0x0800), length 74: 192.168.10.2.12345 > 192.168.20.2.10080: Flags [S], seq 4018363570, win 64240, options [mss 1460,sackOK,TS val 1510067563 ecr 0,nop,wscale 7], length 0
17:33:45.713459 00:0c:29:5b:89:3e (oui Unknown) > 00:0c:29:65:3c:ad (oui Unknown), ethertype IPv4 (0x0800), length 74: 192.168.10.2.12345 > 192.168.30.2.10080: Flags [S], seq 4018363570, win 64240, options [mss 1460,sackOK,TS val 1510067563 ecr 0,nop,wscale 7], length 0
17:33:45.713460 00:0c:29:65:3c:b7 (oui Unknown) > 00:0c:29:15:da:6a (oui Unknown), ethertype IPv4 (0x0800), length 74: 192.168.10.2.12345 > 192.168.30.2.10080: Flags [S], seq 4018363570, win 64240, options [mss 1460,sackOK,TS val 1510067563 ecr 0,nop,wscale 7], length 0
17:33:45.713557 00:0c:29:15:da:6a (oui Unknown) > 00:0c:29:65:3c:b7 (oui Unknown), ethertype IPv4 (0x0800), length 74: 192.168.20.2.10080 > 192.168.10.2.12345: Flags [S.], seq 4008910075, ack 4018363571, win 65160, options [mss 1460,sackOK,TS val 3299425652 ecr 1510067563,nop,wscale 7], length 0
17:33:45.713572 00:0c:29:65:3c:a3 (oui Unknown) > 00:0c:29:06:c7:7e (oui Unknown), ethertype IPv4 (0x0800), length 74: 192.168.20.2.10080 > 192.168.10.2.12345: Flags [S.], seq 4008910075, ack 4018363571, win 65160, options [mss 1460,sackOK,TS val 3299425652 ecr 1510067563,nop,wscale 7], length 0
17:33:45.713802 00:0c:29:06:c7:7e (oui Unknown) > 00:0c:29:65:3c:a3 (oui Unknown), ethertype IPv4 (0x0800), length 66: 192.168.10.2.12345 > 192.168.20.2.10080: Flags [.], ack 1, win 502, options [nop,nop,TS val 1510067564 ecr 3299425652], length 0
17:33:45.713907 00:0c:29:65:3c:ad (oui Unknown) > 00:0c:29:5b:89:3e (oui Unknown), ethertype IPv4 (0x0800), length 66: 192.168.10.2.12345 > 192.168.20.2.10080: Flags [.], ack 1, win 502, options [nop,nop,TS val 1510067564 ecr 3299425652], length 0
17:33:45.714096 00:0c:29:5b:89:3e (oui Unknown) > 00:0c:29:65:3c:ad (oui Unknown), ethertype IPv4 (0x0800), length 66: 192.168.10.2.12345 > 192.168.30.2.10080: Flags [.], ack 4008910076, win 502, options [nop,nop,TS val 1510067564 ecr 3299425652], length 0
17:33:45.714207 00:0c:29:65:3c:b7 (oui Unknown) > 00:0c:29:15:da:6a (oui Unknown), ethertype IPv4 (0x0800), length 66: 192.168.10.2.12345 > 192.168.30.2.10080: Flags [.], ack 1, win 502, options [nop,nop,TS val 1510067564 ecr 3299425652], length 0
17:33:49.369321 00:0c:29:06:c7:7e (oui Unknown) > 00:0c:29:65:3c:a3 (oui Unknown), ethertype IPv4 (0x0800), length 72: 192.168.10.2.12345 > 192.168.20.2.10080: Flags [P.], seq 1:7, ack 1, win 502, options [nop,nop,TS val 1510071219 ecr 3299425652], length 6
17:33:49.369451 00:0c:29:65:3c:ad (oui Unknown) > 00:0c:29:5b:89:3e (oui Unknown), ethertype IPv4 (0x0800), length 72: 192.168.10.2.12345 > 192.168.20.2.10080: Flags [P.], seq 1:7, ack 1, win 502, options [nop,nop,TS val 1510071219 ecr 3299425652], length 6
17:33:49.369819 00:0c:29:5b:89:3e (oui Unknown) > 00:0c:29:65:3c:ad (oui Unknown), ethertype IPv4 (0x0800), length 72: 192.168.10.2.12345 > 192.168.30.2.10080: Flags [P.], seq 0:6, ack 1, win 502, options [nop,nop,TS val 1510071219 ecr 3299425652], length 6
17:33:49.369820 00:0c:29:65:3c:b7 (oui Unknown) > 00:0c:29:15:da:6a (oui Unknown), ethertype IPv4 (0x0800), length 72: 192.168.10.2.12345 > 192.168.30.2.10080: Flags [P.], seq 0:6, ack 1, win 502, options [nop,nop,TS val 1510071219 ecr 3299425652], length 6
17:33:49.370069 00:0c:29:15:da:6a (oui Unknown) > 00:0c:29:65:3c:b7 (oui Unknown), ethertype IPv4 (0x0800), length 66: 192.168.20.2.10080 > 192.168.10.2.12345: Flags [.], ack 7, win 510, options [nop,nop,TS val 3299429309 ecr 1510071219], length 0
17:33:49.370087 00:0c:29:65:3c:a3 (oui Unknown) > 00:0c:29:06:c7:7e (oui Unknown), ethertype IPv4 (0x0800), length 66: 192.168.20.2.10080 > 192.168.10.2.12345: Flags [.], ack 7, win 510, options [nop,nop,TS val 3299429309 ecr 1510071219], length 0
17:33:51.689563 00:0c:29:06:c7:7e (oui Unknown) > 00:0c:29:65:3c:a3 (oui Unknown), ethertype IPv4 (0x0800), length 72: 192.168.10.2.12345 > 192.168.20.2.10080: Flags [P.], seq 7:13, ack 1, win 502, options [nop,nop,TS val 1510073539 ecr 3299429309], length 6
17:33:51.689687 00:0c:29:65:3c:ad (oui Unknown) > 00:0c:29:5b:89:3e (oui Unknown), ethertype IPv4 (0x0800), length 72: 192.168.10.2.12345 > 192.168.20.2.10080: Flags [P.], seq 7:13, ack 1, win 502, options [nop,nop,TS val 1510073539 ecr 3299429309], length 6
17:33:51.690131 00:0c:29:5b:89:3e (oui Unknown) > 00:0c:29:65:3c:ad (oui Unknown), ethertype IPv4 (0x0800), length 72: 192.168.10.2.12345 > 192.168.30.2.10080: Flags [P.], seq 6:12, ack 1, win 502, options [nop,nop,TS val 1510073539 ecr 3299429309], length 6
17:33:51.690131 00:0c:29:65:3c:b7 (oui Unknown) > 00:0c:29:15:da:6a (oui Unknown), ethertype IPv4 (0x0800), length 72: 192.168.10.2.12345 > 192.168.30.2.10080: Flags [P.], seq 6:12, ack 1, win 502, options [nop,nop,TS val 1510073539 ecr 3299429309], length 6
17:33:51.690297 00:0c:29:15:da:6a (oui Unknown) > 00:0c:29:65:3c:b7 (oui Unknown), ethertype IPv4 (0x0800), length 66: 192.168.20.2.10080 > 192.168.10.2.12345: Flags [.], ack 13, win 510, options [nop,nop,TS val 3299431629 ecr 1510073539], length 0
17:33:51.690305 00:0c:29:65:3c:a3 (oui Unknown) > 00:0c:29:06:c7:7e (oui Unknown), ethertype IPv4 (0x0800), length 66: 192.168.20.2.10080 > 192.168.10.2.12345: Flags [.], ack 13, win 510, options [nop,nop,TS val 3299431629 ecr 1510073539], length 0
17:33:55.442820 00:0c:29:06:c7:7e (oui Unknown) > 00:0c:29:65:3c:a3 (oui Unknown), ethertype IPv4 (0x0800), length 66: 192.168.10.2.12345 > 192.168.20.2.10080: Flags [F.], seq 13, ack 1, win 502, options [nop,nop,TS val 1510077293 ecr 3299431629], length 0
17:33:55.442935 00:0c:29:65:3c:ad (oui Unknown) > 00:0c:29:5b:89:3e (oui Unknown), ethertype IPv4 (0x0800), length 66: 192.168.10.2.12345 > 192.168.20.2.10080: Flags [F.], seq 13, ack 1, win 502, options [nop,nop,TS val 1510077293 ecr 3299431629], length 0
17:33:55.443307 00:0c:29:5b:89:3e (oui Unknown) > 00:0c:29:65:3c:ad (oui Unknown), ethertype IPv4 (0x0800), length 66: 192.168.10.2.12345 > 192.168.30.2.10080: Flags [F.], seq 12, ack 1, win 502, options [nop,nop,TS val 1510077293 ecr 3299431629], length 0
17:33:55.443307 00:0c:29:65:3c:b7 (oui Unknown) > 00:0c:29:15:da:6a (oui Unknown), ethertype IPv4 (0x0800), length 66: 192.168.10.2.12345 > 192.168.30.2.10080: Flags [F.], seq 12, ack 1, win 502, options [nop,nop,TS val 1510077293 ecr 3299431629], length 0
17:33:55.486509 00:0c:29:15:da:6a (oui Unknown) > 00:0c:29:65:3c:b7 (oui Unknown), ethertype IPv4 (0x0800), length 66: 192.168.20.2.10080 > 192.168.10.2.12345: Flags [.], ack 14, win 510, options [nop,nop,TS val 3299435425 ecr 1510077293], length 0
17:33:55.486527 00:0c:29:65:3c:a3 (oui Unknown) > 00:0c:29:06:c7:7e (oui Unknown), ethertype IPv4 (0x0800), length 66: 192.168.20.2.10080 > 192.168.10.2.12345: Flags [.], ack 14, win 510, options [nop,nop,TS val 3299435425 ecr 1510077293], length 0

相关内容