Шлюз с помощью iptables (Debian)

Обсуждение настройки и работы сервисов, резервирования, сетевых настроек и вопросов безопасности ОС для молодых и начинающих системных администраторов.

Модератор: SLEDopit

Ответить
uscr
Сообщения: 152
ОС: Fedora

Шлюз с помощью iptables

Сообщение uscr »

Здравствуйте. Есть Debian6. Нужно сделать из него шлюз.
Наткнулся на такую статью - http://www.opennet.ru/docs/RUS/iptables/#EXAMPLERCFIREWALL по скрипту, привёденному в ней, создал свой набор правил. Сейчас всё здорово работает. Натятся соединения из локалки и сам шлюз ходит в интернет. Не могу "пробросить" порт снаружи в локалку.
Итак, на время обкатки шлюз смотрит внешним интерфейсом в офисную сеть, к внутреннему пока подключён только один ноутбук.

Внешний интерфейс:
eth0
inet: 192.168.0.254/24
gw: 192.168.0.1

Внутренний:
eth1
inet: 192.168.1.1/24

Вот мой скрипт с правилами:

Код: Выделить всё

#!/bin/sh
#
# 1. Configuration options.
#
INET_IP="192.168.0.254"
INET_IFACE="eth0"
INET_BROADCAST="192.168.0.255"

LAN_IP="192.168.1.1"
LAN_IP_RANGE="192.168.1.0/24"
LAN_IFACE="eth1"

LO_IFACE="lo"
LO_IP="127.0.0.1"

IPTABLES="/sbin/iptables"

###########################################################################
#
# 2. Module loading.
#

#
# Needed to initially load modules
#

/sbin/depmod -a

#
# 2.1 Required modules
#

/sbin/modprobe ip_tables
/sbin/modprobe ip_conntrack
/sbin/modprobe iptable_filter
/sbin/modprobe iptable_mangle
/sbin/modprobe iptable_nat
/sbin/modprobe ipt_LOG
/sbin/modprobe ipt_limit
/sbin/modprobe ipt_state

#
# 2.2 Non-Required modules
#

#/sbin/modprobe ipt_owner
#/sbin/modprobe ipt_REJECT
#/sbin/modprobe ipt_MASQUERADE
#/sbin/modprobe ip_conntrack_ftp
#/sbin/modprobe ip_conntrack_irc
#/sbin/modprobe ip_nat_ftp
#/sbin/modprobe ip_nat_irc

###########################################################################
#
# 3. /proc set up.
#

#
# 3.1 Required proc configuration
#

#echo "1" > /proc/sys/net/ipv4/ip_forward

#
# 3.2 Non-Required proc configuration
#

#echo "1" > /proc/sys/net/ipv4/conf/all/rp_filter
#echo "1" > /proc/sys/net/ipv4/conf/all/proxy_arp
#echo "1" > /proc/sys/net/ipv4/ip_dynaddr

###########################################################################
#
# 4. rules set up.
#

######
# 4.1 Filter table
#

#
# 4.1.1 Set policies
#

$IPTABLES -P INPUT DROP
$IPTABLES -P OUTPUT DROP
$IPTABLES -P FORWARD DROP

#
# 4.1.2 Create userspecified chains
#

#
# Create chain for bad tcp packets
#

$IPTABLES -N bad_tcp_packets

#
# Create separate chains for ICMP, TCP and UDP to traverse
#

$IPTABLES -N allowed
$IPTABLES -N tcp_packets
$IPTABLES -N udp_packets
$IPTABLES -N icmp_packets

#
# 4.1.3 Create content in userspecified chains
#

#
# bad_tcp_packets chain
#

$IPTABLES -A bad_tcp_packets -p tcp --tcp-flags SYN,ACK SYN,ACK \
-m state --state NEW -j REJECT --reject-with tcp-reset
$IPTABLES -A bad_tcp_packets -p tcp ! --syn -m state --state NEW -j LOG \
--log-prefix "New not syn:"
$IPTABLES -A bad_tcp_packets -p tcp ! --syn -m state --state NEW -j DROP

#
# allowed chain
#

$IPTABLES -A allowed -p TCP --syn -j ACCEPT
$IPTABLES -A allowed -p TCP -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -A allowed -p TCP -j DROP

#
# TCP rules
#

#$IPTABLES -A tcp_packets -p TCP -s 0/0 --dport 21 -j allowed

$IPTABLES -A tcp_packets -p TCP -s 0/0 --dport 22 -j allowed
$IPTABLES -A tcp_packets -p TCP -s 0/0 --dport 4242 -j allowed

#SSH moved to 13579 port
#$IPTABLES -A tcp_packets -p TCP -s 0/0 --dport 13579 -j allowed

#$IPTABLES -A tcp_packets -p TCP -s 0/0 --dport 80 -j allowed
#$IPTABLES -A tcp_packets -p TCP -s 0/0 --dport 113 -j allowed

#
# UDP ports
#

#$IPTABLES -A udp_packets -p UDP -s 0/0 --destination-port 53 -j ACCEPT
#$IPTABLES -A udp_packets -p UDP -s 0/0 --destination-port 123 -j ACCEPT
#$IPTABLES -A udp_packets -p UDP -s 0/0 --destination-port 2074 -j ACCEPT
#$IPTABLES -A udp_packets -p UDP -s 0/0 --destination-port 4000 -j ACCEPT

#
# In Microsoft Networks you will be swamped by broadcasts. These lines
# will prevent them from showing up in the logs.
#

#$IPTABLES -A udp_packets -p UDP -i $INET_IFACE -d $INET_BROADCAST \
#--destination-port 135:139 -j DROP

#
# If we get DHCP requests from the Outside of our network, our logs will
# be swamped as well. This rule will block them from getting logged.
#

#$IPTABLES -A udp_packets -p UDP -i $INET_IFACE -d 255.255.255.255 \
#--destination-port 67:68 -j DROP

#
# ICMP rules
#

$IPTABLES -A icmp_packets -p ICMP -s 0/0 --icmp-type 8 -j ACCEPT
$IPTABLES -A icmp_packets -p ICMP -s 0/0 --icmp-type 11 -j ACCEPT

#
# 4.1.4 INPUT chain
#

#
# Bad TCP packets we don't want.
#

$IPTABLES -A INPUT -p tcp -j bad_tcp_packets

#
# Rules for special networks not part of the Internet
#

$IPTABLES -A INPUT -p ALL -i $LAN_IFACE -s $LAN_IP_RANGE -j ACCEPT
$IPTABLES -A INPUT -p ALL -i $LO_IFACE -s $LO_IP -j ACCEPT
$IPTABLES -A INPUT -p ALL -i $LO_IFACE -s $LAN_IP -j ACCEPT
$IPTABLES -A INPUT -p ALL -i $LO_IFACE -s $INET_IP -j ACCEPT

#
# Special rule for DHCP requests from LAN, which are not caught properly
# otherwise.
#

$IPTABLES -A INPUT -p UDP -i $LAN_IFACE --dport 67 --sport 68 -j ACCEPT

#
# Rules for incoming packets from the internet.
#

$IPTABLES -A INPUT -p ALL -d $INET_IP -m state --state ESTABLISHED,RELATED \
-j ACCEPT
$IPTABLES -A INPUT -p TCP -i $INET_IFACE -j tcp_packets
$IPTABLES -A INPUT -p UDP -i $INET_IFACE -j udp_packets
$IPTABLES -A INPUT -p ICMP -i $INET_IFACE -j icmp_packets

#
# If you have a Microsoft Network on the outside of your firewall, you may
# also get flooded by Multicasts. We drop them so we do not get flooded by
# logs
#

$IPTABLES -A INPUT -i $INET_IFACE -d 224.0.0.0/8 -j DROP

#
# Log weird packets that don't match the above.
#

$IPTABLES -A INPUT -m limit --limit 3/minute --limit-burst 3 -j LOG \
--log-level DEBUG --log-prefix "IPT INPUT packet died: "

#
# 4.1.5 FORWARD chain
#

#
# Bad TCP packets we don't want
#

$IPTABLES -A FORWARD -p tcp -j bad_tcp_packets

#
# Accept the packets we actually want to forward
#

$IPTABLES -A FORWARD -i $LAN_IFACE -j ACCEPT
$IPTABLES -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT

#
# Log weird packets that don't match the above.
#

$IPTABLES -A FORWARD -m limit --limit 3/minute --limit-burst 3 -j LOG \
--log-level DEBUG --log-prefix "IPT FORWARD packet died: "

#
# 4.1.6 OUTPUT chain
#

#
# Bad TCP packets we don't want.
#

$IPTABLES -A OUTPUT -p tcp -j bad_tcp_packets

#
# Special OUTPUT rules to decide which IP's to allow.
#

$IPTABLES -A OUTPUT -p ALL -s $LO_IP -j ACCEPT
$IPTABLES -A OUTPUT -p ALL -s $LAN_IP -j ACCEPT
$IPTABLES -A OUTPUT -p ALL -s $INET_IP -j ACCEPT

#
# Log weird packets that don't match the above.
#

$IPTABLES -A OUTPUT -m limit --limit 3/minute --limit-burst 3 -j LOG \
--log-level DEBUG --log-prefix "IPT OUTPUT packet died: "

######
# 4.2 nat table
#

#
# 4.2.1 Set policies
#

#
# 4.2.2 Create user specified chains
#

#
# 4.2.3 Create content in user specified chains
#

#
# 4.2.4 PREROUTING chain
#

#$IPTABLES -t nat -A PREROUTING -p tcp --dport 4242 -d $INET_IP -j DNAT --to-destination 192.168.1.2:80
$IPTABLES -t nat -A PREROUTING -i $INET_IFACE -p tcp -m tcp --dport 4242 -j DNAT --to-destination 192.168.1.2:80

#
# 4.2.5 POSTROUTING chain
#

#
# Enable simple IP Forwarding and Network Address Translation
#

$IPTABLES -t nat -A POSTROUTING -o $INET_IFACE -j SNAT --to-source $INET_IP


Он же, почищенный от комментариев для удобочитаемости:

Код: Выделить всё

#!/bin/sh
#
# 1. Configuration options.
#
INET_IP="192.168.0.254"
INET_IFACE="eth0"
INET_BROADCAST="192.168.0.255"

LAN_IP="192.168.1.1"
LAN_IP_RANGE="192.168.1.0/24"
LAN_IFACE="eth1"

LO_IFACE="lo"
LO_IP="127.0.0.1"

IPTABLES="/sbin/iptables"

/sbin/depmod -a

/sbin/modprobe ip_tables
/sbin/modprobe ip_conntrack
/sbin/modprobe iptable_filter
/sbin/modprobe iptable_mangle
/sbin/modprobe iptable_nat
/sbin/modprobe ipt_LOG
/sbin/modprobe ipt_limit
/sbin/modprobe ipt_state


$IPTABLES -P INPUT DROP
$IPTABLES -P OUTPUT DROP
$IPTABLES -P FORWARD DROP

$IPTABLES -N bad_tcp_packets

$IPTABLES -N allowed
$IPTABLES -N tcp_packets
$IPTABLES -N udp_packets
$IPTABLES -N icmp_packets

$IPTABLES -A bad_tcp_packets -p tcp --tcp-flags SYN,ACK SYN,ACK \
-m state --state NEW -j REJECT --reject-with tcp-reset
$IPTABLES -A bad_tcp_packets -p tcp ! --syn -m state --state NEW -j LOG \
--log-prefix "New not syn:"
$IPTABLES -A bad_tcp_packets -p tcp ! --syn -m state --state NEW -j DROP

$IPTABLES -A allowed -p TCP --syn -j ACCEPT
$IPTABLES -A allowed -p TCP -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -A allowed -p TCP -j DROP

$IPTABLES -A tcp_packets -p TCP -s 0/0 --dport 22 -j allowed
$IPTABLES -A tcp_packets -p TCP -s 0/0 --dport 4242 -j allowed

$IPTABLES -A icmp_packets -p ICMP -s 0/0 --icmp-type 8 -j ACCEPT
$IPTABLES -A icmp_packets -p ICMP -s 0/0 --icmp-type 11 -j ACCEPT

$IPTABLES -A INPUT -p tcp -j bad_tcp_packets

$IPTABLES -A INPUT -p ALL -i $LAN_IFACE -s $LAN_IP_RANGE -j ACCEPT
$IPTABLES -A INPUT -p ALL -i $LO_IFACE -s $LO_IP -j ACCEPT
$IPTABLES -A INPUT -p ALL -i $LO_IFACE -s $LAN_IP -j ACCEPT
$IPTABLES -A INPUT -p ALL -i $LO_IFACE -s $INET_IP -j ACCEPT

$IPTABLES -A INPUT -p UDP -i $LAN_IFACE --dport 67 --sport 68 -j ACCEPT

$IPTABLES -A INPUT -p ALL -d $INET_IP -m state --state ESTABLISHED,RELATED \
-j ACCEPT
$IPTABLES -A INPUT -p TCP -i $INET_IFACE -j tcp_packets
$IPTABLES -A INPUT -p UDP -i $INET_IFACE -j udp_packets
$IPTABLES -A INPUT -p ICMP -i $INET_IFACE -j icmp_packets

$IPTABLES -A INPUT -i $INET_IFACE -d 224.0.0.0/8 -j DROP

$IPTABLES -A INPUT -m limit --limit 3/minute --limit-burst 3 -j LOG \
--log-level DEBUG --log-prefix "IPT INPUT packet died: "

$IPTABLES -A FORWARD -p tcp -j bad_tcp_packets

$IPTABLES -A FORWARD -i $LAN_IFACE -j ACCEPT
$IPTABLES -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT

$IPTABLES -A FORWARD -m limit --limit 3/minute --limit-burst 3 -j LOG \
--log-level DEBUG --log-prefix "IPT FORWARD packet died: "

$IPTABLES -A OUTPUT -p tcp -j bad_tcp_packets

$IPTABLES -A OUTPUT -p ALL -s $LO_IP -j ACCEPT
$IPTABLES -A OUTPUT -p ALL -s $LAN_IP -j ACCEPT
$IPTABLES -A OUTPUT -p ALL -s $INET_IP -j ACCEPT

$IPTABLES -A OUTPUT -m limit --limit 3/minute --limit-burst 3 -j LOG \
--log-level DEBUG --log-prefix "IPT OUTPUT packet died: "

#$IPTABLES -t nat -A PREROUTING -p tcp --dport 4242 -d $INET_IP -j DNAT --to-destination 192.168.1.2:80
$IPTABLES -t nat -A PREROUTING -i $INET_IFACE -p tcp -m tcp --dport 4242 -j DNAT --to-destination 192.168.1.2:80

$IPTABLES -t nat -A POSTROUTING -o $INET_IFACE -j SNAT --to-source $INET_IP


Пробросить пытаюсь 80 порт с компьютера 192.168.1.2 на 4242 порт внешнего интерфейса. Делаю это правилом $IPTABLES -t nat -A PREROUTING -i $INET_IFACE -p tcp -m tcp --dport 4242 -j DNAT --to-destination 192.168.1.2:80 или $IPTABLES -t nat -A PREROUTING -p tcp --dport 4242 -d $INET_IP -j DNAT --to-destination 192.168.1.2:80 - ни одно из них не работает. Сами запросы на порт 4242 я разрешил правилом $IPTABLES -A tcp_packets -p TCP -s 0/0 --dport 4242 -j allowed. Проверяю telnet'ом. При запуске telnet 192.168.1.2 80 самого шлюза ответы приходят, а telnet 192.168.0.254 4242 из "внешки" - таймаут.

Что не так?
Спасибо сказали:
IMB
Сообщения: 2559
ОС: Debian

Re: Шлюз с помощью iptables

Сообщение IMB »

FORWARDING
Изучите схему движения пакетов, наглядное изображение можно посмотреть, например, здесь http://tresnet.ru/archives/274
Спасибо сказали:
uscr
Сообщения: 152
ОС: Fedora

Re: Шлюз с помощью iptables

Сообщение uscr »

IMB писал(а):
22.02.2011 13:04
FORWARDING
Изучите схему движения пакетов, наглядное изображение можно посмотреть, например, здесь http://tresnet.ru/archives/274

Яснее не стало. Очевидно, что подменить адрес назначения нужно до принятия решения о маршрутизации. Значит PREROUTING и никак иначе.
Спасибо сказали:
IMB
Сообщения: 2559
ОС: Debian

Re: Шлюз с помощью iptables

Сообщение IMB »

А что не понятно?
Вы хотите что бы пакеты направленные на определённый порт шлюза пересылались на внутреннию машину. Для этого вы таблице NAT средствами PREROUTING меняете адрес и, возможно, порт назначения пакета. В результате этот пакет для вашего шлюза становится транзитным и решение о его пропуске принимаются в цепочке FORWARD.
Это если смотреть со стороны фильтрации, но при этом не надо забывать о маршрутизации, если ваш шлюз примет решение припустить этот пакет, он должен знать как его доставить до получателя.
Спасибо сказали:
uscr
Сообщения: 152
ОС: Fedora

Re: Шлюз с помощью iptables

Сообщение uscr »

IMB писал(а):
23.02.2011 18:35
А что не понятно?
Вы хотите что бы пакеты направленные на определённый порт шлюза пересылались на внутреннию машину. Для этого вы таблице NAT средствами PREROUTING меняете адрес и, возможно, порт назначения пакета. В результате этот пакет для вашего шлюза становится транзитным и решение о его пропуске принимаются в цепочке FORWARD.
Это если смотреть со стороны фильтрации, но при этом не надо забывать о маршрутизации, если ваш шлюз примет решение припустить этот пакет, он должен знать как его доставить до получателя.

Ах, ну да! Слона то я и не приметил! Нужно разрешить пакет в FORWARD же!
Кстати, возникла ещё одна странная проблема. Я свой вышеупомянутый скрипт положил в /etc/network/if-up.d но он не выполняется при загрузке. Если зайти по ssh и руками запустить его, он выполняется и всё работает. Что не так?
Спасибо сказали:
IMB
Сообщения: 2559
ОС: Debian

Re: Шлюз с помощью iptables

Сообщение IMB »

В Debian-base этот срабатывает, не забываем о правах доступа и бите исполняемости.
Спасибо сказали:
uscr
Сообщения: 152
ОС: Fedora

Re: Шлюз с помощью iptables

Сообщение uscr »

IMB писал(а):
23.02.2011 21:50
В Debian-base этот срабатывает, не забываем о правах доступа и бите исполняемости.


root@debiangw:~# ls -l /etc/network/if-up.d/rc.firewall
-rwxr-xr-x 1 root root 6905 Feb 24 11:00 /etc/network/if-up.d/rc.firewall

Скрипт исполняемый. Я ведь по ssh без проблем его запускаю.

Но это ещё не конец.
Проверяю я шлюз следующим образом:
В шлюз в интерфейс eth1 (192.168.1.1) подключён ноутбук, на котором установлен апач. У ноутбука адрес 192.168.1.2. Проверяю работоспособность "проброса" я пытаясь с офисного компьютера (внешний интерфейс шлюза, напомню, смотрит пока в офисную сеть) зайти на 4242 порт шлюза (telnet 192.168.0.254 4242) до сегодняшнего утра я получал telnet: Unable to connect to remote host: Connection timed out.
Сегодня утром я первым делом дописал правило $IPTABLES -A FORWARD -i $INET_IFACE -j ACCEPT и наконец смог "телнетнуть" на 4242 порт. Потом я отвлёкся, а вернувшись на место, с полной уверенностью, что всё работает, снёс апач с ноута. Ещё через время меня осенило, что в таком виде правило оставлять нельзя - довольно дыряво. Для последующих тестов снова установил апач на ноутбук, но проброс уже не работает... Перезагружал и ноутбук и шлюз, рестартил демоны - всё без толку. С самого шлюза "телнетнуть" на 192.168.1.2 80 могу без проблем.
Обращаю внимание, главная идея моего мыслеизлияния - "всё работало, потом перестало".


UPD.
А сейчас, перед отправкой сообщения, решил ещё раз ребутнуть шлюз и проброс опять заработал... Осталось только разобраться с автостартом скрипта.

UPD2
Ещё не получается "пробросить" внешний порт на 22 внутренний. Пытаюсь DNAT'ить с 13579 внешки на 127.0.0.1:22 - не работает. А тут ведь должно быть достаточно разрешающего правила $IPTABLES -A tcp_packets -p TCP -s 0/0 --dport 13579 -j allowed, потому как в INPUT пакет всё равно пройдет по цепочке tcp_packets , по правилу $IPTABLES -A INPUT -p TCP -i $INET_IFACE -j tcp_packets. Разве нет?
Спасибо сказали:
Ответить