Pull to refresh

Ubuntu, KVM и proxy_arp — как обмануть злого провайдера

Reading time 3 min
Views 8.1K
Одна фирма расположила на колокейшне серверочек для внутренних нужд и сразу купила /30 адреса для соих потребностей. Сконфигурено это было как алиасы (eth0:0, eth0:1 и т.п.). Все работало великолепно, пока по прошествии некоторого времени появилась здравая идея разнести разные сервисы на разные виртуальные машины. Поскольку в качестве хоста использовался Ubuntu Server, то выбор KVM в качестве виртуализатора произошел сам собой. И здесь, и в остальном нете уже немало умных слов было написано по установку и настройку KVM и сетевого окружения, не буду на этом останавливаться, расскажу лишь про маленькие детские грабельки, удобно подложенные со стороны провайдера.
Прежде всего надо отметить, что все происходило на живой активно используемой технологической машине, где перерывы в предоставлении сервиса были нежелательны, потому все переконфигурации производились по ночам с соответствующим состоянием мозгов;)
Итак, оставив eth0 нетронутым (дабы не прерывались важные производственные сервисы), гасим все алиасы, создаем бридж br0, втыкаем в него eth0 и запускаем виртуальные машины, точно так же, как во всех KVM-букварях написано, втыкая tapX в тот же бридж.
Вуаля — айпишники видны, машины друг друга пингают, время открывать шампань, когда обнаруживается, что из инета доступен только хост. Опуская тонкости поисков проблемы, сразу перехожу к сути — у провайдера, где стоял на колокейшне сервер, свич сконфигурирован с port security, т.е. выпускал наружу только прибитый гвоздями при установке MAC. Пропускать маки виртуальных машин провайдер отказался, за что я его не виню, и это его право устанавливать внутреннюю техническую политику. В ответ на растеряный вопрос: «А как же нам быть?» был дан ответ опять-таки из KVM-букваря: оставляйте на интерфейсе алиасы, на виртуалках указать десятую сетку и дальше «iptables -j DNAT bla-bla-bla»
Погрустив слегка по поводу некоторой корявости подобного решения и вдумчиво покурив гугль, был найден альтернативный вариант с ключевым словом proxy_arp.
Перво-наперво делаем apt-get install uml-utilities
В /etc/network/interfaces прописываем:
auto eth0
iface eth0 inet static
address 1.2.3.1
netmask 255.255.255.0
network 1.2.3.0
broadcast 1.2.3.255
gateway 1.2.3.254
post-up sysctl -w net.ipv4.ip_forward=1
post-up sysctl -w net.ipv4.conf.eth0.proxy_arp=1
pre-down sysctl -w net.ipv4.ip_forward=0

auto qtap1
iface qtap1 inet manual
tunctl_user root
uml_proxy_arp 1.2.3.2
uml_proxy_ether eth0
up ip link set qtap1 up
down ip link set qtap1 down

auto qtap2
iface qtap2 inet manual
tunctl_user root
uml_proxy_arp 1.2.3.3
uml_proxy_ether eth0
up ip link set qtap2 up
down ip link set qtap2 down

Стартуем виртуальные машины:

kvm -m 512 -hda image.img -net nic,macaddr=00:01:02:03:04:05 -net tap,ifname=qtap1,macaddr=00:01:02:03:04:05,script=no -daemonize -vnc :1 и т.д.

Далее в виртуальных машинах в качестве gw прописываем адрес хоста 1.2.3.1 и получаем работающую гроздь виртуалок, заныкавшуюся от провайдера за МАКом хост-машины.

Для тех, кто пока не относит себя к network guru, пару слов о proxy_arp и отличии его от bridge.

По-умолчанию, обычный мост просто передает пакеты с одного интерфейса на другой в неизменном виде. Он рассматривает только аппаратный адрес пакета, чтобы определить — в каком направлении нужно передать пакет. Это означает, что Linux может переправлять любой вид трафика, даже тот, который ему не известен, если пакеты имеют аппаратный адрес.

Псевдо-мост работает несколько иначе и скорее больше походит на скрытый маршрутизатор, чем на мост, но подобно мосту имеет некоторое влияние на архитектуру сети. Правда это не совсем мост, поскольку пакеты в действительности проходят через ядро и могут быть отфильтрованы, изменены, перенаправлены или направлены по другому маршруту.

Еще одно преимущество псевдо-моста состоит в том, что он не может передавать пакеты протоколов, которые «не понимает» — что предохраняет сеть от заполнения всяким «мусором».

В данной схеме когда провайдерский свич желает установить связь с виртуальной машиной, находящейся позади хоста, то он отсылает хосту пакет ARP-запроса, который, в переводе на человеческий язык, может звучать примерно так: «У кого установлен адрес 1.2.3.2? Сообщите по адресу 1.2.3.254». В ответ на запрос, 1.2.3.1 ответит коротким пакетом «Я здесь! Мой аппаратный адрес xx:xx:xx:xx:xx:xx».

Когда 1.2.3.254 получит ответ, он запомнит аппаратный адрес 1.2.3.2 и будет хранить его в кэше некоторое время.

При настройке proxy_arp мы указали интерфейсу eth0 на необходимость отвечать на ARP-запросы. Это вынудит роутер посылать пакеты мосту, который затем обработает их и передаст на соответствующую виртуальную машину.

Таким образом, всякий раз, когда провайдерский роутер по одну сторону моста запрашивает аппаратный адрес компьютера, находящегося по другую сторону, то на запрос отвечает мост, как бы говоря «передавай все через меня», вследствие чего весь трафик попадет на eth0 и будет передан в нужную виртуалку.

При подготовке статьи были использованы материалы «Linux Advanced Routing & Traffic Control HOWTO».
Tags:
Hubs:
+42
Comments 33
Comments Comments 33

Articles