Проверка правил для iptables

Здравствуйте!

В течение последних нескольких дней изучаю работу с межсетевым экраном Netfilter. Прочитал много форумов, статьи wiki (ru + en), статьи пользователей в инете. Взяв от каждого ресурса необходимое и понятное для меня, собрал свои правила для iptables (плюс опирался на опыт использования и настройки фаервола ipfw).

Вобщем получился у меня некий монстр, который я планирую применить, но есть сомнения, что он заработает :)

Пытался создать фаервол закрытого типа без NAT. На машине планируется использовать Web-server, дальше скорее всего еще что-то прикрутится.
Так вот есть у меня огромная просьба к ГУРУ iptables'a (если вы посещаете сей форум) проверить созданый мной конфиг и поделиться замечаниями.

Заранее спасибо!


###############################
#Firewall for a single machine:
###############################
iptables -N TCP			-m comment --comment =Создаем цепочки
iptables -N UDP			-m comment --comment =
iptables -N BAD_PACKETS -m comment --comment =

iptables -P FORWARD DROP	-m comment --comment =Если NATa нет, дропать
iptables -P OUTPUT DROP 	-m comment --comment =Запретить (Разрешить) весь исходящий
iptables -P INPUT DROP		-m comment --comment =Дропать весь входящий

iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT	-m comment --comment =alloy LoopBack

iptables -A INPUT -s 192.168.22.0/24 -j ACCEPT		-m comment --comment =my_local
iptables -A OUTPUT  -s 192.168.22.0/24  -j ACCEPT	-m comment --comment =my_local

#Jump To BAD_PACKETS
iptables -A INPUT -j BAD_PACKETS

iptables -A INPUT -i eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT	-m comment --comment =разрешить пакеты которые были запрошены
iptables -A OUTPUT -o eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT	-m comment --comment =локальными приложениями

iptables -A INPUT -p icmp --icmp-type 0 -j ACCEPT		-m comment --comment =Echo Reply
iptables -A INPUT -p icmp --icmp-type 8 -j ACCEPT		-m comment --comment =Echo request
iptables -A OUTPUT -p icmp -j ACCEPT					-m comment --comment =alloy ping

iptables -A OUTPUT -p UDP --dport 67 --sport 68 -j ACCEPT		-m comment --comment =DHCP
iptables -A OUTPUT -p TCP -o eth0 --dport 443 -j ACCEPT			-m comment --comment =HTTPS
iptables -A OUTPUT -p TCP -o eth0 --dport 80 -j ACCEPT			-m comment --comment =HTTP
iptables -A OUTPUT -p TCP -o eth0 --dport 53 -j ACCEPT			-m comment --comment =DNS
iptables -A OUTPUT -p UDP -o eth0 --dport 53 -j ACCEPT			-m comment --comment =DNS
iptables -A OUTPUT -p TCP -o eth0 --dport 25 -j ACCEPT			-m comment --comment =MAIL_POP
iptables -A OUTPUT -p TCP -o eth0 --dport 110 -j ACCEPT			-m comment --comment =MAIL_SMTP
iptables -A OUTPUT -p TCP -o eth0 --dport 43 -j ACCEPT			-m comment --comment =WHOIS
iptables -A OUTPUT -p TCP -o eth0 --dport 22 -j ACCEPT			-m comment --comment =SSH
iptables -A OUTPUT -p TCP -o eth0 --dport 21 -j ACCEPT			-m comment --comment =FTP

iptables -A OUTPUT -j LOG --log-prefix "OUTPUT DROP: "			-m comment --comment =out ALL Drop $ Log

iptables -A INPUT -m conntrack --ctstate INVALID -j DROP	-m comment --comment =Drop all packets with invalid parameters

#Защита от spoofing attacks
iptables -A INPUT -i eth0 -s 10.0.0.0/8 -j DROP				-m comment --comment =RFC 1918 private IP
iptables -A INPUT -i eth0 -s 172.16.0.0/12 -j DROP			-m comment --comment =RFC 1918 private IP
iptables -A INPUT -i eth0 -s 192.168.0.0/16 -j DROP			-m comment --comment =RFC 1918 private IP
iptables -A INPUT -i eth0 -s 169.254.0.0/16 -j DROP			-m comment --comment =DHCP auto-config
iptables -A INPUT -i eth0 -s 127.0.0.0/8 -j DROP			-m comment --comment =loopback
iptables -A INPUT -i eth0 -s 0.0.0.0/8 -j DROP				-m comment --comment =loopback
iptables -t raw -I PREROUTING -m rpfilter --invert -j DROP		-m comment --comment =Защита от spoofing attacks

iptables -A INPUT -p icmp --icmp-type echo-request -i eth0 -j DROP		-m comment --comment =block all ping requests
iptables -A INPUT -p icmp --icmp-type redirect -j DROP
iptables -A INPUT -p icmp --icmp-type router-advertisement -j DROP
iptables -A INPUT -p icmp --icmp-type router-solicitation -j DROP
iptables -A INPUT -p icmp --icmp-type address-mask-request -j DROP
iptables -A INPUT -p icmp --icmp-type address-mask-reply -j DROP

#Защита от основных атак
iptables -A INPUT -p tcp ! --syn -m state --state NEW -j DROP	-m comment --comment =Force SYN packets check
iptables -A INPUT -f -j DROP								-m comment --comment =Force Fragments packets check
iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP		-m comment --comment =XMAS пакеты
iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP		-m comment --comment =Drop all NULL packets

iptables -A INPUT -p TCP -o eth0 --dport 113 -j DROP		-m comment --comment =Deny ident

#Запрещаем все Netbios службы. 137=name, 138=datagram, 139=session
iptables -A INPUT -p TCP -o eth0 --dport 137 -j DROP
iptables -A INPUT -p TCP -o eth0 --dport 138 -j DROP
iptables -A INPUT -p TCP -o eth0 --dport 139 -j DROP
iptables -A INPUT -p TCP -o eth0 --dport 81 -j DROP

iptables -A INPUT -p tcp --syn -m conntrack --ctstate NEW -j TCP	-m comment --comment =Хорошие новые пакеты
iptables -A INPUT -p udp -m conntrack --ctstate NEW -j UDP			-m comment --comment =Хорошие новые пакеты

#Открытие портов для входящих соединений
iptables -A INPUT -p UDP --dport 67 --sport 68 -j ACCEPT		-m comment --comment =DHCP
iptables -A TCP -p tcp --dport 80 -j ACCEPT						-m comment --comment =80 порт Web-сервер (HTTP))
iptables -A TCP -p tcp --dport 22 -j ACCEPT						-m comment --comment =22 порт SSH

iptables -A INPUT -j LOG --log-prefix "INPUT DROP: "		-m comment --comment =In ALL Drop $ Log

#Drop
iptables -A BAD_PACKETS -p TCP ! --syn -m state --state NEW -j DROP
iptables -A BAD_PACKETS -p TCP --tcp-flags ALL ALL -j DROP
iptables -A BAD_PACKETS -p TCP --tcp-flags ALL NONE -j DROP
iptables -A BAD_PACKETS -p TCP --tcp-flags ALL SYN \-m state --state ESTABLISHED -j DROP
iptables -A BAD_PACKETS -p ICMP --fragment -j DROP
iptables -A BAD_PACKETS -m state --state INVALID -j DROP
iptables -A BAD_PACKETS -d 255.255.255.255 -j DROP
iptables -A BAD_PACKETS -j RETURN
$ uname -a
Linux ArchLinux 4.5.4-1-ARCH #1 SMP PREEMPT Wed May 11 22:21:28 CEST 2016 x86_64 GNU/Linux
Если вы будете применять кучу правил по одному, на каждое заново вызывая команду iptables, суммарное время их загрузки может оказаться неожиданно большим. В особо клинических случаях (я встречал такие) загрузка такого фаерволла может занимать по полминуты даже на мощном сервере.

Поэтому, рекомендуется загружать сразу все правила командой iptables-restore либо из файла, либо, если правила удобнее генерировать скриптом, можно прямо внутри скрипта перенаправлять их на ввод iptables-restore. Такой способ загрузки правил срабатывает мгновенно даже при большом количестве правил, поскольку их применения происходит по одному разу на таблицу (строка COMMIT).

P.S.
По существу написанных правил: по-моему, это дикое нагромождение (да не в обиду будет сказано) надёргано из разных примеров, не очень стыкующихся между собой. Если не трудно, было бы неплохо своими словами описать назначение этой машины, как и куда она подключена, что на ней будет работать и т.д.

Кроме того:
1) Не стоит злоупотреблять действием DROP. Оно "глотает" пакеты молча и без ответа (в отличии от REJECT), так что в случае чего вы даже не поймёте, был пакет дропнут, или ушел не туда, или вообще не дошел до сервера.
2) Не стоит блокировать входящие (и особенно исходящие!) по умолчанию. Если что-то пойдёт не так, и разрешающее правило не загрузится, вы вообще потеряете доступ к серверу, и ничего не сможете исправить удалённо. Что называется – "к командировке". Гораздо безопаснее ставить общее блокирующее правило после разрешающих.
3) Только крайняя степень паранойи может оправдывать блокировку исходящих соединений, то есть открываемых самим сервером.

P.P.S.
Английское слово alloy означает "сплав". Разрешение – allow.
Огромное спасибо за Ваши пояснения!

Действительно, в них присутствует нагромождение.
За основу было взято типовое правило с wiki.archlinux (en)(несколько
отличаются от правил в русской вики), оно было обрезано
и разбавлено правилами из других источников и возможно несколько дублируются
в различном виде.
Старался настроить правила таким образом:
1) По умолчанию все запрещено.
2) Далее разрешаются только необходимые порты и протоколы
для нормального функционирования web и ftp серверов (пока только это,
но неизвестно что мне еще взбредет в будущем).
web и ftp смотрят в открытый Интернет.

Схема сети следующая:
Имеется обычный роутер Асус, он поднимает ПППоЕ с постоянным ip-адресом.
Сервер представляет из себя ноутбук, кабелем подключенный к роутеру.
Т.е. в-принципе физический доступ к нему есть постоянно. Поэтому и выбрал
отновным правилом: все запрещено.

P.S. allow исправил :) в английском не очень силен (самоучка).
$ uname -a
Linux ArchLinux 4.5.4-1-ARCH #1 SMP PREEMPT Wed May 11 22:21:28 CEST 2016 x86_64 GNU/Linux
Если я не ошибаюсь, для сокращения конфига можно объединить строки:

iptables -A OUTPUT -p UDP --dport 67 --sport 68 -j ACCEPT		-m comment --comment =DHCP
iptables -A OUTPUT -p TCP -o eth0 --dport 443 -j ACCEPT			-m comment --comment =HTTPS
iptables -A OUTPUT -p TCP -o eth0 --dport 80 -j ACCEPT			-m comment --comment =HTTP
iptables -A OUTPUT -p TCP -o eth0 --dport 53 -j ACCEPT			-m comment --comment =DNS
iptables -A OUTPUT -p UDP -o eth0 --dport 53 -j ACCEPT			-m comment --comment =DNS
iptables -A OUTPUT -p TCP -o eth0 --dport 25 -j ACCEPT			-m comment --comment =MAIL_POP
iptables -A OUTPUT -p TCP -o eth0 --dport 110 -j ACCEPT			-m comment --comment =MAIL_SMTP
iptables -A OUTPUT -p TCP -o eth0 --dport 43 -j ACCEPT			-m comment --comment =WHOIS
iptables -A OUTPUT -p TCP -o eth0 --dport 22 -j ACCEPT			-m comment --comment =SSH
iptables -A OUTPUT -p TCP -o eth0 --dport 21 -j ACCEPT

в две:

iptables -A OUTPUT -p TCP -o eth0 -m multiport --dports 21,22,43,110,25,53,80,443 -j ACCEPT
iptables -A OUTPUT -p UDP -o eth0 -m multiport --dports 53,67,68 -j ACCEPT

Ну и соотвественно для INPUT тоже самое.
$ uname -a
Linux ArchLinux 4.5.4-1-ARCH #1 SMP PREEMPT Wed May 11 22:21:28 CEST 2016 x86_64 GNU/Linux
И еще не ясен момент, точнее работает это и нет => В вики пушут, что по-умолчанию уже встроена в ядро блокировка на локальные адреса поступающие из глобальной, т.е. это все:
iptables -A INPUT -i eth0 -s 10.0.0.0/8 -j DROP				-m comment --comment =RFC 1918 private IP
iptables -A INPUT -i eth0 -s 172.16.0.0/12 -j DROP			-m comment --comment =RFC 1918 private IP
iptables -A INPUT -i eth0 -s 192.168.0.0/16 -j DROP			-m comment --comment =RFC 1918 private IP
iptables -A INPUT -i eth0 -s 169.254.0.0/16 -j DROP			-m comment --comment =DHCP auto-config
iptables -A INPUT -i eth0 -s 127.0.0.0/8 -j DROP			-m comment --comment =loopback
iptables -A INPUT -i eth0 -s 0.0.0.0/8 -j DROP				-m comment --comment =loopback
включено по дефолту в /usr/lib/sysctl.d/50-default.conf и это дейстривельно присутствует, этакий аргумент rp_filter:
# Source route verification
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.all.rp_filter = 1
А в ipfilter достаточно добавить:
iptables -t raw -I PREROUTING -m rpfilter --invert -j DROP
Но отрабатывается оно корректно или нет кто-то знает или как проверить?
P.S. Нужно ли создавать дополнительный конфик файл /etc/sysctl.d/90-firewall.conf и дублировать там этот аргумент? По умолчанию файла 90-firewall.conf нет. И вообще каталог /etc/sysctl.d пустой. Может правила где-то в другом месте сейчас?
$ uname -a
Linux ArchLinux 4.5.4-1-ARCH #1 SMP PREEMPT Wed May 11 22:21:28 CEST 2016 x86_64 GNU/Linux
Если к интернету подключён роутер, то фаерволл должен быть имено на нём.
И не такой, как у вас, а с форвардингом и натом, потому что внешний IP тоже на нём.
И физический доступ к нему, в случае чего, не поможет, ибо монитор и клавиатуру подключать некуда.
С другой стороны, скорей всего, он там уже есть, хотя настраивать перенаправление портов всё равно надо.

rp_filter (в sysctl) работает без дополнительных правил.

-m multiport тоже работает.

Комментарии, так же, как другие параметры, пишутся БЕЗ пробелов по обе стороны знака = , и в кавычках, если пробелы есть внутри, например -m comment --comment="a b c d"
В общем, воспользовавшись всеми Вашими рекомендациями, оставив на OUTPUT ACCEPT, причесал правила к такому виду:

iptables -N TCP
iptables -N UDP
iptables -N BAD_PACKETS
iptables -N REJECT_PACKETS

iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
iptables -P INPUT DROP

iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -m comment --comment="request packets"
iptables -A INPUT -i lo -j ACCEPT -m comment --comment="allow LoopBack"
iptables -A INPUT -s 192.168.22.0/24 -j ACCEPT -m comment --comment="my_local"

iptables -A INPUT -j BAD_PACKETS -m comment --comment="Jump To BAD_PACKETS"
iptables -A INPUT -j REJECT_PACKETS -m comment --comment="Jump To REJECT"

iptables -t raw -I PREROUTING -m rpfilter --invert -j DROP -m comment --comment="spoofing attacks"

iptables -A INPUT -p icmp --icmp-type 8 -m conntrack --ctstate NEW -j ACCEPT

iptables -A TCP -p tcp --syn -m conntrack --ctstate NEW --dport 80 -j ACCEPT -m comment --comment="Web"
iptables -A TCP -p tcp --syn -m conntrack --ctstate NEW --dport 14922 -j ACCEPT -m comment --comment="ssh"
iptables -A UDP -p udp -m conntrack --ctstate NEW --dport 53 -j ACCEPT -m comment --comment="DNS"

iptables -A REJECT_PACKETS -p tcp -m recent --update --seconds 60 --name TCP-PORTSCAN -j REJECT --reject-with tcp-reset
iptables -A REJECT_PACKETS -p udp -m recent --update --seconds 60 --name UDP-PORTSCAN -j REJECT --reject-with icmp-port-unreachable
iptables -A REJECT_PACKETS -j REJECT --reject-with icmp-proto-unreach

iptables -A INPUT -j LOG --log-prefix "INPUT DROP: " -m comment --comment="In ALL Drop $ Log"
iptables -A INPUT -j LOG --log-prefix "INPUT REJECT: " -m comment --comment="In ALL Reject $ Log"
iptables -A OUTPUT -j LOG --log-prefix "OUTPUT DROP: " -m comment --comment="out ALL Drop $ Log"

#Drop
iptables -A BAD_PACKETS -p TCP ! --syn -m state --state NEW -j DROP -m comment --comment="Force SYN packets check"
iptables -A BAD_PACKETS -p TCP --tcp-flags ALL ALL -j DROP -m comment --comment="XMAS"
iptables -A BAD_PACKETS -p TCP --tcp-flags ALL NONE -j DROP -m comment --comment="Drop all NULL packets"
iptables -A BAD_PACKETS -p TCP --tcp-flags ALL SYN -m state --state ESTABLISHED -j DROP
iptables -A BAD_PACKETS -p ICMP --fragment -j DROP -m comment --comment="Force Fragments packets check"
iptables -A BAD_PACKETS -m conntrack --ctstate INVALID -j DROP -m comment --comment="Drop all packets with invalid parameters"
iptables -A BAD_PACKETS -d 255.255.255.255 -j DROP -m comment --comment="broadcast"
iptables -A BAD_PACKETS -j RETURN
iptables -A BAD_PACKETS -p TCP -o enp4s0 -m multiport --dports 113,81,137,138,139 -j DROP -m comment --comment="Ident, Netbios"

Прошу Ваши замечания!

P.S. На роутере есть и NAT и Фаервол (тоже iptables). Порты прокинуты. По факту на нем стоит busybox..
$ uname -a
Linux ArchLinux 4.5.4-1-ARCH #1 SMP PREEMPT Wed May 11 22:21:28 CEST 2016 x86_64 GNU/Linux
Судя по логам:

iptables -A REJECT_PACKETS -j REJECT --reject-with icmp-proto-unreach
и
iptables -A BAD_PACKETS -j RETURN

одно и тоже.
$ uname -a
Linux ArchLinux 4.5.4-1-ARCH #1 SMP PREEMPT Wed May 11 22:21:28 CEST 2016 x86_64 GNU/Linux
И еще => по умолчанию все логи пишутся в dmesg.
А как вывести в отдельный лог все в /var/log ?
Пока гуглю..
$ uname -a
Linux ArchLinux 4.5.4-1-ARCH #1 SMP PREEMPT Wed May 11 22:21:28 CEST 2016 x86_64 GNU/Linux
iptables -A INPUT -j LOG --log-prefix "INPUT DROP: " -m comment --comment="In ALL Drop $ Log"
iptables -A INPUT -j LOG --log-prefix "INPUT REJECT: " -m comment --comment="In ALL Reject $ Log"
приводит к дублированию - одно и тоже событие записывается в лог с разными метками. И пишет не дропы.
 
Зарегистрироваться или войдите чтобы оставить сообщение.