Был когда-то интересный квест. Ща расскажу.
Крутился внутри сети сайт (на IP 192.168.0.87) который пулял куда-то API-запросы, с такой особенностью, что работал он не как все машины через шлюз 192.168.0.1.
А пулял запросы в другую сеть которая была за шлюзом 192.168.0.176 и далее в дивный неведомый интернет, хуй знает куда он там чего отправляет, это в данном случае не важно.
Важно что запросы должны летать в шлюз 192.168.0.176 а общий шлюз в сети 192.168.0.1 с внешним X.X.X.X.
Все было хорошо, пока манагеры не захотели видеть этот сайт снаружи сети (IP X.X.X.X, всякие DNS опустим, они тут не важны).
Разраб тоже сказал что ему нужна 22 дырка снаружи, и понятно что проброс порта на шлюзе не сработает. Надо выдумывать маршруты.
Присказка окончена, понеслася сказка.
Пишем маршрутизацию
/etc/netplan/00-installer-config.yaml
network:
version: 2
renderer: networkd
ethernets:
eth0:
addresses: [192.168.0.87/24]
routes:
- to: 0.0.0.0/0 # Весь интернет-трафик через 192.168.0.176
via: 192.168.0.176
metric: 100
- to: 192.168.0.1/32 # Явный маршрут до шлюза 192.168.0.1
via: 192.168.0.1
metric: 50 # Более высокий приоритет
nameservers:
addresses: [8.8.8.8, 8.8.4.4]
Применяем изменения (тут если накосячил сообщат)
sudo netplan apply
Создаем отдельную таблицу маршрутизации (table 100)
sudo ip route add default via 192.168.0.1 dev eth0 table 100
Создаем правила маршрутизации для каждого порта:
sudo ip rule add iif eth0 dport 22 lookup 100
sudo ip rule add iif eth0 dport 8080 lookup 100
Что делает:
iif eth0 — трафик, пришедший на интерфейс eth0.
dport 22 и dport 8080 — если это SSH (порт 22) или HTTP (порт 8080).
lookup 100 — использовать таблицу 100 для маршрутизации этого трафика.
Пометка исходящего трафика (iptables mangle + MARK)
sudo iptables -t mangle -A OUTPUT -p tcp --sport 22 -j MARK --set-mark 1
sudo iptables -t mangle -A OUTPUT -p tcp --sport 8080 -j MARK --set-mark 1
Что делает:
-t mangle — таблица mangle для изменения (marking) пакетов.
–sport 22 и –sport 8080 — если исходящий трафик идёт с портов 22 (SSH) или 8080 (HTTP).
–set-mark 1 — помечает такие пакеты меткой 1.
Зачем:
Метка (mark) позволяет позже применить к пакетам особые правила маршрутизации.
Правило маршрутизации по метке (fwmark)
sudo ip rule add fwmark 1 lookup 100
Что делает:
fwmark 1 — если пакет помечен меткой 1 (как в iptables выше).
lookup 100 — использовать таблицу 100 для маршрутизации.
Зачем:
Это гарантирует, что ответы на SSH/HTTP-запросы (исходящие с портов 22/8080) будут направляться через шлюз 192.168.0.1 (из таблицы 100), а не через основной маршрут.
Общий смысл всей настройки:
Для входящих запросов на eth0 (порты 22 и 8080): Ответный трафик маркируется (mark=1).
Маркированный трафик направляется через таблицу 100 (шлюз 192.168.0.1).
Для исходящих ответов (SSH/HTTP с портов 22/8080): Трафик также маркируется и направляется через таблицу 100.
Результат:
Проверяем:
ssh -p 1422 user@Х.Х.Х.Х
curl ident.me #должен вернуть внешний адрес шлюза
Если все отработало, идем дальше.
При перезагрузке вся настроенная маршрутизация слетит.
Надо восстанавливать при каждой перезагрузке. Тут на выбор. Пойдем по пути systemd.
В комментах содержимое portforward-routes.service, в пост не влезло.
[Unit]
Description=Configure portforward routing
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
ExecStart=/sbin/ip route add default via 192.168.0.1 dev eth0 table 100
ExecStart=/sbin/ip rule add iif eth0 dport 22 lookup 100
ExecStart=/sbin/ip rule add iif eth0 dport 8080 lookup 100
ExecStart=iptables -t mangle -A OUTPUT -p tcp --sport 22 -j MARK --set-mark 1
ExecStart=sudo iptables -t mangle -A OUTPUT -p tcp --sport 8080 -j MARK --set-mark 1
ExecStart=/sbin/ip rule add fwmark 1 lookup 100
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
Включаем
sudo systemctl daemon-reload
sudo systemctl enable portforward-routes.service
Перегружаемся\проверяем.








Комментарии