Кожен Mac поставляється з двома речами, які люди називають «брандмауером». Одним із них є брандмауер програм у налаштуваннях системи, перемикач для вхідних з’єднань для кожної програми. Інший, тихіший — pf, фільтр пакетів BSD, який macOS успадкував від лінії FreeBSD/OpenBSD і який сама Apple використовує під капотом для спільного доступу до Інтернету, VPN і NAT. Досвідчені користувачі та адміністратори можуть спілкуватися з ним напряму за допомогою pfctl, а багато посібників показують фрагмент pf.conf і призводять до успіху. Ці посібники рідко пояснюють, де pf перестає бути корисним для того, чого насправді хоче більшість людей: перегляду та контролю того, що надсилають їхні власні програми. Це лабораторна робота, а не лекція — ми ввімкнемо pf, напишемо правило, прочитаємо стан, який воно зберігає, а потім подивимося, чому цей стан є неправильною формою для брандмауера програми.
Що таке pf насправді
pf — це фільтр пакетів на рівні ядра: він перевіряє пакети, коли вони перетинають мережеві інтерфейси, і вирішує, правило за правилом, пропускати їх чи блокувати. It has no concept of "apps" — it works purely on packet headers: source and destination address, port, protocol, interface, direction. Це не обмеження, яке хтось забув виправити; це дизайн. pf was built to filter traffic at the network layer, the same layer routers and gateways operate at, and it is very good at that job.
Ви спілкуєтеся з ним за допомогою pfctl, утиліти керування. Його довідкова сторінка чітко описує поділ між двома речами, які він виконує: він завантажує набори правил із файлу конфігурації та звітує про стан, який утримує ядро. Два прапорці найбільш важливі для ввімкнення та вимкнення фільтра, як зазначено на сторінці довідки: -e («Увімкнути фільтр пакетів») і -d («Вимкнути фільтр пакетів»). Більше нічого щодо pf не ввімкнено чи вимкнено — увесь набір правил рухається разом.
Увімкнення та зчитування стану
Швидка лабораторія на Mac, де вам зручно використовувати sudo. Спочатку перевірте, чи фільтр уже ввімкнено, і подивіться його лічильники:
sudo pfctl -s info
# example output, trimmed — the real thing includes per-rule and per-source-tracking stats with -v
Status: Enabled for 0 days 02:14:07 Debug: err
State Table Total Rate
current entries 42
searches 88213 9.7/s
inserts 611 0.1/s
removals 569 0.1/sПотім перелічіть правила, які наразі підтримує ядро. pfctl -s rules робить саме це; сторінка довідки зазначає, що з -v він також друкує кількість оцінок за правилом, пакетів і байтів:
sudo pfctl -s rules
# example output, trimmed
scrub-anchor "com.apple/*" all fragment reassemble
anchor "com.apple/*" all
block drop in log quick from <blocklist> to anyЦей рядок com.apple/* не є прикрасою. Apple завантажує власні правила в іменовані прив’язки — термін pf для автономного піднабору правил, який можна вводити та виводити без перезавантаження всього іншого. Прапор -a pfctl націлений на певний прив’язок, і, згідно зі сторінкою довідки, використання його із символом підстановки дозволяє рекурсивно друкувати вкладені прив’язки, завдяки чому ви бачите, що сама Apple завантажила разом із усім, що ви додаєте:
sudo pfctl -a '*' -s rules
# example output, trimmed to the anchors that exist on a stock MacНаписання та завантаження тестового правила
Мінімальний файл прив’язки, який блокує вихідну IP-адресу, збережений як /etc/pf.anchors/test-block:
block drop out quick on en0 proto tcp to 203.0.113.10 port 443Щоб завантажити окремий файл прив’язки, pfctl -f читає правила з файлу відповідно до його сторінки довідки, яка описує файл як такий, що містить макроси, таблиці, параметри та правила фільтрації:
sudo pfctl -f /etc/pf.anchors/test-block
sudo pfctl -s rules
block drop out quick on en0 proto tcp from any to 203.0.113.10 port = 443Чому pf не може бути брандмауером вашої програми
Ніщо з наступного не є помилкою. Це те, що відбувається, коли ви спрямовуєте фільтр пакетів мережевого рівня на завдання, яке вимагає знати, який процес надіслав пакет.
Він не знає, яка програма надіслала пакет
Правила pf відповідають IP-адресі, порту, протоколу, інтерфейсу та напрямку. Немає поля для «назви процесу», «ідентифікатора пакета» або «підпису коду», оскільки pf знаходиться на рівні, де існують пакети, а процеси ні. Дві абсолютно різні програми, які відкривають TCP-з’єднання до одного IP-адреси та порту, не відрізняються для pf. Якщо ви хочете дозволити Slack досягати хосту, блокуючи будь-яку іншу програму від доступу до того самого хосту, pf сам по собі не може висловити це правило.
Правило для імені хоста — це правило для будь-якої IP-адреси, яку це ім’я хоста мало під час завантаження
Файли pf.conf часто посилаються на ім’я хоста для зручності читання — block from evil.example.com. Насправді завантажується не це ім'я; це будь-яка адреса, яку він вирішив. Сторінка довідника OpenBSD pf.conf чітко говорить: «Розділення імені хоста та переклад інтерфейсу на адресу виконується під час завантаження набору правил». Немає DNS-пошуку під час виконання під час потоку трафіку — заміна відбувається один раз, коли ви запускаєте pfctl -f, і правило продовжує відповідати цій одній адресі, доки ви його не перезавантажите. Це добре для сервера зі статичним IP. Воно розпадається в той момент, коли його назва — CDN, хмарний балансувальник навантаження або будь-яка служба, яка обертається або балансує навантаження між багатьма адресами — що описує більшість Інтернету в 2026 році. Правило, покликане заблокувати «цю послугу», тихо звужується до «незалежно від того, яка IP-адреса цієї служби відповідала, коли я завантажував правило», і трафік на кожну іншу адресу, через яку вирішується те саме ім’я хоста, проходить прямо.
Ні підказок, ні розмов — лише статичний набір правил
pf не має моделі взаємодії. Він не може призупинити з’єднання та запитати «Пошта хоче отримати доступ до 51.x.x.x на порту 993 вперше — дозволити?» Воно або відповідає правилу, яке ви вже написали, або потрапляє до стандартного. Кожне рішення має бути передбачуваним і записаним заздалегідь, в термінах IP і порту, до того, як відбудеться трафік. Немає еквівалента підказки першого підключення, тому що підказка вимагає знати, яка програма запитує, а pf не має такої інформації.
Ваша рукописна конфігурація не витримує оновлення
Apple розглядає /etc/pf.conf та прив’язки, які він завантажує, як керовану системою конфігурацію, пов’язану з внутрішніми елементами macOS — від цього залежить спільний доступ до Інтернету, VPN, власні прив’язки брандмауера програм. Оновлення macOS можуть безкоштовно переписати або замінити цей файл. Якщо ви вручну відредагували його, щоб додати власні правила, немає гарантії, що вони переживуть наступне оновлення; ви дізнаєтеся про те, що ваше правило мовчки перестало застосовуватися. Файл конфігурації, який людина підтримує вручну, а операційна система періодично перезаписує, — погане місце для збереження єдиної речі, яка вас насправді хвилює — «чи мій Mac знову спілкувався з цією адресою».
Ні перегляду журналів, ні історії, ні карти
pf може реєструвати відповідні пакети до псевдоінтерфейсу, pflog0, якщо правило містить ключове слово log — видиме вище в правилі списку блоків із попереднього виводу -s rules. Але цей журнал — це потік захоплення пакетів, який можна прочитати за допомогою tcpdump -i pflog0, а не журнал для пошуку. Немає вбудованого засобу перегляду, немає списку заблокованих програм для кожної програми, немає країни чи організації, пов’язаної з адресою, нічого, що можна було б показати комусь, щоб відповісти на запитання «що цей Mac намагався знайти минулого тижня». Ви отримуєте необроблені пакети, а решту збираєте самостійно.
Рівень, який Apple створила для цієї роботи
Власна відповідь Apple на питання «Я хочу фільтрувати трафік мого Mac за програмою» не є pf — це фреймворк розширення мережі, зокрема його постачальники фільтрів вмісту. У документації для розробників Apple описується модель безпосередньо: «Фільтр мережевого вмісту на пристрої перевіряє мережевий вміст користувача, коли він проходить через мережевий стек, і визначає, чи повинен він блокувати цей вміст чи дозволити йому перейти до кінцевого пункту призначення», а постачальник даних фільтра — NEFilterDataProvider — «отримує мережевий вміст користувача та перевіряє цей вміст, щоб визначити, блокувати чи дозволяти». Потоки представлені як об’єкти NEFilterFlow (з NEFilterBrowserFlow і NEFilterSocketFlow як конкретними випадками), що є відсутнім елементом, якого ніколи не було: об’єкт потоку, який фільтруюча програма може перевірити та зв’язати з процесом, який його відкрив, перш ніж приймати рішення про проходження чи блокування.
Ось чому вбудований брандмауер програм (перемикач у параметрах системи) відрізняється від pf, а не інтерфейсом для нього. Власний посібник Apple описує це лише у вхідних термінах: він «може захистити ваш Mac від небажаного контакту, ініційованого іншими комп’ютерами», і він працює, дозволяючи вам «вибирати програми та служби та вказувати, чи можуть вони мати доступ через брандмауер». Для окремої програми, так, але лише для з’єднань, які надходять, і лише через спеціальний механізм, створений Apple для цієї однієї роботи. Він відповідає на запитання, відмінне від того, "що надсилає мій додаток".
| Підхід | Бачить IP/порт | Знає, який додаток | Обробляє перейменовані/змінні IP-адреси | Може підказувати користувачеві | Напрямок |
|---|---|---|---|---|---|
pf (pfctl) | так | немає | Ні — вирішується один раз під час завантаження | немає | Або за правилом |
| Брандмауер програм (системні налаштування) | Ні (перемикач на рівні програми) | так | N/A | немає | Лише вхідні |
| Фільтр вмісту розширення мережі | так | Так, через об’єкт потоку | Так — оцінюється за живий потік | Так, завдяки створеному на ньому додатку | Вихідні та вхідні |
Усе це не робить pf марним. Якщо ви використовуєте Mac як легкий маршрутизатор, вам потрібно відхилити завідомо поганий діапазон на рівні ядра незалежно від того, який процес запитує, або хочете зрозуміти, що роблять власні функції спільного доступу до Інтернету та VPN від Apple під капотом, pf — це правильний і єдиний інструмент для цієї роботи, а pfctl -s rules / -s info — це правильний спосіб поглянути на це. Чого він ніколи не збирався робити, так це відповідати на питання, яке насправді виникає у більшості людей: який із моїх додатків з ким спілкується прямо зараз і чи можна мене запитати, перш ніж дійде новий.
Яке місце тут посідають FireAI та HisnLabs
pf and the built-in Application Firewall are both worth using — FireAI does not replace either; it fills the specific gap neither one can, by tying outbound decisions to the app’s code signature and asking before an unknown one gets a first connection.
FireAI — це власний продукт HisnLabs: ШІ-фаєрвол, який працює безпосередньо на вашому Mac. Він показує простою мовою кожне з’єднання, яке встановлюють ваші застосунки, і дає вам вирішувати, що покидає ваш Mac, — його ШІ працює локально, тож ваш трафік ніколи не надсилається ні нам, ні будь-кому іншому. Команда дослідників безпеки HisnLabs — саме вона підтримує точність цих рішень: каталогізує, які домени є звичайною телеметрією, а які — справжнім сервісом, відстежує країну та мережу за з’єднанням і навчає локальну модель (функцію Autopilot) на реальних шаблонах трафіку — і нічого з цього не покидає ваш Mac.
Ви можете почитати про технічні рішення, що лежать в його основі, або спробувати FireAI протягом 17 днів на сторінці FireAI від HisnLabs.
