Иногда требуется замаскировать какой-то сервис так, чтобы он был доступен только для определённых IP-адресов, а все остальные на этом же месте видели что-то другое. Это можно реализовать средствами FirewallD без каких-либо TCP-балансировщиков.
Скрипт для Fedora/CentOS 7
Наш код написан на чистом bash с использованием утилиты firewall-cmd:
#!/bin/bash set -e HPORT=443 PSERVICE=444 HSERVICE=445 OURIP=1.1.1.0/24 ZONE=public function fw_add { sysctl -w net.ipv4.ip_forward=1 firewall-cmd --zone=$ZONE --permanent --add-masquerade firewall-cmd --zone=$ZONE --permanent --add-rich-rule="rule family=\"ipv4\" source address=\"$OURIP\" forward-port port=\"$HPORT\" protocol=\"tcp\" to-port=\"$HSERVICE\"" firewall-cmd --zone=$ZONE --permanent --add-rich-rule="rule family=\"ipv4\" source not address=\"$OURIP\" forward-port port=\"$HPORT\" protocol=\"tcp\" to-port=\"$PSERVICE\"" firewall-cmd --reload } function fw_rem { sysctl -w net.ipv4.ip_forward=0 firewall-cmd --zone=$ZONE --permanent --remove-masquerade firewall-cmd --zone=$ZONE --permanent --remove-rich-rule="rule family=\"ipv4\" source address=\"$OURIP\" forward-port port=\"$HPORT\" protocol=\"tcp\" to-port=\"$HSERVICE\"" firewall-cmd --zone=$ZONE --permanent --remove-rich-rule="rule family=\"ipv4\" source not address=\"$OURIP\" forward-port port=\"$HPORT\" protocol=\"tcp\" to-port=\"$PSERVICE\"" firewall-cmd --reload } function fw_msg { echo "Use additional command-line parameters:" echo " * start - start script and add firewalld rules;" echo " * stop - stop script and remove firewalld rules." } case "$1" in "start") fw_add ;; "stop") fw_rem ;; *) fw_msg ;; esac
Конфигурация
Скрипт имеет несколько настраиваемых пользователем параметров:
- HPORT — переменная, хранящая публичный номер порта, к которому мы будем подключаться, например 443 (HTTPS);
- PSERVICE — номер порта публичного сервиса для чужих пользователей;
- HSERVICE — номер порта скрытого сервиса для наших IP-адресов;
- OURIP — наш внешний IP-адрес, с которого мы будем подключаться сервису (HPORT);
- ZONE — название зоны FirewallD для соединения.
Работа со скриптом
Скрипт добавляет постоянные правила, которые работают до их явной отмены пользователем.
Предположим, что мы сохранили указанный выше код в виде файла под именем rt.sh и выдали ему флаг +x. В таком случае запуск осуществляется так:
./rt.sh start
Отмена всех созданных правил:
./rt.sh stop
Принцип работы
Сценарий запуска:
- включаем маскарадинг для указанной зоны брандмауэра;
- проверяем IP-адрес, с которого пришёл пакет и если он соответствует указанному (наш), перенаправляем на порт скрытого сервиса, иначе (чужой) — на порт публичного.
Сценарий остановки:
- отключаем маскарадинг для указанной зоны брандмауэра;
- удаляем созданные нами правила перенаправления портов.
Лицензия
Код распространяется под лицензией GNU GPL версии 3 без каких-либо гарантий (явных или подразумеваемых). Используйте его исключительно на свой страх и риск.
Литература
При написании статьи использовалась литература из следующих источников:
Зачем подобное может быть нужно?
Например поднимаешь на сервере nginx с HTTPS (слушает порт 444) и openvpn (445), затем подключаешься к openvpn через порт 443. Твой провайдер или кто-то ещё видят в логах соединение на порт 443, решают проверить и видят там вместо VPN сервера обычный веб-сайт.
Это не защитит от DPI.
Разумеется, но: