Я уверен, что системные администраторы Linux хорошо знакомы с iptables
, пользовательский интерфейс к netfilter
структура фильтрации пакетов.
Итак, этот «Вопрос» предназначен для Сообщество вики для сбора различных битов и кусочков iptables
мудрость. Нет ничего слишком обычного или неясного. Публикуйте все, что вы знаете, что поможет другим максимально эффективно использовать iptables
.
#!/bin/bash
WHITELIST=/whitelist.txt
BLACKLIST=/blacklist.txt
#THIS WILL CLEAR ALL EXISTING RULES!
echo 'Clearing all rules'
iptables -F
#
## Whitelist
#
for x in `grep -v ^# $WHITELIST | awk '{print $1}'`; do
echo "Permitting $x..."
$IPTABLES -A INPUT -t filter -s $x -j ACCEPT
done
#
## Blacklist
#
for x in `grep -v ^# $BLACKLIST | awk '{print $1}'`; do
echo "Denying $x..."
$IPTABLES -A INPUT -t filter -s $x -j DROP
done
#!/bin/bash
ALLOWEDTCP="80 3128 3784"
ALLOWEDUDP="3128 3784"
#
## Permitted Ports
#
for port in $ALLOWEDTCP; do
echo "Accepting port TCP $port..."
$IPTABLES -A INPUT -t filter -p tcp --dport $port -j ACCEPT
done
for port in $ALLOWEDUDP; do
echo "Accepting port UDP $port..."
$IPTABLES -A INPUT -t filter -p udp --dport $port -j ACCEPT
done
# Attempt to block portscans
# Anyone who tried to portscan us is locked out for an entire day.
iptables -A INPUT -m recent --name portscan --rcheck --seconds 86400 -j DROP
iptables -A FORWARD -m recent --name portscan --rcheck --seconds 86400 -j DROP
# Once the day has passed, remove them from the portscan list
iptables -A INPUT -m recent --name portscan --remove
iptables -A FORWARD -m recent --name portscan --remove
# These rules add scanners to the portscan list, and log the attempt.
iptables -A INPUT -p tcp -m tcp --dport 139 -m recent --name portscan --set -j LOG --log-prefix "Portscan:"
iptables -A INPUT -p tcp -m tcp --dport 139 -m recent --name portscan --set -j DROP
iptables -A FORWARD -p tcp -m tcp --dport 139 -m recent --name portscan --set -j LOG --log-prefix "Portscan:"
iptables -A FORWARD -p tcp -m tcp --dport 139 -m recent --name portscan --set -j DROP
# Reject spoofed packets
# These adresses are mostly used for LAN's, so if these would come to a WAN-only server, drop them.
iptables -A INPUT -s 10.0.0.0/8 -j DROP
iptables -A INPUT -s 169.254.0.0/16 -j DROP
iptables -A INPUT -s 172.16.0.0/12 -j DROP
iptables -A INPUT -s 127.0.0.0/8 -j DROP
#Multicast-adresses.
iptables -A INPUT -s 224.0.0.0/4 -j DROP
iptables -A INPUT -d 224.0.0.0/4 -j DROP
iptables -A INPUT -s 240.0.0.0/5 -j DROP
iptables -A INPUT -d 240.0.0.0/5 -j DROP
iptables -A INPUT -s 0.0.0.0/8 -j DROP
iptables -A INPUT -d 0.0.0.0/8 -j DROP
iptables -A INPUT -d 239.255.255.0/24 -j DROP
iptables -A INPUT -d 255.255.255.255 -j DROP
# Drop all invalid packets
iptables -A INPUT -m state --state INVALID -j DROP
iptables -A FORWARD -m state --state INVALID -j DROP
iptables -A OUTPUT -m state --state INVALID -j DROP
# Stop smurf attacks
iptables -A INPUT -p icmp -m icmp --icmp-type address-mask-request -j DROP
iptables -A INPUT -p icmp -m icmp --icmp-type timestamp-request -j DROP
iptables -A INPUT -p icmp -m icmp -j DROP
# Drop excessive RST packets to avoid smurf attacks
iptables -A INPUT -p tcp -m tcp --tcp-flags RST RST -m limit --limit 2/second --limit-burst 2 -j ACCEPT
# Don't allow pings through
iptables -A INPUT -p icmp -m icmp --icmp-type 8 -j DROP
ipset
Если вы напишете много аналогичных правил, основанных на простом IP, порте или обоих, рассмотрите возможность использования ipset
для оптимизации производительности netfilter.
Например:
iptables -s 192.168.1.11 -j ACCEPT
iptables -s 192.168.1.27 -j ACCEPT
iptables -s 192.168.1.44 -j ACCEPT
... hundreds of similar rules ...
iptables -s 192.168.251.177 -j ACCEPT
Это означает, что пакет с адресом источника 192.168.251.177 должен сначала пройти через сотни правил, прежде чем он сможет получить свой вердикт ПРИНЯТЬ.
Конечно, опытные системные администраторы разбивают правила по подсетям. Но это по-прежнему означает сотни правил.
ipset
для спасения!
Сначала определите набор IP-адресов ipmap
тип:
ipset -N Allowed_Hosts ipmap --network 192.168.0.0/16
Затем заполните его адресами:
for ip in $LIST_OF_ALLOWED_IP; do ipset -A Allowed_Hosts $ip; done
Наконец, замените сотни правил iptables выше на один правило:
iptables -m set --match-set Allowed_Hosts src -j ACCEPT
Когда приходит пакет, netfilter выполнит очень быстрый поиск по битовой карте для IP-адреса источника (src) пакета по Allowed_Hosts
IP Set. Все пакеты, поступающие из 192.168.0.0/16, будут один правило. И поверьте мне, что поиск по растровому изображению как минимум на два порядка быстрее, чем выполнение сотен проверок правил iptables.
ipset
не ограничивается IP-адресами. Он также может соответствовать на основе портов, кортежа IP-портов, адресов сети / подсети, кортежа IP-MAC и т. Д. И т. Д. И он может соответствовать этим критериям в качестве источника или назначения или их комбинации (в случае кортежей).
И наконец, с ipset
вы можете автоматически помещать IP-адреса в черные / белые списки. Эти черные / белые списки также могут «устареть», таким образом, автоматически удаляя IP-адрес по прошествии настраиваемого количества времени.
Пожалуйста, обратитесь к ipset
страница руководства пользователя Больше подробностей.
Некоторые дистрибутивы Linux могут не иметь "из коробки" поддержку ipset
(например, у Ubuntu 10.04 была эта проблема). В этих системах один из способов - установить ipset
из исходного кода.
Вместо этого загрузите ipset
Источник со своего веб-сайта: http://ipset.netfilter.org/install.html
В качестве альтернативы, если вы используете xtables-addons
, ipset является включены в его источник: http://xtables-addons.sourceforge.net/
Добавьте комментарии к своим правилам:
-m comment --comment "Comments help to read output of iptables -nvL"
Добавьте следующие правила, желательно в -t raw -A PREROUTING
-p tcp --tcp-flags FIN,SYN FIN,SYN -j DROP
-p tcp --tcp-flags SYN,RST SYN,RST -j DROP
-p tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,PSH,URG -j DROP
-p tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN -j DROP
-p tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG NONE -j DROP
-p tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,SYN,RST,PSH,ACK,URG -j DROP
Блокируемые атаки:
(смело редактируйте названия атак выше)
echo 1 > /proc/sys/net/ipv4/ip_forward
/sbin/iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
Шаг 1 устанавливает параметр ядра, разрешающий переадресацию IP, шаг 2 устанавливает правило iptables, которое включает NAT на интерфейсе eth0.
Добавьте следующие правила, желательно в -t raw -A PREROUTING
-p icmp -m u32 ! --u32 "4&0x3FFF=0" -j DROP
-p icmp -m length --length 1492:65535 -j DROP
Первое правило блокирует все пакеты ICMP, чей «флаг фрагментации» не равен 0. (ICMP должен никогда быть фрагментированным; они должны нести небольшие полезные нагрузки)
Второе правило блокирует нефрагментированные ICMP-пакеты слишком большого размера.
(из моего файла iptables_tricks.txt, перекомпилированного из множества мест: P)
Заставляет iptables ждать 15 секунд между новыми подключениями с того же IP-адреса на порт 22 (SSH):
iptables -A INPUT -p tcp -i eth0 -m state --state NEW --dport 22 -m recent --update --seconds 15 -j DROP
iptables -A INPUT -p tcp -i eth0 -m state --state NEW --dport 22 -m recent --set -j ACCEPT
Уже есть ответ, в котором упоминаются наборы IP. Однако он довольно одномерен, поскольку фокусируется на выигрыше в производительности по сравнению с классическими правилами и на том факте, что наборы IP-адресов смягчают проблему с большим количеством отдельных IP-адресов, которые нельзя легко выразить как подсеть в нотации CIDR.
Для ipset
Я буду использовать обозначения, прочитанные ipset restore
и написано ipset save
.
Соответственно для iptables
(и ip6tables
) rules я буду использовать обозначения, как прочитал iptables-restore
и написано iptables-save
. Это сокращает нотацию и позволяет выделить потенциальные возможности использования только IPv4 (с префиксом -4
) или только IPv6 (с префиксом -6
) правила.
В некоторых примерах мы перенаправим поток пакетов в другую цепочку. Предполагается, что цепочка существует в этой точке, поэтому строки для создания цепочек не создаются (при этом не упоминается имя таблицы или команды COMMIT
в конце).
Наборы IP могут намного больше, чем упоминалось в другой ответ и вам обязательно стоит прочитать документацию по IP-адресу (ipset(8)
) вместе с iptables-extensions(8)
в дополнение к этой краткой записи здесь.
Например, я в основном сосредоточусь на трех типах наборов: hash:ip
, hash:net
и list:set
, но их гораздо больше, и все они имеют допустимые варианты использования.
Вы можете, например, также сопоставить номера портов, а не только IP-адреса.
iptables-save
и iptables-restore
Вы можете создавать объявления наборов IP-адресов в большом количестве и импортировать их, передавая их в ipset restore
. Если вы хотите сделать свою команду более устойчивой к уже существующим записям, используйте ipset -exist restore
.
Если ваши правила находятся в файле с именем default.set
вы бы использовали:
ipset -exist restore < default.set
Такой файл может содержать записи для create
наборы и add
записи в них. Но, как правило, похоже, что для большинства команд из командной строки в файлах есть соответствующая версия. Пример (создание набора DNS-серверов):
create dns4 hash:ip family inet
create dns6 hash:ip family inet6
# Google DNS servers
add dns4 8.8.8.8
add dns4 8.8.4.4
add dns6 2001:4860:4860::8888
add dns6 2001:4860:4860::8844
Здесь создается один набор для IPv4 (dns4
) и один для IPv6 (dns6
).
Тайм-ауты в наборах IP-адресов можно установить по умолчанию для каждого набора, а также для каждой записи. Это очень полезно для сценариев, когда вы хотите временно заблокировать кого-либо (например, для сканирования портов или попытки перебора вашего SSH-сервера).
Это работает следующим образом (по умолчанию при создании наборов IP-адресов):
create ssh_loggedon4 hash:ip family inet timeout 5400
create ssh_loggedon6 hash:ip family inet6 timeout 5400
create ssh_dynblock4 hash:ip family inet timeout 1800
create ssh_dynblock6 hash:ip family inet6 timeout 1800
Мы вернемся к этим конкретным наборам ниже и объясним, почему они установлены именно так.
Если вы хотите установить время ожидания для определенного IP-адреса, вы можете просто сказать:
add ssh_dynblock4 1.2.3.4 timeout 7200
Чтобы заблокировать IP 1.2.3.4 на два часа вместо (установленных) полчаса по умолчанию.
Если бы вы посмотрели на это с помощью ipset save ssh_dynblock4
через короткое время вы увидите что-то вроде:
create ssh_dynblock4 hash:ip family inet hashsize 1024 maxelem 65536 timeout 1800
add ssh_dynblock4 1.2.3.4 timeout 6954
Kernel error received: Unknown error -1
).sudo ipset add ssh_dynblock4 1.2.3.4 timeout $((120*60))
Внутри ваших скриптов может быть полезно увидеть, существует ли уже запись. Этого можно достичь с помощью ipset test
который возвращает ноль, если запись существует, и ненулевое значение в противном случае. Таким образом, в скрипте можно применять обычные проверки:
if ipset test dns4 8.8.8.8; then
echo "Google DNS is in the set"
fi
Однако во многих случаях вы предпочтете использовать -exist
переключиться на ipset
чтобы направить его не жаловаться на существующие записи.
iptables
правилаЭто, на мой взгляд, одна из главных черт IP-наборов. Вы можете не только сопоставить записи набора IP-адресов, но и добавить новые записи к существующему набору IP-адресов.
Например в этот ответ на этот вопрос у вас есть:
-A INPUT -p tcp -i eth0 -m state --state NEW --dport 22 -m recent --update --seconds 15 -j DROP
-A INPUT -p tcp -i eth0 -m state --state NEW --dport 22 -m recent --set -j ACCEPT
... с намерением ограничить количество попыток подключения к SSH (TCP-порт 22). Используемый модуль recent
отслеживает недавние попытки подключения. Вместо state
модуль, я предпочитаю conntrack
модуль, однако.
# Say on your input chain of the filter table you have
-A INPUT -i eth+ -p tcp --dport ssh -j SSH
# Then inside the SSH chain you can
# 1. create an entry in the recent list on new connections
-A SSH -m conntrack --ctstate NEW -m recent --set --name tarpit
# 2. check whether 3 connection attempts were made within 2 minutes
# and if so add or update an entry in the ssh_dynblock4 IP set
-4 -A SSH -m conntrack --ctstate NEW -m recent --rcheck --seconds 120 --hitcount 3 --name tarpit -j SET --add-set ssh_dynblock4 src --exist
-6 -A SSH -m conntrack --ctstate NEW -m recent --rcheck --seconds 120 --hitcount 3 --name tarpit -j SET --add-set ssh_dynblock6 src --exist
# 3. last but not least reject the packets if the source IP is in our
# IP set
-4 -A SSH -m set --match-set ssh_dynblock4 src -j REJECT
-6 -A SSH -m set --match-set ssh_dynblock6 src -j REJECT
В этом случае я перенаправляю поток на SSH
цепочка, чтобы мне не приходилось повторяться с -p tcp --dport ssh
для каждого правила.
Чтобы повторить:
-m set
делает iptables
осознавая, что мы используем переключатели из set
модуль (который обрабатывает наборы IP)--match-set ssh_dynblock4 src
говорит iptables
чтобы соответствовать источник (src
) адрес против именованного набора (ssh_dynblock4
) sudo ipset test ssh_dynblock4 $IP
(где $IP
содержит исходный IP-адрес пакета)-j SET --add-set ssh_dynblock4 src --exist
добавляет или обновляет источник (src
) адрес из пакета в набор IP ssh_dynblock4
. Если запись существует (--exist
) просто обновится. sudo ipset -exist add ssh_dynblock4 $IP
(где $IP
содержит исходный IP-адрес пакета)Если вы хотите вместо этого сопоставить целевой / целевой адрес, вы должны использовать dst
вместо того src
. Обратитесь к руководству для получения дополнительных сведений.
Наборы IP могут содержать другие наборы. Теперь, если вы читали статью до этого места, вы задавались вопросом, можно ли комбинировать наборы. И конечно это так. Для указанных выше наборов IP мы можем создать два набора соединений ssh_dynblock
и ssh_loggedon
соответственно, чтобы содержать наборы только для IPv4 и только для IPv6:
create ssh_loggedon4 hash:ip family inet timeout 5400
create ssh_loggedon6 hash:ip family inet6 timeout 5400
create ssh_dynblock4 hash:ip family inet timeout 1800
create ssh_dynblock6 hash:ip family inet6 timeout 1800
# Sets of sets
create ssh_loggedon list:set
create ssh_dynblock list:set
# Populate the sets of sets
add ssh_loggedon ssh_loggedon4
add ssh_loggedon ssh_loggedon6
add ssh_dynblock ssh_dynblock4
add ssh_dynblock ssh_dynblock6
И следующий вопрос, который должен возникнуть у вас в голове: позволяет ли это нам соответствие и манипулировать наборами IP независимо от версии IP.
И ответ на это громкий: ДА! (увы, это не было явно задокументировано в прошлый раз, когда я проверял)
Следовательно, правила из предыдущего раздела можно переписать следующим образом:
-A INPUT -i eth+ -p tcp --dport ssh -j SSH
-A SSH -m conntrack --ctstate NEW -m recent --set --name tarpit
-A SSH -m conntrack --ctstate NEW -m recent --rcheck --seconds 120 --hitcount 3 --name tarpit -j SET --add-set ssh_dynblock src --exist
-A SSH -m set --match-set ssh_dynblock src -j REJECT
что намного короче. И да, это испытано и проверено и работает как шарм.
На моих серверах у меня есть скрипт, запускаемый как cron
задание, которое берет кучу имен хостов и преобразует их в IP-адреса, а затем передает их в набор IP для «доверенных хостов». Идея состоит в том, что доверенные хосты получают больше попыток входа на сервер и не обязательно блокируются на такое время, как кто-либо еще.
И наоборот, у меня целые страны заблокированы для подключения к моему SSH-серверу, за (потенциальным) исключением доверенных хостов (то есть порядок правил имеет значение).
Однако это оставлено читателю в качестве упражнения. Здесь я хотел бы добавить изящное решение, которое будет использовать наборы, содержащиеся в ssh_loggedon
установлен, чтобы разрешить последующие попытки подключения и не подвергаться такой же проверке, как другие пакеты.
Важно помнить, что тайм-аут по умолчанию составляет 90 минут для ssh_loggedon
и 30 минут для ssh_dynblock
глядя на следующие iptables
правила:
-A INPUT -i eth+ -p tcp --dport ssh -j SSH
-A SSH -m set --match-set ssh_loggedon src -j ACCEPT
-A SSH -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A SSH -m conntrack --ctstate NEW -m recent --set --name tarpit
-A SSH -m conntrack --ctstate NEW -m recent --rcheck --seconds 120 --hitcount 3 --name tarpit -j SET --add-set ssh_dynblock src --exist
-A SSH -m set --match-set ssh_dynblock src -j REJECT
К настоящему времени вы должны спросить себя, как подключаемый IP-адрес попадает в ssh_loggedon
подмножества. Так что читайте дальше ...
Если вы экспериментировали с sshrc
и друзья, вы узнаете о его недостатках. Но на помощь приходит PAM. Модуль с именем pam_exec.so
позволяет нам вызывать скрипт во время входа в систему по SSH в момент, когда мы знаем, что пользователь допущен.
В /etc/pam.d/sshd
ниже pam_env
и pam_selinux
записи добавить следующую строку:
session optional pam_exec.so stdout /path/to/your/script
и убедитесь, что ваша версия скрипта (/path/to/your/script
выше) существует и является исполняемым.
PAM использует переменные среды, чтобы сообщать о том, что происходит, поэтому вы можете использовать простой скрипт, подобный этому:
#!/bin/bash
# When called via pam_exec.so ...
SETNAME=ssh_loggedon
if [[ "$PAM_TYPE" == "open_session" ]] && [[ -n "$PAM_RHOST" ]]; then
[[ "x$PAM_RHOST" != "x${PAM_RHOST//:/}" ]] && SETNAME="${SETNAME}6" || SETNAME="${SETNAME}4"
ipset -exist add $SETNAME "$PAM_RHOST"
fi
К сожалению, ipset
Утилита, похоже, не имеет встроенного интеллекта netfilter. Поэтому при добавлении нашей записи нам нужно различать IPv4 и IPv6. В противном случае ipset
предположим, что мы хотим добавить еще один устанавливать к набору наборов вместо IP. И конечно вряд ли будет набор, названный по IP :)
Итак, мы проверяем :
в IP-адресе и добавьте 6
к названию набора в таком случае и 4
в противном случае.
Конец.
с помощью FireHOL - удобная обертка iptables
Мне он показался более интуитивным, чем прямые команды iptables. Специально для людей, имеющих опыт работы с другими межсетевыми экранами:
FireHOL - это генератор брандмауэра iptables, создающий брандмауэры с фильтрацией пакетов iptables с отслеживанием состояния на хостах и маршрутизаторах Linux с любым количеством сетевых интерфейсов, любым количеством маршрутов, любым количеством обслуживаемых сервисов, любым уровнем сложности между вариантами сервисов (включая положительные и отрицательные выражения).
Видеоуроки IPTABLES
Эпизод 1 http://www.youtube.com/watch?v=ldB8kDEtTZA&feature=player_embedded
Эпизод 2 http://www.youtube.com/watch?v=aDaEXxRHeXY&feature=related
Финальный эпизод
http://www.youtube.com/watch?v=JojqHKcSxpo&feature=player_embedded
Будет хорошим стартом для любого новичка.
Другой графический интерфейс, который можно использовать для настройки iptables: Конструктор межсетевого экрана. Он позволяет пользователям создавать элементы правил как объекты в базе данных, а затем перетаскивать эти объекты в редактор правил для создания желаемой политики брандмауэра. Затем приложение создает файл сценария со всеми командами iptables, необходимыми для реализации правил.
В отличие от некоторых других решений с графическим интерфейсом пользователя iptables, где вы можете управлять только одной конфигурацией iptables за раз, с Firewall Builder вы можете управлять большим количеством конфигураций iptables из одного приложения. Firewall Builder работает в Linux, Windows и Mac OS X, существует уже более 10 лет и имеет тысячи активных пользователей по всему миру.
Полное раскрытие информации - я соучредитель NetCitadel, компании, которая разрабатывает Firewall Builder.
Ограничение всех индивидуальных IP-адресов квотой исходящей полосы пропускания с помощью наборов IP
Вы можете настроить свой сервер так, чтобы каждый отдельный IP-адрес использовал 15 гигабайт полосы пропускания в месяц, в надежде отразить или избежать атаки на использование полосы пропускания, возможно, для вашей квоты измеренной полосы пропускания у вашего провайдера. Это может быть выполнено следующим образом:
Сначала создайте наборы IP для IPv4 и IPv6:
ipset create IP_QUOTA_SET_OUT hash:ip timeout 345600 counters
ipset create IP_QUOTA_SET_OUT_INET6 hash:ip timeout 345600 counters family inet6
Теперь добавьте свои правила iptables. Первая строка добавит IP-адрес в набор, если его еще нет. Вторая строка не будет соответствовать, если количество байтов, переданных для IP в наборе, превышает указанное количество. То же самое делается и для IPv6.
iptables -I OUTPUT -m set ! --match-set IP_QUOTA_SET_OUT dst -j SET --add-set IP_QUOTA_SET_OUT dst --timeout 345600
iptables -I OUTPUT -m set --match-set IP_QUOTA_SET_OUT dst --bytes-gt 16106127360 -j DROP
ip6tables -I OUTPUT -m set ! --match-set IP_QUOTA_SET_OUT_INET6 src -j SET --add-set IP_QUOTA_SET_OUT_INET6 src --timeout 345600
ip6tables -I OUTPUT -m set --match-set IP_QUOTA_SET_OUT_INET6 src --bytes-gt 16106127360 -j DROP
Это предотвратит такие атаки, как пользователь, запрашивающий большой файл с вашего веб-сервера в течение длительного периода времени или с любой службы, если на то пошло. То же самое можно сделать для цепочки INPUT.
Пример: у вас есть eth0
и eth1
и хотели бы разрешить трафик между ними?
iptables -A FORWARD -i eth+ -o eth+ -j ACCEPT
Я использовал это в прошлом, чтобы соответствовать veth<something>
интерфейсы, динамически создаваемые и именуемые LXC. Так что я могу сопоставить все сразу с veth+
.
Я также намеренно назвал некоторые интерфейсы _<something>
чтобы противостоять _+
.
регистрировать исходящее соединение с uid
iptables -A OUTPUT -m state --state NEW -m tcp -p tcp -m limit --limit 5/m -j LOG --log-uid --log-prefix="outgoing connection: "
переадресация порта / соединения:
iptables -A PREROUTING -t nat -i eth1 -p tcp --dport 80 -j DNAT --to 10.0.1.7:80
iptables -A INPUT -p tcp -m state --state NEW --dport 80 -i eth1 -j ACCEPT
iptables -t mangle -A PREROUTING -p tcp \
-m conntrack --ctstate NEW -m tcpmss ! --mss 536:65535 -j DROP
Цель этой цели - проверить, устанавливает ли хост, отправивший SYN-пакет, соединение или ничего не делает после инициации SYN-соединения. Если он ничего не делает, он с минимальными усилиями отбрасывает пакет.
Установите пакеты синхронизации в таблицу отслеживания соединений в необработанной таблице
iptables -t raw -A PREROUTING -p tcp -m tcp --dport 80 --syn -j CT --notrack
Включите synproxy для http-сервера:
iptables -A INPUT -p tcp -m tcp --dport 80 -m conntrack --ctstate INVALID,UNTRACKED \
-j SYNPROXY --sack-perm --timestamp --wscale 7 --mss 1460
Ресурс: Цель SYNPROXY из блога RHEL
Что-то, что я делаю, в основном из-за моего незнания более элегантного решения, - это вручную проверять журналы Nginx каждые 4 часа, а журналы почтового сервера каждые 2 минуты на предмет чрезмерного доступа с отдельных IP-адресов. Я запускаю вместе несколько скриптов, которые:
access.log
и перечислите 10 лучших IP-адресов, упорядоченных по количеству обращений к серверу. iptables.save
Вот как это выглядит:
autoBanIPs_mail.sh#!/bin/bash
# This script checks the last 2 minutes of log entries to see if any
# IP has made over 99 connections
now=$(date +"%m_%d_%Y")
/root/bin/checkBadIPs_mail.sh > /home/ipChecker/ipcheckMAIL_$now.txt
cat /home/ipChecker/ipcheckMAIL_$now.txt | \
grep " \\(\\([9][9]\\)\\|\\([0-9][0-9][0-9]\\+\\)\\) " | \
awk '{print $2}' > /home/ipChecker/badMailIPs_$now.sh
sed -i "s/^/\/usr\/local\/sbin\/blockIP /g" /home/ipChecker/badMailIPs_$now.sh
/bin/bash /home/ipChecker/badMailIPs_$now.sh
cat /home/ipChecker/ipcheckMAIL_$now.txt >> /home/ipChecker/ipcheckMAIL_$now.log
rm /home/ipChecker/ipcheckMAIL_$now.txt
rm /home/ipChecker/badMailIPs_$now.sh
checkBadIPs_mail.sh Здесь ОЧЕНЬ важно отметить одну вещь: вам НЕОБХОДИМО настроить белый список, иначе вы собираетесь начать блокировать множество аутентичных IP-адресов с серверов, с которых вы просто получаете много электронной почты, или, в случае других журналов, IP-адреса, которые просто часто попадайте на ваш сервер по уважительным причинам. Мой белый список просто встроен в этот скрипт путем добавления каналов grep сразу после | grep ']' | это выглядит примерно так "grep -v 127.0 |".
Вам нужно потратить время, чтобы научить свой сервер, какие IP-адреса с высоким трафиком являются допустимыми, а какие - нет. Для меня это означало, что мне пришлось потратить первую неделю или около того, проверяя свои журналы вручную каждые пару часов, просматривая ip-адреса с высоким трафиком на iplocation.net, а затем добавляя легальные, такие как amazon, box.com или даже мой дом / офис. IP-адреса попадают в белый список. Если вы этого не сделаете, ваш собственный сервер, скорее всего, будет заблокирован, или вы начнете блокировать законные почтовые / веб-серверы и вызовете перебои в работе электронной почты или трафика.
cat /var/log/mail.log | awk \
-v d1="$(date --date="-2 min" "+%b %_d %H:%M")" \
-v d2="$(date "+%b %_d %H:%M")" \
'$0 > d1 && $0 < d2 || $0 ~ d2' | \
grep '\[' | grep '\]' | \
grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | grep -v 127.0 | \
awk '{print $1}' | sort | uniq -c | sort -n | tail -10
BlockIP #!/bin/bash
sudo iptables -I INPUT -s $1 -j DROP
sudo bash -c "iptables-save > /etc/network/iptables.save"
Опять же, я знаю, что это чертовски грубо, и, вероятно, есть хороший чистый и эффективный протокол, который делает все это, но я не знал об этом, и эта штука работает уже год или два и держит плохих парней в страхе. Единственное, что я очень СЕРЬЕЗНО рекомендую, - это наличие у вас прокси или другого сервера, который вы можете использовать для доступа к вашему основному серверу. Причина в том, что если вы однажды занимаетесь веб-разработкой совершенно неожиданно, и вы пингуйте себя 2000 раз за 5 часов для некоторого тестирования, вы могли быть заблокированы без возврата, кроме прокси.
Вы можете увидеть это в checkBadIPs.sh
Я поместил grep -v 127.0, и в моих фактических файлах у меня есть тонна правил игнорирования для моего собственного IP-адреса и других доверенных диапазонов IP-адресов, но иногда ваш IP-адрес меняется, вы забываете обновить, а затем вы блокируете свой собственный сервер .
В любом случае, надеюсь, что это поможет.
Я немного изменил вещи, так что теперь вместо проверки каждые пару часов у меня есть журналы, проверяемые каждые 2 минуты, в основном мой журнал аутентификации ssh и журнал почты, когда они стучатся :(.
Я настраиваю определенные сценарии для каждого файла журнала, хотя это было бы достаточно просто из ручного сценария, который я использую сам, когда хочу проверить журналы. Выглядит так:
#!/bin/bash
log=$1 time=$2
cat /var/log/${log} | awk \
-v d1="$(date --date="-${time} min" "+%b %_d %H:%M")" \
-v d2="$(date "+%b %_d %H:%M")" \
'$0 > d1 && $0 < d2 || $0 ~ d2' | \
grep '\[' | grep '\]' | \
grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | \
sort | uniq -c | sort -n | tail -10
Для этого требуется 2 входа при запуске: файл журнала, который вы хотите просканировать, и то, как далеко в прошлом вы хотите сканировать.
Итак, если бы я хотел проверить mail.log на счетчик IP, скажем, 75 минут назад, я бы запустил:
$ sudo script.sh mail.log 75
Я согласен с комментариями о флагах ipsets и tcp, но по-прежнему многого не хватает:
Для списков стран используйте xtables-addons geoip match вместо ipsets. Регулярно обновляйте данные geoip (не реже одного раза в месяц). Данные более динамичны, чем список ipset, который запускается и забывается.
Рассмотрим отслеживание состояния соединения с помощью tcp-флагов. Например, tcp RST или ACK имеет смысл только для установленного соединения. SYN имеет смысл только для новых и связанных соединений. SYN для установленного соединения означает, что либо ваш SYN + ACK был утерян, либо попытка взлома, и его следует сбросить, поскольку обе стороны соединения не согласны с утверждением.
Хотя нет, SYN + RST и FIN + RST являются недопустимыми комбинациями, SYN + FIN теперь действителен для TCP fast-open (TCP option 34), особенно для DNS. Пакеты SYN, даже с быстрым открытием, не должны фрагментироваться. Я не считаю правила с флагами PSH и URG полезными. Не путайте состояние отслеживания соединения с состоянием TCP: RST-ответ на SYN-пакет устанавливается для целей отслеживания.
SYNPROXY предназначен для пересылаемых пакетов и ничего не добавляет для локально доставленных, кроме поддержки syncookie.
Пакеты ошибок ICMP всегда будут в соответствующем состоянии и имеют длину 48: 576, если они действительны. Длина 84: 1280 для IPv6. Все остальные следует игнорировать. Поскольку их максимальный размер также является минимальным MTU, их нельзя фрагментировать. Запросы ICMP (эхо-запросы, отметки времени и т. Д.) Всегда будут новыми, а ответы установлены. Отбрасывать пакеты ICMP в других состояниях.
Подобно примеру SSH с последним списком и приемом только последующих пакетов SYN, то же самое следует сделать для SMTP и аналогично «серому списку» только для данных IP-адреса.
В таблице фильтров первое (или второе, если сначала принимает пакеты с установленным состоянием) правило во входных и выходных цепочках должно принимать все на интерфейсе обратной связи. Вы должны доверять своим собственным внутренним пакетам. Если вы не можете, у вас есть более серьезные проблемы, помимо решения брандмауэра.
Наконец, не копируйте правила вслепую, если вы действительно не понимаете, что они делают. Так поступает так много похожих списков правил, и в большинстве случаев результат смехотворен.
#!/bin/bash
# The following iptables/ip6tables configurations have
# been kindly shared with us from ArckWiki. There are
# a few additions apart from what has been defined.
#
#=================Flush current definitions==============
iptables -F
ip6tables -F
iptables -X
ip6tables -X
#
#=================Chains=================================
#
#----Define chains for opened ports
iptables -N TCP
ip6tables -N TCP
iptables -N UDP
ip6tables -N UDP
#
#----Setting up the filter table for NAT
# iptables -N fw-interfaces
# ip6tables -N fw-interfaces
# iptables -N fw-open
# ip6tables -N fw-open
#
#================Default Chain reactions=================
#
#----Default FORWARD reaction
iptables -P FORWARD DROP
ip6tables -P FORWARD DROP
#
#----Default OUTPUT reaction
iptables -P OUTPUT ACCEPT
ip6tables -P OUTPUT ACCEPT
#
#----Shellshock
iptables -A INPUT -m string --algo bm --hex-string '|28 29 20 7B|' -j DROP
ip6tables -A INPUT -m string --algo bm --hex-string '|28 29 20 7B|' -j DROP
#
#----Default INPUT reaction
iptables -P INPUT DROP
ip6tables -P INPUT DROP
#
#----Drop spoofing packets
iptables -A INPUT -i eth0 -s 127.0.0.0/8 -j DROP
iptables -A INPUT -i wlan0 -s 127.0.0.0/8 -j DROP
iptables -A INPUT -i wlan1 -s 127.0.0.0/8 -j DROP
iptables -A INPUT -s 10.0.0.0/8 -j DROP
iptables -A INPUT -s 169.254.0.0/16 -j DROP
iptables -A INPUT -s 172.16.0.0/12 -j DROP
iptables -A INPUT -s 224.0.0.0/4 -j DROP
iptables -A INPUT -d 224.0.0.0/4 -j DROP
iptables -A INPUT -s 240.0.0.0/5 -j DROP
iptables -A INPUT -d 240.0.0.0/5 -j DROP
iptables -A INPUT -s 0.0.0.0/8 -j DROP
iptables -A INPUT -d 0.0.0.0/8 -j DROP
iptables -A INPUT -d 239.255.255.0/24 -j DROP
iptables -A INPUT -d 255.255.255.255 -j DROP
#
#================Ping rate limiting globally=============
iptables -A INPUT -p icmp --icmp-type 8 -m limit --limit 30/min --limit-burst 8 -j ACCEPT
ip6tables -A INPUT -p icmpv6 --icmpv6-type 8 --match limit --limit-burst 8 -j ACCEPT
iptables -A INPUT -p icmp --icmp-type 8 -j DROP
ip6tables -A INPUT -p icmpv6 --icmpv6-type 8 -j DROP
#
#----flooding RST packets, smurf attack Rejection
iptables -A INPUT -p tcp -m tcp --tcp-flags RST RST -m limit --limit 2/second --limit-burst 2 -j ACCEPT
ip6tables -A INPUT -p tcp -m tcp --tcp-flags RST RST -m limit --limit 2/second --limit-burst 2 -j ACCEPT
#
#----Bogus packet DROP
iptables -A INPUT -p tcp -m tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
ip6tables -A INPUT -p tcp -m tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
iptables -A INPUT -p tcp -m tcp --tcp-flags SYN,RST SYN,RST -j DROP
ip6tables -A INPUT -p tcp -m tcp --tcp-flags SYN,RST SYN,RST -j DROP
#
#================RELATED,ESTABLISHED reaction============
iptables -A INPUT --match conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
ip6tables -A INPUT --match conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
#
#================unfetered loopback======================
iptables -A INPUT -i lo -j ACCEPT
ip6tables -A INPUT -i lo -j ACCEPT
#
#================INVALID catagory of packets=============
iptables -A INPUT -p 41 -j ACCEPT
iptables -A INPUT --match conntrack --ctstate INVALID -j DROP
ip6tables -A INPUT --match conntrack --ctstate INVALID -j DROP
#
#================IPv6 reactions and definitions==========
ip6tables -A INPUT -s fe80::/10 -p icmpv6 -j ACCEPT
ip6tables -t raw -A PREROUTING -p icmpv6 -s fe80::/10 -j ACCEPT
ip6tables -t raw -A PREROUTING --match rpfilter -j ACCEPT
ip6tables -t raw -A PREROUTING -j DROP
#
#=======Acceptable INVALIDs and a curteous response======
iptables -A INPUT -p udp --match conntrack --ctstate NEW -j UDP
ip6tables -A INPUT -p udp --match conntrack --ctstate NEW -j UDP
iptables -A INPUT -p tcp --syn --match conntrack --ctstate NEW -j TCP
ip6tables -A INPUT -p tcp --syn --match conntrack --ctstate NEW -j TCP
#
#================Defining the TCP and UDP chains
#
#########################################################
# Notes for port open definitions #
# It is important to note that this should be config- #
# ured differently if you're providing any routing #
# activity for any purpose. it is up to you to actively #
# define what suites your needs to get the job done. #
# In this example, I'm exempting IPv6 from being able #
# to interact with SSH protocols for two reasons. The #
# first is because it is generally easier and more com- #
# for internal networks to be deployed with IPv4. The #
# second reason is, IPv6 can be deployed globally. #
#########################################################
#
#----SSH configured for eth0
iptables -A TCP -i eth0 -p tcp --dport ssh -j ACCEPT
#!---Blocking SSH interactions in IPv6
ip6tables -A TCP -p tcp --dport ssh -j DROP
#!---Leave commented for end service device
# iptables -A TCP -p tcp --dport 80 -j ACCEPT
# ip6tables -A TCP -p tcp --dport 80 -j ACCEPT
# iptables -A TCP -p tcp --dport 443 -j ACCEPT
# ip6tables -A TCP -p tcp --dport 443 -j ACCEPT
#
#!---Uncomment for remote service to this device
# iptables -A TCP -p tcp --dport 22 -j ACCEPT
# ip6tables -A TCP -p tcp --dport 22 -j ACCEPT
#
#!---Uncomment if you're providing routing services
# iptables -A UDP -p udp 53 -j ACCEPT
# ip6tables -A UDP -p udp 53 -j ACCEPT
#
#=================Tricking port scanners=================
#
#----SYN scans
iptables -I TCP -p tcp --match recent --update --seconds 60 --name TCP-PORTSCAN -j DROP
ip6tables -I TCP -p tcp --match recent --update --seconds 60 --name TCP-PORTSCAN -j DROP
iptables -A INPUT -p tcp --match recent --set --name TCP-PORTSCAN -j DROP
ip6tables -A INPUT -p tcp --match recent --set --name TCP-PORTSCAN -j DROP
#
#----UDP scans
iptables -I UDP -p udp --match recent --update --seconds 60 --name UDP-PORTSCAN -j DROP
ip6tables -I UDP -p udp --match recent --update --seconds 60 --name UDP-PORTSCAN -j DROP
iptables -A INPUT -p udp --match recent --set --name UDP-PORTSCAN -j DROP
ip6tables -A INPUT -p udp --match recent --set --name UDP-PORTSCAN -j DROP
#
#----For SMURF attack protection
iptables -A INPUT -p icmp -m icmp --icmp-type address-mask-request -j DROP
iptables -A INPUT -p icmp -m icmp --icmp-type timestamp-request -j DROP
iptables -A INPUT -p icmp -m limit --limit 2/second --limit-burst 2 -j ACCEPT
ip6tables -A INPUT -p icmpv6 -m limit --limit 2/second --limit-burst 2 -j ACCEPT
#
#----Ending all other undefined connections
iptables -A INPUT -j DROP
ip6tables -A INPUT -j DROP
#
#=======Defining the IN_SSH chain for bruteforce of SSH==
#
#!---I've elected to keep IPv6 out of this realm for
#!---ease of use
iptables -N IN_SSH
iptables -A INPUT -p tcp --dport ssh --match conntrack --ctstate NEW -j IN_SSH
iptables -A IN_SSH --match recent --name sshbf --rttl --rcheck --hitcount 3 --seconds 10 -j DROP
iptables -A IN_SSH --match recent --name sshbf --rttl --rcheck --hitcount 4 --seconds 1800 -j DROP
iptables -A IN_SSH --match recent --name sshbf --set -j ACCEPT
iptables -A INPUT -p tcp --dport ssh -m conntrack --ctstate NEW -j IN_SSH
#
#==================Setting up a NAT gateway==============
#
#########################################################
# #
# I commented this half out because it's not something #
# that will apply to all setups. Make note of all par- #
# tinate interfaces and what exactly is going on. #
# #
#########################################################
#
#----Setting up the FORWARD chain
# iptables -A FORWARD --match conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
# ip6tables -A FORWARD --match conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
#
#
#----Defining the fw-interfaces/open chains for FORWARD
# iptables -A FORWARD -j fw-interfaces
# ip6tables -A FORWARD -j fw-interfaces
# iptables -A FORWARD -j fw-open
# ip6tables -A FORWARD -j fw-open
# iptables -A FORWARD -j DROP # Should be REJECT. But, fuck them
# ip6tables -A FORWARD -j DROP
# iptables -P FORWARD DROP
# ip6tables -P FORWARD DROP
#
#
#----Setting up the nat table
# iptables -A fw-interfaces -i ### -j ACCEPT
# ip6tables -A fw-interfaces -i ### -j ACCEPT
# iptables -t nat -A POSTROUTING -s w.x.y.z/S -o ppp0 -j MASQUERADE
# ip6tables -t nat -A POSTROUTING -s fe::/10 -o ppp0 -j MASQUERADE
#----The above lines should be repeated specifically for EACH interface
#
#----Setting up the PREROUTING chain
#
#######################################################
# #
# The PREROUTING chain will redirect either port #
# targets to be redirected. This can also redirect #
# traffic inbound to your network from the gateway #
# to this machine. This can be useful if you're using #
# a honeypot or have any service within your network #
# that you want to be pointed to a specific device. #
# #
#######################################################
#
#----SSH honeypot server
# iptables -A fw-open -d HONEYPOT_IP -p tcp --dport 22 -j ACCEPT
# ip6tables -A fw-open -d HONEYPOT_IP -p tcp --dport 22 -j ACCEPT
#----With intuition, you can configure the above to also direct specific
#----requests to other devices providing those services. The bellow will
#----be for a squid server
# iptables -A fw-open -d SQUID_IP -p tcp --dport 80 -j ACCEPT
# ip6tables -A fw-open -d SQUID_IP -p tcp --dport 80 -j ACCEPT
# iptables -t nat -A PREROUTING -i ppp0 -p tcp --dport 8000 -j DNAT --to SQUID_IP
# ip6tables -t nat -A PREROUTING -i ppp0 -p tcp --dport 8000 -j DNAT --to SQUID_IP
#
#===============Declare configurations=================
iptables -nvL
ip6tables -nvL