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


Виртуализация серверов и рабочих станций в Windows и Linux - Hiperv, KVM, VMWare Сложные сетевые решения (VPN/Routing и т.п.) Мое портфолио, сертификаты и разработки
dhcp firewall gita lxc lxd openvpn ubuntu
 
 

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


(последние правки 1 неделя)

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

Сегодня я хотел бы поговорить о реализации специфичной 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 (и дополнительно добавьте его в скрипт активации виртуального сетевого моста).

Моя официальная страница на FaceBook
Мой микроблог в твиттер

Сборка гипервизора контейнеров LXC (LXD) из исходных кодов и настройка окружения разработчика

Сборка гипервизора контейнеров LXC (LXD) из исходных кодов и настройка окружения разработчика

Данная статья родилась в процессе работ над проектом по тестировнию функционала горячей миграции контейнеров LXC. Мы провели сборку LXD из git-репозитария и описали шаги для повторения этих манипипуляций в дальнейшем. Дополнительно мы подготовили инструкцию по созданию окружения для наших разработчиков.


Управление дисковыми хранилищами LXD из консоли

Управление дисковыми хранилищами LXD из консоли

В предыдущей статье про базовую настройку окружения разработчика мы получили много вопросов по поводу управления дисковыми пулами и по результатам обсуждения статьи мы подготовили небольшую статью HOW-TO по управлению виртуальными дисками (и хранилищами) системы контейнерной изоляции LXD.


Скрипт и поясняющее видео сборки гипервизора контейнеров LXD из исходных кодов (мастер-ветка)

Скрипт и поясняющее видео сборки гипервизора контейнеров LXD из исходных кодов (мастер-ветка)

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


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

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

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


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


Есть вопросы?
Спрашивайте и я обязательно вам отвечу!

* Поля обязательные для заполнения .