9.2 Захисні модулі — що насправді перевіряє кожен¶
[!IMPORTANT] 9.1 завершилася одним правилом: фільтруй дешево і рано, автентифікуй решту. Це модулі, що фільтрують, і кожен перевіряє рівно одну річ —
sanityдоводить, що повідомлення є легальним SIP,secfilterзіставляє рядки зі списками,pikeрахує пакети від джерела,authвстановлює, хто їх надіслав. Жоден не інспектує вільнотекстовий вміст заголовків на shell- чи SQL-безпеку. Розуміння того, хто є хто, — це і є вся гра.
sanity — коректність форми, не безпека¶
sanity_check([msg_checks[, uri_checks]]), що викликається першою в request_route як route("sanity"), відповідає на одне питання: чи це легальний SIP? На провал sanity_reply() видає відповідний 4xx. Задокументовані перевірки — суто структурні: версія і схема R-URI, обов'язкові заголовки (To/From/CSeq/Call-ID/Via), збіг методу в CSeq із методом запиту та валідний integer, Content-Length рівний фактичному розміру тіла (та, що ловить усікання і request smuggling), значення Expires, Proxy-Require, парсовані URI, форма digest-credentials, дублікати To/From tags, наявний-парсований-з-branch перший Via та відповідність RFC 3261 (magic-cookie / lr).
Кожна перевірка — про форму, ніколи — про сенс. І саме ця відмінність є опорною точкою для 9.4:
Підрядок
$(...)усерединіUser-Agentчи'усерединіFrom— абсолютно легальний SIP-токен.sanity_check()пропускає його незмінним.
sanity відхилить пакет, чий Content-Length бреше про своє тіло; він не відхилить — і не може — пакет, що протягує shell-метасимвол чи SQL-фрагмент, бо цей пакет — валідний SIP. Це синтаксичний шлюз — дешевий triage проти malformed-мотлоху, і нічого — проти ворожого-але-коректного вмісту.
secfilter — фільтр вмісту¶
secfilter — найближче в стоковому наборі до фільтрації вмісту: блек- і вайт-листи в пам'яті (завантажені з БД), що зіставляються родиною secf_check_*.
| Функція | Що зіставляє |
|---|---|
secf_check_ip() |
source-IP проти блек-листа |
secf_check_ua() |
User-Agent проти UA-списку |
secf_check_from_hdr() / secf_check_to_hdr() |
user, domain, display-name з From/To |
secf_check_contact_hdr() |
user / domain з Contact |
secf_check_dst(string) |
destination-номер |
secf_check_country(string) |
код країни (потрібен geoip) |
secf_check_sqli_hdr(string) / secf_check_sqli_all() |
заборонені символи в одному значенні / по UA, From, To, Contact |
Це ловить friendly-scanner-UA'и, відомі погані домени, toll-fraud-префікси й очевидні SQLi-проби. Але це статичне зіставлення патернів — рядки і фіксований набір заборонених символів. Воно підвищує вартість наївної атаки; воно не знає, що ваш downstream — БД, shell чи скрипт — зробить зі значенням. Фільтр, а не гарантія — і хибний шар для безпеки в стилі 9.4, що має відбуватися там, де ви використовуєте значення.
pike — детекція флуду¶
pike відповідає на питання: чи одне джерело шле надто швидко? Він трекає rate per-source-IP у shm через дерево з ключем побайтово по адресі (одна структура покриває IPv4 і IPv6). pike_check_req() — або pike_check_ip(ipaddr) для довільної адреси — зараховує кожен hit. Три параметри задають політику: sampling_time_unit (вікно в секундах, default 2), reqs_density_per_unit (дозволено за вікно, default 30), remove_latency (утримання неактивного джерела, default 120).
Повертане значення і є вся суть: 1 — не заблоковано (а також внутрішня помилка — fail-open), -1 — відомий флудер, -2 — новий флудер, перша детекція прямо зараз. Розщеплення -2/-1 дозволяє діяти один раз на першій детекції (залогувати, забанити), а далі дешево short-circuit'ити кожен наступний пакет від того ж джерела. Цей вердикт зазвичай іде прямо в патерн ipban з 9.3: pike детектує, htable — пам'ятає.
topoh / topos — обрізати recon¶
Не фільтри — topology hiding, прочитане тут як відмова в розвідці. Сканер читає Via, Record-Route, Contact і Route, щоб скласти карту вашої внутрішньої адресації; topoh (кодує або зрізає ці заголовки) і topos (ховає стан на боці сервера, повертає непрозорий токен) зменшують те, що витікає у відповідях, які ви таки надсилаєте. Механіка — в 8.1 topology hiding; вони тут, бо загартування edge — це настільки ж про що ви зливаєте у відповідях, наскільки й про що приймаєте в запитах.
auth — єдиний справжній trust boundary на UDP¶
Усе вище — евристика: жодне не встановлює, хто надіслав пакет, а на UDP source-IP не є ідентичністю (9.1). auth проводить межу ідентичності через SIP digest. Challenge-функції — www_challenge(realm, flags[, algorithms]) (401, registrar/UAS), proxy_challenge(...) (407, проксі), auth_challenge(...) (обирає за контекстом) — видають заголовок WWW-/Proxy-Authenticate; сторона перевірки (pv_www_authenticate / pv_proxy_authenticate / pv_auth_check) перераховує digest проти збереженого секрету й приймає лише за збігу. Захист від replay живе в challenge'і: обмежений час життя nonce (nonce_expire, default 300с), а qop додає клієнтський nonce-count, тож перехоплений Authorization не можна просто переграти. Саме це — а не якийсь блек-лист — зупиняє кейси REGISTER-hijack і toll-fraud. Фільтрація купує дешевше відхилення мотлоху; лише auth дозволяє довіряти трафіку, що лишився.
Підсумок¶
| Модуль | Що перевіряє | Де | Чого не робить |
|---|---|---|---|
sanity |
SIP-синтаксис / коректність форми | першим у request_route |
інспектувати вміст на shell/SQL-безпеку |
secfilter |
поля проти списків; SQLi-набір символів | рано, per request | парсити намір; ловити те, чого нема в списку |
pike |
rate запитів per source-IP | per request, edge | дбати про вміст чи ідентичність |
topoh/topos |
(переписує вихідний стан) | per message, edge | відхиляти запити; автентифікувати |
auth |
digest-ідентичність відправника | після дешевих фільтрів | фільтрувати флуди чи malformed-вхід |
Зверху донизу — це доктрина 9.1, зроблена конкретною: відхиляй malformed-мотлох майже задарма (sanity), дропай відомі погані рядки й флуди (secfilter, pike), розкривай мало у відповідях (topoh/topos), витрачай digest-challenge (auth) лише на трафік, що пережив усе це. Прогалина, що стає очевидною: pike забуває флудера після remove_latency, а secf_check_ip() зіставляє лише список, який ви наповнюєте. Перетворення разової детекції на тривалий, поширюваний, кластерний бан — це 9.3.
← Зміст · ← 9.1 Поверхня атаки · Далі: 9.3 Динамічні блок-листи →