Два разных брандмауэра: Application Firewall и pf
В macOS физически живут два независимых межсетевых экрана, и их часто путают.
Первый - Application Firewall (ALF, он же приложенческий брандмауэр mac). Тот самый из Системных настроек -> Сеть -> Брандмауэр (System Settings -> Network -> Firewall). Его логика - не по портам, а по приложениям. Когда процесс пытается слушать входящие соединения, ALF решает: пустить или нет, опираясь на подпись бинаря и твои правила. Это удобно для обычного пользователя: ты разрешаешь "Загрузкам Steam" принимать соединения, не зная, какой там порт.
Второй - pf (Packet Filter), полноценный BSD-фаервол, перенесённый из OpenBSD. Это сетевой экран macos уровня пакетов: фильтрует по IP, портам, протоколам, интерфейсам, направлению, умеет NAT, нормализацию (scrub), очереди трафика. Управляется через pfctl и конфиг /etc/pf.conf. Это инструмент для продвинутых - им пользуются VPN-клиенты, "Общий интернет" (Internet Sharing), сам ALF подвешивает в pf свои якоря.
Ключевое различие на пальцах:
- Application Firewall - простой, по приложениям, только входящие, GUI-управляемый, для всех.
- pf - гибкий, по пакетам и портам, входящие и исходящие, конфиг-управляемый, для тех, кто понимает что делает.

Application Firewall и socketfilterfw из терминала
GUI - это вершина айсберга. Под капотом ALF обслуживает демон socketfilterfw, а управляющая утилита лежит по непривычному пути - не в /usr/bin, а в /usr/libexec/ApplicationFirewall/socketfilterfw. Запоминай этот путь, в PATH его нет.
Посмотрим текущее состояние:
Код: Выделить всё
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --getglobalstate --getstealthmode --getblockall
Firewall is enabled. (State = 1)
Stealth mode disabled
Block all DISABLED!
Включаем защиту целиком (нужен sudo, изменения требуют прав администратора):
Код: Выделить всё
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setglobalstate on
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setstealthmode on
Полезные ключи socketfilterfw:
- --listapps - показать список приложений с их правилами и путями.
- --add /path/to/app и --remove - добавить/убрать приложение в список правил.
- --blockapp / --unblockapp - заблокировать или разрешить входящие конкретному бинарю.
- --setallowsigned on|off - автоматически пускать входящие для встроенных подписанных Apple-приложений.
- --setallowsignedapp on|off - то же для скачанных подписанных приложений (валидный Developer ID).
- --setloggingmode on и --setloggingopt detail - включить детальный лог.
Лог ALF читается через unified logging:
Код: Выделить всё
log show --predicate 'process == "socketfilterfw"' --last 1h --info
Когда нужен контроль по портам и направлениям, выходит на сцену pf mac. Управление - утилитой pfctl.
Состояние и статистика:
Код: Выделить всё
sudo pfctl -s info
Status: Enabled for 3 days 04:11:22 Debug: Urgent
State Table Total Rate
current entries 87
searches 9241003 33.4/s
inserts 284551 1.0/s
Главный конфиг - /etc/pf.conf. И тут первая большая грабля: не вычищай якоря Apple. Дефолтный /etc/pf.conf выглядит так:
Код: Выделить всё
scrub-anchor "com.apple/*"
nat-anchor "com.apple/*"
rdr-anchor "com.apple/*"
dummynet-anchor "com.apple/*"
anchor "com.apple/*"
load anchor "com.apple" from "/etc/pf.anchors/com.apple"
Минимальный пример: блокируем все входящие на dev-порт 8000, кроме localhost. Кладём правила в отдельный файл /etc/pf.anchors/dev.local:
Код: Выделить всё
block in proto tcp from any to any port 8000
pass in proto tcp from 127.0.0.1 to any port 8000
Код: Выделить всё
sudo pfctl -n -f /etc/pf.anchors/dev.local
Код: Выделить всё
sudo pfctl -f /etc/pf.anchors/dev.local
sudo pfctl -e
Код: Выделить всё
sudo pfctl -s rules
sudo pfctl -s nat
Lockdown Mode, VPN и встроенный VPN по требованию
Режим блокировки (Lockdown Mode) - это не фаервол, а резкое сокращение поверхности атаки для тех, кому реально грозит наёмное шпионское ПО (журналисты, активисты, дипломаты). Включается в Системные настройки -> Конфиденциальность и безопасность -> Режим блокировки (System Settings -> Privacy and Security -> Lockdown Mode), в самом низу. Что он отключает на macOS 26 Tahoe: JIT-компиляцию JavaScript в WebKit (сайты грузятся медленнее), большинство типов вложений в Сообщениях, превью ссылок, входящие приглашения FaceTime от незнакомцев, проводные соединения с аксессуарами при заблокированном экране, часть профилей конфигурации MDM. Большинству людей он не нужен и мешает работе - это инструмент для конкретной модели угроз, а не "максимальная безопасность для всех". Сверяйся с support.apple.com, набор ограничений Apple расширяет от версии к версии.
VPN. macOS умеет встроенные клиенты IKEv2, L2TP/IPsec, и через сторонние профили - WireGuard/OpenVPN (NetworkExtension). Настройка - Системные настройки -> Сеть -> добавить VPN, либо импортом профиля .mobileconfig (для парка Mac - через MDM, это норма в DDM-мире 2026). Killer-фича для безопасности - VPN по требованию (On-Demand): туннель поднимается автоматически по правилам - например, всегда, кроме доверенного домашнего Wi-Fi, или для конкретных доменов. Настраивается это в профиле конфигурации (ключи OnDemandRules), GUI такого не даёт. Под капотом VPN-клиенты обычно вешают правила в pf, поэтому после подключения корпоративного VPN ты увидишь в pfctl -s rules чужие строки - это нормально.
Главная грабля: исходящие соединения и брандмауэр разработчика
Запомни накрепко, это ловит даже опытных: Application Firewall не фильтрует исходящие соединения. Совсем. Он контролирует только входящие коннекты к слушающим сокетам. Если зловред или болтливая аналитика в каком-нибудь Electron-приложении стучится наружу на свой сервер - штатный брандмауэр mac это пропустит молча, даже в режиме stealth и при включённом "блокировать всё" (block all тоже про входящие).
Чтобы контролировать исходящий трафик по приложениям, нужен сторонний инструмент:
- LuLu от Objective-See - бесплатный, открытый, блокирует неизвестные исходящие соединения, спрашивая разрешения. Хороший дефолт.
- Little Snitch - платный, более гранулярный: правила, профили, карта соединений, тонкая настройка по доменам и портам.
Брандмауэр для разработчика. Локальные сервисы - частый источник дыр. Практические правила:
- Биндь dev-сервер на 127.0.0.1, а не на 0.0.0.0. Vite, Next, Flask, Postgres по умолчанию иногда слушают все интерфейсы - проверь. Тогда никакой firewall вообще не нужен, сервис недоступен извне физически.
- Проверяй, кто реально слушает: lsof -nP -iTCP -sTCP:LISTEN покажет процесс, порт и адрес. Если в колонке адреса *:8000 - ты открыт наружу, если 127.0.0.1:8000 - только локально.
- Docker и colima пробрасывают порты в обход ALF через свою сеть - помни, что -p 8000:8000 может выставить контейнер на все интерфейсы.
Код: Выделить всё
lsof -nP -iTCP -sTCP:LISTEN
COMMAND PID USER FD TYPE DEVICE NODE NAME
node 44120 dev 23u IPv4 0x... TCP 127.0.0.1:5173 (LISTEN)
postgres 6610 dev 7u IPv6 0x... TCP *:5432 (LISTEN)
Мини-лаба: собери защиту руками
Повтори на своей машине (всё откатывается):
- 1. Сними слепок состояния ALF: sudo /usr/libexec/ApplicationFirewall/socketfilterfw --getglobalstate --getstealthmode.
- 2. Включи брандмауэр и stealth mode теми же командами с --set...on. Проверь, что состояние изменилось.
- 3. Подними тестовый сервер: python3 -m http.server 8000 --bind 0.0.0.0. С другого устройства в сети попробуй открыть http://твой-ip:8000 - откроется (ALF пускает входящие подписанному python или спросит разрешение).
- 4. Теперь dry-run своего pf-правила, блокирующего порт 8000: положи block in proto tcp from any to any port 8000 в файл и прогони sudo pfctl -n -f файл. Загрузи, включи pf через -e, снова постучись извне - соединение должно отвалиться по таймауту.
- 5. Откати: sudo pfctl -d (или -f /etc/pf.conf чтобы вернуть дефолт), верни stealth mode и брандмауэр в исходное состояние из шага 1.
- 6. Бонус: поставь LuLu, запусти любое приложение с сетью и поймай диалог про исходящее соединение - почувствуй разницу с ALF.
- 1. Почему включённый Application Firewall в режиме "блокировать всё" не остановит зловред, отправляющий данные на чужой сервер? Что нужно добавить?
- 2. Чем отличается фильтрация в ALF от фильтрации в pf - по какому признаку каждый принимает решение?
- 3. Зачем нельзя удалять строки anchor "com.apple/*" из /etc/pf.conf и что сломается?
- 4. Что делает stealth mode и почему он полезен именно в публичной Wi-Fi сети?
Защита сети на Mac - это слои с разной природой. Application Firewall (socketfilterfw) - простой контроль входящих по приложениям плюс stealth mode, твой базовый минимум в публичных сетях. pf (pfctl, /etc/pf.conf) - мощный BSD-фаервол для правил по портам и направлениям, для продвинутых сценариев, но не трогай якоря Apple. Lockdown Mode - крайняя мера против таргетированных атак, не для всех. VPN, особенно по требованию, закрывает транзит. А главную дыру - исходящие соединения - штатный брандмауэр не видит вообще, тут нужен LuLu или Little Snitch. И самое дешёвое правило безопасности для разработчика: бинди локальные сервисы на 127.0.0.1 и регулярно смотри lsof, кто там реально слушает наружу.