Posts Tagged ‘ Firewall

Debian Jessie: Трюки вокруг доступа к sshd (iptables, ipset, geoip)

Это заметка из цикла стетей моего небольшого HowTo по Debian Jessie.

Тут я уже описывал ранее вариант фильтрации доступа к ssh по GeoIP. На этот раз покажу вам более интересный вариант с ipset и модуль TARPIT для IPTABLES. Сразу скажу пару слов об этих новых сущностях:
ipset — модуль поддержки таблиц для iptables с сопутствующей обвязкой для управления этими самими таблицами: создание, удаление, работа с элементами таблицы и тп. Сам по себе модуль весьма хорош и здорово повышает эффективность работы iptables с большим количеством ip-адресов и сетей. Но если разсметривать реализацию iptables + ipset вцелом — то оно мне напоминает пятиколесный велосипед с деревянными спицами. Уж простите за такую ассоциацию у человека несколько лет админившего всякие там pf/ipfw в BSD-ях. На High-Load юзать можно и нужно!
TARPIT модуль для IPTABLES — это модуль для it-весельчаков. Суть работы этого модуля заключается в том что он какбы держит открытым указанный TCP порт, но при попытке клиента соединиться — не шлет в ответ абсолютно ничего. Это такой себе blackhole или nullroute на уровне фаервола. Это приводит к «зависшему» соединению с возможностью закрыть его только автоматически по истечению таймаута. Задумка модуля в том чтобы не просто блокировать бота, а истощать его ресурсы на соединение, мизерные, конечно, но всеже … На High-Load юзать не желательно, лучше пользуйте DROP!

Ранее при настройке proftpd мы уже установили geoip, но для тех кто не делал этого понадобится установленный geoip и его база:

gw:~$ sudo apt-get install geoip-bin geoip-database

В Debian модуль TARPIT находится в пакете дополнительных модулей iptables. Установим их:

gw:~$ sudo apt-get install xtables-addons-dkms

Ставим необходимый пакет для добавления ipset:

gw:~$ sudo apt-get install ipset

Одной из приятных фишек таблиц ipset является опция timeout. Она задает количество времени (в секундах) которое элемент содержится в таблице. По истечении timeout-а — элемент автоматически удаляется из таблицы.

Пример борьбы с ssh брутфорсерами:
1. Создаем таблицу, в нее скриптом проверки geoip будем добавлять ботов, timeout ставим 2 часа:

gw:~$ sudo ipset create ssh_bots hash:ip hashsize 16384 timeout 7200

2. Загрузим модуль ядра для действия iptables TARPIT:

gw:~$ sudo modprobe xt_TARPIT

3. Напомню что вот здесь мы базово настроили iptables. Сразу перед правилом розрешающим конект на port 22 добавим правило для блокировки ssh ботов из таблицы ssh_bots. Должно получиться вот так:

...
# Allow DNS connections from anywhere
-A INPUT -p udp --dport 53 -j ACCEPT
-A INPUT -p tcp --dport 53 -j ACCEPT

# TARPIT ssh_bots table
-A INPUT -m set --match-set ssh_bots src -p TCP --dport 22 -j TARPIT

# Allows SSH connections
# The --dport number is the same as in /etc/ssh/sshd_config
-A INPUT -p tcp -m state --state NEW --dport 22 -j ACCEPT
...

4. Теперь сооружаем чуть модифицированный скрипт проверки geoip — /usr/local/bin/ssh_geoip.sh:

gw:~$ sudo vim /usr/local/bin/ssh_geoip.sh

Вставляем туда следующее …

#!/usr/bin/env bash

PATH="/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/root/bin"

ALLOW_COUNTRIES="UA"

if [ $# -ne 1 ]; then
  echo "Usage:  `basename $0` <ip>" 1>&2
  exit 0 # return true in case of config issue
fi

COUNTRY=`geoiplookup $1 |sed -e 's/^.*Edition\:\ //' -e 's/\,.*$//'`

if [[ ${COUNTRY} =~ ${ALLOW_COUNTRIES} ]]; then
    logger "sshd ALLOW connection from IP $1 - [${COUNTRY}]"
    exit 0
  else
    logger "sshd DENY connection from IP $1 - [${COUNTRY}]"
    ipset add ssh_bots $1
    exit 1
fi

Это же скрипт, не забываем дать права на выполнение:

gw:~$ sudo chmod +x /usr/local/bin/ssh_geoip.sh

5. Теперь подправим конфиг /etc/hosts.deny добавив туда:

sshd: ALL

6. Теперь подправим конфиг /etc/hosts.allow добавив туда:

# Whitelist for LAN network 192.168.0.0/16
sshd: 192.168.
# Check Access by GeoIP
sshd: ALL: aclexec /usr/local/bin/ssh_geoip.sh %a

Итак, теперь соединение к ssh-серверу проходит так:
— конект на 22-й порт
— если ip клиента из сети 192.168.0.0/16 — пускаем сразу (см. whitelist в файле /etc/hosts.allow)
— проверка прав дотупа через скрипт /usr/local/bin/ssh_geoip.sh (розрешено только для UA ip-адресов)
— если права даны — приглашение к авторизации
— если права не даны — добавление ip бота в таблицу ssh_bots и сброс соединения
— следующая попытка соединения на порт 22 ведет в модуль TARPIT iptables-а
спустя 7200 секунд (2 часа) ip бота автоматически удаляется из таблицы ssh_bots и может коннектиться снова

Все прохождения через скрипт логируются в /var/log/messages в таком виде:
удачные:

Nov 22 14:14:11 gw logger: sshd ALLOW connection from IP 77.91.130.111 - [UA]

неудачные:

Nov 22 11:30:44 gw logger: sshd DENY connection from IP 123.151.42.61 - [CN]

Посмотреть листинг таблицы ssh_bots:

gw:~$ sudo ipset list ssh_bots
Name: ssh_bots
Type: hash:ip
Revision: 3
Header: family inet hashsize 16384 maxelem 65536 timeout 7200
Size in memory: 295304
References: 1
Members:
222.186.34.74 timeout 2075
43.229.53.69 timeout 3998
gw:~$

Хай щастить!

Debian Jessie: Базовая настройка фаервола (iptables)

Это статья из цикла стетей моего небольшого HowTo по Debian Jessie.
Итак, на данном этапе мы уже порядочно продвинулись с настройками нашего сервера. Мы уже настроили ftp, dhcp, ntp, ssh и вплотную подошли к настройке web-сервера. Но перед этим я бы хотел написать коротенькую заметку про iptables. Это первая настройка фаервола, поэтому тут все будет очень лаконично, чуть позже, после настройки web-сервера мы вернемся к этому вопросу и немного углубимся в тему iptables и безопастности.
Очень рекомендую глянуть пример простейшей настройки iptables на официальном wiki Debian
Ну поехали … Читать полностью

FreeBSD + IPFW: Блокируем SMTP Bruteforce

На предыдущей работе досталось в подчинение пара почтовых серваков с оооочень древними доменами, огромным количеством ящиков и не менее огромным количеством бесконечных брутфорсов. Не знаю что было причиной бесконечных атак на эти серваки, но то что он был в like list у всевозможных ботов — это уж точно! Почта была критичным сервисом, но ближайшие планы включали миграцию на MS Exchange, поэтому позиция руководства была примерно такой «Ну онож работает? Да! Вот и не трогаем пока … нам бы побыстрее мигронуть на эксчендж да вырубить их нафик!» Но один раз случился инцидент который заставил изменить позицию неприкосновения. Несмотря на рендомные пароли, один ящик был сбрутен, и как результат — отправка через наш сервак порядка 40.000 спам писем со ссылками на различные ресурсы интимного направления 🙂
Короче было дано задание «Чтото с этим сделать!» Читать полностью

Bye-bye SSH/FTP Bruteforce

Сегодня утром был злой. Задолбал брутфорс ssh и ftp. Освоил новый инструмент бана. Не секрет что бан фаерволом дороже чем blackhole/nullroute. Опробовал в FreeBSD, забанил пару сеток:

root@black:~# route add -net 46.151.48.0/21 127.0.0.1 -blackhole
add net 46.151.48.0: gateway 127.0.0.1
root@black:~# route add -net 62.201.212.0/22 127.0.0.1 -blackhole
add net 62.201.212.0: gateway 127.0.0.1
root@black:~# route add -net 222.161.0.0/16 127.0.0.1 -blackhole
add net 222.161.0.0: gateway 127.0.0.1

И настроение мое …. сразу улучшилось! Чего и Вам желаю!
Хай щастить!

ESXi 5.0 — Firewall rules by SSH

Понадобилось както розковырять в фаерволе доступ для сети к ESXi 5.0 хосту через SSH. Было стрёмно, но не так уж и сложно:

~ # esxcli network firewall ruleset allowedip add -r sshServer -i 190.100.200.0/24
~ # esxcli network firewall ruleset allowedip add -r vSphereClient -i 190.100.200.0/24

Эти чудесные команды открыли доступ ssh клиентом и vSphereClient-ом на хост ESXi для сети 190.100.200.0/24
Хай щастить!

FreeBSD 9.2 и «хитрый NAT» в PF

Итак, стоит задача пробросить пакеты «с мира» внутрь сети, да еще и «отнатить» их на внутреннем интерфейсе. Для визуализации задачи вот такая схемка:

Host_A (IP 91.91.91.91) -> Host_B (WAN_IP 15.15.15.15 -> LAN_IP 192.168.100.100) -> Host_C (LAN_Router) -> Host_D (IP 172.15.99.99)

Это все довольно просто делается на FreeBSD в PF, если на out политик нету, то достаточно трех правил:

INET_IF = "em0"
INET_LOCAL = "em1"
BACULA_SD = "172.15.99.99"

rdr on $INET_IF proto tcp from 91.91.91.91 to $INET_IF port 9103 -> $BACULA_SD port 9103
nat on $INET_LOCAL from 91.91.91.91 to $BACULA_SD -> $INET_LOCAL
pass in quick log on $INET_IF inet proto tcp from 91.91.91.91 to any port 9103 flags S/SA keep state

Правда провозился я долго, оказалось что тупо забыл включить ip-forwarding 🙂 Читать полностью

Ubuntu 14.04 — Iptables TARPIT

Опять линукс … возвращение на родину после бздьовых годков 🙂 После ipfw и pf в FreeBSD/OpenBSD линуховый iptables вызывает рвотные рефлексы 🙁 Но есть одна фишка которую я просто обожаю в iptables — TARPIT. Это «ложка дегтя» для всяких какеров и прочей нечести блуждающей в инете в поисках чего бы побрутфорсить 🙂 Не успел поднять ProFTPD как поломились китайские боты подбирать пароли 🙂 Ну ничего, пока их немного — скормлю ручками их TARPIT-у … пусть развлекаются! Можно конечно и DROP применять, но TARPIT с одной стороны блочит трафик напрочь, как DROP, а с другой не рвет TCP сессию … а какбы «специально держит ее», чтобы атакующий не мог закрыть соединение. Таким образом тратятся ресурсы как сервера (они тратятся и при DROP), так и бота. Думаю если бы мы жили в идеальном мире и все Linux сервера применяли вместо DROP TARPIT — ботам пришлось бы ой как тяжко 🙂 Но …. мир не идеален — но мы к таковому стремимся!

TARPIT реализован в iptables как дополнительный модуль фаервола и в стандартной поставке его нету. По крайней мере в Ubuntu/Debian это так! Этот модуль включен в пакет вместе с другими интересными модулями фаервола — xtables-addons. Попробуем поискать что есть в репах:

root@Ubuntu:~# apt-cache search xtables
iptables-dev - iptables development files
libxtables10 - netfilter xtables library
xtables-addons-common - Extensions targets and matches for iptables [tools, libs]
xtables-addons-dkms - Extensions targets and matches for iptables
xtables-addons-source - Extensions targets and matches for iptables [modules sources]
root@Ubuntu:~#

Я установил весь пакет, думаю можно собрать конкретные модули из сырцов (xtables-addons-source), но заморачиваться неохота … это же не бздя, нафик самосбор!

root@Ubuntu:~# apt-get install xtables-addons-dkms

Загружаем необходимый модуль:

root@Ubuntu:~# modprobe xt_TARPIT

В логах proftpd светился один крайне назойливый бот, добавляем правило для него:

root@Ubuntu:~# iptables -I INPUT 1 -p tcp -s 175.44.28.125 -j TARPIT

Убедиться что правило добавилось можно просмотрев листинг правил iptables:

root@Ubuntu:~# iptables -L -v -n
Chain INPUT (policy ACCEPT 264 packets, 578K bytes)
 pkts bytes target     prot opt in     out     source               destination        
    0     0 TARPIT     tcp  --  *      *       175.44.28.125        0.0.0.0/0            -j TARPIT --tarpit

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination        

Chain OUTPUT (policy ACCEPT 448 packets, 1149K bytes)
 pkts bytes target     prot opt in     out     source               destination        
root@Ubuntu:~#

Ну вот и все! В следующий раз данному боту обломится нас брутфорсить, да и все остальные сервисы по TCP ему будут недоступны 🙂

P.S. Это простейший метод, ручной. Если вы хотите автоматически блокировать ботов анализируя лог-файлы различных сервисов, вам нужно настроить fail2ban или подобный сервис. Думаю что в ближайшем будущем я напишу о его установке и настройке.

Хай щастить!

MS Outlook 2007/2010/2012 — Ошибка «На сервере отсутствует поддержка указанного типа шифрования»

На некоторой части машин под виндой начала появляться ошибка при отправке почты:
«Отправка тестового сообщения: На сервере отсутствует поддержка указанного типа шифрования подключений. Попробуйте изменить способ шифрования. За дополнительными сведениями обратитесь к администратору почтового сервера или к поставщику услуг Интернета.»
Ни обновление Outlook, ни переустановка ничего не давала. Решение нагуглилось на зарубежных форумах и оказалось довольно неожиданным — нужно удалить обновление Windows KB980436
Для этого идем в «Панель Управления -> Программы-> Программы и компоненты -> Установленные обновления» ищем данный апдейт, правой кнопкой на нем и «Удалить». После этого reboot и все прекрасно начинает работать.
Также, вполне возможно, глюк порождал кривой конфиг Fortigate-а. В процессе поиска решения его настройки тоже ковыряли 🙂

Updated: также в одном случае помогло выключение антивируса касперского. Так что думаю сперва убедитесь что работу почты не блокирует антивирус/фаервол, а потом уже ищите глючные апдейты!

Мдяяяя … реально был удивлен!

Настройка PF — nat + firewall

Статья из серии статей о настройке сервера для небольшого офиса на OpenBSD.

Захотелось вот настроить на старенькой машинке маршрутизатор для небольшой дружественной компании. Парк машин (читай, количество клиентов) около 20-30 штук. Такчто особой вычислительной мощи от компа и не требуется. Конечно же вопрос о выборе системы тоже обдумывался. Самым весомым аргументом в выборе было личное любопытство к пакетному фильтру PF. Вот чтото захотелось мне его пощупать. Много всякого слышал о pf, кто хвалит, кто ругает … почитал немного в инете разные тематические форумы, посмотрел как люди делают … и тд.- вот и загорелся желанием и сам опробовать в действии сей продукт. Да и начальник о pf лестно отзывался — мол просто настраивается и работает стабильно. Ну ладно, раз так — значит буду пробовать! Но тут еще засада с выбором OS, pf то есть в нескольких операционках! Точнее во всех семейства BSD 🙂 Правда, после того как я узнал что PF был разработан как сетевой фильтр именно для OpenBSD, выбор был сделан именно в пользу опёнка.
Как, что и куда крутить — инфы в инете скопилось навалом. Но всеже с самого начала очень рекомендую почитать на официальном сайте OpenBSD очень хорошее FAQ по PF Львиная часть, кстати, на русском 🙂 Почитали? Тогда начнемс!

Итак, что имеем вначале:

  • весьма скромная железка в духе Celeron 1GHz, RAM 256M, HDD 40G
  • установил на нее OpenBSD 4.6 — тоесть с OS тоже понятно 🙂
  • набор политик безопасности
  • соображения по обеспечению оптимальной работы с каналом internet
  • машину внутри сети с windows для которой нужны будут некоторые «плюшки»
  • желание разобраться с новым для меня инструментом — PF

Для простоты изложения назову основных участников конфигурации:

gw — наш сервер с OpenBSD
win2k3 — виндосервер внутри сети на который админам надо дать доступ из инета
clients — остальные клиенты внутри сети
admins — ip или DNS адреса машин админов (дом/работа) которым нужен доступ на gw
Что хотим получить:

— Политики:

  • «натим» только нужные нам протоколы — tcp,udp,icmp
  • по smtp пускаем общаться с сервером провайдера только gw и win2k3
  • по smtp clients могут общаться только с gw
  • для admins необходимо пробросить RDP и VNC порты на win2k3
  • максимально закрыться от доступа со стороны internet
  • подбирающих пароли к ssh  — банить (желательно средствами pf)
  • предусмотреть защиту от DDoS

— Некоторые соображения по оптимизации работы всех клиентов с каналом доступа в internet:

необходимо настроить QoS для того чтобы, при всем желании один или пара клиентов, не смогли «занять весь канал» закачкой какогото фильма, не давая остальным отправить/почитать почту.

Главный конфигурационный файл pf в OpenBSD находится обычно тут: /etc/pf.conf

Вот что я туда накалякал:

root@gw:~# cat /etc/pf.conf
#
# Remember to set net.inet.ip.forwarding=1 and/or net.inet6.ip6.forwarding=1
# in /etc/sysctl.conf if packets are to be forwarded between interfaces.
INET_IF = "tun0"
LAN_IF = "rl0"
NAT_PROT = "{tcp, udp, icmp}"
WIN_2K3 = "192.168.0.10"
CYFRA_SMTP = "smtp.uatele.com"
ICMP_TYPE = "{echoreq, unreach}"
####   <== We need some Tables ==> ####
table <admins> const {99.55.66.22, 66.44.88.22, 93.51.57.66}
table <rfc1918> const {127.0.0.0/8, 192.0.2.0/24, 172.16.0.0/12, 169.254.0.0/16, 0.0.0.0/8, 240.0.0.0/4}
table <bruteforce> persist

set skip on lo0         # Skip All Rules For lo Interface
set block-policy return # Policy for icmp
set timeout { frag 10, tcp.established 3600 } # timeout policy for TCP sessions
set loginterface $INET_IF
set loginterface $LAN_IF

altq on $INET_IF cbq bandwidth 4Mb queue \
{ main, smtp, admin, ssh, ack, icmp }
  queue main  bandwidth 63% priority 2 cbq(default borrow red)
  queue smtp  bandwidth 10% priority 3 cbq(borrow red)
  queue admin bandwidth 8%  priority 4 cbq(borrow red)
  queue ssh   bandwidth 8%  priority 5 cbq(borrow red)
  queue ack   bandwidth 6%  priority 6 cbq(borrow red)
  queue icmp  bandwidth 4%  priority 0 cbq
#altq on $INET_IF bandwidth 960Kb hfsc queue { ack, dns, admin, ssh, main, mail, icmp }
#  queue ack        bandwidth 30% priority 8 qlimit 500 hfsc (realtime 20%)
#  queue dns        bandwidth  5% priority 7 qlimit 500 hfsc (realtime  5%)
#  queue admin      bandwidth 10% priority 6 qlimit 500 hfsc (realtime  7%)
#  queue ssh        bandwidth 10% priority 6 qlimit 500 hfsc (realtime 10%) {ssh_login, ssh_bulk}
#   queue ssh_login bandwidth 50% priority 6 qlimit 500 hfsc
#   queue ssh_bulk  bandwidth 50% priority 5 qlimit 500 hfsc
#  queue main       bandwidth 30% priority 5 qlimit 500 hfsc (realtime 20% default)
#  queue mail       bandwidth 10% priority 3 qlimit 500 hfsc (realtime  5%)

#  queue icmp       bandwidth  5% priority 2 qlimit 500 hfsc (realtime  5%)
##### <== Main Rule For NAT ==> #####
nat on $INET_IF proto $NAT_PROT from $LAN_IF:network to any -> ($INET_IF)

##### <== Redirect VNC and RDP to WIN2K3 ==> #####
rdr pass on $INET_IF proto tcp from  to ($INET_IF) port {5900, 3389} -> $WIN_2K3
#####<== By Default Block All ==> #####
block log on { $INET_IF, $LAN_IF } all
#block in quick log from urpf-failed                             # PF Spoofing proteCt!!!
#antispoof log quick for { lo0, $INET_IF, $LAN_IF } inet # PF Spoofing protect IPv4
block log quick from <bruteforce>                              # Block ssh bruteforcers

##### <== Block Not Routable  Networks ==> #####
block drop in quick log on $INET_IF from <rfc1918> to any
block drop out quick log on { $INET_IF , $LAN_IF } from any to <rfc1918>

##### <== For Redirected Ports ==> #####
pass out quick on $LAN_IF proto {tcp,udp} from <admins> to $WIN_2K3 port {5900, 3389}
##### <== Rules for 25 PORT ==> #####
pass in quick log on $LAN_IF inet proto tcp from $WIN_2K3 to $CYFRA_SMTP port 25 queue (smtp, ack)
pass in quick log on $LAN_IF inet proto tcp from $LAN_IF:network to $INET_IF port 25 queue (smtp, ack)
pass in quick log on $INET_IF inet proto tcp from { $CYFRA_SMTP <admins> } to $INET_IF port 25 queue (smtp, ack)
block in quick log on $LAN_IF inet proto tcp from any to ! $LAN_IF port 25
block out quick log on $INET_IF proto tcp from $INET_IF to ! $CYFRA_SMTP port 25
##### <=== For LanNetwork ===> #####
pass in on $LAN_IF from $LAN_IF:network to any
##### <=== For PFStat ===> #####
pass in on $INET_IF inet proto tcp from <admins> to port 80 queue (admin, ack)
##### <=== VPN RULES ===> #####
pass in on $INET_IF inet proto tcp from <admins> to port pptp queue (admin, ack)
pass in on $INET_IF proto gre from <admins> to any queue (admin, ack)
pass out on $LAN_IF inet from 192.168.0.200/30 to $LAN_IF:network queue (admin, ack)
pass out on $LAN_IF inet from tun to $LAN_IF:network
##### <== SSH RULES ==> #####
pass in quick on $INET_IF inet proto tcp from <admins>  to $INET_IF port 22 queue (ssh, ack) modulate state
pass in on $INET_IF inet proto tcp from any to $INET_IF port 22 queue (ssh, ack) synproxy state \
(max-src-conn 10, max-src-conn-rate 5/30, overload <bruteforce> flush global)

##### <== Pass OUT ==> #####
pass out on $INET_IF inet to any queue (main, ack) modulate state
##### <== Pass ICMP ==> #####
pass log inet proto icmp all icmp-type $ICMP_TYPE queue icmp
root@gw:~#

Понятие о том что здесь написано приходит после прочтения FAQ по PF . А вообще, благодаря очень простому синтаксису и принципу работы, правила pf читаются очень легко 🙂

Более подробно остановлюсь, разве что, на ssh правилах. Последнее время розвелось много всяких паскудных ботов, которые подбирают пароли для входа по всему чем можно войти 😀 Приходится както защищаться от километровых failed — ов в логах 🙂 Вот один из вариантов для ssh:

#####<== SSH RULES ==> #####
pass in quick on $INET_IF inet proto tcp from <admins>  to $INET_IF port 22 queue (ssh, ack) modulate state
pass in on $INET_IF inet proto tcp from any to $INET_IF port 22 queue (ssh, ack) synproxy state \
(max-src-conn 10, max-src-conn-rate 5/30, overload  flush global)

Первое правило — пропускаем тех кто в таблице admins без всяких там приколов.

Второе — пропускаем из инета на порт 22 всех но с ограничениями:

  • max-src-conn 10 — не более 10 state с одного ip
  • max-src-conn-rate 5/30 — не более 5 соединений в течении 30 секунд

Все кто превысил данные лимиты, помещаются в таблицу bruteforce и блокируются правилом

block log quick from <bruteforce>             # Block ssh bruteforcers

Для очистки этой таблицы использую такую вот командочку, которую засунул в cron и выполняю раз в час:

admin@gw:~$ sudo crontab -l |grep -i brute
#### <- For clean entries from table SSH BRUTEFORCES older than 1 hour ! -> ####
59      *       *       *       *       /sbin/pfctl -t bruteforce -T expire 86400
admin@gw:~$

В процессе отладки наш лучший друг, товарищ и брат — tcpdump, который может слушать как реальные интерфейсы, так и интерфейс pflog0 на котором видно те пакеты, которые логируются (слово log в правиле какраз для этого). Использование снифера с такими опциями:

root@gw:~# tcpdump -n -e -ttt -i pflog0
tcpdump: listening on pflog0, link-type PFLOG
Mar 16 22:12:22.963961 rule 1/(match) block in on rl0: 0.0.0.0.68 > 255.255.255.255.67: xid:0x52525230 secs:39663 flags:0x8000 [|bootp] [ttl 1]
^C
1 packets received by filter
0 packets dropped by kernel
root@gw:~#

очень информативно рассказывает о судьбе пакетов. В данном примере мы видим что пакет заблочен (block) первым правилом (rule 1) на внутресетевом интерфейсе (rl0) ну и source/destination пакета — 0.0.0.0.68 > 255.255.255.255.67 (в конце после четвертого октета, после точки, показан номер порта источника/назначения соответственно)

Ну вот какбы и все 🙂 Пакетики натятся, клиенты довольные сидят в инете 🙂 А админы пьют пиво и закусывают рыбкой …. все удачи!

Домашний сервер с Debian — Firewall + NAT

Появилось сегодня настроение «покрутить за настройки» свой домашний сервер с Debian Lenny на борту 🙂 С чего бы это вдруг … даже не спрашивайте — чето захотелось срочно поадминить 😀 Ну чтоже настраивать то? Вроде и так все работает и даже кушать не просит! Однакоже, давно мне не давала покоя мысль что firewall у меня дома, ну вообще не по фэншую настроен. Чего только стоит default policy ACCEPT во всех цепочках 😀 Из умений нынешних стоит отметить лиш NAT — работает исправно, не ломался пока еще, и вообще проблем никаких. Вот так вот … на работе сижу вылизываю все, а дома когдато поднял по быстрячку, лиш бы работало — и сплю спокойно! Все как обычно — сапожник без сапог … но это поправимо! Вот, собственно, нашелся обьект «донастройки»? Вполне подойдет, подумалось мне, и взялся я за него основательней!

Итак, задача видется мне так:

1. Улучшить защиту домашнего сервера со стороны интернета

  • перейти на Default Policy — DROP в цепочках INPUT и FORWARD
  • дать доступ к серверу из интернета только на такие сервисы DNS, HTTP, SSH

2. Роздать интернет клиенту из внутрисети, имея настройки:

  • внешний фиксированный ipaddress сервера — 123.123.123.123
  • ipaddress/netmask внутреннего интерфейса — 192.168.0.1/24
  • ipaddress/netmask клиента — 192.168.0.3/24 (в последствии дал доспут по mac address чтобы не зависеть от ip)

3. Предоставить доступ клиенту из внутрисети ко всем доступным на сервере сервисам (samba, imap, ssh, smtp, http)

4. Пробросить порты tcp {4662} и udp {4672, 4665} из внешнего интерфейса сервера на клиента. Открываем «прямой» доступ из интернет для amule на клиенте, ато с low id много не накачаеш 😉

Ну чтож, вроде все вполне очевидно — клиент должен ходить везде (весь интернет + сервисы на домашнем сервере), а из интернета на сервер можно попасть только на порты ssh (мне же нужна админская ходка), на apache (лежит несколько сайтов) и на DNS (чтобы отрезолвить несколько моих и неочень зон).

Для того чтобы все это организовать, достаточно одной только программы — iptables. Нужно также знать, что iptables можно «поднимать» по разному. Можно запускать как сервис при старте системы, а можно только при поднятии интерфейсов скриптом. А если заморочиться … то по любому пришедшему в голову системному событию (параноидальная мысль) 🙂 Я выбрал вариант включения фаервола скриптом с нужными правилами при поднятии сетевых интерфейсов.
В этом случае, скриптик приведенный ниже, надо положить в /etc/network/if-pre-up/ Даже видно из названия директории в которую я его поместил, что он запустится перед поднятием сетевых интерфейсов. Название дал ему 00-snat, вы можете назвать как пожелаете. Главное чтобы у него был бит X — тоесть розрешен запуск. Итак, скрипт:

#!/bin/sh
### - Delete All Rules - ###
iptables -F
iptables -F -t nat
### - Rules For IP from INET - ###
iptables -N from_inet
iptables -A from_inet -p tcp -m conntrack --ctstate NEW,INVALID --tcp-flags SYN,ACK SYN,ACK -j REJECT --reject-with tcp-reset
iptables -A from_inet -p tcp -m multiport --dports 22,53,80 -j ACCEPT
iptables -A from_inet -p udp -m multiport --dports 53 -j ACCEPT
iptables -A from_inet -p icmp --icmp-type 8 -j ACCEPT
#iptables -N from_lan
#iptables -A from_lan -p tcp -m multiport --dports 22,53,80,139,445 -j ACCEPT
#iptables -A from_lan -p udp -m multiport --dports 53,137,138 -j ACCEPT
#iptables -A from_lan -p icmp -j ACCEPT
#iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -i eth0 -j from_inet
### - Rules For IP from LAN - ###
#iptables -A INPUT -i eth1 -j from_lan
iptables -A INPUT -i eth1 -j ACCEPT
### - FWD Rules - ###
iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -m mac --mac-source 00:CC:AA:FF:AA:FF -j ACCEPT
iptables -A FORWARD -p tcp -d 192.168.0.3 --dport 4662 -j ACCEPT
### - NAT - ###
iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -o eth0 -j SNAT --to-source 123.123.123.123
### - Default Policies - ###
iptables -P INPUT DROP
iptables -P OUTPUT ACCEPT
iptables -P FORWARD DROP
## - DNAT for AMule - ###
iptables -t nat -A PREROUTING -i eth0 -p tcp --destination-port 4662 -j DNAT --to-destination 192.168.0.3:4662
iptables -t nat -A PREROUTING -i eth0 -p udp --destination-port 4672 -j DNAT --to-destination 192.168.0.3:4672
iptables -t nat -A PREROUTING -i eth0 -p udp --destination-port 4665 -j DNAT --to-destination 192.168.0.3:4665

Даем права на запуск:

# chmod +x /etc/network/if-pre-up/00-snat

Вот такой скрипт 🙂 Ничего сложного и непонятного тут нету. Все предельно просто.

Как видите есть даже заготовка для случая с недоверенной локальной сетью. Если необходимо — просто розкомментируйте все что касается from_lan и закомментируйте правило:

#iptables -A INPUT -i eth1 -j ACCEPT

В результате все что придет на внутренний интерфейс сервера в цепочку INPUT будет направляться в цепочку from_lan и обрабатываться ее правилами, а уж что неполучит ACCEPT в цепочке from_lan, согласно default police для INPUT, будет молча игнорироваться — DROP! Тоесть мы получим еще и полный контроль над траффиком который приходит из внутрисети непосредственно на внутренний интерфейс сервера 🙂

Кроме того, я заморочился, и разрешил forwarding только для одного mac адреса — конечно, клиентского. Чегото захотелось выпендриться. Можете смело заменить на правило с ip, а то что с mac убрать 🙂

Тоесть, заменяем вот это правило с mac address:

iptables -A FORWARD -m mac --mac-source 00:CC:AA:FF:AA:FF -j ACCEPT

На правило с конкретным ip (если доступ нужно дать только одному клиенту) :

iptables -A FORWARD -s 192.168.0.3 -j ACCEPT

Или на приавило вида ip/mask (если доступ надо дать целой подсети):

iptables -A FORWARD -s 192.168.0.0/24 -j ACCEPT

Ну вот и все! Скажу лиш напоследок, что данный набор правил работает у меня дома вполне исправно уже несколько месяцев. К томуже, написан весьма прозрачно для дополнительных правок, поэтому легко можно модифицировать и под более сложные задачи 😉

Также замечу, что для еще большей безопасности, использую программку fail2ban которая очень эффективно защищает от атак называемых bruteforce. После нескольких неверных попыток авторизации или поиска у нас на сервере чегото непонятно чего (Error 404 в Apache) клиент блочится фаерволом на определенный промежуток времени. Все это достаточно тонко настраивается, может напишу в следующих заметках. Данная утилитка позволяет защищать сервер от какеров которые пытаются сломать ssh, apache, dovecot, разные ftp и много всего (правила для срабатывая блокировки описываются перловыми regexp-ами — это дает нам возможность защитить что угодно при условии наличия логов).

За сим все … всем удачи и супер-пупер безопасности! И чтобы спалось спокойно ….