четверг, 29 октября 2009 г.

Solaris 10, NMap и OS fingerprinting

Тема OS fingerprinting (удаленная идентификация операционных систем хостов) актуальна всегда. Простейший поиск в Гугле дает кучу результатов. Далеко не все рекомендации, однако, дают положительные результаты при реальном тестировании сканерами, в частности, всем известным NMap.

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

Давайте попробуем посмотреть, можно ли что-то сделать в связи с необходимостью защиты от OS fingerprinting, реализованном NMap.

Если резюмировать практический опыт, то рекомендации полностью соответствуют методологии сканирования.

Как выполняется определение ОС сканерами?

1. Самоочевидная вещь - сканирование баннеров сервисов. Соответственно, необходимо использовать tcpwrappers итп. или минимизировать баннеры сервисов, максимально скрывая версию служб.
2. Сканеры посылают характерные пакеты для определения версии ОС либо пакеты с определенными опциями (вне установленных сессий - см. ниже). Не менее самоочевидная вещь - блокирование соответствующих пакетов файрволом.
3. Иногда с целью сканирования посылаются обычные пакеты, появление которых, однако, вне установленных сессий TCP нехарактерно (ACK итп.)
4. Сканеры как правило имеют базы данных характерных особенностей (параметров) стеков TCP/IP, которые позволяют в рамках обычных сессий к сервисам достаточно четко идентифицировать целевую ОС.

Соответственно, защита от идентификации ОС (не абсолютная, разумеется, однако достаточно продвинутая - во всяком случае, от автоматического сканирования) выполняется по нескольким направлениям.

1. Максимально минимизируем информацию о сервисах. Там, где это возможно - пересобираем сервисы, меняя версии и названия на что угодно произвольное. Например, модифицируем название и версию для OpenSSH в файле version.h.

2 и 3. Пишем блокирующие правила для IPFilter (фрагмент конфигурации):

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

# Block all IP fragments
block in quick all with frag

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

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

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

Кроме того, модифицируются правила для входящих сервисных соединений следующим образом (пример):

pass in quick on bge0 proto tcp from any to myhost port=80 flags S/SA keep state group 200

(данное правило переводится на русский язык следующим образом - "мы не принимаем вне сессий (до посылки SYN) пакетов ACK")

4. Данный пункт менее очевиден и требует определенных ухищрений, в частности, на Solaris. Во-первых, большая часть параметров стека TCP/IP на Solaris динамическая и через /etc/system не задается. Требуется модификация посредством ndd. Во-вторых - нужно знать, какие параметры требуется модифицировать и каким образом. Чтобы, в частности, не пострадало поведение систем и не упала производительность.

В Solaris выполнение данного пункта слегка осложнено тем, что штатного механизма задания параметров стека TCP/IP при запуске системы в Солярис не существует. Тот единственный и глубоко закопанный пример, который мне удалось найти - содержит ошибки и неработоспособен без существенных корректировок (неспособный пройти валидацию сервисный манифест, не слишком удобный и неполный управляющий метод - отсутствует перенаправление в штатные логи SMF итп.).

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

Параметры с удобством задаются в /etc/ndd.conf:

# Harden fingerprinting
tcp tcp_mss_def_ipv4 583
ip ip_path_mtu_discovery 0
tcp tcp_xmit_hiwat 64373
tcp tcp_recv_hiwat 64373
tcp tcp_ipv4_ttl 121
# Functional settings
ip ip_strict_dst_multihoming 1
# Security settings
ip ip_respond_to_echo_broadcast 0
ip ip_send_redirects 0
# Performance tunables
tcp tcp_conn_req_max_q 1024
tcp tcp_conn_req_max_q0 4096
tcp tcp_ip_abort_interval 60000
tcp tcp_keepalive_interval 900000
tcp tcp_rexmit_interval_max 10000
tcp tcp_rexmit_interval_min 3000

Установка данных параметров (первой группы) искажает специфические для Solaris поведенческие параметры стека TCP/IP до неузнаваемости сканерами.

Параметр ip_strict_dst_multihoming также позволяет решить одну давнюю задачу - ответ сервисов на multihomed-машине по тем же портам, с которых пришел запрос (по умолчанию в Solaris стоит значение данного параметра равное 0 - Loose, то есть возвратные пакеты посылаются по любым активным интерфейсам по round robin).

Что получилось в результате?

Удалось ли лишить NMap возможности определения типа и версии ОС?

Проверяем. Целевая машина - Solaris 10 x64 10/09, с поднятым согласно приведенным рекомендациям файрволом (IPF) и установленным вышеупомянутым сервисом NetTune:

root @ athena / # nmap -v -sV -O -A -PN 192.168.0.2

Starting Nmap 5.00 ( http://nmap.org ) at 2009-10-29 17:12 ALMT
NSE: Loaded 53 scripts for scanning.
Initiating Parallel DNS resolution of 1 host. at 17:12
Completed Parallel DNS resolution of 1 host. at 17:12, 0.15s elapsed
Initiating SYN Stealth Scan at 17:12
Scanning 192.168.201.22 [1000 ports]
SYN Stealth Scan Timing: About 15.00% done; ETC: 17:16 (0:02:56 remaining)
SYN Stealth Scan Timing: About 28.55% done; ETC: 17:16 (0:02:33 remaining)
SYN Stealth Scan Timing: About 42.05% done; ETC: 17:16 (0:02:05 remaining)
SYN Stealth Scan Timing: About 57.00% done; ETC: 17:16 (0:01:31 remaining)
SYN Stealth Scan Timing: About 70.50% done; ETC: 17:16 (0:01:03 remaining)
SYN Stealth Scan Timing: About 83.05% done; ETC: 17:16 (0:00:37 remaining)
Completed SYN Stealth Scan at 17:16, 217.23s elapsed (1000 total ports)
Initiating Service scan at 17:16
Initiating OS detection (try #1) against 192.168.201.22
Retrying OS detection (try #2) against 192.168.201.22
NSE: Script scanning 192.168.201.22.
NSE: Script Scanning completed.
Host 192.168.201.22 is up.
All 1000 scanned ports on 192.168.201.22 are filtered
Too many fingerprints match this host to give specific OS details

Read data files from: /usr/local/share/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 227.99 seconds
Raw packets sent: 2048 (94.672KB) | Rcvd: 0 (0B)

На деле, изменение параметров стека даже более важно, нежели настройка или вообще наличие файрвола. Протестируем машину с установленным сервисом NetTune и снятым файрволом (Solaris 10 SPARC 10/09):

Starting Nmap 5.00 ( http://nmap.org ) at 2009-10-29 17:19 Северная Центр. Азия (зима)
NSE: Loaded 30 scripts for scanning.
Initiating SYN Stealth Scan at 17:19
Scanning host1.example.com (192.168.0.5) [1000 ports]
Discovered open port 21/tcp on 192.168.0.5
Discovered open port 443/tcp on 192.168.0.5
Discovered open port 111/tcp on 192.168.0.5
Discovered open port 8080/tcp on 192.168.0.5
Discovered open port 80/tcp on 192.168.0.5
Discovered open port 4045/tcp on 192.168.0.5
Discovered open port 6112/tcp on 192.168.0.5
Increasing send delay for 192.168.0.5 from 0 to 5 due to 21 out of 68 dropped probes since last increase.
Increasing send delay for 192.168.0.5 from 5 to 10 due to max_successful_tryno increase to 4
Discovered open port 2049/tcp on 192.168.0.5
Discovered open port 6003/tcp on 192.168.0.5
Discovered open port 32771/tcp on 192.168.0.5
Discovered open port 32773/tcp on 192.168.0.5
Discovered open port 32772/tcp on 192.168.0.5
Discovered open port 2222/tcp on 192.168.0.5
Discovered open port 32777/tcp on 192.168.0.5
Discovered open port 32779/tcp on 192.168.0.5
Discovered open port 1521/tcp on 192.168.0.5
Discovered open port 5000/tcp on 192.168.0.5
Discovered open port 32778/tcp on 192.168.0.5
Completed SYN Stealth Scan at 17:20, 27.20s elapsed (1000 total ports)
Initiating Service scan at 17:20
Scanning 18 services on host1.example.com (192.168.0.5)
Completed Service scan at 17:22, 122.13s elapsed (18 services on 1 host)
Initiating OS detection (try #1) against host1.example.com (192.168.0.5)
Retrying OS detection (try #2) against host1.example.com (192.168.0.5)
Retrying OS detection (try #3) against host1.example.com (192.168.0.5)
Retrying OS detection (try #4) against host1.example.com (192.168.0.5)
Retrying OS detection (try #5) against host1.example.com (192.168.0.5)

192.168.0.5: guessing hop distance at 1
Initiating Traceroute at 17:22
Completed Traceroute at 17:22, 0.13s elapsed
Initiating Parallel DNS resolution of 2 hosts. at 17:22
Completed Parallel DNS resolution of 2 hosts. at 17:22, 0.38s elapsed
NSE: Script scanning 192.168.0.5.
NSE: Starting runlevel 1 scan
Initiating NSE at 17:22
Completed NSE at 17:22, 7.59s elapsed
NSE: Script Scanning completed.

Host host1.example.com (192.168.0.5) is up (0.027s latency).

Interesting ports on host1.example.com (192.168.0.5):

Not shown: 982 closed ports

PORT STATE SERVICE VERSION
21/tcp open ftp?
80/tcp open http Oracle Application Server 10g httpd 10.1.2.0.0
111/tcp open rpcbind
| rpcinfo:
| 100000 2,3,4 111/udp rpcbind
| 100003 2,3 2049/udp nfs
| 100227 2,3 2049/udp nfs_acl
| 100021 1,2,3,4 4045/udp nlockmgr
| 100026 1 32780/udp bootparam
| 100024 1 32787/udp status
| 100133 1 32787/udp nsm_addrand
| 100001 2,3,4 32797/udp rstatd
| 100011 1 32798/udp rquotad
| 100005 1,2,3 32799/udp mountd
| 100000 2,3,4 111/tcp rpcbind
| 100003 2,3,4 2049/tcp nfs
| 100227 2,3 2049/tcp nfs_acl
| 100021 1,2,3,4 4045/tcp nlockmgr
| 100026 1 32771/tcp bootparam
| 1073741824 1 32772/tcp fmproduct
| 100024 1 32773/tcp status
| 100133 1 32773/tcp nsm_addrand
|_ 100005 1,2,3 32777/tcp mountd
443/tcp open ssl/http Oracle Application Server 10g httpd 10.1.2.0.0
1521/tcp open oracle-tns Oracle TNS Listener 10.2.0.4.0 (for Solaris)
2049/tcp open rpcbind
2222/tcp open ssh (protocol 2.0)
| ssh-hostkey: 1024 1f:ed:ac:a3:26:86:65:e1:df:42:61:61:0a:69:bf:37 (DSA)
|_ 2048 02:53:46:67:91:0d:0b:0c:f5:45:d7:48:00:39:61:b1 (RSA)
4045/tcp open rpcbind
5000/tcp open upnp?
6003/tcp open X11:3?
6112/tcp open dtspc?
8080/tcp open http Apache httpd 2.0.63 ((Unix) DAV/2)
|_ html-title: Test Page for Apache Installation
32771/tcp open rpcbind
32772/tcp open rpcbind
32773/tcp open rpcbind
32777/tcp open rpcbind
32778/tcp open sometimes-rpc19?
32779/tcp open oracle-tns Oracle TNS Listener

==============NEXT SERVICE FINGERPRINT (SUBMIT INDIVIDUALLY)==============
SF-Port2222-TCP:V=5.00%I=7%D=10/29%Time=4AE97A6E%P=i686-pc-windows-windows
SF:%r(NULL,12,"SSH-2\.0-unknown\r\n");
==============NEXT SERVICE FINGERPRINT (SUBMIT INDIVIDUALLY)==============

SF-Port32779-TCP:V=5.00%I=7%D=10/29%Time=4AE97A91%P=i686-pc-windows-windows%r(oracle-tns,24,"\0\$\0\0\x04\0\0\0\"\0\0\x18\(DESCRIPTION=\(ERR=115\)\)\SF:0");

No exact OS matches for host (If you know what OS is running on it, see http://nmap.org/submit/ ).

TCP/IP fingerprint:

OS:SCAN(V=5.00%D=10/29%OT=21%CT=1%CU=42571%PV=Y%DS=1%G=Y%TM=4AE97AF8%P=i686
OS:-pc-windows-windows)SEQ(SP=106%GCD=1%ISR=10B%TI=I%CI=I%II=I%SS=S%TS=7)SE
OS:Q(SP=106%GCD=1%ISR=10B%TI=I%CI=I%TS=7)OPS(O1=NNT11M5B4NW0NNS%O2=NNT11M5B
OS:4NW0NNS%O3=NNT11M5B4NW0%O4=NNT11M5B4NW0NNS%O5=NNT11M5B4NW0NNS%O6=NNT11M5
OS:B4NNS)WIN(W1=C050%W2=C330%W3=C1CC%W4=C0E9%W5=C068%W6=C0B7)ECN(R=Y%DF=N%T
OS:=3C%W=C1E8%O=M5B4NW0NNS%CC=Y%Q=)T1(R=Y%DF=N%T=3C%S=O%A=S+%F=AS%RD=0%Q=)T
OS:2(R=N)T3(R=N)T4(R=Y%DF=Y%T=80%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T5(R=Y%DF=N%T=8
OS:0%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)T6(R=Y%DF=Y%T=80%W=0%S=A%A=Z%F=R%O=%RD=0%
OS:Q=)T7(R=N)U1(R=Y%DF=N%T=FF%IPL=70%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUD=G
OS:)IE(R=Y%DFI=S%T=FF%CD=S)

Uptime guess: 1.257 days (since Wed Oct 28 11:12:15 2009)
Network Distance: 1 hop
TCP Sequence Prediction: Difficulty=262 (Good luck!)
IP ID Sequence Generation: Incremental

TRACEROUTE (using port 1025/tcp)

HOP RTT ADDRESS
1 109.00 192.168.2.1
2 0.00 host1.example.com (192.168.0.5)

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 173.69 seconds
Raw packets sent: 1641 (77.208KB) | Rcvd: 1075 (46.164KB)

Сюрприз! Здесь, несмотря на снятый файрвол, ОС идентифицировать не удалось! (хотя человек, глядя на баннеры, которые никто и не думал прятать, конечно, идентифицирует ОС с высокой вероятностью).

Проверим еще одну машину Solaris 10 x86 (32 бита) 10/09 с установленным сервисом NetTune и настроенным по рекомендациям файрволом:

Starting Nmap 5.00 ( http://nmap.org ) at 2009-10-29 17:42 Северная Центр. Азия (зима)

NSE: Loaded 30 scripts for scanning.
Initiating ARP Ping Scan at 17:42
Scanning 192.168.0.3 [1 port]
Completed ARP Ping Scan at 17:42, 0.22s elapsed (1 total hosts)
Initiating SYN Stealth Scan at 17:42
Scanning ktulhu.fhtagn.com (192.168.0.3) [5 ports]
Discovered open port 53/tcp on 192.168.0.3
Discovered open port 80/tcp on 192.168.0.3
Discovered open port 8080/tcp on 192.168.0.3
Discovered open port 2222/tcp on 192.168.0.3
Completed SYN Stealth Scan at 17:42, 1.25s elapsed (5 total ports)
Initiating UDP Scan at 17:42
Scanning ktulhu.fhtagn.com (192.168.0.3) [5 ports]
Completed UDP Scan at 17:42, 1.25s elapsed (5 total ports)
Initiating Service scan at 17:42
Scanning 9 services on ktulhu.fhtagn.com (192.168.0.3)
Discovered open port 53/udp on 192.168.0.3
Discovered open|filtered port 53/udp on ktulhu.fhtagn.com (192.168.0.3) is actually open
Discovered open port 123/udp on 192.168.0.3
Discovered open|filtered port 123/udp on ktulhu.fhtagn.com (192.168.0.3) is actually open
Completed Service scan at 17:43, 55.03s elapsed (9 services on 1 host)
Initiating OS detection (try #1) against ktulhu.fhtagn.com (192.168.0.3)
Retrying OS detection (try #2) against ktulhu.fhtagn.com (192.168.0.3)
NSE: Script scanning 192.168.0.3.
NSE: Starting runlevel 1 scan
Initiating NSE at 17:43
Completed NSE at 17:43, 4.27s elapsed
NSE: Script Scanning completed.

Host ktulhu.fhtagn.com (192.168.0.3) is up (0.00s latency).

Interesting ports on ktulhu.fhtagn.com (192.168.0.3):

PORT STATE SERVICE VERSION
53/tcp open domain ISC BIND unknown
80/tcp open http Apache httpd
|_ html-title: 403 Forbidden
123/tcp filtered ntp
2222/tcp open ssh OpenSSH 5.3 (protocol 2.0)
| ssh-hostkey: 1024 e8:01:51:4d:86:55:72:fb:40:1d:46:d4:82:1c:c0:cf (DSA)
|_ 1024 60:8f:2a:57:12:3b:e8:6b:14:28:9a:85:38:b5:b2:21 (RSA)
8080/tcp open http-proxy Squid webproxy 2.7.STABLE4
| http-open-proxy: Potentially OPEN proxy.
|_ Methods successfully tested: GET HEAD CONNECT
53/udp open domain ISC BIND unknown
|_ dns-recursion: Recursion appears to be enabled
80/udp open|filtered http
123/udp open ntp NTP v4
2222/udp open|filtered msantipiracy
8080/udp open|filtered unknown

MAC Address: 00:D0:B7:A0:87:74 (Intel)

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 (86%)

Aggressive OS guesses: Sun Solaris 10 (86%)

No exact OS matches for host (test conditions non-ideal).

Network Distance: 1 hop

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 69.99 seconds
Raw packets sent: 107 (9704B) | Rcvd: 22 (1218B)

Здесь вероятность обнаружения резко выше, практически до попадания.

Почему? Потому что выполнялся UDP-скан, есть двунаправленные порты (53, например); а при наличии пары "открытый порт - закрытый порт" вероятность обнаружения повышается вплоть до точного попадания даже при выполнении всех вышеописанных настроек. То есть, на вероятность детектирования ОС влияют также общие параметры настройки файрвола, открытые и закрытые сервисные порты и режимы сканирования (Та же самая машина в режиме сканирования только TCP не идентифицируется по типу и версии ОС, либо NMap бодро рапортует об OpenBSD 4.0).

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

Также, впрочем, как и обеспечить абсолютную невидимость боевого истребителя от радарного обнаружения. ;)

понедельник, 26 октября 2009 г.

Оперативная память и ZFS III

Несмотря на утверждения некоторых специалистов Sun, что-де ZFS лучше знает и в тюнинге не нуждается, все чаще оказывается, что это утверждение не вполне соответствует действительности. Касательно очень многих приложений, прежде всего, СУБД и некоторых комплексных решений.

В предыдущих статьях - здесь и здесь - я писал о том, что нужно во многих случаях менять параметры хранения ZFS. Это действительно так, подстройка recordsize позволяет облегчить выполнение IO-операций.

Несмотря на эти мероприятия, однако, ZFS (а точнее, его ARC) по умолчанию склонен к расползанию по оперативной памяти. Насколько велико это расползание? Давайте попробуем посмотреть, сколько в точности потребляет ARC и нельзя ли что-нибудь с этим сделать.

Замечание: Да, понятно, что тюнинг-зло. Да, понятно, что ZFS разработана чтобы не красть память у приложений и возвращать ее по первому требованию. Однако, как быть с накладными расходами на освобождение в критичных по отклику системах?

Так как статистика ZFS не находится на поверхности и не относится к легкодоступным, воспользуемся почти сановскими инструментами - arcstat.pl и arc_summary.pl.

Можно также взять сырые данные непосредственно при помощи kstat -m zfs, однако они не вполне в удобоваримом виде.

Вышеуказанные скрипты как раз дают возможность перемолоть данные kstat и представить в пригодном к употреблению виде.

Посмотрим на две системы. Первая - SPARC, 4 Гб RAM, вся на ZFS, вторая x64, 4 Гб RAM, тоже вся на ZFS:

root @ host1 / # ./arcstat.pl
Time read miss miss% dmis dm% pmis pm% mmis mm% arcsz c
13:19:21 997K 20K 2 9K 1 10K 10 11K 4 1G 3G
13:19:22 2 0 0 0 0 0 0 0 0 1G 3G
13:19:23 0 0 0 0 0 0 0 0 0 1G 3G
13:19:24 0 0 0 0 0 0 0 0 0 1G 3G
13:19:25 0 0 0 0 0 0 0 0 0 1G 3G
^C

root @ host2 / # arcstat.pl
Time read miss miss% dmis dm% pmis pm% mmis mm% arcsz c
13:20:51 157K 25K 16 15K 11 10K 44 4K 12 743M 3G
13:20:52 4 0 0 0 0 0 0 0 0 743M 3G
13:20:53 0 0 0 0 0 0 0 0 0 743M 3G
13:20:54 0 0 0 0 0 0 0 0 0 743M 3G
13:20:55 0 0 0 0 0 0 0 0 0 743M 3G
^C

Нас особенно интересуют два последних столбца. Что они означают?

Дабы это понять, спросим второй скрипт (обратите внимание, что это статистика первого хоста):

root @ host1 / # ./arc_summary.pl
System Memory:
Physical RAM: 4017 MB
Free Memory : 1731 MB
LotsFree: 62 MB

ZFS Tunables (/etc/system):

ARC Size:
Current Size: 1179 MB (arcsize)
Target Size (Adaptive): 3013 MB (c)
Min Size (Hard Limit): 376 MB (zfs_arc_min)
Max Size (Hard Limit): 3013 MB (zfs_arc_max)

ARC Size Breakdown:
Most Recently Used Cache Size: 49% 1506 MB (p)
Most Frequently Used Cache Size: 50% 1506 MB (c-p)

ARC Efficency:
Cache Access Total: 997204
Cache Hit Ratio: 97% 976716 [Defined State for buffer]
Cache Miss Ratio: 2% 20488 [Undefined State for Buffer]
REAL Hit Ratio: 88% 885287 [MRU/MFU Hits Only]

Data Demand Efficiency: 99%
Data Prefetch Efficiency: 58%
....

А вот что: arcsz это текущий размер ARC, а в последнем столбце у нас Target Size, то есть величина, до которой разрешается расползаться кэшу. Первая же поверхностная проверка показывает, что в большинстве машин с ZFS данное значение выбирается из соотношения приблизительно 3/4 всей оперативной памяти.

Для некоторых приложений это то, что нужно. Но не для всех.

Например, для кэширующих приложений, типа squid, webcache, итп. - которые сами используют память для целей кэширования - запросы на освобождение памяти ARC в большом количестве вызовут определенную и достаточно чувствительную перегрузку, которая, к тому же, усугубится необходимостью чекпоинтинга большого ARC.

Нельзя ли что-нибудь втереть, или вправить или еще что-нибудь?

Конечно, можно.

Воспользуемся лимитом и ограничим для второй машины размеры ARC величиной 1 Гб - то есть 1/4 от оперативной памяти (на ней как раз находится Oracle, OHS и webcache):

set zfs:zfs_arc_max=1073741824

Насколько изменились показатели?

root @ host2 / # arc_summary.pl
System Memory:
Physical RAM: 4087 MB
Free Memory : 2032 MB
LotsFree: 63 MB

ZFS Tunables (/etc/system):
set zfs:zfs_arc_max=1073741824

ARC Size:
Current Size: 797 MB (arcsize)
Target Size (Adaptive): 1024 MB (c)
Min Size (Hard Limit): 128 MB (zfs_arc_min)
Max Size (Hard Limit): 1024 MB (zfs_arc_max)

ARC Size Breakdown:
Most Recently Used Cache Size: 61% 630 MB (p)
Most Frequently Used Cache Size: 38% 393 MB (c-p)

ARC Efficency:
Cache Access Total: 232698
Cache Hit Ratio: 87% 203107 [Defined State for buffer]
Cache Miss Ratio: 12% 29591 [Undefined State for Buffer]
REAL Hit Ratio: 80% 188141 [MRU/MFU Hits Only]

Data Demand Efficiency: 92%
Data Prefetch Efficiency: 33%
...

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

Что важно - практически минимизировался чекпоинтинг ZFS (больший кэш не всегда лучше), реально освободилась память. Если раньше эта машина была весьма склонна к пожиранию свободной памяти настолько (не безвозвратно, и тем не менее), что метрику Oracle EM free_memory приходилось задирать, то теперь она удерживается в разумных рамках.

Кроме того, чрезмерно большой кэш в ряде случаев будет склонен к переохлаждению, то есть будет заметно падать Hit ratio.

У меня не сохранилось для интересующей нас машины начальной статистики, однако новая статистика ARC объективно лучше:

root @ host2 / # arc_summary.pl
System Memory:
Physical RAM: 4087 MB
Free Memory : 2028 MB
LotsFree: 63 MB

ZFS Tunables (/etc/system):
set zfs:zfs_arc_max=1073741824

ARC Size:
Current Size: 800 MB (arcsize)
Target Size (Adaptive): 1024 MB (c)
Min Size (Hard Limit): 128 MB (zfs_arc_min)
Max Size (Hard Limit): 1024 MB (zfs_arc_max)

ARC Size Breakdown:
Most Recently Used Cache Size: 61% 632 MB (p)
Most Frequently Used Cache Size: 38% 391 MB (c-p)

ARC Efficency:
Cache Access Total: 237200
Cache Hit Ratio: 87% 207433 [Defined State for buffer]
Cache Miss Ratio: 12% 29767 [Undefined State for Buffer]
REAL Hit Ratio: 80% 191734 [MRU/MFU Hits Only]

Data Demand Efficiency: 92%
Data Prefetch Efficiency: 35%
...

Кроме того, ообратите внимание, что, поскольку мы реально не используем 3 Гб под кэш ARC, то нет смысла резервировать под target 3/4 оперативной памяти, оставив эту память под другие приложения.

Да, ZFS и так бы освободила память по запросу - однако в большинстве случаев ценой дисковой записи по чекпойнту.

Так что, заявления вида "Tuning is Evil" представляются в некоторых случаях весьма спорными. ;)

Лучше, чем у авторов заявления не скажешь (читать внимательно):

[цитата]
Tuning is Evil

Tuning is often evil and should rarely be done.

First, consider that the default values are set by the people who know the most about the effects of the tuning on the software that they supply. If a better value exists, it should be the default. While alternative values might help a given workload, it could quite possibly degrade some other aspects of performance. Occasionally, catastrophically so.

Over time, tuning recommendations might become stale at best or might lead to performance degradations. Customers are leery of changing a tuning that is in place and the net effect is a worse product than what it could be. Moreover, tuning enabled on a given system might spread to other systems, where it might not be warranted at all.

Nevertheless, it is understood that customers who carefully observe their own system may understand aspects of their workloads that cannot be anticipated by the defaults. In such cases, the tuning information below may be applied, provided that one works to carefully understand its effects.

[конец цитаты]

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

вторник, 20 октября 2009 г.

Обновление 8 Solaris 10 - переход на 10/09

Sun выпустил новое обновление Solaris. Что нового? Есть ли трудности?

Первое, что стоит отметить - нового достаточно, но оно слегка не такое, как ожидалось.

Теперь Солярис больше не идет на CD-имиджах. Только DVD. Старые системы рыдают. ;)

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

Улучшения ZFS - существенные, но криптование все еще не поддерживается. Flash-установка с ZFS-стримов (реально поддерживается с лета), расширенная схема кэширования. Возможность задавать свойства пулов при их создании. Восстановление ZIL. Откат датасетов без их размонтирования. Посылка инкрементальных снапшотов в кумулятивный - очень полезно при бэкапах огромных сторидж-пулов (я-то все гадал, как это будет выглядеть при многотерабайтных объемах). NFS-style ACL's.

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

В целом, изменения в большей степени коснулись ZFS (теперь она версии 4, следует обновлять пулы и датасеты - и - важно! - бэкапы можно записывать заново, Сан не гарантирует обратной совместимости).

Не пересказываю new features целиком, умеющие читать прочитают сами. ;)

Как обновляться?

Просто. При помощи LU.

Как показал практический опыт, наиболее правильной процедурой обновления (предполагается, что 5/09 у вас уже стоит на ZFS root pool) будет следующая последовательность:

1. До начала обновления нужно обязательно обновить пакеты LU с дистрибутива, конкретно - SUNWlucfg, SUNWlur, SUNWluu. Об этом сказано в руководстве по установке 10/09, но кто сейчас читает руководства? ;) Старые пакеты нужно удалить, а новые установить.

2. Только после этого можно создавать новый BE. Само обновление проходит без проблем, следует иметь в виду, что старинный баг с некорректным обновлением menu.lst на платформах x86/x64 теперь корректно исправлен, нет необходимости при активации нового BE что-либо делать руками.

3. После завершения активации и перезагрузки системы первое, что необходимо сделать (убедившись в стабильности нового BE) - обновить сперва пулы, а затем файловые системы (датасеты) командами zpool upgrade и zfs upgrade. Ну и, разумеется, записать новые резервные копии (сделать новые снапшоты).

Собственно, больше никаких сюрпризов в обновлении нет. Честно говоря, я впервые настолько легко провел целую серию обновлений средствами LU.

понедельник, 12 октября 2009 г.

Файловые системы, базы данных, IOPS и ZFS

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

Знаете, коллеги, что непонятно? Давным-давно (теперь уже), практически во времена она, сцепились так же (нет, не васи пупкины на iXBT) AMD и Intel. По поводу тактовых частот их процессоров и реальной производительности. И анонимные эксперты с iXBT, и все, кто мало-мальски разбирался в сути вопроса (сравнительной фаллометрии бенчмарков, синтетических тестах и реальной производительности) - все пришли к выводу, что не гигагерцем единым, но реальной производительностью конкретных приложений определяется быстродействие процессоров.

И который год лично я наблюдаю (и даже иногда участвую) в фаллометрических схватках, как надо строить системы хранения под БД, потому что (см. пруфлинк 1, пруфлинк 2, пруфлинк 3), дескать, медленно все в том или другом случае.

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

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

Иногда это провоцируют сами вендоры (чего далеко ходить, Evil Tuning Guide от Sun дорогого стоит) - де, "позвольте ZFS самой разобраться!". Иногда - синтетические тесты ( "а в IOPSах я все-таки длиннее!").

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

Давайте попробуем разобраться, правомерно ли использование синтетических тестов и бенчмарков, а также IOPS, во всех случаях. В частности, нас интересует сочетание "ZFS и базы данных".

ZFS использует ряд совершенно нетрадиционных парадигм среди остальных файловых систем. Прежде всего, она является системой с сильно отложенной записью. Предпочитающей умное кэширование (ARC и L2ARC) и предвыборку и имеющую очень специфический принцип журналирования (журналирование намерений, ZIL - ZFS Intent Log). Но, самое главное, ZFS имеет очень продвинутые структуры метаданных, позволяющие во-первых, не иметь такой общей для большинства файловых систем проблемы, как фрагментация, а во-вторых, иметь крайне низкие накладные расходы на модификацию этих самых метаданных и, как следствие, и собственно данных, хранящихся в файловой системе.

Не буду пытаться пересказывать концепции ZFS или, тем более, разжевывать их. Все уже разжевано и самим автором и Sun Microsystems.

Попробую кратко изложить суть тюнинга ZFS под базы данных Oracle (и некоторые общие соображения, касающиеся особенностей функционирования ZFS при вводе-выводе).

1. Конфигурация пулов/файловых систем ZFS по умолчанию не слишком оптимальна для баз данных. Пруфлинк.

Sun Microsystems и опытные администраторы все, как один, сходятся в одном. Для баз данных, для которых в наибольшей степени характерны короткие чтения, размер записи ZFS должен быть равен размеру блока БД. Значение по умолчанию в 128К приводит к избыточной предвыборке, перегрузке кэша ARC ненужными предвыборками и дискредитирует интеллектуальное поведение ARC. В конечном итоге, это приводит к ненужным задержкам в отклике серверов БД и перегрузке оперативной памяти чрезмерно кэшированными данными.

2. Redo-логи таких баз данных должны располагаться на файловых системах с наибольшим размером записи (т.е 128К).

Данная рекомендация преследует уменьшение накладных расходов на запись (сокращая количество операций как самой записи, так и уменьшая объем информации, записываемый в ZIL, где бы этот самый ZIL не располагался). Особенно эффективна данная рекомендация в сочетании с определенным (в общем случае - максимальном) значении параметра maxphys.

Я уже писал ранее о необходимости правильного структурирования пулов ZFS под базы данных и указания для них правильных параметров хранения здесь и здесь.

Практически, выполнение рекомендаций Sun позволило избежать на одном из фронтальных серверов с БД Oracle позади веб-сервера хронической (хотя и появлявшейся не в очень большом количестве) ошибки "503 Server Busy". Внутренняя статистика также показала улучшение времени отклика более, чем вчетверо (с 0,3 сек до 0,02 сек в среднем).

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

Об IOPS вообще разговор особый.

Сторонники измерения производительности систем хранения (и в частности их части - файловых систем) в IOPS как-то упускают из виду тот факт, что по определению, IOPS измеряет конечную производительность аппаратных частей систем хранения (процитирую определение полностью):

IOPS (Input/Output Operations Per Second) is a common benchmark for harddisks and other computer storage media. Like with any benchmark, IOPS numbers published by drive and SAN vendors are often misleading and do not guarantee real-world application performance.

Как следует из определения, сам по себе показатель IOPS вообще ничего не говорит о реальной производительности файловой системы как таковой. Более того, он никакого отношения, собственно, к файловой системе-то и не имеет. И - самое главное - исключительно специфика работы файловой системы будет определять количество IO-операций, реально дошедших до железа и измеренных на железе.

(Я хочу перевести определение на совсем элементарный язык. Значение IOPS показывает лишь, как быстро дрыгают диски головками и как быстро крутятся их шпиндели и при прочих равных условиях показатель тем выше, чем большее количество дисков собрано в одну систему хранения. И ВСЕ! Никакого отношения к количеству записанных-прочитанных гигабайт в секунду в реальных условиях работы с реальными приложениями данный показатель не имеет и иметь не может!)

Говоря простым языком, если ZFS показывает на порядок-два меньшее число IOPS на одном и том же железе - это отнюдь не означает, что ZFS медленная. Скорее, наоборот.

Выводы из всего вышесказанного будут следующие:

1. IOPS не показатель ни скорости работы файловой системы по отношению к другой файловой системе.

2. IOPS не показатель скорости работы системы в целом вообще.

3. ZFS не проигрывает другим файловым системам и LVM в скорости. Сравнения, утверждающие нечто подобное, почти всегда являются некорректными.

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

Последнее утверждение я перефразирую на основе собственного опыта как "Тюнинг не является злом. Он по-прежнему необходим - даже с ZFS".