Настройка 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 еще называют SNAT (Source NAT), т.к. изначально меняется адрес источника (src, source). Есть другой NAT — DNAT (destination nat, dst nat). Но морочить себе голову сейчас мы не дадим, не так ли 😉
Если в дальнейшем будет нужна статистика и пр., то настроить Squid будет не так и сложно.
Для простоты обозначений, наш шлюз будем называть сервер. Поехали.
1. Создаем скрипт правил iptables iptables.sh
Например, в директории /root создадим файл iptables.sh, дадим ему права на исполнение:
chmod +x /root/iptables.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
$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
# 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
# SNAT — local users to out internet
$IPT -t nat -A POSTROUTING -o $IF_EXT -j MASQUERADE
$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
# new local connections
$IPT -A OUTPUT -m state —state NEW,ESTABLISHED,RELATED -j ACCEPT
2. Комментарии к скрипту iptables.sh
- Все секции снабжены минимальными комментариями, поэтому в них не запутается даже новичок.
- Наиболее «туманная» секция — # PROTECT FIREWALL, но во-первых, временно вы можете ее вообще убрать, а во-вторых, если задуматься, там всё просто. Мы защищаем наш сервер от атак, когда из внешней сети пытаются «прикинуться» внутренними адресами. Вот и все.
- Чтобы наш сервер в принципе мог выпускать во внешний мир клиентов локальной сети, обязательно надо включить 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
$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) естественно, удаляем либо комментируем символом #.
Для того, чтобы после перезагрузки правила iptables не стирались, после того, как выполните скрипт iptables.sh и убедитесь, что все работает так, как надо, выполните команду:
service iptables save
Эта команда сохранит настройки iptables. Эта команда подойдет для RHEL-основанных дистрибутивов. Для других не знаю. Если нужен универсальный метод — поместите запуск этого скрипта в автозагрузку.
Источник
Iptables — скрипты для конфигурирования
В статье представлено несколько скриптов для конфигурирования iptables и ip6tables: сброс настроек по умолчанию для всех таблиц, цепочек фаервола с удалением пользовательских названий цепочек и базовые конфигурации для iptables протоколов IPv4 и IPv6. Описание процесса настройки iptables, ip6tables и как сохранить конфигурацию фаервола после перезагрузки сервера — читайте тут: Как настроить iptables.
Очистка всех настроек
Этот скрипт поможет очистить все настройки iptables, ip6tables и установить политики по умолчанию для всех цепочек firewall. Его можно установить в cron и запускать, например, раз в 20 минут, для того, чтобы в ходе экспериментов с фаерволом не лишиться доступа к удаленному серверу.
Если запустить скрипт без параметров, то в консоль пользователю будет выводиться информация о конфигурации скрипта (какие firewall будут затронуты и политика по умолчанию). После положительного ответа (нажатия Y) отобразится краткий отчет по проведенным действиям.
Чтобы скрипт запустился в автоматическом режиме, например из cron, необходимо запускать скрипт с параметром -cron:
В этом случае, не будет запрашиваться подтверждение на выполнение изменений в iptables, и скрипт выполнится без отображения запускаемых им команд.
Закомментировав строку iptables_path[1] или iptables_path[2] — можно выбрать, для какого из протоколов, IPv4 или IPv6 будут применяться настройки. Также, присвоив переменной def_val значение DROP, можно полностью закрыть сервер от сети, но ни в коем случае не применяйте параметр DROP для той сети, по которой подключены, если работаете удаленно!
# Полный путь к iptables
iptables_path[1]=»/sbin/iptables»
# Полный путь к ip6tables
iptables_path[2]=»/sbin/ip6tables»
# Состояние по умолчанию, устанавливаемое скриптом
def_val=»ACCEPT»
# Таблицы iptables
ipt_table[1]=’filter’
ipt_table[2]=’nat’
ipt_table[3]=’mangle’
ipt_table[4]=’raw’
ipt_table[5]=’security’
# Цепочки для каждой таблицы
chain_filter=( INPUT OUTPUT FORWARD )
chain_nat=( PREROUTING INPUT OUTPUT POSTROUTING )
chain_mangle=( PREROUTING INPUT FORWARD OUTPUT POSTROUTING )
chain_raw=( PREROUTING OUTPUT )
chain_security=( INPUT OUTPUT FORWARD )
if [ «$1» != «$cron_flag» ]
then
echo «Firewall set default and clear user settings.»
echo «»
echo «Setting:»
echo «Firewall path: $
echo «Default value for all chains tables: $def_val.»
echo «»
read -p «Are you sure to start (y/n): » AMSURE.
if [ «$AMSURE» != «y» ]
then
echo «Exit, no changes.»
exit
fi
fi
[ «$1» != «$cron_flag» ] && echo «»
[ «$1» != «$cron_flag» ] && echo «Firewal script $iptables_path:»
# Запуск настроек iptables
for c in $(eval echo «\$<$chain[@]>«); do
$iptables_path -t $table -P $c $def_val
$iptables_path -t $table -F
$iptables_path -t $table -X
chains=»$
done
if [ «$1» != «$cron_flag» ]
then
chains=»$
echo » — Table \»$table\», chains: $chains — all setting cleared.»
fi
done
[ «$1» != «$cron_flag» ] && echo «»
done
Конфигурация iptables
Скрипт iptables_conf_set загружает в iptables базовую конфигурацию, предварительно очистив все правила и пользовательские цепочки для ВСЕХ таблиц iptables, и записывает настройки в файл, указанный в переменной $IPTCONF.
Правила разрешают доступ из вне на указанном сетевом интерфейсе только к определенным портам и запрещают весь остальной входящий трафик (таблица filter, цепочка INPUT). Также, в качестве примера, приведены настройки для блокирования исходящего трафика в цепочке OUTPUT таблицы filter. Но, поскольку, последним правилом в OUTPUT записано: «-A OUTPUT -j ACCEPT», что разрешает весь исходящий (созданный сервером) трафик, то в не зависимости от правил цепочки, остальные пакеты блокироваться не будут. Если нужно блокировать все, кроме разрешенных, соединения, инициированные сервером, можно установить в последнем правиле цепочки OUTPUT направление DROP, как это сделано в цепочке INPUT.
Перед запуском скрипта внимательно проверьте все устанавливаемые им правила, чтобы не лишиться доступа к серверу, если конфигурирование происходит удаленно.
# Полный путь к iptables
IPT=»/sbin/iptables»
# Полный путь к iptables-save
IPTS=»/sbin/iptables-save»
# Полный путь к файлу, в котором будет сохранена конфигурация iptables
IPTCONF=»/etc/iptables.conf»
# Название сетевого интерфейса, к которому будут применены разрешающие правила
# Название можно найти тут: /etc/network/interfaces
PUBIF=»eth0″
# IP-адрес сервера
SRVIP=`ifconfig $PUBIF | grep ‘inet addr’ | awk <'print $2'>| sed s/.*://`
# Состояние по умолчанию, устанавливаемое скриптом
def_val=»ACCEPT»
# Таблицы iptables
ipt_table[1]=’filter’
ipt_table[2]=’nat’
ipt_table[3]=’mangle’
ipt_table[4]=’raw’
ipt_table[5]=’security’
# Цепочки для каждой таблицы
chain_filter=( INPUT OUTPUT FORWARD )
chain_nat=( PREROUTING INPUT OUTPUT POSTROUTING )
chain_mangle=( PREROUTING INPUT FORWARD OUTPUT POSTROUTING )
chain_raw=( PREROUTING OUTPUT )
chain_security=( INPUT OUTPUT FORWARD )
echo «Starting IPv4 firewall (iptables) configure»
read -p «Are you sure to start (y/n): » start
if [ «$start» != «y» ]
then
echo «Exit, no changes.»
exit
fi
echo «»
echo «Step 1: clean old configuration»
# Сброс настроек iptables
for c in $(eval echo «\$<$chain[@]>«); do
$IPT -t $table -P $c $def_val
$IPT -t $table -F
$IPT -t $table -X
chains=»$
done
chains=»$
echo » — Table \»$table\», chains: $chains — all setting cleared.»
done
echo «»
echo «Step 2: saved main configuration»
# Полный доступ интерфейса loopback
$IPT -A INPUT -i lo -j ACCEPT
$IPT -A OUTPUT -o lo -j ACCEPT
# Разрешить весь исходящий трафик и инициированный им входящий
$IPT -A INPUT -i $PUBIF -m conntrack —ctstate RELATED,ESTABLISHED -j ACCEPT
#$IPT -A OUTPUT -o $PUBIF -m conntrack —ctstate NEW,ESTABLISHED,RELATED -j ACCEPT
# Разрешить входящий ICMP
$IPT -A INPUT -i $PUBIF -p icmp -j ACCEPT
$IPT -A OUTPUT -o $PUBIF -p icmp -j ACCEPT
# Разрешить SSH
$IPT -A INPUT -i $PUBIF -p tcp -m tcp —dport 22 -j ACCEPT
$IPT -A OUTPUT -o $PUBIF -p tcp -m tcp —sport 22 -j ACCEPT
# Разрешить HTTP
$IPT -A INPUT -i $PUBIF -p tcp -m tcp —dport 80 -j ACCEPT
$IPT -A OUTPUT -o $PUBIF -p tcp -m tcp —sport 80 -j ACCEPT
# Разрешить HTTPS
$IPT -A INPUT -i $PUBIF -p tcp -m tcp —dport 443 -j ACCEPT
$IPT -A OUTPUT -o $PUBIF -p tcp -m tcp —sport 443 -j ACCEPT
# Открыть порт OpenVPN
$IPT -A INPUT -i $PUBIF -m tcp -p tcp —dport 1723 -j ACCEPT
$IPT -A INPUT -i $PUBIF -p gre -j ACCEPT
$IPT -A OUTPUT -o $PUBIF -p tcp -m tcp —sport 1723 -j ACCEPT
$IPT -A OUTPUT -o $PUBIF -p gre -j ACCEPT
# Nat для VPN-подключения
$IPT -t nat -A POSTROUTING -j SNAT —to-source $SRVIP
# Логирование всего, что не попало под правила ACCEPT
# $IPT -A INPUT -i $PUBIF -j LOG
# Запретить весь входящий и исходящий трафик на всех сетевых интерфейсах
# не попавший под правила ACCEPT вверху
$IPT -A INPUT -j DROP
$IPT -A OUTPUT -j ACCEPT
# Записать настройки в конфигурационный файл iptables,.
# настройки из которого загружаются сразу после перезагрузки
$IPTS > $IPTCONF
echo «IPv4 firewall configured, config saved to «$IPTCONF
Конфигурация ip6tables
Скрипт ip6tables_conf_set для базовой конфигурации фаервола ip6tables протокола IPv6.
# Полный путь к ip6tables
IPT6=»/sbin/ip6tables»
# Полный путь к ip6tables-save
IPT6S=»/sbin/ip6tables-save»
# Полный путь к файлу, в котором будет сохранена конфигурация ip6tables
IPT6CONF=»/etc/ip6tables.conf»
# Название сетевого интерфеса, к которому будут применены разрешающие правила
# Название можно найти тут: /etc/network/interfaces
PUBIF=»eth0″
# Состояние по умолчанию, устанавливаемое скриптом
def_val=»ACCEPT»
# Таблицы iptables
ipt_table[1]=’filter’
ipt_table[2]=’nat’
ipt_table[3]=’mangle’
ipt_table[4]=’raw’
ipt_table[5]=’security’
# Цепочки для каждой таблицы
chain_filter=( INPUT OUTPUT FORWARD )
chain_nat=( PREROUTING INPUT OUTPUT POSTROUTING )
chain_mangle=( PREROUTING INPUT FORWARD OUTPUT POSTROUTING )
chain_raw=( PREROUTING OUTPUT )
chain_security=( INPUT OUTPUT FORWARD )
echo «Starting IPv6 firewall (ip6tables) configure»
read -p «Are you sure to start (y/n): » start
if [ «$start» != «y» ]
then
echo «Exit, no changes.»
exit
fi
echo «»
echo «Step 1: clean old configuration»
# Сброс настроек ip6tables
for c in $(eval echo «\$<$chain[@]>«); do
$IPT6 -t $table -P $c $def_val
$IPT6 -t $table -F
$IPT6 -t $table -X
chains=»$
done
chains=»$
echo » — Table \»$table\», chains: $chains — all setting cleared.»
done
echo «»
echo «Step 2: saved main configuration»
# По умолчанию разрешить весь входящий, исходящий и запретить перенаправляемый трафик
$IPT6 -P INPUT ACCEPT
$IPT6 -P OUTPUT ACCEPT
$IPT6 -P FORWARD DROP
# Полный доступ интерфеса loopback
$IPT6 -A INPUT -i lo -j ACCEPT
$IPT6 -A OUTPUT -o lo -j ACCEPT
# Разрешить весь исходящий трафик и инициированный им входящий
$IPT6 -A INPUT -i $PUBIF -m state —state ESTABLISHED,RELATED -j ACCEPT
$IPT6 -A OUTPUT -o $PUBIF -m state —state NEW,ESTABLISHED,RELATED -j ACCEPT
# Разрешить входящий ICMP
$IPT6 -A INPUT -i $PUBIF -p ipv6-icmp -j ACCEPT
$IPT6 -A OUTPUT -o $PUBIF -p ipv6-icmp -j ACCEPT
# Здесь можно добавить свои правила, например открыть 80 порт по IPv6
# .
# Логирование всего, что не попало под правила ACCEPT
$IPT6 -A INPUT -i $PUBIF -j LOG
# Запретить весь входящий и исходящий трафик на всех сетевых интерфейсах
# не попавший под правила ACCEPT вверху
$IPT6 -A INPUT -j DROP
$IPT6 -A OUTPUT -j DROP
# Записать настройки в конфигурационный файл ip6tables,
# настройки из которого загружаются сразу после перезагрузки
$IPT6S > $IPT6CONF
echo «IPv6 firewall configured, config saved to «$IPT6CONF
Источник