Iptables AWS ECS позволяет одному и тому же IP-адресу отправителя и получателя
В настоящее время с AWS ECS в сочетании с внутренним NLB невозможно установить межсистемную связь. Значение контейнера 1 (в экземпляре 1) -> внутренний NLB -> контейнер 2 (в экземпляре 1). Поскольку IP-адрес источника не изменяется и остается тем же, что и адрес назначения, экземпляр ECS отбрасывает этот трафик.
Я нашел ветку на форумах AWS здесь https://forums.aws.amazon.com/message.jspa?messageID=806936 объясняется моя проблема.
Я связался со службой поддержки AWS, и они заявили, что в своей дорожной карте есть исправление, но они не могут сказать мне, когда это будет исправлено, поэтому я ищу способы решить его самостоятельно, пока AWS не исправит его навсегда.
Это должно быть исправлено путем изменения iptables ECS, но у меня недостаточно знаний, чтобы полностью прочитать их настройку iptables и понять, что нужно изменить, чтобы это исправить.
iptabels-save output:
:DOCKER - [0:0]
:DOCKER-ISOLATION - [0:0]
:DOCKER-USER - [0:0]
-A FORWARD -j DOCKER-USER
-A FORWARD -j DOCKER-ISOLATION
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A DOCKER -d 172.17.0.3/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 5000 -j ACCEPT
-A DOCKER -d 172.17.0.2/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 5000 -j ACCEPT
-A DOCKER -d 172.17.0.5/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 8086 -j ACCEPT
-A DOCKER-ISOLATION -j RETURN
-A DOCKER-USER -j RETURN
COMMIT
# Completed on Wed Jan 31 22:19:47 2018
# Generated by iptables-save v1.4.18 on Wed Jan 31 22:19:47 2018
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [38:2974]
:POSTROUTING ACCEPT [7147:429514]
:DOCKER - [0:0]
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A PREROUTING -d 169.254.170.2/32 -p tcp -m tcp --dport 80 -j DNAT --to-destination 127.0.0.1:51679
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT -d 169.254.170.2/32 -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 51679
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
-A POSTROUTING -s 172.17.0.3/32 -d 172.17.0.3/32 -p tcp -m tcp --dport 5000 -j MASQUERADE
-A POSTROUTING -s 172.17.0.2/32 -d 172.17.0.2/32 -p tcp -m tcp --dport 5000 -j MASQUERADE
-A POSTROUTING -s 172.17.0.5/32 -d 172.17.0.5/32 -p tcp -m tcp --dport 8086 -j MASQUERADE
-A DOCKER -i docker0 -j RETURN
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 32769 -j DNAT --to-destination 172.17.0.3:5000
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 32777 -j DNAT --to-destination 172.17.0.2:5000
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 32792 -j DNAT --to-destination 172.17.0.5:8086
COMMIT
# Completed on Wed Jan 31 22:19:47 2018
ip a:
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
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc mq state UP group default qlen 1000
link/ether 0a:b4:86:0b:c0:c4 brd ff:ff:ff:ff:ff:ff
inet 10.12.80.181/26 brd 10.12.80.191 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::8b4:86ff:fe0b:c0c4/64 scope link
valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ca:cf:36:ae brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:caff:fecf:36ae/64 scope link
valid_lft forever preferred_lft forever
7: vethbd1da82@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether 36:6d:d6:bd:d5:d8 brd ff:ff:ff:ff:ff:ff link-netnsid 1
inet6 fe80::346d:d6ff:febd:d5d8/64 scope link
valid_lft forever preferred_lft forever
27: vethc65a98f@if26: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether e6:cf:79:d4:aa:7a brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::e4cf:79ff:fed4:aa7a/64 scope link
valid_lft forever preferred_lft forever
57: veth714e7ab@if56: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether 1e:c2:a5:02:f6:ee brd ff:ff:ff:ff:ff:ff link-netnsid 3
inet6 fe80::1cc2:a5ff:fe02:f6ee/64 scope link
valid_lft forever preferred_lft forever
1 ответ
У меня нет информации о готовящихся решениях, но я подозреваю, что любой обходной путь будет включать предотвращение подключения экземпляра к себе и вместо этого всегда подключение к другому экземпляру... или, возможно, использование исходного адреса балансировщика для закрепленных подключений вместо исходного адреса.
Основная проблема заключается в следующем: балансировщик работает путем интеграции с сетевой инфраструктурой и выполнения преобразования сетевых адресов, изменения исходного целевого адреса на выходе и исходного адреса на обратном пути, чтобы экземпляр в целевой группе видит реальный адрес источника на стороне клиента, но не наоборот... но это не совместимо с асимметричной маршрутизацией. Когда экземпляр в конечном итоге говорит сам с собой, маршрут становится довольно асимметричным.
Предположим, балансировщиком является 172.30.1.100, а экземпляром - 172.30.2.200.
Соединение TCP инициируется с 172.30.2.200 (экземпляр) до 172.30.1.100 (балансировщик). Порты не очень важны, но давайте предположим, что исходный порт - 49152 (эфемерный), целевой порт балансировщика - 80, а целевой порт экземпляра - 8080.
172.30.2.200:49152 > 172.30.1.100:80 SYN
NLB является устройством NAT, так что это переводится:
172.30.2.200:49152 > 172.30.2.200:8080 SYN
Это отправляется обратно в экземпляр.
Это уже не имеет смысла, потому что экземпляр только что получил входящий запрос от себя, от чего-то внешнего, даже если он не сделал этот запрос.
Предполагая, что он отвечает, а не отбрасывает то, что уже является бессмысленным пакетом, теперь у вас есть это:
172.30.2.200:8080 > 172.30.2.200:49152 SYN+ACK
Если бы 172.30.2.200:49152 действительно отправил пакет на 172.20.2.200:8080, он ответил бы ACK, и соединение было бы установлено.
Но это не так.
Следующее, что происходит, должно быть примерно так:
172.30.2.200:49152 > 172.30.2.200:8080 RST
Между тем 172.30.2.200:49152 ничего не слышал от 172.30.1.100:80, поэтому он попытается, а затем в конце концов сдастся: Connection timed out
,
Когда исходная и целевая машины различаются, NLB работает, потому что это не настоящая (виртуальная) машина, подобная тем, что предоставляются ELB/ALB, - это что-то, что делает сама сеть. Это единственно возможное объяснение, поскольку в противном случае эти пакеты с переведенными адресами возвращаются на исходный компьютер с NAT, происходящим в обратном направлении, и это может произойти только в том случае, если сеть VPC хранит таблицы состояний этих соединений и транслирует их.
Обратите внимание, что в VPC шлюз по умолчанию не является реальным. На самом деле, подсети не реальны. Сеть Ethernet не настоящая. (И все это не критика. Здесь есть какие-то совершенно блестящие разработки.) Все это эмулируется программным обеспечением в сетевой инфраструктуре VPC. Когда две машины в одной подсети общаются друг с другом напрямую... ну, они этого не делают. Они разговаривают по программно-определенной сети. Таким образом, сеть может видеть эти пакеты и выполнять перевод, требуемый NLB, даже когда машины находятся в одной подсети.
Но не тогда, когда машина разговаривает сама с собой, потому что когда это происходит, трафик никогда не появляется на проводе - он остается внутри одной виртуальной машины вне зоны действия сетевой инфраструктуры VPC.
Я не верю, что возможен обходной путь на основе экземпляра.
¹ они не. Очень интересной иллюстрацией этого является мониторинг трафика в двух экземплярах в одной подсети с помощью Wireshark. Откройте группы безопасности, затем пропингуйте один экземпляр из другого. Исходный компьютер отправляет запрос ARP и, кажется, получает ответ ARP от цели... но нет никаких доказательств этого взаимодействия ARP с целью. Это потому, что этого не происходит. Сеть обрабатывает ответ ARP для целевого экземпляра. Это одна из причин, по которой невозможно подделать один экземпляр от другого - поддельные пакеты не пересылаются сетью, поскольку они явно недопустимы, и сеть это знает. После этого происходит ARP, пинг нормальный. Трафик, кажется, идет напрямую от экземпляра к экземпляру, основываясь на заголовках уровня 2, но это не то, что на самом деле происходит.