Настройка системы Linux
Чтобы была возможность раздавать интернет внутри VPN сети, необходимо разрешить перенаправление пакетов внутри ядра Linux. Без этих параметров не получится настроить маршрутизацию.
Открываем файл /etc/sysctl.d/99-custom.conf
nano /etc/sysctl.d/99-custom.conf
Добавляем следующие строки в конец файла (или их можно раскомментировать внутри файла, если они там есть)
net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1
#Включить многопутевую маршрутизацию
net.ipv4.conf.all.rp_filter=0
net.ipv4.conf.default.rp_filter=0
Выполняем команду применения изменений
sysctl -p
добовляем таблицы маршрутизации
mkdir /etc/iproute2/
touch /etc/iproute2/rt_tables
chmod 644 /etc/iproute2/rt_tables
echo "1001 isp1_table" >> /etc/iproute2/rt_tables
echo "1002 isp2_table" >> /etc/iproute2/rt_tables
Настраиваем сетевые интерфейсы ip адреса получаются автоматически nano /etc/network/interfaces
#isp1
auto ens19
iface ens19 inet dhcp
metric 5
#isp2
auto ens20
iface ens20 inet dhcp
metric 10
post-up ip route add default via 10.0.23.1 dev ens19 table isp1_table
post-up ip route add default via 10.0.17.1 dev ens20 table isp2_table
post-up ip rule add from 10.0.23.1 lookup isp1_table
post-up ip rule add from 10.0.17.1 lookup isp2_table
post-up ip rule add fwmark 0x1 lookup isp1_table
post-up ip rule add fwmark 0x2 lookup isp2_table
post-up ip route add table isp1_table 10.0.23.0/24 dev ens19
post-up ip route add table isp2_table 10.0.17.0/24 dev ens20
настраиваем nftables что бы он отвечал с интерфейса на который пришол пакет
table inet mangle {
chain prerouting {
type filter hook prerouting priority mangle; policy accept;
# Маркировка соединений
iifname "ens19" ct mark set 1
iifname "ens20" ct mark set 2
# Применение маршрутной метки
ct mark 1 meta mark set 1
ct mark 2 meta mark set 2
}
chain output {
type filter hook output priority mangle; policy accept;
# Для WireGuard что бы он шёл через второго провайдера
udp dport 55625 ip daddr (ip адрес филиала) meta mark set 2
}
}
table ip nat {
chain postrouting {
type nat hook postrouting priority srcnat; policy accept;
oifname "ens20" masquerade
oifname "ens19" masquerade
}
}
Скрипт перелючение каналов
#!/bin/bash
# Основной и резервный шлюзы
GW1=10.0.23.1
GW2=10.0.17.1
# Интерфейсы
iface1=ens19
iface2=ens20
# IP-адреса на интерфейсах (src для пинга)
SRC1=10.0.23.127
SRC2=10.0.17.121
# Адрес для проверки
srctest=8.8.8.8
logfile="/var/log/channel_switch.log"
# Проверка основного канала (по src IP)
result1=$(ping -c 3 -I $SRC1 $srctest -W 1 2>&1 | grep -icE 'unknown|expired|unreachable|time out|100% packet loss')
# Проверка резервного канала (по src IP)
result2=$(ping -c 3 -I $SRC2 $srctest -W 1 2>&1 | grep -icE 'unknown|expired|unreachable|time out|100% packet loss')
# Текущий маршрут по умолчанию
current_gw=$(ip route show default 2>/dev/null | awk '{print $3}')
# --- Логика переключения ---
if [ $result1 -eq 0 ]; then
# Основной работает
if [ "$current_gw" != "$GW1" ]; then
echo "$(date '+%Y-%m-%d %H:%M:%S') — Переключение на основной канал ($GW1)" | tee -a "$logfile"
ip route del default || true
ip route add default via $GW1 dev $iface1 src $SRC1 metric 100
ip route add default via $GW2 dev $iface2 src $SRC2 metric 200
ip route flush cache
conntrack -F
fi
else
# Основной не работает
if [ $result2 -eq 0 ]; then
if [ "$current_gw" != "$GW2" ]; then
echo "$(date '+%Y-%m-%d %H:%M:%S') — Переключение на резервный канал ($GW2)" | tee -a "$logfile"
ip route del default || true
ip route add default via $GW2 dev $iface2 src $SRC2 metric 100
ip route add default via $GW1 dev $iface1 src $SRC1 metric 200
ip route flush cache
conntrack -F
fi
else
echo "$(date '+%Y-%m-%d %H:%M:%S') — ВНИМАНИЕ! Оба канала недоступны" | tee -a "$logfile"
fi
fi
exit 0
Сделаем запуск скрипта через systemd
Создаем systemd service
nano /etc/systemd/system/check_gatawey.service
[Unit]
Description=Check Gateway Script
Wants=network-online.target
After=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/scripts/check_gatawey.sh
Restart=on-failure
RestartSec=10s
StandardOutput=journal
StandardError=journal
SyslogIdentifier=check_gatawey
[Install]
WantedBy=multi-user.target
Создаем systemd timer
nano /etc/systemd/system/check_gatawey.timer
[Unit]
Description=Run Check Gateway Script every 1 minute
[Timer]
OnBootSec=1min
OnUnitActiveSec=1min
Unit=check_gatawey.service
[Install]
WantedBy=timers.target
Включаем службу
systemctl daemon-reload
systemctl enable check_gatawey.service
перезапускаем ее
systemctl restart check_gatawey.service
Проверка работы
systemctl status check_gatawey.service
systemctl list-timers | grep check_gatawey
journalctl -u check_gatawey.service -f
Дальше расмотрим такую схему сети что бы у нас филиалы продолжали работать при недоступности первого провайдера
Установка WireGuard
На всех узлах выполните:
sudo apt update && sudo apt install wireguard -y
Настройка WireGuard
Пример для Node1 соеденяется через isp1 (10.0.0.1/30):
# /etc/wireguard/wg0.conf
[Interface]
Address = 10.0.0.1/30
PrivateKey = <Node1_private_key>
ListenPort = 51820
[Peer]
PublicKey = <Node2_public_key>
AllowedIPs = 10.0.0.2/32
Endpoint = <Node2_public_IP>:51820
PersistentKeepalive = 25
Пример для соеденяется через isp1 Node2 (10.0.0.2/30):
# /etc/wireguard/wg0.conf
[Interface]
Address = 10.0.0.2/30
PrivateKey = <Node2_private_key>
ListenPort = 51820
[Peer]
PublicKey = <Node1_public_key>
AllowedIPs = 10.0.0.1/32
Endpoint = <Node1_public_IP_isp1>:51820
PersistentKeepalive = 25
Пример для Node1 соеденяется через isp2 (10.0.1.1/30):
# /etc/wireguard/wg1.conf
[Interface]
Address = 10.0.1.1/30
PrivateKey = <Node1_private_key>
ListenPort = 55625
[Peer]
PublicKey = <Node2_public_key>
AllowedIPs = 10.0.1.2/32
Endpoint = <Node2_public_IP>:55625
PersistentKeepalive = 25
Пример для соеденяется через isp2 Node2 (10.0.1.2/30):
# /etc/wireguard/wg1.conf
[Interface]
Address = 10.0.0.2/30
PrivateKey = <Node2_private_key>
ListenPort = 55625
[Peer]
PublicKey = <Node1_public_key>
AllowedIPs = 10.0.0.1/32
Endpoint = <Node1_public_IP_isp2>:55625
PersistentKeepalive = 25
Запуск WireGuard
На всех узлах:
sudo systemctl enable wg-quick@wg0
sudo systemctl start wg-quick@wg0
sudo systemctl enable wg-quick@wg1
sudo systemctl start wg-quick@wg1
Создание очередей на интерфейсах wg (при необходимости)
Надо добавть в конфигкрацию wireguar в секцию [Interface] PostUp и PostDown
PostUp = /etc/wireguard/wg0_tc.sh
PostDown = tc qdisc del dev wg0 root
Сам скрипт /etc/wireguard/wg0_tc.sh
#!/bin/bash
# Настройка cake для wg0 (egress + ingress)
WG_IF="wg0"
WG_SPEED="185mbit" # внутренняя скорость в туннеле
IFB_ID="ifb1" # виртуальный интерфейс для входящего трафика
set -e
# Определяем MTU интерфейса wg0
WG_MTU=$(ip link show dev $WG_IF | awk '/mtu [0-9]+/ {print $5}')
if [ -z "$WG_MTU" ]; then
echo "Ошибка: не удалось определить MTU для интерфейса $WG_IF"
exit 1
fi
# Рассчитываем оптимальный r2q для HTB
# r2q = rate / (10 * MTU). MTU в битах = MTU * 8
R2Q=$((185000000 / (10 * $WG_MTU * 8)))
R2Q=${R2Q:-10} # значение по умолчанию, если расчет не удался
# Ограничиваем r2q разумными пределами (1-65535)
if [ $R2Q -lt 1 ]; then
R2Q=1
elif [ $R2Q -gt 65535 ]; then
R2Q=65535
fi
# Создаём ifb для входящего трафика
ip link del $IFB_ID 2>/dev/null || true
modprobe ifb numifbs=2
ip link add $IFB_ID type ifb 2>/dev/null || true
# Устанавливаем такой же MTU для IFB, как у WG_IF
ip link set dev $IFB_ID mtu $WG_MTU
ip link set dev $IFB_ID up
# Чистим старые правила
tc qdisc del dev $WG_IF root 2>/dev/null || true
tc qdisc del dev $WG_IF ingress 2>/dev/null || true
tc qdisc del dev $IFB_ID root 2>/dev/null || true
# ===== Исходящий трафик wg0 =====
tc qdisc add dev $WG_IF root handle 1: htb r2q $R2Q
tc class add dev $WG_IF parent 1: classid 1:1 htb rate $WG_SPEED ceil $WG_SPEED
tc class add dev $WG_IF parent 1:1 classid 1:10 htb rate $WG_SPEED ceil $WG_SPEED
tc qdisc add dev $WG_IF parent 1:10 cake
# ===== Входящий трафик wg0 =====
tc qdisc add dev $WG_IF handle ffff: ingress
tc filter add dev $WG_IF parent ffff: protocol all u32 match u32 0 0 \
action mirred egress redirect dev $IFB_ID
tc qdisc add dev $IFB_ID root handle 1: htb r2q $R2Q
tc class add dev $IFB_ID parent 1: classid 1:1 htb rate $WG_SPEED ceil $WG_SPEED
tc class add dev $IFB_ID parent 1:1 classid 1:10 htb rate $WG_SPEED ceil $WG_SPEED
tc qdisc add dev $IFB_ID parent 1:10 cake
echo "Настройка завершена. Использован MTU: $WG_MTU, r2q: $R2Q"
Установка FRRouting (OSPF)
На всех узлах:
sudo apt install frr -y
Включите OSPF в /etc/frr/daemons:
ospfd=yes
Перезапустите FRR:
sudo systemctl restart frr
Настройка OSPF
Используйте vtysh для настройки OSPF.
Пример через провайдера isp1 для Node1:
vtysh
configure terminal
interface wg0
ip ospf cost 1000
ip ospf dead-interval 40
exit
router ospf
network 10.0.0.0/24 area 0 # Туннельная сеть
network <LAN_Node1_подсеть> area 0 # Например, 192.168.1.0/24
exit
exit
write
Пример через провайдера isp1 для Node2:
vtysh
configure terminal
interface wg0
ip ospf cost 1000
ip ospf dead-interval 40
exit
router ospf
network 10.0.0.0/24 area 0 # Туннельная сеть
network <LAN_Node2_подсеть> area 0 # Например, 192.168.2.0/24
exit
exit
write
Пример через провайдера isp2 для Node1:
vtysh
configure terminal
interface wg1
ip ospf cost 2000
ip ospf dead-interval 40
exit
router ospf
network 10.0.0.0/24 area 0 # Туннельная сеть
network <LAN_Node1_подсеть> area 0 # Например, 192.168.1.0/24
exit
exit
write
Пример через провайдера isp2 для Node2:
vtysh
configure terminal
interface wg1
ip ospf cost 2000
ip ospf dead-interval 40
exit
router ospf
network 10.0.0.0/24 area 0 # Туннельная сеть
network <LAN_Node2_подсеть> area 0 # Например, 192.168.2.0/24
exit
exit
write
Проверка OSPF
Проверьте соседей:
vtysh -c "show ip ospf neighbor"
Посмотрите таблицу маршрутизации:
vtysh -c "show ip route ospf"