Назад | Перейти на главную страницу

Ограничение исходящего сетевого трафика по доменному имени (Linux)

Моя основная цель - не дать злоумышленникам установить несанкционированные исходящие соединения на моем сервере (например, для оболочек обратного соединения).

Я могу добиться этого, заблокировав все порты для исходящего трафика с помощью «ufw», за исключением тех, которые необходимы серверу (например, DNS, HTTP, SSH и SMTP).

ufw позволяет мне разрешать исходящие DNS-соединения только со статическим IP-адресом (поэтому я настрою сервер на использование Google DNS) и позволяет мне ограничивать исходящий SSH, предназначенный для 127.0.0.1 (мой сценарий автоматического развертывания требует этого с Git).

Как я узнал, ufw действительно не разрешает исходящие ограничения на основе доменных имен, что имеет смысл (с точки зрения производительности). Мне нужно иметь возможность сделать это, чтобы ограничить исходящие SMTP-подключения к домену моего почтового сервера (в настоящее время просто использовать Gmail для тестирования) и для HTTP-подключений к серверам Ubuntu (для обновлений системы).

Я знаю, что iptables позволяет указывать правила на основе доменов, но они переводятся при запуске и не выполняются каждый раз (т.е. обратный DNS). Я знаю, что это сделано специально из соображений производительности.

Итак, каково же решение ограничить исходящий сетевой трафик по имени домена (т.е. каждое исходящее соединение должно иметь IP-адрес назначения, обратный DNS и сопоставленный с белым списком доменных имен)?

Я думаю, что если я не могу заставить работать половину исходящих ограничений на основе домена, нет особого смысла ограничивать DNS и SSH по IP с помощью ufw.

Затем я понял, что при получении перенаправленного трафика узнать исходный IP-адрес назначения невозможно. Вот когда я нашел https://github.com/mitmproxy/mitmproxy и обнаружил, что он (как прозрачный прокси Python) взаимодействует с интерфейсом iptables для определения исходного IP-адреса назначения сокета.

У меня еще не все работает, но я уверен, что этот подход должен работать.

Это работает только на одной машине, потому что оно зависит от прозрачного прокси, способного взаимодействовать с iptables и получите исходный IP-адрес назначения исходящего трафика.

Также обратите внимание, что этот метод немного хакерский в том смысле, что для преодоления проблемы с бесконечным циклом (перенаправление на прокси -> перенаправление на прокси -> ...) правила брандмауэра применяются к группе пользователей операционной системы, что означает что любой пользователь, не входящий в группу, не будет перенаправлять свой исходящий трафик через прокси.

Шаги:

  1. Создайте новую группу пользователей операционной системы под названием доверенное лицо

  2. Добавьте всех пользователей операционной системы (кроме root!) В эту новую группу

  3. Получить мне бы из доверенное лицо группа и запомни это на потом

  4. Настройте какой-либо прозрачный прокси-сервер, который может принимать протоколы, которые вы хотите использовать, и может взаимодействовать с iptables. я использовал mitmproxy (который основан на Python) и настроить его для работы в качестве корневой службы и прослушивания порт прокси.

  5. Добавить правило в iptables для перенаправления всего исходящего трафика, предназначенного для определенного порта (например, http), на 127.0.0.1:порт прокси, вот так:

    iptables -t nat -A OUTPUT -m owner --gid-owner proxyGID -p tcp --dport 80 -j DNAT --to 127.0.0.1:proxyPort, заменяя proxyGID и порт прокси соответственно

  6. Настроить iptables или ufw разрешить исходящий трафик на порт прокси, разрешите проксирование любого порта (например, 80) и запретите все остальные по умолчанию.

  7. Настройте прозрачный прокси-сервер для отбрасывания запросов, как вам нравится. Чтобы ответить на этот вопрос, вы должны настроить прокси-сервер для выполнения обратного DNS на исходном IP-адресе назначения и проверить, что полученный домен находится в предварительно настроенном белом списке, в противном случае трафик должен быть отброшен.