Мой блог - OpenVPN-сеть для LXD-кластера без назначения адресов клиентов (использование стороннего DHCP для управления клиентами VPN-сети)

OpenVPN-сеть для LXD-кластера без назначения адресов клиентов (использование стороннего DHCP для управления клиентами VPN-сети)

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

Фотография автора

Автор: Антон Черноусов
Опубликовано: 2 месяца, 3 недели (последние правки: 0 минут назад) - 0 комментариев
Категории записи: LXC/LXD, Networking, OpenVPN, Системное администрирование


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

Схема тестовой виртуальной сети

Конфигурация клиента и сервера OpenVPN

Конфигурация сервера:

port 39998
local 94.177.218.44
proto udp
dev tap-aruba-virt
ca ca.crt
cert aruba-virual-network.crt
key aruba-virual-network.key
dh dh2048.pem
script-security 2
up aruba-bridge-up.sh
mode server
client-to-client
tls-server
keepalive 10 120
comp-lzo
persist-key
persist-tun
crl-verify /etc/openvpn/crl.pem

Скрипт конфигурации моста сервера aruba-bridge-up.sh:

#!/bin/sh

ifconfig tap-aruba-virt up
brctl addif aruba-virtual tap-aruba-virt

exit 0

Конфигурация клиента:

client
proto udp
remote 94.177.218.44 39998
dev tap-aruba-virt
resolv-retry infinite
nobind
persist-key
persist-tun
ns-cert-type server
script-security 2
up aruba-bridge-up.sh
comp-lzo
verb 3

<ca>
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
</ca>
<cert>
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
</cert>
<key>
-----BEGIN PRIVATE KEY-----
...
-----END PRIVATE KEY-----
</key>

Скрипт конфигурации моста клиента aruba-bridge-up.sh:

#!/bin/sh

ifconfig tap-aruba-virt up
brctl addif aruba-virtual tap-aruba-virt

exit 0

Создание пустого (фиктивного) сетевого моста

Если открыт официальную страницу руководства Ubuntu Linux посвященную сетевым мостам (https://help.ubuntu.com/community/NetworkConnectionBridge), то все приведенные там примеры подразумевают создание сетевого моста содержащего хотябы один сетевой интерфейс на этапе их описания в файле /etc/network/interfaces, но как вы наверное поняли в нашем случае такой подход не подойдет и если описать сетевой мост для виртуальных машин содержащий наш виртуальный интерфейс, то это будет черевато рядом ошибок, так как на этапе создания сетевого моста виртуальный интерфейс еще не создан и добавить в мосте его нельзя, следовательно сетевая подсистема будет проинициализирована с ошибкой.

Фактически мне на самом деле требуется содать "фэйковый" сетевой мост без входящих в него интерфейсов и я могу сделать это просто одной командой в консоли:

# brctl addbr lxd-cluser-01

Не забудьте установить пакет управления сетевыми мостами:

# aptitude install bridge-utils

И честно говоря до недавнего времени я не знал как описать мост без входящих в него интерфейсов в штатной конфигурации /etc/network/interfaces и мне приходилось городить дополнительный огород сервисов, но после вдумчивого просмотра примеров я с удивлением увидел, что фейковый сетевой мост не только можно описать в конфигурационном файле, но и делается это элементарно и вместо имени интерфейса в параметр bridge_ports укзать none, а полностью конфигурация фиктивного сетевого моста выглядит следующим образом:

auto lxd-cluser-01
iface lxd-cluser-01 inet static
    bridge_ports none
    address 10.252.0.4
    netmask 255.255.255.0

Настройка сетевого интерфейса по умолчанию для контейнеров LXD

Для того, чтобы создаваемые контейнеры LXD автоматически подключались в режим моста к виртуальному сетевому интерфейсу lxd-cluser-01, достаточно выполнить простую команду:

# lxc network attach-profile lxd-cluser-01 default eth0

Однако, если сетевой интерфейс уже сконфигурирован в профиле по умолчанию, вы получите ошибку:

error: Device already exists: eth0

В этом случае просто удалите назначенный базовому профилю сетевой интерфейс:

# lxc profile device remove default eth0

Настройка центрального DHCP-сервера

Я придерживаюсь мнения, что всем адресам в сети должны по возможности назначаться адреса и именно назначаться средствами DHCP-сервера, а не прописываться в ручную на устройствах как статический IP-адрес. В том случае когда необходимо резервирование связки MAK-адрес -> IP-адрес это резервирование должно производиться на уровне DHCP-сервера, а устройства в которых невозможно назначение адресов средствами DHCP все равно должны быть описанны как зарезервированные.

Такой подход совместно с автоматической регистрацией устройств в локальном DNS, позволяет построить более управляемую сеть, чем сеть в которой адреса серверов и устройств заданы "квадратно-гнездовым методом" с блоками диапазонов-исключений.

В своей практике я использую классический DHCP-сервер "isc-dhcp-server", он входит практически во все Linux дистрибутивы и в Ubuntu linux, он устанавливается командой:

# apt-get install isc-dhcp-server

Перезапуск сервиса производится командой:

# systemctl restart isc-dhcp-server.service

Первым делом отредактируйте файл /etc/default/isc-dhcp-server и принудительно укажите сетевой интерфейс который будет обслуживать DHCP-сервер:

INTERFACES="lxd-network-virtual"

В простейшем виде конфигурация выглядит следующим образом (в файле /etc/dhcp/dhcpd.conf):

ddns-update-style none;
option domain-name "local.mypirates.ru";
option domain-name-servers 10.252.0.1;
default-lease-time 3600;
max-lease-time 36000;
log-facility local7;

subnet 10.252.0.0 netmask 255.255.255.0 {
    range 10.252.0.2 10.252.0.200;
    option routers 10.252.0.1;
}

include "/etc/dhcp/reserved_ips.conf";

Как вы видите в последней строке я вынес конфигурацию зарезервированных адресов в отдельный файл /etc/dhcp/reserved_ips.conf, такой подход неплохо себя зарекомендовал и этот файл содержит только описания конфигураций контейнеров (да и всего что работает с виртуальным мостом и получает адреса):

host eltex-test-network {
    hardware ethernet a8:f9:4b:10:40:11;
    fixed-address 10.252.0.2;
}

host gita-banan {
    hardware ethernet 02:8e:07:c1:62:aa;
    fixed-address 10.252.0.3;
}

host US-LXD-01-AMAZON {
    hardware ethernet e2:ee:39:e7:08:ca;
    fixed-address 10.252.0.4;
}

Настройка доступа в интернет для контейнеров узла виртуализации LXD

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

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

#!/bin/sh

IPT="/sbin/iptables"
INET_INTERFACE="eth0"
VPN_INTERFACE="eth0"

# Clean all tables
# Set default rules
$IPT -F
$IPT -X
$IPT -t nat -F
$IPT -t nat -X
$IPT -t mangle -F
$IPT -t mangle -X

# All Drop by Design
$IPT -P OUTPUT ACCEPT
$IPT -P INPUT DROP
$IPT -P FORWARD DROP

# Allow localnetwork
$IPT -A INPUT -i lo -j ACCEPT
$IPT -A FORWARD -o lo -j ACCEPT

# Curent connections
$IPT -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# Enable SSH from External Interface
$IPT -A INPUT -i $INET_INTERFACE  -p tcp --dport 22 -j ACCEPT

# Allow all from VPN network
$IPT -A INPUT -i $VPN_INTERFACE -j ACCEPT

# Nginx for web sites
$IPT -A INPUT -i $INET_INTERFACE  -p tcp --dport 80 -j ACCEPT
$IPT -A INPUT -i $INET_INTERFACE  -p tcp --dport 443 -j ACCEPT

# Enable NAT from Virtual Network
$IPT -A FORWARD -s 10.252.0.0/24 -j ACCEPT
$IPT -A FORWARD -d 10.252.0.0/24 -j ACCEPT
$IPT -t nat -A POSTROUTING -o $INET_INTERFACE -j MASQUERADE

# PortForwarding to VPN-Servers
/etc/port-forwarding.sh

exit 0

Для активации правил при настройке сетевого интерфейса используется опция post-up, которая идеально подходит для настройки firewall и вы можете просто добавит параметр:

 post-up /opt/scripts/firewall.sh

В соотвтествующий раздел файла /etc/network/interfaces (и дополнительно добавьте его в скрипт активации виртуального сетевого моста).

Пожалуйста, оцените мою статью (всего оценок 0, средняя оценка 4.00):

Комментарии к статье:

Пока комментариев нет

Оставьте комментарий:

обязательно

обязательно (не публикуется)

необязательно

обязательно

обязательно

Последние записи

Архив

2018

Категории

Ленты

RSS / Atom