Задумал я как-то настроить себе сетевой роутер под Linux-машиной. Чтобы через неё гнался весь трафик, а остальные машины получали бы адрес по DHCP и DNS запросы также обрабатывались бы этой машиной. Начал гуглить. Изначально мысль была просто настроить Netplan, но по ходу настройки я столкнулся с тем, что iptables всё-равно настраивать пришлось. Сложных DNS запросов мне делать не нужно, сеть будет состоять максимум из 10 - 15 машин, но DNS-сервер всё-равно нужен - периодически будет появляться один-два сетевых HTTP-сервера. Это - испытательный стенд, и не хотелось бы "гадить" в сеть. Гуглил я долго, и информацию пришлось собирать буквально по крупицам - где-то описано, как настраивать Netplan, где-то - iptables. С dnsmasq-ом тоже не всё было гладко - после полной настройки я выяснил, что все DNS запросы из сети обрабатываются, а с хоста - нет. Прошу обратить на это внимание - в статье будет момент об этом.
Но по итогу получил результат, который при re-тесте я настроил минут за 20! В тот день я задержался на работе, а до вечера хотелось ещё раз протестировать идею, чтобы - если будут замечания - подкорректировать материал перед тем, как публиковать статью. Но решение получилось настолько элегантным, что для сети из 10-20 машин лучше и не придумаешь: весь DNS настраивается в одном файле. Если у вас два интерфейса и две сети - большего и не нужно! Да, можно настроить netplan - но это будет чуть более громоздкое решение, и iptables всё-равно настраивать.
Несколько раз протестировал на Debian-12. Решение полностью работоспособное. Я - только "студент" пока, так что комментарии, замечания и конструктивная критика принимается и даже приветствуется.
А, если кому-то эта идея будет полезна - я только рад! Пользуйтесь!
Одно замечание. Я привык настройки машины делать из под рута. Не лучшая практика, но для такого случая допустимо. Если вы будете делать из под локального пользователя, то стоит использовать sudo.
Для настройки собственного роутера нам понадобится:
Сервер с двумя и более сетевыми интерфейсами (один из них уже должен быть настроен для выхода в интернет - выходит за рамки данной заметки)
В качестве сетевого менеджера я буду использовать network interfaces (по умолчанию в Debian)
Включить пересылку пакетов между интерфейсами (по умолчанию отключена в Linux)
Настроить nftables (мы будем использовать собственный DNS сервер с DHCP, поэтому перенаправление на другой сервер в nftables делать не будем)
Собственный DNS сервер (мы будем использовать dnsmasq)
1. Проверка настроек сетевых интерфейсов:
а. Проверяем, какие сетевые интерфейсы у нас есть:
ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host noprefixroute valid_lft forever preferred_lft forever 2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether 08:00:27:1b:df:b1 brd ff:ff:ff:ff:ff:ff inet 10.0.2.15/24 metric 100 brd 10.0.2.255 scope global dynamic enp0s3 valid_lft 80772sec preferred_lft 80772sec inet6 fd00::a00:27ff:fe1b:dfb1/64 scope global dynamic mngtmpaddr noprefixroute valid_lft 86161sec preferred_lft 14161sec inet6 fe80::a00:27ff:fe1b:dfb1/64 scope link valid_lft forever preferred_lft forever 3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether 08:00:27:81:ff:ba brd ff:ff:ff:ff:ff:ff inet 192.168.10.1/24 brd 192.168.10.255 scope global enp0s8 valid_lft forever preferred_lft forever inet6 fe80::a00:27ff:fe81:ffba/64 scope link valid_lft forever preferred_lft forever
Значит, у нас есть интерфейсы enp0s3 и enp0s8, причём enp0s3 - выходит в интернет.
2. Проверяем настройки сети:
cat /etc/nework/interfaces
# This file describes the network interfaces available on your system # and how to activate them. For more information, see interfaces(5). source /etc/network/interfaces.d/* # The loopback network interface auto lo iface lo inet loopback # The primary network interface allow-hotplug enp0s3 iface enp0s3 inet dhcp dns-nameservers 127.0.0.1 # This is an autoconfigured IPv6 interface # iface enp0s3 inet6 auto allow-hotplug enp0s8 iface enp0s8 inet static address 192.168.10.1 netmask 255.255.255.0 dns-nameservers 127.0.0.1
Сеть у нас настроена, но по тому, как её настраивать в интернете много информации.
Мы поняли главное: локальная сеть у нас работает на сети 192.168.10.0/24 и наша машина в локальной сети - 192.168.10.1 . Какие сервера использовать для DNS - тут не принципиально - мы будем настраивать их дальше. А, вот, имя сети и имя машины - очень важны - впоследствии именно она будет использоваться как шлюз.
3. Включаем в ядре бондинг:
а. Скачиваем, если он ещё не скачан - nftables:
apt install nftables - y systemctl start nftables systemctl enable nftables
б. Делаем первичную настройку nftables:
# Создаем таблицу и цепочки nft add table inet nat nft add chain inet nat postrouting { type nat hook postrouting priority 100\; } # Правило для DNS (в фильтрующей цепочке) nft add table inet filter nft add chain inet filter input { type filter hook input priority 0\; } nft add rule inet filter input udp dport 53 accept # Правило MASQUERADE nft add rule inet nat postrouting oif "enp0s3" masquerade
... и сохраняем её.
nft list ruleset >> /etc/nftables.conf
в. Устанавливаем modprobe iptable_nat:
modprobe iptable_nat echo 1 > /proc/sys/net/ipv4/ip_forward
г. Сохраним настройки модулей:
vim /etc/modules
# Добавляем эту строку iptable_nat
д. Сохраним настройки трафика:
vim /etc/sysctl.conf
# Снимаем комментрарий с этой строки net.ipv4.ip_forward=1
3. Тестируем связь с другой машины в локальной сети:
Проверяем и - при необходимости - настраиваем сеть (у нас пока DHCP не поднят, поэтому - только статика):
ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host noprefixroute valid_lft forever preferred_lft forever 2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether 08:00:27:63:46:3b brd ff:ff:ff:ff:ff:ff inet 192.168.10.2/24 brd 192.168.10.255 scope global enp0s3 valid_lft forever preferred_lft forever inet6 fe80::a00:27ff:fe63:463b/64 scope link valid_lft forever preferred_lft forever
Пингуем наш шлюз:
ping 192.168.10.1 PING 192.168.10.1 (192.168.10.1) 56(84) bytes of data. 64 bytes from 192.168.10.1: icmp_seq=1 ttl=64 time=1.45 ms 64 bytes from 192.168.10.1: icmp_seq=2 ttl=64 time=0.923 ms 64 bytes from 192.168.10.1: icmp_seq=3 ttl=64 time=1.15 ms 64 bytes from 192.168.10.1: icmp_seq=4 ttl=64 time=1.12 ms 64 bytes from 192.168.10.1: icmp_seq=5 ttl=64 time=1.02 ms 64 bytes from 192.168.10.1: icmp_seq=6 ttl=64 time=0.958 ms 64 bytes from 192.168.10.1: icmp_seq=7 ttl=64 time=0.964 ms --- 192.168.10.1 ping statistics --- 7 packets transmitted, 7 received, 0% packet loss, time 6005ms rtt min/avg/max/mdev = 0.923/1.084/1.447/0.168 ms
Пингуем интернет - DNS у нас пока не настроен, поэтому только по ip:
ping 8.8.8.8 PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data. 64 bytes from 8.8.8.8: icmp_seq=1 ttl=254 time=55.3 ms 64 bytes from 8.8.8.8: icmp_seq=2 ttl=254 time=25.3 ms 64 bytes from 8.8.8.8: icmp_seq=3 ttl=254 time=25.5 ms 64 bytes from 8.8.8.8: icmp_seq=4 ttl=254 time=25.1 ms 64 bytes from 8.8.8.8: icmp_seq=5 ttl=254 time=25.4 ms 64 bytes from 8.8.8.8: icmp_seq=6 ttl=254 time=65.0 ms 64 bytes from 8.8.8.8: icmp_seq=7 ttl=254 time=87.4 ms 64 bytes from 8.8.8.8: icmp_seq=8 ttl=254 time=25.0 ms 64 bytes from 8.8.8.8: icmp_seq=9 ttl=254 time=28.8 ms --- 8.8.8.8 ping statistics --- 9 packets transmitted, 9 received, 0% packet loss, time 8008ms rtt min/avg/max/mdev = 24.952/40.314/87.449/21.920 ms
Перезагружаем шлюз и снова проверяем пинг со второй машины, чтобы проверить, что все настройки сохранились корректно.
5. Устанавливаем и настраиваем dnsmasq:
а. Устанавливаем сам dnsmasq:
apt install dnsmasq systemctl enable dnsmasq systemctl start dnsmasq
После установки или старта сервиса мы можем увидеть ошибку:
failed to create listening socket for port 53: Address already in use
Как правило, она связана с тем, что на компьютере работает сервис systemd-resolved, который занял порт 53. Чтобы это исправить, отключаем его:
systemctl disable systemd-resolved --now
У меня при настройке появилась проблема: при пинге по доменному имени внутри сети всё работало, а вот с локальной машины - хотя я и отключил systemd-resolved - пинг не шёл. Нашёл несложное решение:
# /etc/resolv.conf прописываем: nameserver 127.0.0.1 # и запрещаем менять его chattr +i /etc/resolv.conf
б. Конфигурируем dnsmasq.conf:
cp /etc/dnsmasc.conf /etc/dnsmasq.conf.backup vim /etc/dnsmasq.conf
# По умолчянию Linux слушает DNS в systemd-resolv, # Мы его отключили, # Поэтому - чтобы убрать ошибку, с этим связанную, # устанавливаем этот параметр no-resolv # Настраиваем адреса, на которых сервер будет слушать DNS запрсы # Настраиваем на 127.0.0.1, чтобы сервер работал со своими же запросами listen-address=127.0.0.1 # Настраиваем интерфейсы, на которых будет работать сервис (нужны оба!) interface=enp0s8,enp0s3 # Настройка DHCP dhcp-range=192.168.10.100,192.168.10.254,255.255.255.0,24h # Настройка внешних DNS серверов, куда будут # отправляться запросы на неизвестные сервера server=8.8.8.8 all-servers # Настройка внутренних доменных имён address=/example_domain.com/192.168.10.1 # Настраиваем логи log-queries log-facility=/var/log/dnsmasq.log
Соответственно, поле address задаёт доменные имена для локальной сети.
в. Перезагружаем dnsmasq:
systemctl restart dnsmasq
6. Снова тестируем работу со второй машины:
а. Проверяем DHCP:
vim /etc/network/interfaces
# This file describes the network interfaces available on your system # and how to activate them. For more information, see interfaces(5). source /etc/network/interfaces.d/* # The loopback network interface auto lo iface lo inet loopback # The primary network interface allow-hotplug enp0s3 iface enp0s3 inet dhcp # This is an autoconfigured IPv6 interface # iface enp0s3 inet6 auto
б. Перезапускаем сеть:
systemctl restart networkiing
в. Проверяем, что ip-адрес присвоился:
ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host noprefixroute valid_lft forever preferred_lft forever 2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether 08:00:27:bf:4c:a6 brd ff:ff:ff:ff:ff:ff inet 192.168.10.111/24 brd 192.168.10.255 scope global dynamic enp0s3 valid_lft 86370sec preferred_lft 86370sec inet6 fe80::a00:27ff:febf:4ca6/64 scope link valid_lft forever preferred_lft forever
г. Снова пингуем сеть:
ping 192.168.10.1 PING 192.168.10.1 (192.168.10.1) 56(84) bytes of data. 64 bytes from 192.168.10.1: icmp_seq=1 ttl=64 time=1.82 ms 64 bytes from 192.168.10.1: icmp_seq=2 ttl=64 time=1.12 ms 64 bytes from 192.168.10.1: icmp_seq=3 ttl=64 time=12.5 ms 64 bytes from 192.168.10.1: icmp_seq=4 ttl=64 time=1.17 ms 64 bytes from 192.168.10.1: icmp_seq=5 ttl=64 time=0.905 ms --- 192.168.10.1 ping statistics --- 5 packets transmitted, 5 received, 0% packet loss, time 5242ms rtt min/avg/max/mdev = 0.905/3.493/12.452/4.489 ms
ping 8.8.8.8 PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data. 64 bytes from 8.8.8.8: icmp_seq=1 ttl=254 time=25.9 ms 64 bytes from 8.8.8.8: icmp_seq=2 ttl=254 time=24.8 ms 64 bytes from 8.8.8.8: icmp_seq=3 ttl=254 time=25.2 ms 64 bytes from 8.8.8.8: icmp_seq=4 ttl=254 time=26.3 ms 64 bytes from 8.8.8.8: icmp_seq=5 ttl=254 time=28.0 ms 64 bytes from 8.8.8.8: icmp_seq=6 ttl=254 time=27.9 ms --- 8.8.8.8 ping statistics --- 6 packets transmitted, 6 received, 0% packet loss, time 5745ms rtt min/avg/max/mdev = 24.839/26.349/27.951/1.212 ms
ping ya.ru PING ya.ru (77.88.44.242) 56(84) bytes of data. 64 bytes from ya.ru (77.88.44.242): icmp_seq=1 ttl=254 time=14.5 ms 64 bytes from ya.ru (77.88.44.242): icmp_seq=2 ttl=254 time=13.2 ms 64 bytes from ya.ru (77.88.44.242): icmp_seq=3 ttl=254 time=14.6 ms 64 bytes from ya.ru (77.88.44.242): icmp_seq=4 ttl=254 time=14.9 ms 64 bytes from ya.ru (77.88.44.242): icmp_seq=5 ttl=254 time=15.4 ms 64 bytes from ya.ru (77.88.44.242): icmp_seq=6 ttl=254 time=14.5 ms --- ya.ru ping statistics --- 6 packets transmitted, 6 received, 0% packet loss, time 6228ms rtt min/avg/max/mdev = 13.187/14.517/15.367/0.662 ms
nslookup ya.ru Server: 192.168.10.1 Address: 192.168.10.1#53 Non-authoritative answer: Name: ya.ru Address: 77.88.55.242 Name: ya.ru Address: 5.255.255.242 Name: ya.ru Address: 77.88.44.242 Name: ya.ru Address: 2a02:6b8::2:242
Мы видим наш сервер как первый в каскаде DNS запросов
7. Тестируем локальный DNS:
а. Проверяем, что DNS работает на локальной машине:
ping example_domain.com PING example_domain.com (192.168.10.1) 56(84) bytes of data. 64 bytes from 192.168.10.1 (192.168.10.1): icmp_seq=1 ttl=64 time=0.043 ms 64 bytes from 192.168.10.1 (192.168.10.1): icmp_seq=2 ttl=64 time=0.061 ms 64 bytes from 192.168.10.1 (192.168.10.1): icmp_seq=3 ttl=64 time=0.055 ms 64 bytes from 192.168.10.1 (192.168.10.1): icmp_seq=4 ttl=64 time=0.202 ms 64 bytes from 192.168.10.1 (192.168.10.1): icmp_seq=5 ttl=64 time=0.057 ms 64 bytes from 192.168.10.1 (192.168.10.1): icmp_seq=6 ttl=64 time=0.055 ms 64 bytes from 192.168.10.1 (192.168.10.1): icmp_seq=7 ttl=64 time=0.057 ms 64 bytes from 192.168.10.1 (192.168.10.1): icmp_seq=8 ttl=64 time=0.060 ms --- example_domain.com ping statistics --- 8 packets transmitted, 8 received, 0% packet loss, time 7012ms rtt min/avg/max/mdev = 0.043/0.073/0.202/0.048 ms
б. Проверяем локальный DNS из сети:
ping example_domain.com PING example_domain.com (192.168.10.1) 56(84) bytes of data. 64 bytes from 192.168.10.1 (192.168.10.1): icmp_seq=1 ttl=64 time=2.03 ms 64 bytes from 192.168.10.1 (192.168.10.1): icmp_seq=2 ttl=64 time=0.883 ms 64 bytes from 192.168.10.1 (192.168.10.1): icmp_seq=3 ttl=64 time=1.03 ms 64 bytes from 192.168.10.1 (192.168.10.1): icmp_seq=4 ttl=64 time=1.05 ms 64 bytes from 192.168.10.1 (192.168.10.1): icmp_seq=5 ttl=64 time=1.08 ms 64 bytes from 192.168.10.1 (192.168.10.1): icmp_seq=6 ttl=64 time=0.778 ms 64 bytes from 192.168.10.1 (192.168.10.1): icmp_seq=7 ttl=64 time=1.13 ms 64 bytes from 192.168.10.1 (192.168.10.1): icmp_seq=8 ttl=64 time=0.992 ms --- example_domain.com ping statistics --- 8 packets transmitted, 8 received, 0% packet loss, time 7011ms rtt min/avg/max/mdev = 0.778/1.122/2.029/0.358 ms
б. Проверяем доменную зону:
ping my_app.example_domain.com PING my_app.example_domain.com (192.168.10.1) 56(84) bytes of data. 64 bytes from 192.168.10.1 (192.168.10.1): icmp_seq=1 ttl=64 time=2.02 ms 64 bytes from 192.168.10.1 (192.168.10.1): icmp_seq=2 ttl=64 time=0.904 ms 64 bytes from 192.168.10.1 (192.168.10.1): icmp_seq=3 ttl=64 time=1.10 ms 64 bytes from 192.168.10.1 (192.168.10.1): icmp_seq=4 ttl=64 time=0.889 ms 64 bytes from 192.168.10.1 (192.168.10.1): icmp_seq=5 ttl=64 time=1.20 ms 64 bytes from 192.168.10.1 (192.168.10.1): icmp_seq=6 ttl=64 time=0.907 ms 64 bytes from 192.168.10.1 (192.168.10.1): icmp_seq=7 ttl=64 time=1.01 ms 64 bytes from 192.168.10.1 (192.168.10.1): icmp_seq=8 ttl=64 time=0.892 ms 64 bytes from 192.168.10.1 (192.168.10.1): icmp_seq=9 ttl=64 time=1.10 ms --- my_app.example_domain.com ping statistics --- 9 packets transmitted, 9 received, 0% packet loss, time 8009ms rtt min/avg/max/mdev = 0.889/1.112/2.020/0.337 ms
Мы настроили шлюз!