![如何将所有发往旧主机的流量重定向到新主机?](https://linux22.com/image/1444876/%E5%A6%82%E4%BD%95%E5%B0%86%E6%89%80%E6%9C%89%E5%8F%91%E5%BE%80%E6%97%A7%E4%B8%BB%E6%9C%BA%E7%9A%84%E6%B5%81%E9%87%8F%E9%87%8D%E5%AE%9A%E5%90%91%E5%88%B0%E6%96%B0%E4%B8%BB%E6%9C%BA%EF%BC%9F.png)
我们正在转移一系列服务,比如从1.2.3.4
到5.6.7.8
。
为了测试新服务是否配置正确,我们希望将来自测试工作站的所有发往原始主机的流量重定向(到新主机)。
当然,这样的重定向可以在网络内的路由器上实现 - 但出于稳定性原因,我们决定直接在每个工作站上实现它(所有都是 OS X 10.10 Yosemite,因此使用 pre-v4.7 OpenBSD pf)。
我已添加到/etc/pf.anchors/com.apple
:
rdr-anchor "910.TestServiceMove/*"
anchor "910.TestServiceMove/*"
load anchor "910.TestServiceMove" from "/etc/pf.anchors/910.TestServiceMove"
并创建/etc/pf.anchors/910.TestServiceMove
:
rdr pass log on lo0 from any to 1.2.3.4 -> 5.6.7.8
pass out log route-to lo0 from any to 1.2.3.4 keep state
加载规则后,两者似乎都能正常工作:
$ sudo tcpdump -v -n -e -ttt -i pflog0 tcpdump:警告:pflog0:未分配 IPv4 地址 tcpdump:监听 pflog0,链接类型为 PFLOG(OpenBSD pflog 文件),捕获大小为 65535 字节 00:00:00.000000 规则 0.910.TestServiceMove.0/0(匹配):在 en1 上传递:(tos 0x0、ttl 64、id 40691、偏移量 0、标志 [DF]、proto TCP(6)、长度 64) 9.9.9.9.58029 > 1.2.3.4.22:标志 [S]、cksum 0x291a(正确)、seq 3399416413、win 65535、选项 [mss 1460、nop、wscale 5、nop、nop、TS val 2063366865 ecr 0、sackOK、eol]、长度 0 00:00:00.000047 规则 0/0(匹配):rdr 在 lo0 上:(tos 0x0、ttl 64、id 40691、偏移量 0、标志 [DF]、proto TCP(6)、长度 64、坏 cksum 896a(->b4da)!) 9.9.9.9.58029 > 5.6.7.8.22:标志 [S]、cksum 0xb284(正确)、seq 3399416413、win 65535、选项 [mss 1460、nop、wscale 5、nop、nop、TS val 2063366865 ecr 0、sackOK、eol]、长度 0
但 TCP 握手并未完成(SYN-ACK 被忽略,并且 SYN 被重复发送直到连接超时):
$ sudo tcpdump -v -n -e -ttt 主机 5.6.7.8 tcpdump:数据链路类型 PKTAP tcpdump:监听 pktap,链接类型为 PKTAP(Packet Tap),捕获大小为 65535 字节 00:00:00.000000 e8:80:2e:e7:67:bc > 84:80:2d:35:e5:43,以太网类型 IPv4 (0x0800),长度 78:(tos 0x0,ttl 63,id 40691,偏移量 0,标志 [DF],proto TCP (6),长度 64) 9.9.9.9.58029 > 5.6.7.8.22:标志 [S]、cksum 0xb284(正确)、seq 3399416413、win 65535、选项 [mss 1460、nop、wscale 5、nop、nop、TS val 2063366865 ecr 0、sackOK、eol]、长度 0 00:00:00.015524 84:80:2d:35:e5:43 > e8:80:2e:e7:67:bc,以太网类型 IPv4 (0x0800),长度 74:(tos 0x0,ttl 52,id 0,偏移量 0,标志 [DF],proto TCP (6),长度 60) 5.6.7.8.22 > 9.9.9.9.58029:标志 [S.],cksum 0x7ce4(正确),seq 1901846890,ack 3399416414,win 14480,选项 [mss 1460,sackOK,TS val 523934721 ecr 2063366865,nop,wscale 7],长度 0 00:00:00.986946 e8:80:2e:e7:67:bc > 84:80:2d:35:e5:43,以太网类型 IPv4 (0x0800),长度 78:(tos 0x0,ttl 63,id 25319,偏移量 0,标志 [DF],proto TCP (6),长度 64) 9.9.9.9.58029 > 5.6.7.8.22:标志 [S]、cksum 0xae9c(正确)、seq 3399416413、win 65535、选项 [mss 1460、nop、wscale 5、nop、nop、TS val 2063367865 ecr 0、sackOK、eol]、长度 0 00:00:00.014938 84:80:2d:35:e5:43 > e8:80:2e:e7:67:bc,以太网类型 IPv4 (0x0800),长度 74:(tos 0x0,ttl 52,id 0,偏移量 0,标志 [DF],proto TCP (6),长度 60) 5.6.7.8.22 > 9.9.9.9.58029:标志 [S.],cksum 0x78fa(正确),seq 1901846890,ack 3399416414,win 14480,选项 [mss 1460,sackOK,TS val 523935723 ecr 2063366865,nop,wscale 7],长度 0 00:00:00.397794 84:80:2d:35:e5:43 > e8:80:2e:e7:67:bc,以太网类型 IPv4 (0x0800),长度 74:(tos 0x0,ttl 52,id 0,偏移量 0,标志 [DF],proto TCP (6),长度 60) 5.6.7.8.22 > 9.9.9.9.58029:标志 [S.],cksum 0x776c(正确),seq 1901846890,ack 3399416414,win 14480,选项 [mss 1460,sackOK,TS val 523936121 ecr 2063366865,nop,wscale 7],长度 0 00:00:00.588237 e8:80:2e:e7:67:bc > 84:80:2d:35:e5:43,以太网类型 IPv4 (0x0800),长度 78:(tos 0x0,ttl 63,id 50201,偏移量 0,标志 [DF],proto TCP (6),长度 64) 9.9.9.9.58029 > 5.6.7.8.22:标志 [S],cksum 0xaab4(正确),seq 3399416413,win 65535,选项 [mss 1460,nop,wscale 5,nop,nop,TS val 2063368865 ecr 0,sackOK,eol],长度 0
我猜想 TCP 堆栈会丢弃来自 SYN 发送目标主机以外的主机的 SYN-ACK。但重定向规则不应该重写两个都方向——事实上,难道不应该keep state
确保为此目的跟踪连接吗?