Estamos movendo um monte de serviços, digamos de 1.2.3.4
para 5.6.7.8
.
Para testar se os novos serviços estão configurados corretamente, gostaríamos de redirecionar (para o novo host) todo o tráfego destinado ao host original originado de nossas estações de trabalho de teste.
É claro que tal redirecionamento poderia ser implementado em roteadores dentro da própria rede - mas por razões de estabilidade nós decidimos implementá-lo diretamente em cada estação de trabalho (que são todos do OS X 10.10 Yosemite, então use pre-v4.7 OpenBSD pf).
Adicionei a /etc/pf.anchors/com.apple
:
rdr-anchor "910.TestServiceMove/*"
anchor "910.TestServiceMove/*"
load anchor "910.TestServiceMove" from "/etc/pf.anchors/910.TestServiceMove"
E criou /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
Quando as regras são carregadas, ambas parecem funcionar corretamente:
$ sudo tcpdump -v -n -e -ttt -i pflog0
tcpdump: WARNING: pflog0: no IPv4 address assigned
tcpdump: listening on pflog0, link-type PFLOG (OpenBSD pflog file), capture size 65535 bytes
00:00:00.000000 rule 0.910.TestServiceMove.0/0(match): pass out on en1: (tos 0x0, ttl 64, id 40691, offset 0, flags [DF], proto TCP (6), length 64)
9.9.9.9.58029 > 1.2.3.4.22: Flags [S], cksum 0x291a (correct), seq 3399416413, win 65535, options [mss 1460,nop,wscale 5,nop,nop,TS val 2063366865 ecr 0,sackOK,eol], length 0
00:00:00.000047 rule 0/0(match): rdr in on lo0: (tos 0x0, ttl 64, id 40691, offset 0, flags [DF], proto TCP (6), length 64, bad cksum 896a (->b4da)!)
9.9.9.9.58029 > 5.6.7.8.22: Flags [S], cksum 0xb284 (correct), seq 3399416413, win 65535, options [mss 1460,nop,wscale 5,nop,nop,TS val 2063366865 ecr 0,sackOK,eol], length 0
Mas o handshake TCP não é concluído (os SYN-ACKs são ignorados e o SYN é enviado repetidamente até a conexão expirar):
$ sudo tcpdump -v -n -e -ttt host 5.6.7.8
tcpdump: data link type PKTAP
tcpdump: listening on pktap, link-type PKTAP (Packet Tap), capture size 65535 bytes
00:00:00.000000 e8:80:2e:e7:67:bc > 84:80:2d:35:e5:43, ethertype IPv4 (0x0800), length 78: (tos 0x0, ttl 63, id 40691, offset 0, flags [DF], proto TCP (6), length 64)
9.9.9.9.58029 > 5.6.7.8.22: Flags [S], cksum 0xb284 (correct), seq 3399416413, win 65535, options [mss 1460,nop,wscale 5,nop,nop,TS val 2063366865 ecr 0,sackOK,eol], length 0
00:00:00.015524 84:80:2d:35:e5:43 > e8:80:2e:e7:67:bc, ethertype IPv4 (0x0800), length 74: (tos 0x0, ttl 52, id 0, offset 0, flags [DF], proto TCP (6), length 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], length 0
00:00:00.986946 e8:80:2e:e7:67:bc > 84:80:2d:35:e5:43, ethertype IPv4 (0x0800), length 78: (tos 0x0, ttl 63, id 25319, offset 0, flags [DF], proto TCP (6), length 64)
9.9.9.9.58029 > 5.6.7.8.22: Flags [S], cksum 0xae9c (correct), seq 3399416413, win 65535, options [mss 1460,nop,wscale 5,nop,nop,TS val 2063367865 ecr 0,sackOK,eol], length 0
00:00:00.014938 84:80:2d:35:e5:43 > e8:80:2e:e7:67:bc, ethertype IPv4 (0x0800), length 74: (tos 0x0, ttl 52, id 0, offset 0, flags [DF], proto TCP (6), length 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], length 0
00:00:00.397794 84:80:2d:35:e5:43 > e8:80:2e:e7:67:bc, ethertype IPv4 (0x0800), length 74: (tos 0x0, ttl 52, id 0, offset 0, flags [DF], proto TCP (6), length 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], length 0
00:00:00.588237 e8:80:2e:e7:67:bc > 84:80:2d:35:e5:43, ethertype IPv4 (0x0800), length 78: (tos 0x0, ttl 63, id 50201, offset 0, flags [DF], proto TCP (6), length 64)
9.9.9.9.58029 > 5.6.7.8.22: Flags [S], cksum 0xaab4 (correct), seq 3399416413, win 65535, options [mss 1460,nop,wscale 5,nop,nop,TS val 2063368865 ecr 0,sackOK,eol], length 0
Eu acho que a pilha TCP está descartando SYN-ACKs que se originaram de um host diferente daquele para o qual o SYN foi enviado. Mas as regras de redirecionamento não devem reescrever o tráfego em ambas direções? De fato, não deve keep state
garantir que a conexão seja rastreada para essa finalidade?