Содержание

Плавающие IP-адреса для организации сети в публичных и частных облаках OpenStack / Хабр

Автор: Piotr Siwczak

Недавно я описал, как работает VlanManager и как он обеспечивает масштабируемость сети и изолированность пользователей. Но до настоящего момента я говорил только о сетях с фиксированным IP-адресом, принадлежащих различным пользователям. И хотя по умолчанию экземплярам выделяются фиксированные IP-адреса, они не гарантируют немедленной доступности экземпляров из-за пределов сети (или из других ЦОД). Представьте себе следующий сценарий:

Вы запускаете небольшой веб-сайт с одним www-сервером, сервером базы данных, и брандмауэром, который выполняет трансляцию сетевых адресов (NAT) и фильтрацию трафика. Обычно вы применяете следующие настройки:
-Все серверы общаются внутри сети в рамках частного (немаршрутизируемого) сетевого диапазона (например, 192.168.0.0/24).
-Есть один публичный маршрутизируемый IP-диапазон, на котором виден www-сервер.

Вы делаете следующее:

-Присваиваете брандмауэру публичный IP-адрес.
-Создаете правило NAT на брандмауэре для маршрутизации трафика с публичного IP-адреса на частный IP-адрес www-сервера.

Фиксированные IP-адреса в OpenStack работают так же, как и сетевой диапазон 192.168.0.0/24 в примере выше. Они гарантируют только взаимодействие между экземплярами внутри одного кластера OpenStack. Но OpenStack также вводит другой пул IP-адресов под названием “плавающие IP-адреса”. Плавающие IP-адреса — это публично маршрутизируемые IP-адреса, которые вы покупаете у провайдера интернет-услуг (того, который помещается в указанный выше брандмауэр). Пользователи могут назначать IP-адреса своим экземплярам, делая их доступными из внешней сети.

Различия между плавающими и фиксированными IP-адресами

Плавающие IP-адреса не назначаются виртуальным машинам по умолчанию. Пользователи облака должны явным образом “взять” их из пула, настроенного администратором OpenStack, а затем назначить их своим виртуальным машинам. Как только пользователь забрал плавающий IP-адрес из пула, он становится его “владельцем” (то есть в любой момент он может открепить IP-адрес от виртуальной машины и прикрепить его к другой). Если виртуальная машина по каким-то причинам прекращает существование, пользователь не теряет плавающий IP-адрес — он может его затем назначить другому экземпляру. К сожалению, сейчас невозможно совместно использовать один плавающий IP-адрес несколькими виртуальными машинами для балансировки нагрузки, как например с эластичной балансировкой нагрузки на Amazon EC2.

С другой стороны фиксированные IP-адреса назначаются динамически компонентом nova-network при загрузке ВМ. Нет возможности приказать OpenStack назначить конкретный фиксированный IP-адрес виртуальной машине. Таким образом, вы можете оказаться в ситуации, когда при случайном завершении работы виртуальной машины после её восстановления из снимка новый экземпляр загружается с новым фиксированным IP-адресом.

Системные администраторы могут настраивать несколько пулов плавающих IP-адресов.

Тем не менее, в отличие от пулов фиксированных IP-адресов, пулы плавающих IP-адресов нельзя соотнести с конкретными пользователями. Каждый пользователь может “взять” плавающий IP-адрес из любого пула плавающих IP-адресов. Но основная мотивация для создания нескольких пулов плавающих IP-адресов в том, чтобы каждый пул обслуживал свой поставщик доступа в интернет. Таким образом, мы можем гарантировать возможность подключения, даже при сбое у одного из поставщиков.

В итоге основные функции плавающих IP-адресов следующие:
-Плавающие IP-адреса не назначаются виртуальным машинам автоматически по умолчанию (их необходимо назначать инстансам вручную).
-Если виртуальная машина прекращает свое существование, пользователь может повторно использовать плавающий IP-адрес, назначив его другому инстансу.

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

Плавающие IP-адреса—внутренние или внешние облака

“Публичная доступность” плавающего IP-адреса – это относительное понятие. Для публичных облаков вы, возможно, захотите определить пул плавающих IP-адресов как пул IP-адресов, публично доступных из интернета. Затем ваши клиенты смогу назначать их виртуальным машинам, чтобы заходить в них через SSH со своих домашних или рабочих компьютеров:

Если в вашем ЦОД запущено корпоративное облако, то пул плавающих IP-адресов может быть любым диапазоном IP-адресов, который предоставляет доступ к инстансам OpenStack из остального ЦОД.

Для трафика своего ЦОД вы можете определить следующий диапазон: 10.0.0.0/16.

Внутри OpenStack вы можете создать следующий диапазон фиксированных IP-адресов: 192.168.0.0/16, разбитый на подсети пользователей.
Чтобы сделать экземпляры OpenStack доступными из всего ЦОД вы можете определить пул плавающих IP-адресов как подсеть 10.0.0.0/8, (например, 10. 0.0.0/16) и зарегистрировать её в OpenStack, чтобы пользователи могли брать оттуда IP-адреса.

Работа с плавающими IP-адресами

Как я упомянул ранее, сначала системный администратор регистрирует пул плавающих IP-адресов в OpenStack:
nova-manage floating create --ip_range=PUBLICLY_ROUTABLE_IP_RANGE --pool POOL_NAME

Таким образом, публичный пул становится доступным пользователям.

Теперь пользователи следуют данной процедуре:
-Загрузить экземпляр:

+—————————————+———+———+———————————+
| ID | Name | Status | Networks |
+—————————————+———+———+———————————+
| 79935433-241a-4268-8aea-5570d74fcf42 | inst1 | ACTIVE | private=10.0.0.4 |

+—————————————+———+———+———————————+

-Перечислить доступные пулы плавающих IP-адресов:

nova floating-ip-pool-list

+——+
| name |
+——+
| pub |
| test |
+——+

-Взять плавающий IP-адрес из пула “pub” (или при желании из пула “test”):

nova floating-ip-create pub

+—————+————-+———-+——+
| Ip | Instance Id | Fixed Ip | Pool |
+—————+————-+———-+——+
| 172. 24.4.225 | None | None | pub |

+—————+————-+———-+——+

-Назначить плавающий IP-адрес экземпляру:

nova add-floating-ip 79935433-241a-4268-8aea-5570d74fcf42 172.24.4.225

(где первый аргумент — это uuid экземпляра, а второй – сам плавающий IP-адрес)

-Проверить правильность всех настроек:

nova floating-ip-list

+—————+—————————————+———-+——+
| Ip | Instance Id | Fixed Ip | Pool |
+—————+—————————————+———-+——+
| 172.24.4.225 | 79935433-241a-4268-8aea-5570d74fcf42 | 10.0.0.4 | pub |
+—————+—————————————+———-+——+

Теперь экземпляр должен быть виден из-за пределов кластера OpenStack по плавающему IP-адресу.

Как работают плавающие IP-адреса

Что происходит внутри экземпляра после добавления плавающего IP-адреса? Правильный ответ – ничего. Если вы подключитесь к нему по SSH и посмотрите конфигурацию сети, вы увидите, что существует один интерфейс сети с настроенным фиксированным IP-адресом.

Вся настройка выполняется на вычислительном узле. Вся работа, связанная с плавающим IP-адресом, выполняется сервисом nova-network: организуется транслятор сетевых адресов (NAT) между фиксированным и плавающим IP-адресами экземпляра. Объяснение, как работает NAT, можно найти тут.

Взгляните на следующую диаграмму:

Схема отображает один вычислительный узел, настроенный в режиме сети c распределением узлов и VlanManager, используемый для настраивания фиксированных IP-сетей. Вычислительный узел оснащен двумя сетевыми интерфейсами: интерфейс eth0 выделен для трафика с фиксированным IP/VLAN, а eth2 – это интерфейс, по которому вычислительный узел подключается к внешней сети; в нем располагаются плавающие IP-адреса. (Информацию о том, как VlanManager настраивает фиксированные IP-сети см. в предыдущей статье)

Примите во внимание, что в то время как на интерфейсе eth0 (фиксированном/частном) не настроен адрес, интерфейсу eth2 назначен IP-адрес, который является шлюзом по умолчанию для вычислительного узла (91.

207.15.105).

Когда пользователь назначает плавающий IP-адрес (91.207.16.144) инстансу VM_1, происходят две вещи:
-Плавающий IP-адрес настроен как вторичный адрес на интерфейсе eth2: это на выходе команды “ip addr show eth2″, содержащей следующие действия:
inet 91.207.15.105/24 scope global eth2 # primary eth2 ip
inet 91.207.16.144/32 scope global eth2 # floating ip of VM_1

-Набор правил NAT для плавающего IP-адреса настраивается в таблицах iptables. Ниже приведены все соответствующие записи из таблицы «nat» вычислительного узла (за исключением команды “iptables –S -t nat». Подробно о том, как настроить NAT с помощью таблиц iptables в Linux можно посмотреть здесь):

# this rule ensures that packets originating from compute node
# where the instance resides, will reach the instance via its floating IP:
-A nova-network-OUTPUT -d 91.207.16.144/32 -j DNAT —to-destination 10.0.0.3

# ensures that all external traffic to the floating IP
# is directed to the fixed IP of the instance
-A nova-network-PREROUTING -d 91. 207.16.144/32 -j DNAT —to-destination 10.0.0.3

# all the traffic originating from the instance will be SNAT-ted to its floating IP
-A nova-network-float-snat -s 10.0.0.3/32 -j SNAT —to-source 91.207.16.144

В общем, nova-network добавляет дополнительные цепочки к тем, которые предварительно определены в таблице NAT. Порядок цепочек по отношению к трафику по плавающему IP-адресу показан ниже (с использованием правил, показанных выше):
Chain OUTPUT — Chain nova-network-OUTPUT — Rule: -d 91.207.16.144/32 -j DNAT —to-destination 10.0.0.3

Chain PREROUTING — Chain nova-network-PREROUTING — Rule: -d 91.207.16.144/32 -j DNAT —to-destination 10.0.0.3

Chain POSTROUTING — Chain nova-postrouting-bottom — Chain nova-network-snat — Chain nova-network-float-snat — Rule: -s 10.0.0.3/32 -j SNAT —to-source 91.207.16.144

-Код, ответственный за задание правил, располагается в nova/network/linux_net.py в функции:
def floating_forward_rules(floating_ip, fixed_ip):

return [(‘PREROUTING’, ‘-d %s -j DNAT —to %s’ % (floating_ip, fixed_ip)),
(‘OUTPUT’, ‘-d %s -j DNAT —to %s’ % (floating_ip, fixed_ip)),
(‘float-snat’,
‘-s %s -j SNAT —to %s’ % (fixed_ip, floating_ip))]

Возвращаемся к диаграмме. Если пользователь хочет получить доступ к виртуальной машине по своему IP-адресу из внешней сети (например, “ping 91.20.16.144″):
-Трафик достигает публичного интерфейса (eth2) вычислительного узла. В nova-network-PREROUTING выполняется DNAT, меняющий IP-адрес назначения пакетов с 91.207.16.144 на 10.0.0.3.
-Вычислительный узел обращается к своей таблице маршрутизации и видит, что сеть 10.0.0.0 доступна на интерфейсе br100 (за исключением “ip route show” вычислительного узла):
10.0.0.0/24 dev br100

Таким он направляет пакет на интерфейс br100, затем пакет достигает виртуальной машины.

Если виртуальная машина отправляет пакет во внешний мир (например, “ping 8.8.8.8):
-Так как адрес назначения не находится в локальной сети виртуальной машины, пакеты отправляются на шлюз виртуальной машины по умолчанию с IP-адресом 10.0.0.1 (адрес устройства “br100″ на вычислительном узле).
-Вычислительный узел проверяет свои таблицы маршрутизации и обнаруживает, что в непосредственно подключенных сетях нет адреса 8. 8.8.8, поэтому он переадресует пакет на шлюз по умолчанию (который является первичным адресом eth2 — 91.207.15.105 в данном случае).
-Пакет попадает в цепочку POSTROUTING и передается цепочке “nova-network-float-snat”, где его исходный IP-адрес переписывается на плавающий IP-адрес (91.207.16.144).

Примечания о безопасности

При использовании OpenStack системные администраторы передают полный контроль за таблицами iptables сервисам nova. Набор настраиваемых правил очень сложен и с легкостью нарушается любым вмешательством извне. Более того, при каждом перезапуске демона nova-network он применяет все правила в цепочках таблиц iptables, связанных с OpenStack. Если есть необходимость каким-либо образом изменить поведение таблиц iptables, это можно сделать, изменив код в соответствующих местах linux_net.py (для правил NAT это будут floating_forward_rules).

Также стоит сказать, что nova-network не отслеживает свои таблицы каким-либо образом. Таким образом, если мы вручную удаляем какие-либо правила из цепочек, связанных с OpenStack, они не восстановятся при следующем запуске nova-network.

Таким образом, системный администратор может легко случайно открыть нежелательный доступ к вычислительному узлу. Помните, что nova-network поместил плавающий IP-адрес как вторичный на интерфейсе eth2 и настроил правила DNAT, которые направляют трафик на фиксированный IP-адрес виртуальной машины:
-A nova-network-PREROUTING -d 91.207.16.144/32 -j DNAT —to-destination 10.0.0.3

Таким образом, весь трафик, направленный на 91.207.16.144, попадает на адрес 10.0.0.3.

Теперь давайте представим, что системный администратор ночью решал проблемы подключения к сети и случайно удалил все правила NAT, напечатав:
iptables –F –t nat

Указанное выше правило NAT было удалено, но интерфейсу eth2 все ещё присвоен вторичный IP-адрес 91.207.16.144. Таким образом, мы всё ещё можем обратиться к адресу 91.207.16.144 извне, но вместо того, чтобы попасть на виртуальную машину, у нас теперь есть доступ к самому вычислительному узлу (IP-адрес назначения более не транслируется по правилу DNAT, так как мы удалили все правила NAT). Эта дыра в безопасности не будет закрыта до следующего перезапуска процесса nova-network, который заново создаст правила.

Настройка плавающих IP-адресов

В сервисе nova.conf существуют флаги, которые влияют на поведение плавающих IP-адресов:
# the interface to which floating ips are attached
# as secondary addresses
public_interface=«eth2»

# the pool from which floating IPs are taken by default
default_floating_pool=«pub»

# we can add a floating ip automatically to every instance that is spawned
auto_assign_floating_ip=false

Итоговые комментарии

Кроме предоставления доступа к виртуальным машинам напрямую из интернета, механизм плавающих IP-адресов дает пользователям облака некоторую гибкость. После “забора” плавающего IP-адреса они могут менять их принадлежность, то есть на ходу назначать их различным виртуальным машинам и переназначать их, что значительно облегчает выпуск нового кода и обновления системы. Для системных администраторов это представляет потенциальную угрозу безопасности, так как лежащий в основе механизм (iptables) работает очень сложно и не отслеживается OpenStack. Поэтому очень важно, чтобы только программное обеспечение OpenStack могло менять политики брандмауэра и чтобы они не менялись вручную.

Оригинал статьи на английском языке

Использование плавающих IP-адресов | 8HOST.COM