Назад | Перейти на главную страницу

Гость KVM не может подключиться к себе после DNAT

Описание сети

Среда виртуального хостинга (KVM):

Гость:

Ubuntu 14.04.5 LTS \n \l
Linux ari 3.8.0-29-generic #42~precise1-Ubuntu SMP Wed Aug 14 15:31:16 UTC 2013 i686 i686 i686 GNU/Linux

Хост:

Ubuntu 14.04.3 LTS \n \l
Linux host 3.13.0-74-generic #118-Ubuntu SMP Thu Dec 17 22:52:10 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

Сеть:

          eth0 |----------| virbr63                    eth0 |----------|
---------------|   HOST   |---------------------------------|  ari     |
  11.22.33.44  |----------| 192.168.63.1       192.168.63.2 |----------|

На HOST есть правило iptables:

-I PREROUTING -p tcp -d 11.22.33.44 --dport 80 -j DNAT --to 192.168.63.2:8888

Скажем mydomain.com разрешается до 11.22.33.44. ari обслуживает все HTTP-запросы, поступающие на 11.22.33.44. Вьющийся mydomain.com работает из любого места в Интернете.

Проблема

Когда я пытаюсь получить доступ mydomain.com через HTTP от ari, не работает (зависает curl).

Вот как выглядит неудачная попытка завивки в tcpdump (на хосте):

host$ sudo tcpdump -i virbr63 port 8888
22:03:15.541155 IP 192.168.63.2.42740 > 192.168.63.2.8888: Flags [S], seq 786111635, win 14600, options [mss1460,sackOK,TS val 1662005624 ecr 0,nop,wscale 5], length 0
22:03:15.541173 IP 192.168.63.2.42740 > 192.168.63.2.8888: Flags [S], seq 786111635, win 14600, options [mss1460,sackOK,TS val 1662005624 ecr 0,nop,wscale 5], length 0

Это повторяется каждые несколько секунд.

Вот как выглядит успешная попытка завивки (извне) в tcpdump (на хосте):

host$ sudo tcpdump -i virbr63 port 8888
21:59:10.924031 IP external.xxx.47812 > 192.168.63.2.8888: Flags [S], seq 2881442181, win 29200, options [mss 1420,sackOK,TS val 4022859071 ecr 0,nop,wscale 7], length 0
21:59:10.924339 IP 192.168.63.2.8888 > external.xxx.47812: Flags [S.], seq 1044842547, ack 2881442182, win 14480, options [mss 1460,sackOK,TS val 1661944471 ecr 4022859071,nop,wscale 5], length 0
21:59:10.968371 IP external.xxx.47812 > 192.168.63.2.8888: Flags [.], ack 1, win 229, options [nop,nop,TS val 4022859117 ecr 1661944471], length 0
21:59:10.976415 IP external.xxx.47812 > 192.168.63.2.8888: Flags [P.], seq 1:72, ack 1, win 229, options [nop,nop,TS val 4022859117 ecr 1661944471], length 71
21:59:10.976683 IP 192.168.63.2.8888 > external.xxx.47812: Flags [.], ack 72, win 453, options [nop,nop,TS val 1661944484 ecr 4022859117], length 0
21:59:10.977985 IP 192.168.63.2.8888 > external.xxx.47812: Flags [P.], seq 1:909, ack 72, win 453, options [nop,nop,TS val 1661944484 ecr 4022859117], length 908
21:59:11.025271 IP external.xxx.47812 > 192.168.63.2.8888: Flags [.], ack 909, win 243, options [nop,nop,TS val 4022859175 ecr 1661944484], length 0
21:59:11.030033 IP external.xxx.47812 > 192.168.63.2.8888: Flags [F.], seq 72, ack 909, win 243, options [nop,nop,TS val 4022859175 ecr 1661944484], length 0
21:59:11.030375 IP 192.168.63.2.8888 > external.xxx.47812: Flags [F.], seq 909, ack 73, win 453, options [nop,nop,TS val 1661944497 ecr 4022859175], length 0
21:59:11.075205 IP external.xxx.47812 > 192.168.63.2.8888: Flags [.], ack 910, win 243, options [nop,nop,TS val 4022859223 ecr 1661944497], length 0

Это настройка мониторинга, поэтому я ищу решение с минимальными изменениями на host насколько возможно. Желательно без изменений на хосте, просто убедительно ari (гость) для приема пакетов и маршрутизации ответов по сети.

Нерешения

Что не решает мою проблему

Доступ ari: 8888 напрямую

Это не помогает, потому что это настройка мониторинга, и вся ее цель - проверить, работает ли 11.22.33.44:80.

Доступ с другого гостя (виртуальной машины)

Он работает (также из той же сети, 192.168.63.0/24), но это не решает проблемы.

Что я пробовал, но не работает

Похожие вопросы

Я рассмотрел следующие вопросы и ответы:

DNAT от localhost (127.0.0.1)

Гость KVM не может подключиться к хосту, но работает наоборот

accept_local

ari$ sudo sysctl -w net.ipv4.conf.eth0.accept_local=1

Это не решает проблему, не меняет вывод tcpdump.

route_localnet

ari$ sudo sysctl -w net.ipv4.conf.eth0.route_localnet=1

Это не решает проблему, не меняет вывод tcpdump.

rp_filter

ari$ sudo sysctl -w net.ipv4.conf.eth0.rp_filter=0

Это не решает проблему, не меняет вывод tcpdump.

Второй (виртуальный) сетевой интерфейс включен ari

Я пробовал добавить второй сетевой интерфейс eth0:1 с IP-адресом 192.168.63.200. Доступ 192.168.63.2:8888 из 192.168.63.200 не работает точно так же:

17:42:08.746328 IP 192.168.63.200.41676 > 192.168.63.2.8888: Flags [S], seq 3211292625, win 14600, options [mss 1460,sackOK,TS val 1744488483 ecr 0,nop,wscale 5], length 0
17:42:08.746351 IP 192.168.63.200.41676 > 192.168.63.2.8888: Flags [S], seq 3211292625, win 14600, options [mss 1460,sackOK,TS val 1744488483 ecr 0,nop,wscale 5], length 0

РЕДАКТИРОВАТЬ: аналогичное решение

После ответа Купсона я нашел здесь очень похожее решение:

http://idallen.com/dnat.txt (ищите «Много клиентов - слишком много SNAT»). Оно имеет:

iptables -t nat -A POSTROUTING -s 172.16.0.0/24 -d 172.16.0.0/24 -m conntrack --ctstate DNAT  -j SNAT --to 172.16.0.254

Одно из возможных решений - использовать SNAT на ХОСТЕ, чтобы изменить исходный адрес пакетов и перенаправить их обратно на виртуальную машину "ari". Это не самое производительное решение, но оно простое и достаточно хорошее для многих настроек.

# fixup chain
iptables -t nat -N fixup-snat
iptables -t nat -A fixup-snat -m conntrack --ctstate DNAT -j MASQUERADE

# please select proper network ranges and NIC names below
iptables -t nat -I POSTROUTING -s 192.168.63.0/24 -d 192.168.63.0/24 -o virbr63 -j fixup-snat

Вы можете объединить это в один iptables Правило, для ясности предпочитаю отдельную цепочку.

Вы также должны отключить обработку пакетов iptables на интерфейсе моста:

sysctl -w net.bridge.bridge-nf-call-arptables=0
sysctl -w net.bridge.bridge-nf-call-ip6tables=0
sysctl -w net.bridge.bridge-nf-call-iptables=0

Чтобы они выжили после перезагрузки в системах Debian, отредактируйте /etc/sysctl.conf файл или создать новый файл в /etc/sysctl.d/ каталог.