Доступ к веб-серверу DNAT из локальной сети

12

У меня есть небольшая сеть с маршрутизатором, который поддерживает подключение к Интернету, серверу и некоторым рабочим станциям в локальной сети.

Карта сети

Сервер предназначен для доступа из Интернета, и в iptables маршрутизатора установлено несколько записей DNAT, например:

-A PREROUTING -i ppp0 -p tcp -m multiport --dports 22,25,80,443 -j DNAT --to-destination 192.168.2.10

Внешние пакеты поступают в маршрутизатор через ppp0интерфейс, а внутренние - из br-lanкоммутатора и адаптера WLAN. Проблема заключается в том, что, хотя внешний доступ работает нормально, попытка получить доступ к серверу изнутри локальной сети по DNS-разрешенному внешнему IP-адресу (назначенному ppp0) не удалась.

Единственное решение, которое я смог придумать, - это добавить статические записи в /etc/hostsуказатель маршрутизатора на внутренний IP-адрес, но поскольку здесь нет подстановочных знаков (и у меня есть как минимум три домена верхнего уровня, назначенных этой системе, не считая десятков поддоменов), это довольно хрустящий и подверженный сбоям. Можете ли вы предложить что-то лучше?

Я только нашел этот вопрос , который не был очень полезным.

Если это актуально, роутер запускает OpenWRT 10.03 Kamikaze с dnsmasq.

whitequark
источник
Какая версия OpenWRT?
Кори С.
@Corey 10.03 Стабильно, но это не имеет ничего общего с самим openwrt, не так ли?
whitequark

Ответы:

3

Я удивлен, что спустя почти 8 лет никто не объяснил, как сделать это правильно, используя систему конфигурации UCI, используемую по умолчанию в OpenWRT.

Ответ Стивена Понедельника верен, но он использует iptablesкоманды напрямую, что является более низким уровнем, чем система конфигурации UCI, и, по возможности, лучше его не трогать большинством пользователей OpenWRT.

Правильный способ доступа к внутренним серверам через их общедоступные комбинации IP / портов с другого внутреннего хоста в UCI состоит в том, чтобы включить параметр конфигурации для reflectionкаждой конкретной цели DNAT в файле /etc/config/firewall. Это поведение задокументировано здесь .

Например:

config redirect option target 'DNAT' option src 'wan' option dest 'lan' option proto 'tcp' option src_dport '44322' option dest_ip '192.168.5.22' option dest_port '443' option name 'apache HTTPS server' option reflection '1'

Примечание. Согласно указанной документации OpenWRT reflectionпо умолчанию включено. В моем тестировании это было не так.

vittorio88
источник
15

Я удалил свой оригинальный ответ, потому что я не был полностью уверен, что он был правильным. С тех пор у меня было некоторое время, чтобы настроить небольшую виртуальную сеть виртуальных машин для симуляции рассматриваемой сети. Вот набор правил брандмауэра, который работал для меня (в iptables-saveформате, только для natтаблицы):

-A PREROUTING -d 89.179.245.232/32 -p tcp -m multiport --dports 22,25,80,443 -j DNAT --to-destination 192.168.2.10
-A POSTROUTING -s 192.168.2.0/24 -o ppp0 -j MASQUERADE
-A POSTROUTING -s 192.168.2.0/24 -d 192.168.2.10/32 -p tcp -m multiport --dports 22,25,80,443 -j MASQUERADE

Первое POSTROUTINGправило - это простой способ совместного использования интернет-соединения с локальной сетью. Я оставил это там для полноты.

PREROUTINGПравило и второе POSTROUTINGправило вместе устанавливают соответствующие NATs, так что подключение к серверу через внешний IP - адрес может произойти, независимо от того , соединения происходят из - за пределов или внутри локальной сети. Когда клиенты в локальной сети подключаются к серверу через внешний IP-адрес, сервер видит подключения как исходящие с внутреннего IP-адреса маршрутизатора (192.168.2.1).

Интересно, что оказывается, что есть пара вариантов второго правила POSTROUTING, которые также работают. Если цель изменяется на -j SNAT --to-source 192.168.2.1, эффект (не удивительно) такой же, как MASQUERADE: сервер видит соединения от клиентов локальной сети как исходящие с внутреннего IP-адреса маршрутизатора . С другой стороны, если цель изменяется на -j SNAT --to-source 89.179.245.232, тогда NAT все еще работают, но на этот раз сервер видит подключения клиентов локальной локальной сети как исходящие от внешнего IP-адреса маршрутизатора (89.179.245.232).

Наконец, обратите внимание, что исходное PREROUTING/ DNATправило с -i ppp0не работает, потому что правило никогда не совпадает с пакетами, поступающими от клиентов LAN (так как они не входят в маршрутизатор через ppp0интерфейс). Можно было бы заставить его работать, добавив второе PREROUTINGправило только для клиентов внутренней ЛВС, но оно было бы не элегантным (IMO) и все равно требовало бы явной ссылки на внешний IP-адрес.

Теперь, даже после того, как я подробно изложил решение «шпилька NAT» (или «петля NAT», или «отражение NAT», или как его предпочитают называть), я по-прежнему считаю, что решение DNS с разделением горизонта - - с разрешением внешних клиентов на внешние IP и разрешением внутренних клиентов на внутренние IP --- было бы более приемлемым путем. Почему? Потому что больше людей понимают, как работает DNS, чем понимают, как работает NAT, и большая часть построения хороших систем выбирает использование частей, которые можно обслуживать. Настройка DNS более понятна и, следовательно, правильно поддерживается, чем тайная настройка NAT (конечно, IMO).

Стивен Понедельник
источник
Это прекрасно работает, большое спасибо! Я согласен с тем, что настройка DNS лучше, но вы не можете перенаправлять разные порты на одном и том же внешнем IP на разные машины в локальной сети с ним. Во всяком случае, я единственный, кто когда-либо будет поддерживать эту настройку, так что все в порядке.
Whitequark
Я рад слышать, что это сработало для вас!
Стивен Понедельник
Что такое "ИМО"? Международная метеорологическая организация www.imo.net?
Джонатан Комар
@ macmadness86 IMO == По моему мнению
Стивен Понедельник,
3

Распространенным решением является указание ваших внутренних хостов на локальный DNS-сервер, который возвращает правильный «внутренний» адрес для этих имен хостов.

Другое решение - и мы используем это там, где я работаю на наших брандмауэрах Cisco, - это переписать ответы DNS на брандмауэре, которые соответствуют этим адресам. Я не думаю, что есть инструменты для Linux, которые делают это прямо сейчас.

Вы должны быть в состоянии настроить маршрутизацию на вашем шлюзе для правильной работы. Возможно, вам придется настроить серверы так, чтобы они знали их IP-адрес, отображаемый извне (например, назначив его фиктивному интерфейсу). При такой конфигурации связь от одной внутренней системы к другой внутренней системе - используя ее «внешний» адрес - будет проходить через маршрутизатор.

larsks
источник
Хм. Итак, вы предлагаете добавить внешний IP к интерфейсам серверов, а затем настроить маршрутизатор, чтобы он перенаправлял все пакеты на внешний IP, приходящий из локальной сети на этот сервер? Интересно, скоро проверю.
Уайткварк
Можете ли вы предложить конфигурацию? Я попробовал это:, ip rule add to 89.179.245.232 dev br-lan table 10; ip route add 89.179.245.232 via 192.168.2.10 dev br-lan table 10и это не работает.
Whitequark
Что находится в таблице маршрутизации 10? На внутренних серверах вы, вероятно, захотите, чтобы они имели локальный адрес 192.168.xx (для локальной связи) и общедоступный адрес (в качестве псевдонима) на своем основном интерфейсе.
Larsks
2

То, что вы просите сделать, называется NAT Loopbackи требует добавления правила SNAT, чтобы пакеты, отправленные из вашей локальной сети на ваш сервер, возвращались через маршрутизатор:

-A POSTROUTING -p tcp -s 192.168.2.0/24 -d 192.168.2.10 -m multiport --dports 22,25,80,443 -j SNAT --to-source 89.179.245.232
SiegeX
источник
К сожалению, это не работает. Первоначально я пропустил -i ppp0опцию в моем правиле, о котором идет речь, так как он был обработан другой цепочкой; это правило предотвратит маршрутизацию пакетов, поступающих из локальной сети (и если я включу его, пакеты будут отправлены из неверного источника и будут отклонены).
whitequark
Ты пробовал это? Это повлияет только на пакеты из вашей ЛВС, идущие на IP вашего сервера через эти очень специфические порты.
SiegeX
Да. (И я попытался изменить первое правило тоже). Например, dig отправляет пакет на 192.168.2.1 # 53, а затем получает неожиданный ответ от 192.168.2.10 # 53 с вашим правилом или без него.
Whitequark
0

Комментарий larsks о размещении внутренней версии пространства имен \ domain - это, как правило, способ решения этой проблемы в прошлом. Конечно, для этого вам нужен внутренний DNS-сервер.

CurtM
источник
Да, я написал, что я использую dnsmasq. Есть идеи по настройке автоматической замены?
whitequark
Я ничего не знаю об OpenWRT и Kamikaze, но основываясь на том, что я читаю, - что если вы добавите следующее в ваш /etc/dnsmasq.conf "cname = ext-hostname.domain.com, int-hostname.domain.com"
CurtM
Ну, насколько мне удалось определить, dnsmasq cnameне поддерживает маски и, следовательно, не подходит для меня из-за подсчета поддоменов.
Whitequark
0

Я предложил следующее решение, чтобы разрешить моей гостевой сети подключаться к портам, которые были перенаправлены из моей сети wan на локальную сеть. Этот скрипт находится в моем разделе «Сеть -> Брандмауэр -> Пользовательские правила»:

# lookup the public IP (DDNS resolves to this)
wanip=$(ip route get 8.8.8.8 | awk -F"src " 'NR==1{split($2,a," ");print a[1]}')

# Guest network to LAN
# srcname is the guest network name, this needs to match for iptables
srcname=guest
# CIDR notation of guest and lan networks
srcnet=192.168.15.0/24
tgtnet=192.168.10.0/24
# router (openwrt) IP on lan network
tgtrouter=192.168.10.1
# host on lan network where ports are normally forwarded
tgthost=192.168.10.5
# ports to forward as a list or range
tcpports=8080,9090
udpports=12345

prechain=prerouting_${srcname}_rule
postchain=postrouting_${srcname}_rule

# reset the tables to prevent duplicate rules
iptables -t nat -F ${prechain}
iptables -t nat -F ${postchain}

iptables -t nat -A ${prechain} -s ${srcnet} -d ${wanip}/32 -p tcp -m tcp -m multiport --dports ${tcpports} -m comment --comment "${srcname} NAT reflection TCP DNAT" -j DNAT --to-destination ${tgthost}
iptables -t nat -A ${postchain} -s ${srcnet} -d ${tgthost}/32 -p tcp -m tcp -m multiport --dports ${tcpports} -m comment --comment "${srcname} NAT reflection TCP SNAT" -j SNAT --to-source ${tgtrouter}
iptables -t nat -A ${prechain} -s ${srcnet} -d ${wanip}/32 -p udp -m udp -m multiport --dports ${udpports} -m comment --comment "${srcname} NAT reflection UDP DNAT" -j DNAT --to-destination ${tgthost}
iptables -t nat -A ${postchain} -s ${srcnet} -d ${tgthost}/32 -p udp -m udp -m multiport --dports ${udpports} -m comment --comment "${srcname} NAT reflection UDP SNAT" -j SNAT --to-source ${tgtrouter}

Для поддержки перезагрузок мне нужно было запустить следующую команду из командной строки ssh на openwrt (в противном случае, я считаю, что есть условие гонки, когда некоторые правила были добавлены, а затем сброшены во время перезагрузки):

uci set firewall.@include[0].reload="1"
uci commit firewall

Отражение NAT настраивается для соединений внутри сети LAN с самим собой, но не с другими сетями, если вы создали несколько интерфейсов для изоляции трафика. Я попытался настроить правило пересылки из веб-интерфейса, но оно отправляет весь трафик на порт из гостевой сети на этот узел локальной сети. Выше только перехватывает запросы к IP WAN вместо всего сетевого трафика.

Вместо этого можно использовать внутренний DNS, но только в том случае, если переадресация всех портов идет только на один хост. Если у вас несколько хостов, на которые вы перенаправляете разные порты, вы можете повторить правила для разных портов для разных tgthostIP-адресов и портов.

BMitch
источник
В текущих ядрах есть conntrackмодуль соответствия. И все, что вам нужно, чтобы решить проблему, это использовать одно правило:iptables -t nat -A POSTROUTING --dst <lan-net> ! --src <lan-gw-ip> -m conntrack --ctstate DNAT --ctorigdst <wan-gw-ip> -j MASQUERADE
Антон Данилов
@AntonDanilov приятно, мне это нравится. Правила, которые я использовал, были основаны на правилах отражения NAT, уже существующих в OpenWRT для соединений из той же подсети. Не уверен, что у них были какие-то другие причины, кроме того, что они могли быть написаны до того, как стал доступен Conntrack
BMitch