Прежде всего, вот как выглядит моя инфра и как она работает:
Controller1 / 2 и Compute1 / 2 запускают виртуальную машину и связаны друг с другом через VPN. На каждом сервере интерфейс br-ext соединен с интерфейсом ext (vpn). Все серверы могут взаимодействовать друг с другом, как и виртуальные машины на своих частных интерфейсах.
У меня есть два маршрутизатора ubuntu 16.04 (2 коробки с ETH3 и BR-ext), только один активен одновременно (второй - отказоустойчивый с keepalived) и одновременно владеет общедоступной подсетью (51.38.XY / 27 ) и IP 10.38.166.190 (который действует как шлюз для всех виртуальных машин).
Я использую Iptables и Iproute2, чтобы разрешить трафику, скажем, 51.38.X.YYA достичь 10.38.X.YYA, а с 10.38.X.YYA - пройти через 51.38.X.YYA.
С одной из виртуальных машин я могу без проблем выйти наружу, и если я запустил curl ifconfig.co, мне будет предложено указать общедоступный IP-адрес, который я хочу.
Моя проблема:
Если я попытаюсь связаться с виртуальной машиной 2 с виртуальной машины 1, используя ее общедоступный IP-адрес, это вообще не сработает.
Я возьму две виртуальные машины, чтобы проиллюстрировать свою проблему, и дам всю конфигурацию по ней:
VM1: 10.38.166.167 / 51.38.166.167 VM2: 10.38.166.166 / 51.38.166.166
Что я уже сделал:
На router1:
ETH1 = Главный интерфейс (управление) ETH3 = Интерфейс, который содержит все IP и NAT для ВМ br-ext = мост, содержащий интерфейс VPN ext = Интерфейс VPN (подключен к мосту br-ext)
[root@network3] ~# ip a l
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether fa:16:3e:19:3e:41 brd ff:ff:ff:ff:ff:ff
inet 51.38.166.162/32 brd 51.38.x.162 scope global eth1
valid_lft forever preferred_lft forever
inet6 fe80::f816:3eff:fe19:3e41/64 scope link
valid_lft forever preferred_lft forever
5: eth3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether fa:16:3e:72:94:cb brd ff:ff:ff:ff:ff:ff
inet 51.38.166.163/32 brd 51.38.x.163 scope global eth3
valid_lft forever preferred_lft forever
inet 51.38.166.166/32 scope global eth3
valid_lft forever preferred_lft forever
inet 51.38.166.167/32 scope global eth3
valid_lft forever preferred_lft forever
7: br-ext: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether d2:f8:64:36:64:f2 brd ff:ff:ff:ff:ff:ff
inet 10.0.0.103/9 brd 10.127.255.255 scope global br-ext
valid_lft forever preferred_lft forever
inet 10.0.0.120/32 scope global br-ext
valid_lft forever preferred_lft forever
inet 10.38.166.190/32 scope global br-ext
valid_lft forever preferred_lft forever
10: ext: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br-ext state UNKNOWN group default qlen 1000
link/ether d2:f8:64:36:64:f2 brd ff:ff:ff:ff:ff:ff
Я установил несколько маршрутов, позволяющих маршрутизировать пакеты, приходящие извне на 51.38.x.160 / 27, на 10.38.x.y / 27.
[root@network3] ~# ip ru l | grep "lookup 103"
9997: from 10.38.x.167 lookup 103
9998: from 10.38.x.166 lookup 103
# rules to tells that each IP of the /27 need to use table 103
10301: from 51.38.166.163 lookup 103
10302: from all to 51.38.166.163 lookup 103
10307: from 51.38.166.166 lookup 103
10308: from all to 51.38.166.166 lookup 103
10309: from 51.38.166.167 lookup 103
10310: from all to 51.38.166.167 lookup 103
[root@network3] ~# ip r s table 103
default via 51.38.166.190 dev eth3
51.38.166.160/27 dev eth3 scope link
[root@network3] ~# ip r s
default via 51.38.166.190 dev eth1 onlink
10.0.0.0/9 dev br-ext proto kernel scope link src 10.0.0.103
172.16.0.0/16 dev br-manag proto kernel scope link src 172.16.0.103
Мои iptables выглядят следующим образом:
[root@network3] ~# iptables -nvL
Chain INPUT (policy ACCEPT 21334 packets, 1015K bytes)
pkts bytes target prot opt in out source destination
91877 4376K ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0 /* 000 accept all icmp */
18 1564 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0 /* 001 accept all to lo interface */
0 0 REJECT all -- !lo * 0.0.0.0/0 127.0.0.0/8 /* 002 reject local traffic not on loopback interface */ reject-with icmp-port-unreachable
343K 123M ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state ESTABLISHED /* 003 accept related established rules */
243 14472 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 multiport dports 1022 /* 030 allow SSH */
481M 42G ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 multiport dports 3210:3213 /* 031 allow VPNtunnel */
4155 241K DROP all -- eth0 * 0.0.0.0/0 0.0.0.0/0 /* 999 drop all */
Chain FORWARD (policy ACCEPT 98325 packets, 8874K bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 964M packets, 93G bytes)
pkts bytes target prot opt in out source destination
Iptables NAT правила
[root@network3] ~# iptables -t nat -nvL --line
Chain PREROUTING (policy ACCEPT 156K packets, 6455K bytes)
num pkts bytes target prot opt in out source destination
31 11228 771K DNAT all -- * * 0.0.0.0/0 51.38.166.166 /* 112 NAT for 10.38.166.166 */ to:10.38.166.166
32 11624 809K DNAT all -- * * 0.0.0.0/0 51.38.166.167 /* 112 NAT for 10.38.166.167 */ to:10.38.166.167
Chain INPUT (policy ACCEPT 85077 packets, 3527K bytes)
num pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 16505 packets, 1294K bytes)
num pkts bytes target prot opt in out source destination
Chain POSTROUTING (policy ACCEPT 105K packets, 4357K bytes)
num pkts bytes target prot opt in out source destination destination
31 17 1196 SNAT all -- * * 10.38.166.166 0.0.0.0/0 to:51.38.166.166
32 8 549 SNAT all -- * * 10.38.166.167 0.0.0.0/0 to:51.38.166.167
Я также вставил некоторые правила в таблицы RAW, чтобы помочь мне отслеживать пакеты:
[root@network3] ~# iptables -t raw -nvL
Chain PREROUTING (policy ACCEPT 3765 packets, 227K bytes)
pkts bytes target prot opt in out source destination
0 0 TRACE all -- * * 51.38.166.167 0.0.0.0/0
185 12988 TRACE all -- * * 0.0.0.0/0 51.38.166.167
Chain OUTPUT (policy ACCEPT 7941 packets, 837K bytes)
pkts bytes target prot opt in out source destination
Тестирование с ВМ1:
ubuntu@test-1:~$ ip a l dev ens3
2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc pfifo_fast state UP group default qlen 1000
link/ether fa:16:3e:51:0a:0b brd ff:ff:ff:ff:ff:ff
inet 10.38.166.167/24 brd 10.38.166.255 scope global ens3
valid_lft forever preferred_lft forever
inet6 fe80::f816:3eff:fe51:a0b/64 scope link
valid_lft forever preferred_lft forever
ubuntu@test-1:~$ curl ifconfig.co
51.38.166.167
ubuntu@test-1:~$ ping 51.38.166.166 -c 4
PING 51.38.166.166 (51.38.166.166) 56(84) bytes of data.
--- 51.38.166.166 ping statistics ---
4 packets transmitted, 0 received, 100% packet loss, time 3031ms
Тестирование с ВМ2:
ubuntu@test-2:~$ ip a l dev ens3
2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc pfifo_fast state UP group default qlen 1000
link/ether fa:16:3e:9d:79:ce brd ff:ff:ff:ff:ff:ff
inet 10.38.166.166/24 brd 10.38.166.255 scope global ens3
valid_lft forever preferred_lft forever
inet6 fe80::f816:3eff:fe9d:79ce/64 scope link
valid_lft forever preferred_lft forever
ubuntu@test-2:~$ curl ifconfig.co
51.38.166.166
ubuntu@test-2:~$ ping 51.38.166.167 -c 4
PING 51.38.166.167 (51.38.166.167) 56(84) bytes of data.
--- 51.38.166.167 ping statistics ---
4 packets transmitted, 0 received, 100% packet loss, time 3023ms
ЖУРНАЛЫ из сети3:
[root@network3] ~# tail -f /var/log/kern.log | grep "SRC=10.38.166.166 DST=51.38.166.167"
Jul 5 11:58:12 network3 kernel: [79540.314496] TRACE: nat:PREROUTING:rule:32 IN=br-ext OUT= MAC=de:01:31:2d:47:18:fa:16:3e:9d:79:ce:08:00 SRC=10.38.166.166 DST=51.38.166.167 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=49094 DF PROTO=ICMP TYPE=8 CODE=0 ID=4992 SEQ=57
Jul 5 11:58:13 network3 kernel: [79541.322501] TRACE: raw:PREROUTING:policy:3 IN=br-ext OUT= MAC=de:01:31:2d:47:18:fa:16:3e:9d:79:ce:08:00 SRC=10.38.166.166 DST=51.38.166.167 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=49203 DF PROTO=ICMP TYPE=8 CODE=0 ID=4992 SEQ=58
Jul 5 11:58:13 network3 kernel: [79541.322543] TRACE: mangle:PREROUTING:policy:1 IN=br-ext OUT= MAC=de:01:31:2d:47:18:fa:16:3e:9d:79:ce:08:00 SRC=10.38.166.166 DST=51.38.166.167 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=49203 DF PROTO=ICMP TYPE=8 CODE=0 ID=4992 SEQ=58
Jul 5 11:58:13 network3 kernel: [79541.322574] TRACE: nat:PREROUTING:rule:32 IN=br-ext OUT= MAC=de:01:31:2d:47:18:fa:16:3e:9d:79:ce:08:00 SRC=10.38.166.166 DST=51.38.166.167 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=49203 DF PROTO=ICMP TYPE=8 CODE=0 ID=4992 SEQ=58
Jul 5 11:58:14 network3 kernel: [79542.330582] TRACE: raw:PREROUTING:policy:3 IN=br-ext OUT= MAC=de:01:31:2d:47:18:fa:16:3e:9d:79:ce:08:00 SRC=10.38.166.166 DST=51.38.166.167 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=49367 DF PROTO=ICMP TYPE=8 CODE=0 ID=4992 SEQ=59
Jul 5 11:58:14 network3 kernel: [79542.330615] TRACE: mangle:PREROUTING:policy:1 IN=br-ext OUT= MAC=de:01:31:2d:47:18:fa:16:3e:9d:79:ce:08:00 SRC=10.38.166.166 DST=51.38.166.167 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=49367 DF PROTO=ICMP TYPE=8 CODE=0 ID=4992 SEQ=59
Jul 5 11:58:14 network3 kernel: [79542.330639] TRACE: nat:PREROUTING:rule:32 IN=br-ext OUT= MAC=de:01:31:2d:47:18:fa:16:3e:9d:79:ce:08:00 SRC=10.38.166.166 DST=51.38.166.167 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=49367 DF PROTO=ICMP TYPE=8 CODE=0 ID=4992 SEQ=59
^C
Поскольку идентификатор не меняется для данного SEQ, я могу искать в журнале все, что касается этого идентификатора / SEQ:
[root@network3] ~# grep "ID=49367" /var/log/kern.log
Jul 5 11:58:14 network3 kernel: [79542.330582] TRACE: raw:PREROUTING:policy:3 IN=br-ext OUT= MAC=de:01:31:2d:47:18:fa:16:3e:9d:79:ce:08:00 SRC=10.38.166.166 DST=51.38.166.167 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=49367 DF PROTO=ICMP TYPE=8 CODE=0 ID=4992 SEQ=59
Jul 5 11:58:14 network3 kernel: [79542.330615] TRACE: mangle:PREROUTING:policy:1 IN=br-ext OUT= MAC=de:01:31:2d:47:18:fa:16:3e:9d:79:ce:08:00 SRC=10.38.166.166 DST=51.38.166.167 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=49367 DF PROTO=ICMP TYPE=8 CODE=0 ID=4992 SEQ=59
Jul 5 11:58:14 network3 kernel: [79542.330639] TRACE: nat:PREROUTING:rule:32 IN=br-ext OUT= MAC=de:01:31:2d:47:18:fa:16:3e:9d:79:ce:08:00 SRC=10.38.166.166 DST=51.38.166.167 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=49367 DF PROTO=ICMP TYPE=8 CODE=0 ID=4992 SEQ=59
Если я обращусь к этой диаграмме: http://inai.de/images/nf-packet-flow.png
Похоже, дело в выборе маршрута. (Я отказался от возможности застрять в решении о соединении, потому что это точно такое же поведение, если я сделаю то же самое без какого-либо моста).
Другая возможность состоит в том, что он соответствует правилам предварительной маршрутизации NAT 32, но не применяет его, но я не могу понять, почему.
какая-нибудь подсказка о том, что мне не хватает в этом случае?
Наиболее частой причиной отбрасывания пакетов при выборе маршрутизации является rp_filter
.
Проверить вывод команды ip route get 51.38.166.167 from 10.38.166.166 iif br-ext
. В нормальном случае он должен возвращать действительный маршрут. В invalid cross-device link
результат означает, что пакеты будут отброшены rp_filter
. Также проверьте вывод nstat -az TcpExtIPReversePathFilter
. Это счетчик таких сброшенных пакетов.
Чтобы проверить текущий режим rp_filter
использовать ip netconf show dev br-ext
команда.
Использовать sysctl
команда для настройки этого параметра.