У меня есть виртуальная машина под управлением CentOS с веб-сервером, который я использую для размещения случайных служб, которые я развертываю там, поэтому, чтобы сделать ее доступной из Интернета, я открыл порт 80, используя iptables
. Поскольку сам веб-сервер работает как служба под выделенным пользователем, который не корень, он не может использовать порт 80 напрямую. Таким образом, прочитав документы, я добавил перенаправление с порта 80 на 8080, чтобы веб-сервер мог быть привязан к этому порту (я планирую добавить поддержку HTTPS позже, возможно, я куплю правильный домен, а затем воспользуюсь Let's Зашифровать что ли).
До сих пор он работал нормально, но недавно я заметил, что порт 8080 также был оставлен широко открытым, поэтому любые запросы, нацеленные на порт 80 или 8080, получат такой же ответ. Дело в том, что мне нужен только порт 80, чтобы быть доступным извне, потому что почему-то мой провайдер считает, что оставить порт 8080 открытым для какого-то потенциального злоупотребления? В любом случае, я не хочу, чтобы внешние запросы, направленные на порт 8080, получали ответ, только те, кто нацелен на порт 80, должны получать его.
Пока что вот как мой файл конфигурации для iptables
выглядит как:
*nat
:PREROUTING ACCEPT [89:7936]
:INPUT ACCEPT [70:3812]
:OUTPUT ACCEPT [41:2756]
:POSTROUTING ACCEPT [41:2756]
-A PREROUTING -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 8080
COMMIT
*filter
:INPUT ACCEPT [916:134290]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [819:117300]
:f2b-sshd - [0:0]
-A INPUT -p tcp -m multiport --dports 22 -j f2b-sshd
-A INPUT -p tcp -m tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -p tcp -m tcp --dport 8080 -m state --state NEW,ESTABLISHED -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
COMMIT
Я попытался удалить правило, открывающее порт 8080, но после перезагрузки iptables
сервер также не отвечал на запросы с порта 80. Совсем недавно я подумал о том, чтобы, возможно, добавить еще одно правило перенаправления, которое изменило бы исходный IP-адрес на что-то конкретное для приема в порту 8080, но я не уверен, что это сработает. Здесь мне нужно руководство.
Примечание: Я не слишком разбираюсь в этом инструменте, это главный источник моих сомнений. Кроме того, возможно, мне не хватает некоторых правил, которые могут быть полезны, поэтому любые предложения по новым правилам в комментариях ниже будут оценены.
это схематический должны помочь вам понять, как выполняется обработка пакетов:
Правила filter / INPUT видят только пакеты после того, как они были преобразованы в NAT / PREROUTING, поэтому по умолчанию не могут отличить получение пакета на порт 8080, потому что клиент отправил его напрямую, от получения пакета на порт 8080, потому что клиент отправил его на порт 80, который затем был перенаправлен на порт 8080. В обоих случаях они видят пакет прибывает на порт 8080. Таким образом, вам нужна дополнительная информация, чтобы можно было различить эти два случая.
Перво-наперво: это правило следует удалить, поскольку оно бесполезно:
-A INPUT -p tcp -m tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
потому что, как объяснялось, filter / INPUT не увидит пакет на порту 80: теперь он прибывает на порт 8080. Не доверяйте tcpdump
здесь вслепую: как видно на схеме, tcpdump
(AF_PACKET) видит пакеты перед всем этим, поэтому увидит порт 80.
Вы можете использовать iptables conntrack
match, который запрашивает систему отслеживания соединений netfilter и, таким образом, имеет доступ к недостающей информации: в этом случае, является ли текущий входящий пакет частью соединения, которое подверглось преобразованию DNAT, используя --ctstate DNAT
(REDIRECT - это особый случай DNAT, так же как MASQUERADE - это особый случай SNAT). Есть и другие варианты этого матча, например --ctorigdstport
и т.д., которые, вероятно, могут привести к аналогичным результатам.
Я просто изложу важные правила для этого случая, а не для всего, чтобы проиллюстрировать объяснение. Просто используйте их, когда это необходимо, в нужном месте.
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8080
наверное сразу после родового ... ESTABLISHED,RELATED -j ACCEPT
линия:
iptables -A INPUT -p tcp --dport 8080 -m conntrack --ctstate DNAT -j ACCEPT
iptables -A INPUT -p tcp --dport 8080 -j DROP
(или не добавляйте это последнее правило DROP, если позже появится универсальное правило удаления).
Первое правило INPUT будет соответствовать трафику, поступающему на порт 8080, который был DNATed (здесь изначально поступил на порт 80), в то время как второе правило отбрасывает то, что остается поступающим на порт 8080: попытки прямого подключения.
Примечание: если вам интересно, почему state
матч и conntrack
совпадение выглядит похоже, что state
был заменен conntrack
. Собственно, внутренне модуль ядра xt_conntrack.ko
обрабатывает state
матч в дополнение к conntrack
совпадение для обратной совместимости.
Другой метод передачи этой информации - использование пакета отметка, который является более общим методом и может применяться во многих других случаях. Это произвольное число, которое будет отмечать пакет (только в ядре, а не на проводе) и может использоваться в нескольких местах, включая iptables. mark
соответствовать, чтобы изменить решения. Как MARK
цель не прекращение правило его можно использовать до фактического REDIRECT
правило. Поскольку они отображаются обратно в шестнадцатеричном формате, я установил их также в шестнадцатеричном формате. Вы сами выбираете, что это значит. Здесь 0x80 (который является десятичным 128) будет передавать информацию «пораженный порт 80 и был перенаправлен на порт 8080» сам по себе, поэтому нет необходимости повторно проверять порт позже, отметка подтверждает все. Как обычно, учитывается первый пакет соединения: каждый другой пакет этого соединения обрабатывается общим правилом conntrack с отслеживанием состояния. ... ESTABLISHED,RELATED -j ACCEPT
.
iptables -t nat -A PREROUTING -p tcp --dport 80 -j MARK --set-mark 0x80
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8080
После общего ... ESTABLISHED,RELATED -j ACCEPT
линия:
iptables -A INPUT -m mark --mark 0x80 -j ACCEPT
iptables -A INPUT -p tcp --dport 8080 -j DROP
Я также должен предостеречь вас от опасности использования правила REJECT без предварительного отбрасывания (а не отклонения) пакетов состояния INVALID. Это может вызвать проблемы со случайным сбросом соединения в некоторых редких случаях перегруженности, когда TCP-пакеты прибывают в неправильном порядке. Соответствующий документация по этой проблеме в настоящее время рассматривается возможность добавления:
Итак, вместо:
-A INPUT ... -j REJECT
рассмотрите возможность использования:
-A INPUT ... -m conntrack --ctstate INVALID -j DROP -A INPUT ... -j REJECT
REDIRECT просто изменяет номер порта, поэтому, если соединение было:
client -> public_addres:80
это становится
client -> public_address:8080
Таким образом, вы не сможете одновременно блокировать и принимать, делая то, что делаете.
Сначала удалите это правило:
-A INPUT -p tcp -m tcp --dport 8080 -m state --state NEW,ESTABLISHED -j ACCEPT
И используйте DNAT вместо REDIRECT, что-то вроде:
-A PREROUTING -i eth0 -p tcp -m tcp --dport 80 -j DNAT --to 127.0.0.1:8080
Это может сработать.
Вы также можете слушать только 127.0.0.1:8080 (в отличие от 0.0.0.0:8080).
По моему опыту, вы обычно меняете привязку для службы 8080.
IE вместо привязки к 0.0.0.0:8080 вы бы привязали службу к 127.0.0.1:8080, что означает, что приложение не слушает ваши общедоступные интерфейсы.
В этом случае я бы настроил обратный прокси (nginx) с порта 80/443 на порт 8080, что позволит вам настроить перенаправление с http-порта 80 на https-порт 443, при этом приложение может работать на порту 8080 без знать о SSL.
Я не эксперт в iptables, поэтому я не буду пытаться исправить то, что у вас есть выше.