Постановка задачи.
Последнее время на некоторых территориях тема обработки транзитного трафика на домашнем роутере стала популярна как никогда раньше. Интервал между новыми вызовами сократился с нескольких лет до нескольких дней. Задачи становятся всё интересней и сложней.
Перешитый на 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: исправлено несколько опечаток.
Goron_Dekar
В этой вот схеме важно добиться устойчивой работы интернета (насколько возможно устойчивой в "новой реальности") при выключенном сервере. И поэтому роутер должен обнаруживать отсутствие контейнера и в таком случае перенаправлять трафик напрямую провайдеру.
RTFM13 Автор
Автоматическое переключение на небезопасный канал связи может быть не только полезно, но и вредно. Я намерено не касался этого и других вопросов.
Идея была напомнить о том, что можно без особого труда вынести обработку трафика с роутера в изолированную среду. Без возни с кросс-компилятором, не рискуя окирпичить роутер или остаться без удалённого доступа и т.п.
Старые подключения мы не трогаем, клиенты всегда могут переключиться на них, в том числе автоматически.