Сервер в кармане, или просто о сложном!

главная - Статьи - Linux, FreeBSD

Настройка iptables и NAT

Теги: Linux Iptables NAT

Задача: настроить шлюз в интернет для офиса на основе обычного компьютера с установленной Linux с двумя сетевыми картами.

Условимся, что внутренняя сетевая карта называется eth1, внешняя - eth0.

Чуть-чуть ликбеза. Мы настроим (1) forwarding (маршрутизацию) и (2) NAT (netowrk address translation).

(1) Маршрутизация (forwarding) в данном случае означает, что когда пакет из локальной сети в поисках "ya.ru" (или иного сайта или внешнего IP) попадает на наш шлюз, то шлюз должен знать, что такие пакеты надо передать на внешний интерфейс (eth0) - мол, летите, соколы, дальше. Дальше точно так же (ну, пусть не точно также, ну пусть и совсем не так же) от одного узла до другого провайдеры перекидывают наш пакет все дальше от нас и все ближе к цели.

(2) NAT. Как много в этом слове... Пример. Вася открывает сайт ya.ru (IP: 213.180.193.3). Т.к. в локальной сети IP-адреса локальные (не маршрутизируются в интернет, ну никак), то наш шлюз подменяет адрес источника пакета (ноутбук Васи, src=192.168.1.134) на свой собственный IP адрес (src=1.2.3.4), выданный провайдером. Сайт ya.ru будет считать, что IP Васи не 192.168.1.134, а 1.2.3.4. И ответный пакет ya.ru отправит нашему шлюзу. При получении ответа от удаленного сервера наш шлюз вспомнит, какая локальная машина запрашивала 213.180.193.3 и в ответном пакете поменяет dst с 1.2.3.4 на 192.168.1.134.

суть NAT

Такой NAT еще называют SNAT (Source NAT), т.к. изначально меняется адрес источника (src, source). Есть другой NAT - DNAT (destination nat, dst nat). Но морочить себе голову сейчас мы не дадим, не так ли ;)

Если в дальнейшем будет нужна статистика и пр., то настроить Squid будет не так и сложно.

Для простоты обозначений, наш шлюз будем называть сервер. Поехали...

iptables nat internet firewall

1. Создаем скрипт правил iptables iptables.sh

Например, в директории /root создадим файл iptables.sh, дадим ему права на исполнение:

chmod +x /root/iptables.sh

Теперь поместим в этот файл следующий текст:

#!/bin/sh

# Define vars
IF_EXT="eth0"
IF_INT="eth1"
IPT="/sbin/iptables"

# flush
$IPT --flush
$IPT -t nat --flush
$IPT -t mangle --flush
$IPT -X

# loopback
$IPT -A INPUT -i lo -j ACCEPT
$IPT -A OUTPUT -o lo -j ACCEPT

# default
$IPT -P INPUT DROP
$IPT -P OUTPUT DROP
$IPT -P FORWARD DROP

# allow forwarding
echo 1 > /proc/sys/net/ipv4/ip_forward

# PROTECT FIREWALL

$IPT -N bad_packets
$IPT -P bad_packets ACCEPT

$IPT -A bad_packets -i $IF_EXT -s 10.0.0.0/8 -j DROP
$IPT -A bad_packets -i $IF_EXT -s 172.16.0.0/12 -j DROP
$IPT -A bad_packets -i $IF_EXT -s 192.168.0.0/12 -j DROP
$IPT -A bad_packets -i $IF_EXT -s 127.0.0.0/8 -j DROP
$IPT -A bad_packets -i $IF_EXT -s 0.0.0.0/8 -j DROP
$IPT -A bad_packets -i $IF_EXT -s 169.254.0.0/16 -j DROP
$IPT -A bad_packets -i $IF_EXT -s 192.0.2.0/24 -j DROP
$IPT -A bad_packets -i $IF_EXT -s 204.152.64.0/23 -j DROP
$IPT -A bad_packets -i $IF_EXT -s 224.0.0.0/3 -j DROP
$IPT -A bad_packets -i $IF_EXT -s 240.0.0.0/5 -j DROP

$IPT -A INPUT -j bad_packets
$IPT -A OUTPUT -j bad_packets
$IPT -A FORWARD -j bad_packets

# FORWARD chain
# #########################################

# allow new connections from local net to out
$IPT -A FORWARD -i $IF_INT -o $IF_EXT -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
# do not allow new connections from internet, but support established connections from local network
$IPT -A FORWARD -i $IF_EXT -o $IF_INT -m state --state ESTABLISHED,RELATED -j ACCEPT

# NAT
# #########################################

# SNAT - local users to out internet
$IPT -t nat -A POSTROUTING -o $IF_EXT -j MASQUERADE

# INPUT chain
# #########################################

$IPT -A INPUT -p tcp ! --syn -m state --state NEW -j DROP
$IPT -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

$IPT -A INPUT -i $IF_INT -p tcp --dport 22 -j ACCEPT

# OUTPUT chain
# #########################################

# new local connections
$IPT -A OUTPUT -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT

2. Комментарии к скрипту iptables.sh

  1. Все секции снабжены минимальными комментариями, поэтому в них не запутается даже новичок.
  2. Наиболее "туманная" секция -  # PROTECT FIREWALL, но во-первых, временно вы можете ее вообще убрать, а во-вторых, если задуматься, там всё просто. Мы защищаем наш сервер от атак, когда из внешней сети пытаются "прикинуться" внутренними адресами. Вот и все.
  3. Чтобы наш сервер в принципе мог выпускать во внешний мир клиентов локальной сети, обязательно надо включить forwarding (почти в самом начале скрипта):

    # allow forwarding
    echo 1 > /proc/sys/net/ipv4/ip_forward

    Данный параметр также может быть задан через параметр:

    net.ipv4.ip_forward = 1 в файле /etc/sysctl.conf.

    Чтобы изменения в файле sysctl.conf вступили в силу, выполните следующую команду:

    sysctl -p /etc/sysctl.conf

  4. В секции # INPUT chain мы разрешаем клиентам локальной сети подключаться к серверу по ssh. Обратите внимание, несмотря на то, что к самому серверу можно обратиться только по ssh, клиенты локальной сети не будут ограничены в выходе в интернет. Цепочка INPUT не для них!
  5. В цепочке # OUTPUT chain мы разрешаем серверу обращаться во внешний мир (скачивать обновления, например). Для упрощения считаем, что мы доверяем нашему серверу и разрешаем ему любые исходящие соединения.
  6. Еще раз отмечу - цепочки INPUT и OUTPUT работают только для тех пакетов, которые адресованы локальной машине, в нашем случае это сам сервер.
  7. Фактически, пакет из локальной сети в интернет проходит две (упрощенно) цепочки: FORWARD -> POSTROUTING. Более детальное описание этапов прохождения пакетов через iptables смотрите в статье "Порядок прохождения таблиц и цепочек IPTABLES". Поэтому все ограничения клиентов локальной сети (разрешить ли ICQ, WWW, POP3 и т.п.) настраиваются правилами FORWARD (секция #FORWARD chain). Например, для того, чтобы разрешить доступ только к сайтам, пишем:

    $IPT -A FORWARD -i $IF_INT -o $IF_EXT -dport 80 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT

    Правило по-умолчанию ($IPT -A FORWARD -i $IF_INT -o $IF_EXT -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT) естественно, удаляем либо комментируем символом #.
  8. Для того, чтобы после перезагрузки правила iptables не стирались, после того, как выполните скрипт iptables.sh и убедитесь, что все работает так, как надо, выполните команду:

    service iptables save

    Эта команда сохранит настройки iptables. Эта команда подойдет для RHEL-основанных дистрибутивов. Для других не знаю. Если нужен универсальный метод - поместите запуск этого скрипта в автозагрузку. 
  9. Пожалуй, все. Естественно, если вы новичок, НИКОГДА не настраивайте правила iptables находясь не за клавиатурой самого сервера. Ведь если вы случайно запретите себе доступ, то придется ноги-в-руки-и-на-работу :) Если вы уже знаете, что делаете, это к вам не относится.
  10. Если есть вопросы, пишите!

Авторизуйтесь для добавления комментариев!


    забыли пароль?    новый пользователь?