Постановка задачи: Есть сервер с двумя интерфесами eth0 и eth1. По интерфейсу eth1 создан тунель для pppoe соединений с провайдером ppp0 и ppp1. Необходимо обезопасить нашу локальную сеть от нехорошего влияния извне, а так же сам Интернет от влияния нашей маленькой сети. Понятно, что за основу был взят скрипт из бескрайной паутины, но был адаптирован для нашей сети для выполнения следующих целей: запретить все; разрешить только то, что можно; дать с помощью маскарадинга интернет в локальную сеть (кому положено); сделать редирект на прозрачный сквид; дать торрент для одной машины из сети.
На самом деле есть библия по IpTables, где изложено все! Абсолютно все про IpTables...
Создадим новый скрипт в каталоге /etc/init.d:
Сама статья сырая и будет еще перерабатываться, но пока я приведу описание основных моментов и приведу сам конфиг 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 - канал 1 провайдера)
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
$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-5!5 - 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"
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 (only Internal Lan):"
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 ""
;;
reload|force-reload) echo -n "Reloading configuration files for firewall: iptables"
echo "."
;;
*) echo "Usage: /etc/init.d/rc.firewall start|stop|restart|reload|force-reload"
exit 1
;;
esac
exit 0
Выставим правильные права на сам скрипт:
И добавим скрипт в автозагрузку:
Обратите внимание на то, что ссылка создается в каталог /etc/rc3.d Если у Вас в /etc/inittab установлен не 3 режим работы сервера (id:3:initdefault: многопользовательская платформа с поддержкой сети), а второй (id:2:initdefault: однопользовательская платформа с поддержкой сети) то необходимо создать эту сслыку в каталог rc2.d!!!