我们正在移动一堆服务,从1.2.3.4到5.6.7.8 。
为了testing新服务的configuration是否正确,我们希望redirect(到新主机)发往我们testing工作站的原始主机的所有stream量。
当然,这样的redirect可以在networking中的路由器上实现 – 但是出于稳定性原因,我们决定直接在每个工作站上实现它们(所有OS X 10.10 Yosemite,所以使用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"
并创build/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,链接typesPFLOG(OpenBSD pflog文件),捕获大小65535字节 (tos 0x0,ttl 64,id 40691,offset 0,flags [DF],proto TCP(6),length 64)00:00:00.000000 rule 0.910.TestServiceMove.0 / 0 9.9.9.9.58029> 1.2.3.4.22:Flags [S],0x981a(正确),seq 3399416413,win 65535,选项[mss 1460,nop,wscale 5,nop,nop,TS val 2063366865 ecr 0,sackOK ,eol],长度为0 (tos 0x0,tt144,id 40691,offset 0,flags [DF],proto TCP(6),length 64,bad cksum 896a( - )的规则0/0(匹配):rdr > b4da)!) 5.6.7.8.22:标志[S],正确0xb284(正确),seq 3399416413,获胜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:数据链接typesPKTAP
tcpdump:监听pktap,链接型PKTAP(Packet Tap),捕获大小为65535字节
00:00:00.000000 e8:80:2e:e7:67:bc> 84:80:2d:35:e5:43,以太网typesIPv4(0x0800),长度78:(tos 0x0,tt163,id 40691,offset 0 ,标记[DF],原始TCP(6),长度64)
5.6.7.8.22:标志[S],正确0xb284(正确),seq 3399416413,获胜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,以太网typesIPv4(0x0800),长度74:(tos 0x0,tt152,id 0,offset 0 ,标记[DF],原始TCP(6),长度60)
5.6.7.8.22> 9.9.9.9.58029:Flags [S.],cksum 0x7ce4(correct),seq 1901846890,ack 3399416414,win 14480,options [mss 1460,sackOK,TS val 523934721 ecr 2063366865,nop,wscale 7 ],长度为0
00:00.986946 e8:80:2e:e7:67:bc> 84:80:2d:35:e5:43,以太网typesIPv4(0x0800),长度78:(tos 0x0,tt163,id 25319,offset 0 ,标记[DF],原始TCP(6),长度64)
5.6.7.8.22:标志[S],0x989c(正确),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,以太网typesIPv4(0x0800),长度74:(tos 0x0,tt152,id 0,offset 0 ,标记[DF],原始TCP(6),长度60)
5.6.7.8.22> 9.9.9.9.58029:Flags [S.],cksum 0x78fa(correct),seq 1901846890,ack 3399416414,win 14480,options [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,ethertype IPv4(0x0800),长度74:(tos 0x0,tt152,id 0,offset 0 ,标记[DF],原始TCP(6),长度60)
5.6.7.8.22> 9.9.9.9.58029:Flags [S.],cksum 0x776c(correct),seq 1901846890,ack 3399416414,win 14480,options [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,以太网typesIPv4(0x0800),长度78:(tos 0x0,tt163,id 50201,offset 0 ,标记[DF],原始TCP(6),长度64)
5.6.7.8.22:标志[S],正确0xaab4(正确),seq 3399416413,胜利65535,选项[mss 1460,nop,wscale 5,nop,nop,TS val 2063368865 ecr 0,sackOK ,eol],长度为0
我猜测TCP协议栈正在丢弃源自SYN以外的主机的SYN-ACK。 但是不应该redirect规则在两个方向重写stream量 – 事实上,不应该keep state确保连接跟踪为此目的?
如果您正在访问的服务都是通过名称访问的,那么我只需在开发机器上的hosts文件中创build一个主机条目。
例如,如果你的机器被称为myserver并parsing为1.2.3.4那么你现在可以创build一个主机文件入口/ etc / hosts
myserver 5.6.7.8
现在试图达到我的服务器的任何事情将最终击中新的机器。
或者,只需在旧地址处使用新服务器创build一个新的隔离networking,并将您的开发机器插入其中进行testing。
直接redirect或路由规则的问题是,新的服务器不回答旧地址的名称。 所以你必须使用NAT。
将机器扔在简单的负载均衡器或NAT之后不是简单吗? 无论如何,这通常是更符合行业标准的做法,并且可以让您随着时间的推移进一步扩展应用程序。
你可以只提供从“新”服务器的子接口的“旧”地址,或者是一个完全不同的子网中的新地址?
如果您不能将新IP附加到新服务器,那么您并没有真正移动该地址。 要将stream量通过旧地址路由到新服务器,您需要在旧子网中NAT地址。 stream量将落在“旧”地址上,然后源NAT到同一服务器/设备上的新地址,并发送到“新”IP。 返回的stream量然后会返回到SNAT地址,这将解除stream量的NAT并将其返回到原始请求者。 这实际上不是一个好的长期解决scheme,特别是如果“新”地址通过WAN链接。 你已经推迟了不可避免的失败,并增加了延迟。
一个更好的长期解决scheme将考虑:1.使用DNS而不是IP 2.虚拟化IP地址(NAT'ing设备像防火墙或ipmasq盒),3.或服务器本身(负载平衡器)