让我从一个图表开始:
Workstation -> TrafficShaper -> Internet
| ^
V |
LinuxProxy ---------
我的流量整形器有一个功能,允许我将数据包转移到另一台主机(图中的 LinuxProxy)。它通过将以太网目标 MAC 地址设置为 LinuxProxy 的接口并将数据包放置到 LinuxProxy 将接收它们的网络上来实现此目的。 LinuxProxy 可以自由地对数据包执行其想要的操作,任何响应都应放置在网络上,并将 TrafficShaper 设置为以太网目标。
举个例子,假设工作站向 www.google.com 发送 TCP SYN。数据包流向 TrafficShaper,然后 TrafficShaper 将其发送至 LinuxProxy。 LinuxProxy 尝试使用 SYN-ACK 进行回复(该 SYN-ACK 将流向 TrafficShaper,然后返回工作站),但是存在一个问题,即 LinuxProxy 不知道要使用哪个以太网目标 MAC 地址。 TrafficShaper 的数据接口没有 IP 绑定,因此我认为这意味着我无法设置路由来将流量直接发送回 TrafficShaper。更糟糕的是,TrafficShaper 的 MAC 地址可能会根据发出请求的工作站而变化。我需要 LinuxProxy 将回复数据包发送到它们最初来自的 MAC 地址。如果我只是尝试对 TCP 连接执行此操作,有没有办法记住每个连接的 MAC 地址并始终向该 MAC 发送回复数据包?或者也许记住源 IP 地址的 MAC 地址并在回复该 IP 时始终使用该 MAC?
使用 tcpdump 更新(tcpdump -n -nn -i eth1 -e -vv 端口 80 或 arp):
1) 当工作站发出 HTTP 请求时,如果我没有在 LinuxProxy 上配置路由,LinuxProxy 会看到以下内容:
16:02:02.382023 TrafficShaper:VirtualInterfaceX > LinuxProxy:eth1, ethertype IPv4 (0x0800), length 66: (tos 0x0, ttl 122, id 30174, offset 0, flags [DF], proto TCP (6), length 52)
Workstation:IP.21875 > RandomWebserver.80: Flags [S], cksum 0x2ffb (correct), seq 1782577522, win 65535, options [mss 1460,nop,wscale 2,nop,nop,sackOK], length 0
我什至没有看到 SYN-ACK,因为没有路由,LinuxProxy 不知道要在哪个接口上响应。我什至在 dmesg 中看到以下内容:
[177553.396852] device eth1 entered promiscuous mode
[177555.286091] IPv4: martian source LinuxProxyIP from WorkstationIP, on dev eth1
[177555.294651] ll header: 00000000: XX XX XX XX XX RT.1....5.:...
[177560.529102] device eth1 left promiscuous mode
2) 让我们添加一条路由,以便 LinuxProxy 知道要回复哪个接口(注意,流量整形器没有 IP,所以我只将接口放在这里):
route add default dev eth1
现在我的 tcpdump 显示 LinuxProxy 尝试对工作站的 IP 进行 ARP,但 TrafficShaper 不应答 ARP,并且不将 ARP 转发到另一端。 (无论如何,工作站的MAC是没有用的)
16:41:14.800321 TrafficShaper:VirtualInterfaceX > LinuxProxy:eth1, ethertype IPv4 (0x0800), length 62: (tos 0x0, ttl 122, id 30787, offset 0, flags [DF], proto TCP (6), length 48)
Workstation:IP.21975 > RandomWebserver.80: Flags [S], cksum 0xc8cf (correct), seq 2481765147, win 65535, options [mss 1460,nop,nop,sackOK], length 0
16:41:14.800432 LinuxProxy:eth1 > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 42: Ethernet (len 6), IPv4 (len 4), Request who-has Workstation:IP tell 10.89.14.11, length 28
16:41:15.800890 LinuxProxy:eth1 > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 42: Ethernet (len 6), IPv4 (len 4), Request who-has Workstation:IP tell 10.89.14.11, length 28
16:41:16.802797 LinuxProxy:eth1 > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 42: Ethernet (len 6), IPv4 (len 4), Request who-has Workstation:IP tell 10.89.14.11, length 28
16:41:17.792513 TrafficShaper:VirtualInterfaceX > LinuxProxy:eth1, ethertype IPv4 (0x0800), length 62: (tos 0x0, ttl 122, id 30788, offset 0, flags [DF], proto TCP (6), length 48)
Workstation:IP.21975 > RandomWebserver.80: Flags [S], cksum 0xc8cf (correct), seq 2481765147, win 65535, options [mss 1460,nop,nop,sackOK], length 0
3) 只是为了验证如果我从 TrafficShaper 中对 MAC 进行硬编码,这是否有效,我创建了一个伪造的 ARP 条目并更改了转到该 IP 的路由。注意:我无法在生产中执行此操作,因为 TrafficShaper 有大约 50 个不同的虚拟接口,每个接口都有自己的 MAC,我的许多工作站通过以下方式实现负载平衡:
ip neighbor add FAKE_IP lladdr TrafficShaper:VirtualInterfaceX dev eth1
route del default dev eth1
route add default gw FAKE_IP
现在 3 次握手完成:
16:52:17.077903 TrafficShaper:VirtualInterfaceX > LinuxProxy:eth1, ethertype IPv4 (0x0800), length 66: (tos 0x0, ttl 122, id 31076, offset 0, flags [DF], proto TCP (6), length 52)
Workstation:IP.22033 > RandomWebserver.80: Flags [S], cksum 0x5a9f (correct), seq 3325648471, win 65535, options [mss 1460,nop,wscale 2,nop,nop,sackOK], length 0
16:52:17.078024 LinuxProxy:eth1 > TrafficShaper:VirtualInterfaceX, ethertype IPv4 (0x0800), length 66: (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 52)
RandomWebserver.80 > Workstation:IP.22033: Flags [S.], cksum 0x99ab (incorrect -> 0x18fa), seq 1232307723, ack 3325648472, win 29200, options [mss 1460,nop,nop,sackOK,nop,wscale 7], length 0
16:52:17.157231 TrafficShaper:VirtualInterfaceX > LinuxProxy:eth1, ethertype IPv4 (0x0800), length 60: (tos 0x0, ttl 122, id 31077, offset 0, flags [DF], proto TCP (6), length 40)
Workstation:IP.22033 > RandomWebserver.80: Flags [.], cksum 0xfbdb (correct), seq 1, ack 1, win 53248, length 0
16:52:17.165426 LinuxProxy:eth1 > TrafficShaper:VirtualInterfaceX, ethertype IPv4 (0x0800), length 54: (tos 0x0, ttl 64, id 20208, offset 0, flags [DF], proto TCP (6), length 40)
... extras removed ...
我知道每个工作站 IP 将负载均衡到 TrafficShaper 上的特定虚拟接口。如果我有办法将给定工作站 IP 的回复数据包发送回接收数据包的 MAC,那么我的问题就可以解决。我目前正在浏览 netfilter 文档,看看是否有办法将 WorkstationIP->MAC 映射保存在字典中,然后在发回数据包时查找该 MAC。