Постановка задачи: Есть сервер с двумя интерфесами eth0 и eth1. По интерфейсу eth1 создан тунель для PPPoE соединений с провайдером ppp0 и ppp1. Необходимо обезопасить нашу локальную сеть от нехорошего влияния извне, а так же сам Интернет от влияния нашей маленькой сети. Понятно, что за основу был взят скрипт из бескрайной паутины, но был адаптирован для нашей сети для выполнения следующих целей: запретить все; разрешить только то, что можно; дать с помощью маскарадинга интернет в локальную сеть (кому положено); сделать редирект на прозрачный сквид; дать торрент для одной машины из сети.
На самом деле есть библия по IpTables, где изложено все! Абсолютно все про IpTables... www.opennet.ru/docs/RUS/iptables/index.html Итак, начнём – cоздадим новый скрипт в каталоге /etc/init.d:
server:/# touch /etc/init.d/rc.firewall server:/# vim /etc/init.d/rc.firewall
Примечание: В любом случае, чтобы применять этот скрипт, нужно чётко понимать что он делает до мельчайших деталей. иначе Вы можете только себе навредить. Идея правильного межсетевого экрана проста – запретить всё, кроме того, что явно разрешено. Всегда отталкивайтесь от этого тезиса и будет Вам счастье.
Важным моментом является текстовый файл, в котором перечислены IP-адреса разрешенных к доступу к сети Интернет /etc/allow.txt... Нет ну серьёзно, Вы же не намерены открывать доступ к сети Интернет для всех желающих в Вашей сети?!
server:/# cat /etc/allow.txt 192.168.1.2 192.168.1.5 192.168.1.6 192.168.1.7 192.168.1.8 192.168.1.9 192.168.1.12 192.168.1.14 ... 192.168.1.128 192.168.1.187 192.168.1.224 192.168.1.254
Дополнтельно обратите внимание на текстовый файл с перечнем пиринговых сетей, которые мы пускаем в обход шейпера на основе squid3, так как на то он и пиринг, чтобы его не ограничивать...
server:/# cat /etc/perring.txt 80.94.160.0/24 80.94.162.0/24 80.94.164.0/24 86.57.253.204/32
Скрипт понимает несколько ключей запуска, таких как start|stop|save|restart. Назначение их вполне ясное. Другие же, важные опции расписаны в коде самого скрипта, генерирующего наши правила для iptables.
#! /bin/sh ### BEGIN INIT INFO # Provides: rc.firewall # Required-Start: # Required-Stop: # Default-Start: 3 # Default-Stop: 0 6 # Short-Description: Run /etc/init.d/rc.firewall if it exist ### END INIT INFO ###################################################################################### # Configured by Demon, 2009 ###################################################################################### # Внешний интерфейс (к ADSL модему 1) EXTIF="eth1" # Внешний интерфейс (тунель по EXTIF - канал Интернета провайдера, объединяет ppp0 и ppp1) PPPIF="ppp+" # Внутренний интерфейс (Локальная сеть) INTIF="eth0" # Loop-устройство - localhost LPDIF=lo LPDIP=127.0.0.1 LPDMSK=255.0.0.0 LPDNET="$LPDIP/$LPDMSK" # Переменные текстовых инструментов IPT='/sbin/iptables' IFC='/sbin/ifconfig' G='/bin/grep' SED='/bin/sed' UNPRIPORTS="1024:65535" # Перечень ip адресов закрытых для FORWARD FILENAME_DENY="/etc/deny_inet_hosts" FILENAME_ALLOW="/etc/allow.txt" FILENAME_PERRING="/etc/perring.txt" start_fw() { echo "" echo "IpTables configured by Demon" # Deny вместо accept: предотвращает открытие "дыр" # в то время, как мы закрываем порты и все такое. Все запрещено! $IPT -P INPUT DROP $IPT -P OUTPUT DROP $IPT -P FORWARD DROP # Сброс всех существующих цепочек и стирание персональных цепочек CHAINS=`cat /proc/net/ip_tables_names 2>/dev/null` for i in $CHAINS do $IPT -t $i -F $IPT -t $i -X done echo 1 > /proc/sys/net/ipv4/tcp_syncookies echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts # Проверка адреса источника for f in /proc/sys/net/ipv4/conf/*/rp_filter; do echo 1 > $f done # Запрет маршрутизации IP от источника и редиректов ICMP for f in /proc/sys/net/ipv4/conf/*/accept_source_route; do echo 0 > $f done for f in /proc/sys/net/ipv4/conf/*/accept_redirects; do echo 0 > $f done # Включить перенаправление пакетов через ядро. echo 1 > /proc/sys/net/ipv4/ip_forward # Установка переменных среды для внешнего интерфейса ETH1 EXTIP="192.168.2.2" EXTBC="192.168.2.255" EXTMSK="255.255.255.0" EXTNET="$EXTIP/$EXTMSK" echo "" echo "EXTIP=$EXTIP EXTBC=$EXTBC EXTMSK=$EXTMSK EXTNET=$EXTNET" # Устанвка переменных среды для внутреннего интерфейса INTIP="192.168.1.1" INTBC="192.168.1.255" INTMSK="255.255.255.0" INTNET="192.168.1.0/24" echo "" echo "INTIP=$INTIP INTBC=$INTBC INTMSK=$INTMSK INTNET=$INTNET" # Отключаем сообщения о том, что цепочки уже существуют (чтобы перезапуск был без мусора) $IPT -N DROP 2> /dev/null $IPT -N REJECT 2> /dev/null # Весь траффик от устройства loopback принимается # если IP совпадает с любым из наших интерфейсов. $IPT -A INPUT -i $LPDIF -s $LPDIP -j ACCEPT $IPT -A INPUT -i $LPDIF -s $EXTIP -j ACCEPT $IPT -A INPUT -i $LPDIF -s $INTIP -j ACCEPT # Широковещательные пакеты $IPT -A INPUT -i $INTIF -d $INTBC -j ACCEPT $IPT -A OUTPUT -o $EXTIF -d $EXTBC -j ACCEPT $IPT -A OUTPUT -o $INTIF -d $INTBC -j ACCEPT $IPT -A FORWARD -o $EXTIF -d $EXTBC -j ACCEPT $IPT -A FORWARD -o $INTIF -d $INTBC -j ACCEPT # Блокируем доступ к внутренней сети из WAN # Это также призвано не дать нечестивым крякерам использовать нашу сетку # в качестве отправной точки для атак на других людей # Перевод с языка iptables: # "если пришедшие на наружный интерфейс пакеты были отправлены не с выданного # nefarious адреса, выкинуть их как горячую картошку" $IPT -A INPUT -i $EXTIF -d ! $EXTIP -j DROP # А сейчас мы блокируем внутренние адреса, кроме двух, присвоенных нашим двум # внутренним интерфейсам.....только помните, что если вы воткнете свой лэптоп или # какой другой pc в напрямую в одну из этих сетевых карт, то нужно удостовериться, # что они имеют именно эти IP-адреса или добавить соответствующий адрес отдельно. # Первый интерфейс/внутренняя сеть $IPT -A INPUT -i $INTIF -s ! $INTNET -j DROP $IPT -A OUTPUT -o $INTIF -d ! $INTNET -j DROP $IPT -A FORWARD -i $INTIF -s ! $INTNET -j DROP $IPT -A FORWARD -o $INTIF -d ! $INTNET -j DROP # Дополнительная Egress-проверка $IPT -A OUTPUT -o $EXTIF -s ! $EXTNET -j DROP # Разрешаем пакеты ICMP (смысла особого их блокировать я не нашел) $IPT -A INPUT -p icmp -j ACCEPT $IPT -A OUTPUT -p icmp -j ACCEPT $IPT -A FORWARD -p icmp -j ACCEPT # Косяное PPPoE треубет динамической настройки размера передаваемого пакета средствами iptables # иначе часть сайтов работать не будет... Вообще! $IPT -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1300 # печально известные порты: # 0 - tcpmux; у SGI есть уязвимость, через которую можно атаковать # 13 - daytime # 98 - Linuxconf # 111 - sunrpc (portmap) # SNMP: 161,2 # Флотилия Squid: 8000, 8008, 8080 # 1214 - Morpheus или KaZaA # 2049 - NFS # 3049 - очень заразный троян для Linux, часто путаемый с NFS # Часто атакуемые: 1999, 4329, 6346 # Частые трояны 12345 65535 COMBLOCK="0:1 13 98 111 161:162 1214 1999 2049 3049 4329 6346 8000 8008 12345 65535" # Порты TCP: # 98 - Linuxconf # 512-515 - rexec, rlogin, rsh, printer(lpd) # [очень серьезеные уязвимости; продолжаются ежедневные атаки] # 1080 - прокси-серверы Socks # 6000 - X (ЗАМЕЧАНИЕ. X через SSH - безопасен, и работает на порту TCP 22) # Блокировка 6112 (CDE у Sun и HP) TCPBLOCK="$COMBLOCK 98 512:515 1080 6000:6009 6112" # Порты UDP: # 161:162 - SNMP # 520=RIP, 9000 - Sangoma # 517:518 - talk и ntalk (самые надоедливые) UDPBLOCK="$COMBLOCK 520 123 517:518 1427 9000" echo "" echo "Blocking attacks to TCP port" for i in $TCPBLOCK; do echo -n "$i " $IPT -A INPUT -p tcp --dport $i -j DROP $IPT -A OUTPUT -p tcp --dport $i -j DROP $IPT -A FORWARD -p tcp --dport $i -j DROP done echo "" echo "Blocking attacks to UDP port " for i in $UDPBLOCK; do echo -n "$i " $IPT -A INPUT -p udp --dport $i -j DROP $IPT -A OUTPUT -p udp --dport $i -j DROP $IPT -A FORWARD -p udp --dport $i -j DROP done echo "" # Открываем отлеживание соединений по ftp MODULES="ip_nat_ftp ip_conntrack_ftp" for i in $MODULES; do echo "Inserting module $i" modprobe $i done # Защищаем некоторые распространенные клиенты для чата. # Уберите из списка допустимых лишние для пущей безопасности или добавьте новые. IRC='ircd' # сервис IRC MSN=1863 # сервис MSN WebMoney=2802 # сервис WebMoney ICQ=5190 # сервис ICQ SSH2=122 # наш порт SSH2 ADD="81 88" # "редкие" порты ТСР Lineage="2106 6666 7777 9923 17453" # игра Lineage CS="27015 27016 27017 27018" # игра Half-Life, CS Cardsh="10300 10500 11150 14450" # порты для кардшаринга RA="3389 4899 2083 9010 3128 8080" # удаленное администрирование NFS='sunrpc' # распределенная файловая система PORTAGE='rsync' OpenPGP_HTTP_Keyserver=11371 # Все альясы портов сервисов читаются из /etc/services и преобразуются в цифровое значние TCPSERV="domain http https ftp ftp-data mail pop3 pop3s imap3 imaps imap2 time www webmin $WebMoney $SSH2 $RA $PORTAGE $MSN $ICQ $IRC $Lineage $Cardsh $ADD $CS $OpenPGP_HTTP_Keyserver" UDPSERV="domain time netbios-ns netbios-dgm netbios-ssn microsoft-ds $CS" # Теперь разрешаем открытые порты на всех интерфесах и для всех, кому Интернет открыт из файла FILENAME_ALLOW echo "" echo -n "Allowing inside systems to use service TCP:" echo "" for i in $TCPSERV; do echo -n "$i " $IPT -A INPUT -i $INTIF -p tcp --dport $i --syn -m state --state NEW -j ACCEPT $IPT -A INPUT -i $EXTIF -p tcp --dport $i --syn -m state --state NEW -j ACCEPT $IPT -A INPUT -i $PPPIF -p tcp --dport $i --syn -m state --state NEW -j ACCEPT $IPT -A OUTPUT -o $INTIF -p tcp --dport $i --syn -m state --state NEW -j ACCEPT $IPT -A OUTPUT -o $EXTIF -p tcp --dport $i --syn -m state --state NEW -j ACCEPT $IPT -A OUTPUT -o $PPPIF -p tcp --dport $i --syn -m state --state NEW -j ACCEPT # форвардинг по TCP разрешаем только тем кому можно (кто имеет доступ Интернет из локальной сети for ip in $(cat $FILENAME_ALLOW); do $IPT -A FORWARD -i $INTIF -p tcp -s $ip --dport $i --syn -m state --state NEW -j ACCEPT done done echo "" echo -n "Allowing inside systems to use service UDP:" echo "" for i in $UDPSERV; do echo -n "$i " $IPT -A INPUT -i $INTIF -p udp --dport $i -m state --state NEW -j ACCEPT $IPT -A OUTPUT -o $INTIF -p udp --dport $i -m state --state NEW -j ACCEPT $IPT -A OUTPUT -o $EXTIF -p udp --dport $i -m state --state NEW -j ACCEPT # форвардинг по UDP разрешаем только тем кому можно (кто имеет доступ # в интернет из локальной сети for ip in $(cat $FILENAME_ALLOW); do $IPT -A FORWARD -i $INTIF -p udp -s $ip --dport $i -m state --state NEW -j ACCEPT done done # надо открыть наружу UDP порт domain=53 (иначе не работает DNS) $IPT -A OUTPUT -o $PPPIF -p udp --dport domain -m state --state NEW -j ACCEPT $IPT -A INPUT -i $PPPIF -p udp --dport domain -m state --state NEW -j ACCEPT # DNS rndc сервер на Lo разрешаем. (обход ошибки connection refused) $IPT -A OUTPUT -p tcp -m tcp -o $LPDIF --dport 953 --sport $UNPRIPORTS -j ACCEPT echo "" echo "SQUID exceptions and REDIRECT" # у нас есть пиринг! нет смысла заворачивать его на squid3? иначе он начнет резать скорость, # банеры и проч. А пиринг - это хорошо, потому что быстро! Поэтому еще на этапе PREROUTING # мы принимаем пакеты и выпускаем их в локальную сеть минуя squid for ip in $(cat $FILENAME_PERRING); do $IPT -t nat -A PREROUTING -p tcp -d $ip --dport 80 -j ACCEPT done # Заворачиваем весь остальной трафик по 80 порту на наш прозрачный SQUID $IPT -t nat -A PREROUTING -i eth0 -p tcp -s $INTNET -d ! 192.168.1.1 -m multiport --dport 80 -j REDIRECT --to-port 3128 echo "" echo "NAT up!" $IPT -t nat -A PREROUTING -j ACCEPT $IPT -t nat -A POSTROUTING -o $PPPIF -s $INTNET -j MASQUERADE $IPT -t nat -A POSTROUTING -j ACCEPT $IPT -t nat -A OUTPUT -j ACCEPT # Разрешаем все уже Установленные соединения $IPT -A INPUT -p tcp --dport auth --syn -m state --state NEW -j ACCEPT $IPT -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT $IPT -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT $IPT -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT # Все что не разрешили - отбрасываем! # *********** Важно чтобы было именно так, иначе от вашего файервола проку мало... ************ $IPT -A INPUT -j DROP $IPT -A OUTPUT -j REJECT $IPT -A FORWARD -j DROP } flush_fw() { # Сброс всех цепочек, стандартных, нестандартных. Обнуление нашего iptables $IPT -P INPUT ACCEPT $IPT -P FORWARD ACCEPT $IPT -P OUTPUT ACCEPT $IPT -t nat -P PREROUTING ACCEPT $IPT -t nat -P POSTROUTING ACCEPT $IPT -t nat -P OUTPUT ACCEPT $IPT -t mangle -P PREROUTING ACCEPT $IPT -t mangle -P OUTPUT ACCEPT $IPT -F $IPT -t nat -F $IPT -t mangle -F $IPT -X $IPT -t nat -X $IPT -t mangle -X } case "$1" in start) echo -n "Starting firewall: iptables" start_fw echo "" echo -n "Starting firewall Ok!" echo "" ;; stop) echo -n "Stopping firewall: iptables" flush_fw echo "" echo -n "Stopping firewall Ok!" echo "" ;; save) echo -n "Saving firewall: iptables" iptables-save > /etc/rules-save echo "" echo -n "Status save Ok!." echo "" ;; restart) echo -n "Restarting firewall: iptables" flush_fw start_fw echo "" echo -n "Status restart Ok!" echo "" ;; *) echo "Usage: /etc/init.d/rc.firewall start|stop|save|restart" exit 1 ;; esac exit 0
Выставим правильные права на сам скрипт:
server:/# chown root:root /etc/init.d/rc.firewall server:/# chmod +x /etc/init.d/rc.firewall
И добавим скрипт в автозагрузку:
server:/# ln -s /etc/init.d/rc.firewall /etc/rc3.d/S99rc.firewall
Обратите внимание на то, что ссылка создается в каталог /etc/rc3.d Если у Вас в /etc/inittab установлен не 3 режим работы сервера (id:3:initdefault: многопользовательская платформа с поддержкой сети), а второй (id:2:initdefault: однопользовательская платформа с поддержкой сети) то необходимо создать эту сслыку в каталог rc2.d!!!
Другой вариант добавления в автозагрузку заключается в использовании утилиты update-rc.d. Используя ее мы добавляем наш скрипт под номером 98 в 2,3 уровни запуска и под номером 90 в останов системы и перезагрузку с командами start и stop соответственно.
server:/# cd /etc/init.d server:/# update-rc.d rc.firewall start 98 2 3 . stop 90 0 6 .
Комментарии 6
- 1
Дмитрий — Apr 09, 2015 at 04:32 PM
Расскажите пожалуйста как Вы справились с https и прозрачным squid. Будьте добры. Очень интересует Ваша точка зрения.
Дмитрий Владимирович — Dec 26, 2014 at 10:26 AM
sergei, это проблема вёрстки - тут был перенос инструкции на новую строчку (исправил). Должно было быть вот так:
$IPT -t nat -A PREROUTING -i eth0 -p tcp -s $INTNET -d ! 192.168.1.1 -m multiport \
--dport 80 -j REDIRECT --to-port 3128
Дополнительно скажу, что в данном случае "-m multiport" избыточно. Был момент, когда я отправлял не только HTTP (80) трафик но и HTTPS (443) на squid пробуя шейпить/блокировать сайты по HTTPS (например, https://vk.com) и это место выглядело так:
-m multiport --dport 80, 443
sergei — Dec 26, 2014 at 01:54 AM
В строке 272, в "-m multiport \ --dport 80", символ "\" к чему относится? кто нить знает?
Дмитрий Владимирович — Nov 03, 2014 at 11:42 AM
В принципе тут есть дублирование, но в целом цепочки могут быть стандартными (по-умолчанию) и пользовательскими...
Флаг -P нужен чтобы определиться с политиками цепочек по-умолчанию. Политика по-умолчанию устанавливается командой:
iptables [-P {chain} {policy}]
Политика по-умолчанию представляет собой действие, которое применяется к пакету, не попавшему под действие ни одного из правил в цепочке.
Флаг же -A добавляет в конец конкретных цепочек (например пользовательских) правило "отбросить все". Вот и вся разница.
В данном примере можно было оставить только -P. Но лучше все цепочки и всгда закрывать еще и по -A.
Павел — Nov 01, 2014 at 07:03 PM
Зачем писать
$IPT -A INPUT -p udp --dport $i -j DROP
$IPT -A OUTPUT -p udp --dport $i -j DROP
$IPT -A FORWARD -p udp --dport $i -j DROP
Когда по умолчанию все вначале запрещено?
$IPT -P INPUT DROP
$IPT -P OUTPUT DROP
$IPT -P FORWARD DROP
Mikolai — Feb 12, 2013 at 11:19 AM
А как настроить файер, если у меня нет PPPoE, а только eth0 и eth1?
Спасибо заранее!