вторник, 11 октября 2011 г.

IPFilter: Как скрыть существование файрвола?

Я несколько раз писал о своем подходе в настройке файрвола Solaris. Основных принципов два - мы создаем файрвол закрытого типа и мы не скрываем его существования

Иначе говоря, закрыто все, кроме того, что разрешено, и нам наплевать, что сканеры видят наличие файрвола. Делаем мы это с умыслом - мы не скрываем существования файра, максимально затрудняем сканирование таймаутами, и не отвечаем пакетами на запросы, которые нас не интересуют.

Как сканеры определяют существование файрвола?

Очень просто. Если при открытии сессии (посылке пакета SYN) возникает таймаут (файрвол глотает пакет и молчит), значит, порт определяется как filtered. 

Штатное поведение стека TCP в такой ситуации следующее. Есть порт, за которым нет сервиса - стек отвечает пакетом RST.

Если посмотреть на нашу типовую конфигурацию IPFilter, то можно заметить, что все наши блокирующие правила глухо молчат в ответ на сканирование/установление соединений:

# Rules groups setup
# Group 100 - Blocked networks/packets on any interface
# Group 100 setup
block in all head 100
# Group 200 - Opened incoming ports on e1000g0
# Group 200 setup
pass in on e1000g0 head 200

# ---------------------
# Common blocking rules
# ---------------------

# Block all IP fragments
block in quick all with frag group 100

# Block all short IP fragments
block in quick proto tcp all with short group 100

# Block any IP packets with options set in them
block in quick all with ipopts group 100

# Block OS fingerprint attempts
block in log first quick proto tcp all flags SF/SF group 100
block in log first quick proto tcp all flags SF/SFRA group 100
block in log first quick proto tcp all flags /SFRA group 100
block in log first quick proto tcp all flags SFUP/SFUP group 100
block in log first quick proto tcp all flags FUP/FUP group 100
block in log first quick proto tcp all flags F/F group 100
block in log first quick proto tcp all flags U/U group 100
block in log first quick proto tcp all flags P/P group 100

# Anti-spoofing rules
#block in quick from 192.168.0.0/16 to any group 100
block in quick from 172.16.0.0/12 to any group 100
block in quick from 10.0.0.0/8 to any group 100
block in quick from 127.0.0.0/8 to any group 100
block in quick from 0.0.0.0/8 to any group 100
block in quick from 169.254.0.0/16 to any group 100
block in quick from 192.0.2.0/24 to any group 100
block in quick from 204.152.64.0/23 to any group 100
block in quick from 224.0.0.0/3 to any group 100

# Finally block all unmatched
block in quick all

Сканер показывает закрытые порты как отфильтрованные:

Starting Nmap 5.21 ( http://nmap.org ) at 2011-10-11 16:54 Центральная Азия (зима)
NSE: Loaded 36 scripts for scanning.
Initiating ARP Ping Scan at 16:54
Scanning 192.168.192.3 [1 port]
Completed ARP Ping Scan at 16:54, 0.31s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 16:54
Completed Parallel DNS resolution of 1 host. at 16:54, 5.64s elapsed
Initiating SYN Stealth Scan at 16:54
Scanning 192.168.192.3 [1000 ports]
Discovered open port 2222/tcp on 192.168.192.3
Completed SYN Stealth Scan at 16:54, 8.73s elapsed (1000 total ports)
Initiating Service scan at 16:54
Scanning 1 service on 192.168.192.3
Completed Service scan at 16:54, 6.00s elapsed (1 service on 1 host)
Initiating OS detection (try #1) against 192.168.192.3
Retrying OS detection (try #2) against 192.168.192.3
NSE: Script scanning 192.168.192.3.
NSE: Starting runlevel 1 (of 1) scan.
Initiating NSE at 16:54
Completed NSE at 16:54, 0.53s elapsed
NSE: Script Scanning completed.
Nmap scan report for 192.168.192.3
Host is up (0.00s latency).
Not shown: 999 filtered ports
PORT     STATE SERVICE VERSION
2222/tcp open  ssh     (protocol 2.0)
| ssh-hostkey: 1024 3f:8d:b6:e2:68:1a:f2:c7:2c:3e:00:27:9d:96:64:bb (DSA)
|_2048 01:63:b5:7c:cf:b9:e8:b6:1d:68:9c:8b:dd:53:39:a3 (RSA)
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at http://www.insecure.org/cgi-bin/servicefp-submit.cgi :
SF-Port2222-TCP:V=5.21%I=7%D=10/11%Time=4E942071%P=i686-pc-windows-windows
SF:%r(NULL,13,"SSH-2\.0-Fuck\x20YEA!\r\n");
MAC Address: 08:00:27:0C:6F:75 (Cadmus Computer Systems)
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: general purpose
Running (JUST GUESSING) : Sun Solaris 10|9 (92%)
Aggressive OS guesses: Sun Solaris 10 (92%), Sun Solaris 10 (SPARC) (92%), Sun Solaris 9 or 10 (SPARC) (88%)
No exact OS matches for host (test conditions non-ideal).
Uptime guess: 0.073 days (since Tue Oct 11 15:09:20 2011)
Network Distance: 1 hop
TCP Sequence Prediction: Difficulty=263 (Good luck!)
IP ID Sequence Generation: Incremental

HOP RTT     ADDRESS
1   0.00 ms 192.168.192.3

Read data files from: C:\Program Files\Nmap
OS and Service detection performed. Please report any incorrect results at http://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 29.36 seconds
           Raw packets sent: 2088 (97.006KB) | Rcvd: 18 (1030B)

Вот как выглядит наличие файрвола:

Могу добавить, что при заданной конфигурации файрвола и при честном перезапуске ОС, ее определение невозможно, как показано в предыдущих статьях.

Можем ли мы скрыть наличие файрвола от сканера? С учетом вышесказанной особенности, и, если закрыть глаза на то, что система начнет при сканировании отсылать встречные пакеты RST (что может быть проблемой при непиринговом трафике) - одной строчкой. Достаточно переписать финальное блокирующее правило следующим образом:

# Finally block all unmatched
block return-rst in quick all

Давайте для чистоты эксперимента честно рестартуем ОС и посмотрим, что мы сможем узнать посредством сканера теперь.

Starting Nmap 5.21 ( http://nmap.org ) at 2011-10-11 17:06 Центральная Азия (зима)
NSE: Loaded 36 scripts for scanning.
Initiating ARP Ping Scan at 17:06
Scanning 192.168.192.3 [1 port]
Completed ARP Ping Scan at 17:06, 0.16s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 17:06
Completed Parallel DNS resolution of 1 host. at 17:06, 5.64s elapsed
Initiating SYN Stealth Scan at 17:06
Scanning 192.168.192.3 [1000 ports]
Discovered open port 2222/tcp on 192.168.192.3
Completed SYN Stealth Scan at 17:06, 1.53s elapsed (1000 total ports)
Initiating Service scan at 17:06
Scanning 1 service on 192.168.192.3
Completed Service scan at 17:06, 6.00s elapsed (1 service on 1 host)
Initiating OS detection (try #1) against 192.168.192.3
Retrying OS detection (try #2) against 192.168.192.3
NSE: Script scanning 192.168.192.3.
NSE: Starting runlevel 1 (of 1) scan.
Initiating NSE at 17:06
Completed NSE at 17:06, 0.28s elapsed
NSE: Script Scanning completed.
Nmap scan report for 192.168.192.3
Host is up (0.00s latency).
Not shown: 999 closed ports
PORT     STATE SERVICE VERSION
2222/tcp open  ssh     (protocol 2.0)
| ssh-hostkey: 1024 3f:8d:b6:e2:68:1a:f2:c7:2c:3e:00:27:9d:96:64:bb (DSA)
|_2048 01:63:b5:7c:cf:b9:e8:b6:1d:68:9c:8b:dd:53:39:a3 (RSA)
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at http://www.insecure.org/cgi-bin/servicefp-submit.cgi :
SF-Port2222-TCP:V=5.21%I=7%D=10/11%Time=4E942331%P=i686-pc-windows-windows
SF:%r(NULL,13,"SSH-2\.0-Fuck\x20YEA!\r\n");
MAC Address: 08:00:27:0C:6F:75 (Cadmus Computer Systems)
Device type: general purpose
Running (JUST GUESSING) : Sun Solaris 9|10 (86%)
Aggressive OS guesses: Sun Solaris 9 or 10 (SPARC) (86%), Sun Solaris 10 (85%), Sun Solaris 9 (85%)
No exact OS matches for host (test conditions non-ideal).
Uptime guess: 0.003 days (since Tue Oct 11 17:02:38 2011)
Network Distance: 1 hop
TCP Sequence Prediction: Difficulty=257 (Good luck!)
IP ID Sequence Generation: Incremental

HOP RTT     ADDRESS
1   0.00 ms 192.168.192.3

Read data files from: C:\Program Files\Nmap
OS and Service detection performed. Please report any incorrect results at http://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 20.03 seconds
           Raw packets sent: 1135 (54.786KB) | Rcvd: 1045 (42.102KB)

Стала определяться операционная система (естественно, мы теперь отвечаем на пакеты сканера по всему диапазону закрытых портов), однако мы больше не видим существования файрвола. Порты помечены как закрытые.

Ну и визуально мы видим следующее:

Что и требовалось доказать. Хотя машина наглухо (кроме одного порта) закрыта файрволом, внешне она выглядит как незащищенная.

пятница, 7 октября 2011 г.

Повышение системных лимитов в Solaris 10

Хотя Солярис достаточно неплохо оптимизирован "из коробки", в некоторых случаях может возникнуть необходимость повысить системные лимиты, например, с целью масштабирования системы.

Примеров сколько угодно - высоконагруженный веб-сервер, прокси-сервер предприятия с огромной локальной сетью, просто необходимость дозагрузить вычислительные ресурсы.

Как и обычно, все это делается через kernel tunables. Да, безусловно, можно попробовать поиграться с ulimit, НО - не все глобальные параметры можно изменить даже от рута.
Рассмотрим простенький пример. Прокси-сервер бизнес-центра. Должен масштабироваться по умолчанию. Железка достаточно сильная, однако в пиках нагрузки дает too many open files/too much user processes.

Вскрытие показывает, что на машине работает Squid с 192 редиректорами (суммарно). Ругается на процессы/открытые файлы явно прокси.

ulimit показывает нам маленькое количество файловых дескрипторов на пользователя и лимит в 27 с чем-то тысяч процессов на пользователя.

Мониторинг сервера показывает наличие свободных ресурсов по памяти и процессору (само собой разумеется, Squid не склонен к перегрузке процессоров).

Что ж, увеличиваем:

set rlim_fd_max=65536


Перезапускаем, смотрим. Ругань на файлы исчезла, ulimit показывает заданную величину.

Займемся процессами.

set max_nprocs=65536
set maxuprc=32767


Первый параметр - максимально количество процессов в системе. По умолчанию около 30 тысяч. Если его не задать, второй параметр будет ограничен той же величиной (чуть меньшей, 29995).

Перезапускаем. Смотрим:

root @ ktulhu / echo max_nprocs/D | mdb -k
max_nprocs:
max_nprocs:     30000
root @ ktulhu /

root @ ktulhu / echo maxuprc/D | mdb -k
maxuprc:
maxuprc:        29995


Почему? Мы ведь увеличили таблицу процессов. Оказывается, мы забыли один лимитирующий параметр, впрямую связанный с max_nprocs - pidmax. Задаем:

set rlim_fd_max=65536
set pidmax=65536
set max_nprocs=65536
set maxuprc=32767


Перезапускаемся еще раз. Проверяем:

root @ ktulhu / # ulimit -a
core file size          (blocks, -c) unlimited
data seg size           (kbytes, -d) unlimited
file size               (blocks, -f) unlimited
open files                      (-n) 256
pipe size            (512 bytes, -p) 10
stack size              (kbytes, -s) 10240
cpu time               (seconds, -t) unlimited
max user processes              (-u) 32767
virtual memory          (kbytes, -v) unlimited


Вот теперь порядок. Наша заданная величина max user processes установлена глобально, проблема решена.

Маленькое предупреждение напоследок. Повышение системных лимитов не должно выполняться бездумно. Это чревато, например, исчерпанием их в случае перегрузки сверх расчетных пределов. Желательно запустить калькулятор и перед повышением оценить и просчитать возможности сервера по повышению этих самых лимитов. В противном случае неумышленный DDoS весьма вероятен.

PS. С другой стороны, планка оперативной памяти стоит как лопата дерьма и, в нашем конкретном примере с прокси, при необходимости можно достаточно легко нарастить физические пределы сервера по процессам. В любом случае следует помнить, что оптимизация производительности и масштабирование на 90% состоят из мониторинга и медитации.