Примеры применения Linux network namespaces (netns)

В ядре Linux(начиная с версии 2.6.29) имеется весьма интересный и полезный функционал network namespaces(netns), однако про его существование, чаще всего, либо не знают, либо не понимают что с ним можно делать. В этой заметке рассматривается несколько примеров применения этого функционала:

  • Мониторинг L3VPN с пересекающимися адресными пространствами средствами zabbix и zabbix-proxy
  • Автоматизированное тестирование сетевого ПО(dhcp, pppoe-сервера и т.п.)
  • Предоставление услуги L3VPN с дополнительными сервисами(NAT, DHCP и другими) и виртуализация абонентской CPE как частный случай решения этой задачи
  • Изоляция управления сервером от остальных сервисов

Функционал похож на Cisco VRF, но ещё больше напоминает Juniper logical-system. Кроме того, описываемые задачи можно решать с помощью создания множества обычных виртуальных машин или контейнеров OpenVZ. Традиционная виртуализация не очень удобна для “чисто сетевых” задач “изоляции” и так или иначе, имеет накладные расходы(в том числе на обслуживание). OpenVZ почти всем хорош, кроме того, что не закоммичен в апстрим и как следствие ограничивает вас в выборе ядра, привязывает к себе(тянет себя как зависимость).
Для написания этой заметки использовался дистрибутив Ubuntu 12.04.2 LTS, однако почти всё применимо и для большинства других современных дистрибутивов. Прежде чем пытаться что-то сделать, нужно проверить наличие netns в ядре и поддержку сетевых пространств в userspace-утилите ip, которая используется для конфигурирования:

# cat /boot/config-`uname -r` | grep CONFIG_NET_NS
CONFIG_NET_NS=y

# ip netns help
Usage: ip netns list
       ip netns add NAME
       ip netns delete NAME
       ip netns exec NAME cmd ...
       ip netns monitor

Каждый netns это свои интерфейсы, таблицы маршрутизации, свой фаервол и собственные сокеты, изолированные от других netns. Для простоты изложения, первым примером будет демонстрация как netns можно использовать для автоматизированного тестирования сетевого ПО(создающее интерфейсы, маршруты и т.п.) на примере pppoe-сервера accel-pppd. Схема тестирования: схема тестирования сетевого ПО

В первую очередь, создаём 2 netns и 2 виртуальных ethernet интерфейса(привязанные к разным netns) и связываем их между собой линком:

#Создание 2ух netns:
ip netns add Server ; ip netns add Client

#Создание 2ух veth-интерфейса и линка между ними
ip link add veth0-C type veth peer name veth0-S

#Привязка интерфейсов к своим netns:
ip link set veth0-C netns Client
ip link set veth0-S netns Server

#Поднятие интерфейсов(ifconfig выполняется уже в разных netns):
ip netns exec Client ifconfig veth0-C up
ip netns exec Server ifconfig veth0-S up

Таким образом, получили L2-связность между двумя netns, при этом оба netns изолированы от глобального. Далее запускаем сервер и клиент, каждый в своём сетевом пространстве:

ip netns exec Server /etc/init.d/accel-ppp start
ip netns exec Client pppd call test1

Конфигурация /etc/accel-ppp.conf (авторизовываться можно с любым логином/паролем). Конфигурацию клиента(/etc/ppp/peers/test1 ) можно сгенерировать командой “ip netns exec Client pppoeconf”.

Результат:

# ip netns exec Client ip route show
default dev ppp0  scope link 
192.0.2.1 dev ppp0  proto kernel  scope link  src 192.0.2.2 

# ip netns exec Server ip route show
192.0.2.2 dev ppp0  proto kernel  scope link  src 192.0.2.1 

# ip netns exec Client ping 192.0.2.1 -c 1
PING 192.0.2.1 (192.0.2.1) 56(84) bytes of data.
64 bytes from 192.0.2.1: icmp_req=1 ttl=64 time=0.155 ms
...

Как видно, pppoe-сессия установлена, созданные интерфейсы и маршруты никому не мешают, т.к. не попали в namespace по умолчанию. Аналогичным образом можно тестировать dhcp/l2tp/openvpn/прочие сервисы в пределах одного хоста, что в свою очередь позволяет легко автоматизировать процесс тестирования, потому что нет никаких препятствий, чтобы написать скрипт, создающий netns-ы, интерфейсы и запускающий в них процессы(сервер и клиент(ы)). Для проведения тестов не нужно привязываться к стороннему ПО типа openvz или vmware и писать сложные скрипты, чтобы ими управлять.

Вторым примером будет использование netns и zabbix+zabbix proxy для мониторинга нескольких vrf/l2vpn с пересекающимися адресными пространствами.

Схема мониторинга нескольких vrf
Через eth0.10 и eth0.20 осуществляется выход в клиентские vrf, через veth-интерфейсы реализуется связность между глобальным netns(в котором запущен zabbix-server) и процессами zabbix-proxy. Через интерфейс eth0(или eth1) организовано управлением сервером.

#Создание 2ух netns
ip netns add vrf1; ip netns add vrf2

#Создание 2ух dot1Q сабынтерфейсов
vconfig add eth0 10; vconfig add eth0 20

#Привязка сабынтерфейсов к своим netns
ip link set eth0.10 netns vrf1
ip link set eth0.20 netns vrf2

#Назначение IP-адреса и указание шлюза для доступа в клиентские vpn
ip netns exec vrf1 ifconfig eth0.10 192.0.2.2/30 up
ip netns exec vrf2 ifconfig eth0.20 192.0.2.2/30 up
ip netns exec vrf2 ip route add default via 192.0.2.1
ip netns exec vrf1 ip route add default via 192.0.2.1

#Связность между vrf1 и глобальным netns
ip link add veth1-P type veth peer name veth1-S; ip link set veth1-P netns vrf1
ifconfig veth1-S add 2001:DB8::1/126 up
ip netns exec vrf1 ifconfig veth1-P add 2001:DB8::2/126

#Связность между vrf2 и глобальным netns
ip link add veth2-P type veth peer name veth2-S; ip link set veth2-P netns vrf1
ifconfig veth2-S add 2001:DB8::5/126 up
ip netns exec vrf1 ifconfig veth2-P add 2001:DB8::6/126

#Запуск zabbix-ов
/etc/init.d/zabbix-server start
ip netns exec vrf1 zabbix_proxy1_start
ip netns exec vrf2 zabbix_proxy2_start

Очевидно, что адресация на veth-линках не должна пересекаться, в примере используются ipv6-адреса (чтобы не согласовывать эти адреса со всеми клиентами и не использовать реальные IPv4-адреса). Адреса на “внешних” интерфейсах eth0.10 и eth0.20 нужно согласовывать с клиентами, но они могут пересекаться, проще говоря, нужно всего лишь попросить клиента выделить любую /30 из его адресного плана (или сделать это самостоятельно, если это ваш технологический vpn).

Настройка самого zabbix выходит за рамки этой заметки, но принципиальных отличий от схемы с множеством хостов нет (за исключением того, что на одном сервере будет несколько конфигураций и скриптов запуска zabbix-proxy)

Далее пойдёт речь об организации L3VPN с дополнительными сервисами(DHCP-сервер и интернет через NAT)
Схема организации L3VPN с помощью netns

В сетевом пространстве Client1 интерфейс eth0.10 используется для выхода в интернет, интерфейсы eth0.11-eth0.19 смотрят в точки подключения клиента(на каждую точку подключения выделяется свой vlan). Выделение реальных адресов осуществляется по схеме ip unnumbered. В данном примере это реализуется на маршрутизаторе ASBR. Как настроить ip unnumbered со статическим распределением адресов на Cisco или Linux можно без проблем найти на просторах интернета. Если же роль ASBR-а выполняет сам сервер(на котором реализуются абонентские vpn), то тогда роль интерфейсов eth0.10 и eth0.20 будут играть veth-интерфейсы(между netns клиента и глобальным netns), а ip unnumbered будет реализован на этом же хосте в сетевом пространстве по умолчанию.

Включение маршрутизации и NAT осуществляется следующим образом:

ip netns exec Client1 sysctl net.ipv4.ip_forward=1
ip netns exec Client1 iptables -t nat -I POSTROUTING -o eth0.10 -j SNAT --to-source 192.0.2.2
ip netns exec Client2 sysctl net.ipv4.ip_forward=1
ip netns exec Client2 iptables -t nat -I POSTROUTING -o eth0.20 -j SNAT --to-source 192.0.2.3

Остальные необходимые действия(создание netns и назначение адресов) рассматривались в первых двух примерах. При необходимости можно предоставлять клиентам DHCP-сервис, для этого нужно запустить dhcpd в соответствующем netns. Если клиент хочет bgp в своём vpn, то можно запустить quagga/bird в его netns.
Нетрудно догадаться, что в случае, когда клиенсткая точка одна, то решение этой задачи будет представлять ни что иное как виртуализация абонентской CPE(или как сейчас модно говорить, облачная CPE). Такой вариант может быть интересен для предоставление сервиса высокодоходным клиентам, для массового же сервиса не имеет смысла выделять netns под каждого клиента, а просто выделять клиентам различные серые сети(из диапазона RFC6598) в одном сетевом пространстве.

Заключительным примером использования будет перенос управления сервером в неглобальный netns.

/etc/init.d/ssh stop
ip netns exec MGMT /usr/sbin/sshd -D

Теперь, подключившись по ssh к этому серверу вы окажитесь в сетевом пространстве MGMT(выполнив ifconfig будут отображаться интерфейсы, относящиеся только к netns MGMT). Можно “перейти” в любой другой netns таким образом: “ip netns exec Other-ns bash”, но не в глобальный. Чтобы выбраться в глобальный netns придётся скомпилировать утилиту ns_exec из документации к функции setns(man setns)(копия исходника ns_exec.c)

gcc ns_exec.c -o ns_exec
#Использование ns_exec:
./ns_exec /proc/1/ns/net bash

(где 1 – номер процесса init)

P.S. При создании нового netns, в нём не поднят интерфейс-петля(lo), будьте внимательны. Из-за этого не работает ping локальных IP-адресов(назначенных на интерфейсах) из самого netns. Чтобы поднять loopback, нужно выполнить “ip netns exec NS ifconfig lo 127.0.0.1 up”

Advertisements

5 thoughts on “Примеры применения Linux network namespaces (netns)

  1. Pingback: Burst vs буфер коммутации | Net-Labs.in

  2. Pingback: VRF (L3VPN) в Mikrotik RouterOS: defective by design | Net-Labs.in

  3. Pingback: Linux Network Namespaces: Examples of Usage | Net-Labs.in

  4. Pingback: Маршрутизация multicast в Linux (IGMPv3 и IGMPv2) | Net-Labs.in

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s