Моя основная цель - не дать злоумышленникам установить несанкционированные исходящие соединения на моем сервере (например, для оболочек обратного соединения).
Я могу добиться этого, заблокировав все порты для исходящего трафика с помощью «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-адрес назначения исходящего трафика.
Также обратите внимание, что этот метод немного хакерский в том смысле, что для преодоления проблемы с бесконечным циклом (перенаправление на прокси -> перенаправление на прокси -> ...) правила брандмауэра применяются к группе пользователей операционной системы, что означает что любой пользователь, не входящий в группу, не будет перенаправлять свой исходящий трафик через прокси.
Шаги:
Создайте новую группу пользователей операционной системы под названием доверенное лицо
Добавьте всех пользователей операционной системы (кроме root!) В эту новую группу
Получить мне бы из доверенное лицо группа и запомни это на потом
Настройте какой-либо прозрачный прокси-сервер, который может принимать протоколы, которые вы хотите использовать, и может взаимодействовать с iptables
. я использовал mitmproxy
(который основан на Python) и настроить его для работы в качестве корневой службы и прослушивания порт прокси.
Добавить правило в 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 и порт прокси соответственно
Настроить iptables
или ufw
разрешить исходящий трафик на порт прокси, разрешите проксирование любого порта (например, 80) и запретите все остальные по умолчанию.
Настройте прозрачный прокси-сервер для отбрасывания запросов, как вам нравится. Чтобы ответить на этот вопрос, вы должны настроить прокси-сервер для выполнения обратного DNS на исходном IP-адресе назначения и проверить, что полученный домен находится в предварительно настроенном белом списке, в противном случае трафик должен быть отброшен.