DNAT и с чем его едят

В статье рассказывается, как осуществить port/ip forwarding в сети, соединенной с Интернетом посредством шлюза на базе iptables

[Дмитрий Коптев (dimez@nm.ru)]

ДАНО: Локальная сеть, роутер с двумя сетевыми карточками (под управлением Linux), в одну карточку включен шнур, по которому идет Интернет. Из роутера идет второй шнур, который раздает этот Интернет всей локальной сети.

НАДО: "Пробросить" порт внутрь локалки (либо вообще "выкинуть" машину наружу), то есть обеспечить доступ извне (из "дикого" Интернета) к какой-либо локальной машине.

РЕШЕНИЕ: Сразу скажу, что на ядрах 2.2.x это получается только с использованием утилиты iproute2 Алексея Кузнецова (сам не пробовал, но, говорят, работает). Так что я рассматриваю вариант kernel-2.4.x + iptables.

Ставим ядро (посвежее), в ядре включаем всё, что касается iptables, ставим iptables (если ещё не поставлены, кстати, рекомендую ставить тоже самые свежие)

Обозначения

$EXT_R_IP - внешний IP роутера
$LOCAL_IP - внутренний адрес машины, которую надо "выкидывать" наружу
$PORT1 - Порт, на который будут заходить извне и попадать на локальную машину
$PORT2 - Порт, который "выбрасывается" наружу (например, 80 - http, либо 21 - ftp)
На роутере выполняем следующие команды (от имени root)
# iptables -t nat -A PREROUTING -p tcp -d $EXT_R_IP --dport $PORT1 -j DNAT --to-destination $LOCAL_IP:$PORT2
# iptables -A FORWARD -i eth0 -d $LOCAL_IP -p tcp --dport $PORT2 -j ACCEPT
Вуаля! Машина видна снаружи!

!!! БОЛЬШОЕ ПРЕДУПРЕЖДЕНИЕ !!!
Прежде чем "выкидывать" порт наружу, имеет смысл поставить на эту машину firewall, либо поставить новую версию программы (web-сервера и прочего), которую случайно не "взломают".

Вариант #2 - требуется вообще "выкинуть" машину наружу, но чисто административными мерами (то есть, не трогая самой машины)

!!! Тут ЕЩЕ БОЛЬШЕЕ ПРЕДУПРЕЖДЕНИЕ !!!
Это гораздо опаснее, чем обычный "проброс" порта - так что ставить нормальный firewall просто необходимость, а не прихоть!!!

Обозначения

1) $IFACE - внешний сетевой интерфейс на роутере (например, eth0)
2) $NEW_IP - новый IP, который будет присвоен "выведенной" из локальной сети машине (если провайдер дал Вам больше одного внешнего IP-адреса)
3) $BC,$NM,$GW - соответственно, broadcast,netmask,gateway, который выдаёт провайдер (в общих чертах)
4) $LOCAL_IP - тоже самое, что и в предыдущем случае
Сначала надо сделать alias (у нас же нет третьей сетевой карточки) сетевого интерфейса (все команды - от имени root, естественно)
# ifconfig $IFACE:0 $NEW_IP netmask $NM broadcast $BC
# route add $NEW_IP gw $GW netmask 0.0.0.0 metric 1 dev $IFACE:0
# iptables -t nat -A PREROUTING -p tcp -d $NEW_IP -j DNAT --to-destination $LOCAL_IP
# iptables -A FORWARD -i eth0 -d $LOCAL_IP -j ACCEPT
Ещё можно написать скрипт, который легко опускает/поднимает DNAT
---cat-/etc/rc.d/rc.dnat---

#!/bin/bash
$IFACE=eth0
$LOCAL_IP="192.168.1.251"
$NEW_IP="q.w.e.r"
$NM="a.s.d.f"
$BC="z.x.c.v"
$GW="p.o.i.u"

case "$1" in
	'stop')
	iptables -D FORWARD -i eth0 -d $LOCAL_IP -j ACCEPT
	iptables -t nat -D PREROUTING -p tcp -d $NEW_IP -j DNAT --to-destination $LOCAL_IP
	route del $NEW_IP gw $GW netmask 0.0.0.0 metric 1 dev $IFACE:0
	ifconfig $IFACE:0 down
	;;
	'start')
	ifconfig $IFACE:0 $NEW_IP netmask $NM broadcast $BC
	route add $NEW_IP gw $GW netmask 0.0.0.0 metric 1 dev $IFACE:0
	iptables -t nat -A PREROUTING -p tcp -d $NEW_IP -j DNAT --to-destination $LOCAL_IP
	iptables -A FORWARD -i eth0 -d $LOCAL_IP -j ACCEPT
	;;
	'restart')
	$0 stop && $0 start
	;;
	*)
	echo "usage $0 start|stop|restart"
	;;
esac

---end-of-cat---

Все! Теперь нашу локальную машину могут ломать хакеры всего Интернета!

[ опубликовано 24/04/2003 ]

Дмитрий Коптев (dimez@nm.ru) - DNAT и с чем его едят   Версия для печати