Постановка задачи.

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

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

Как и у многих, у меня рядом с роутером есть небольшой NAS на базе PC. Который с помощью второй сетевухи мог бы легко превратиться в роутер. Но как это сделать удаленно? И как сделать из сервера роутер, не трогая по-возможности сервер и роутер? Легко!

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

Конфигурация

Используем OpenWRT + сервер на Debian + LXC. Опытные товарищи тут уже всё поняли и дальше могут не читать.

Кабели мы договорились не трогать. По этому трафик на сервер входить и выходить будет через 1 сетевуху включенную в LAN порт роутера. Мешать всё в кучу не будем и для разделения используем 802.1Q VLAN.

Трафик будет ходить следующим образом:
клиент - роутер - контейнер_на_сервере - роутер - интернет.

Добавляем VLAN для клиентов (описываю действия в веб-морде):
Network - Switch - Add VLAN
VLAN ID указываем первый свободный номер (например "3")
Порты СPU и LAN к которому подключен сервер ставим "tagged", остальные "off"
здесь и далее после каждого изменения жмём "save&apply"

Добавляем новую сеть WiFi
Network - Wireless - Add
AccessPoint - <SSID> - сеть пока не указываем
SSID, пароль и т.п. указываем по вкусу, это будет вайфай сеть для клиентов с обработанным трафиком.

Добавляем мост
Network - Interface - Devices - Add device
Bridge Device - brLAN3 - eth0.3
Bridge ports надо будет выбрать из списка. eth0 это интерфейс CPU, у вас может быть другой. 3 - VLANID вы указывали выше.

Добавляем интерфейс без IP
Network - interfaces - Add interface ("LAN3" - "Unmanaged" - "brLAN3")
LAN3 - имя сети, я для удобства добавляю номер VLAN

Возвращаемся и добавляем интерфейс к Wi-Fi
Network - Wireless - SSID_Name - Edit
Network: LAN3

Должна появится сеть но при попытке подключения не должен выдаваться IP.

Если к этой сети нужно подключить клиента кабелем например к порту №4, то идём
Network - Switch
в столбце соответствующем нужному порту
Для VLANID 1: untagged меняем на off
Для VLANID 3: off меняем на untagged


На этом с роутером всё.

Идём на сервер.

Ставим LXC по инструкции. (в простейшем случае sudo apt install lxc)

Скрытый текст

KVM/QEMU я посчитал избыточным, хотя потенциально проблем с ним будет меньше и установка и настройка даже проще. Но и ресурсов будет жрать больше.

Среди дистрибутивов LXC доступен OpenWRT но я захотел полноценный дебиан.

Выбор между привилегированными и непривилегированными контейнерами оставлю за кадром, всё прекрасно описано по ссылке.

создаем контейнер (я использую тот же дебиан)
lxc-create -n containerouter -t download -- --dist debian --release bookworm --arch amd64

Далее (я это делал в графической оболочке еще давно при установке системы, сей-час нет под рукой машины проверить комманды nmcli)
1. удаляем локальное кабельное подключение.
2. создаём мост br0 указав сетевую карту (что-то типа "enpXsY") в bridged connections.
3. Настройки IP указываем в параметрах br0

br0 будет у нас виртуальным коммутатором аналогичным физическому в роутере.

lxcbr0 вместе со штатной сетевой системой контейнеров мы оставим и использовать в данном примере не будем.

Открываем /var/lib/lxc/containerouter/config

Скрытый текст

# Network configuration
lxc.net.0.type = veth
lxc.net.0.name = eth0
lxc.net.0.link = br0
lxc.net.0.flags = up
lxc.net.0.ipv4.address = 192.168.1.103/24
lxc.net.0.ipv4.gateway = 192.168.1.1
lxc.net.1.type = vlan
lxc.net.1.name = eth1
lxc.net.1.vlan.id = 3
lxc.net.1.link = enpXsY
lxc.net.1.flags = up
lxc.net.1.ipv4.address = 192.168.3.1/24

192.168.1.103 это адрес контейнера в вашем роутере. Зарезервируйте его в настройках DHCP на всякий случай. 192.168.1.1 - адрес роутера.

192.168.3.1/24 это подсеть из которой будут получать адреса клиенты контейнерного роутера.

enpXsY это наш физический сетевой интерфейс хоторый мы добавили в бридж на хосте выше.

обращаем внимание на номер vlan.id, тот же номер мы настраивали в роутере.

IP адрес 192.168.1.103 в этом конфиге в данном случае приведен для декорации, т.к. я не советую использовать дефолтный DHCP клиент в контейнере из-за его кривизны. Вернёмся к этому ниже. Как сделать более красиво пишите в комментариях.

Если в роутере будут туннели на базе tun интерфейса, например openvpn, добавляем ниже строчку

lxc.mount.entry = /dev/net/tun dev/net/tun none bind,create=file

Запускаем контейнер.

lxc-start --name=containerouter

Если нет ошибок подключаемся

lxc-attach containerouter

тут у нас почти обычный дебиан.

Первым делом идём настроим настоящий IP в /etc/systemd/network/eth0.network

[Match]
Name=eth0

[Network]
Address=192.168.1.103/24
Gateway=192.168.1.1
DNS=192.168.1.1

выходим, перегружаем, заходим

ставим сразу обновления, я обычно сразу ставлю midnight commander (apt install mc)

ставим dnsmasq

apt install dnsmasq

/etc/dnsmasq.d/dhcp.conf

port=0

interface=eth1

dhcp-range=192.168.3.100,192.168.3.150,255.255.255.0,12h
dhcp-option=3,192.168.3.1 # Gateway
dhcp-option=6,8.8.8.8,8.8.4.4 # DNS servers правим если надо
dhcp-leasefile=/var/lib/misc/dnsmasq.leases
dhcp-authoritative

log-dhcp
log-queries
log-facility=/var/log/dnsmasq.log

Выходим, перезапускаем контейнер, переподключаемся. Между остановкой и запуском контейнера возможно понадобится подождать минуту пока сетевой сервис контейнеров удалит тегированный VLAN с сетевого интерфейса хоста, иначе контейнер не запустится.

В простейшем случае можно добавить что-то типа

iptables -t nat -A POSTROUTING -s 192.168.3.0/24 -j MASQUERADE

проверяем что

root@containerouter# cat /proc/sys/net/ipv4/ip_forward
1

И клиенты новой сети должны получать адреса и интернет

Настраиваем фаервол, ssh и т.п. по вкусу. Не забываем поставить пароль на рута. В системе два сетевых интерфейса eth0 это внешний смотрит на локальную сеть роутера. eth1 внутренний раздаёт адреса клиентам.

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

UPD 2024-08-27: исправлено несколько опечаток.

Комментарии (2)


  1. Goron_Dekar
    27.08.2024 06:58

    В этой вот схеме важно добиться устойчивой работы интернета (насколько возможно устойчивой в "новой реальности") при выключенном сервере. И поэтому роутер должен обнаруживать отсутствие контейнера и в таком случае перенаправлять трафик напрямую провайдеру.


    1. RTFM13 Автор
      27.08.2024 06:58

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

      Идея была напомнить о том, что можно без особого труда вынести обработку трафика с роутера в изолированную среду. Без возни с кросс-компилятором, не рискуя окирпичить роутер или остаться без удалённого доступа и т.п.

      Старые подключения мы не трогаем, клиенты всегда могут переключиться на них, в том числе автоматически.