Захисний перемикач pf у macOS для OpenVPN: правила, які зачиняються
Набір правил pf блокує прямий трафік, поки тунель опущений. Збережіть шлях клієнта до його сервера, потім доведіть блокування з вимкненим тунелем.
У macOS захисний перемикач добрий настільки, наскільки добра політика пакетного фільтра за ним, і pf — та частина, яка цю політику виконує. Політика мусить робити дві протилежні речі одночасно: пускати клієнта до його сервера, щоб тунель міг існувати, і не пускати все інше назовні напряму. Більшість опублікованих наборів правил дають раду з другим і забувають про перше, тому машина втрачає зв'язок замість того, щоб отримати захист. Версія, яка працює, називає кінцеву точку, резолвер і тунель, і більше нічого.
Що може вирішити пакетний фільтр, а що ні
pf дивиться на інтерфейси, адреси, номери протоколів і порти та на цьому зупиняється. Він ніколи не дізнається, який процес відкрив сокет, тому дозвіл, написаний для однієї програми, стає дозволом для кожної програми, яка може дістатися того самого порту. Так щедрий виняток UDP перетворює захисний перемикач назад на звичайну мережу. Блокування з урахуванням застосунку належить клієнтові або системному розширенню, а не цьому файлу.
Фільтр також не створює маршрутів. Коли клієнт падає, маршрут за замовчуванням може все ще вказувати на мертвий тунель, і pf перетворює це на заблоковані пакети, а не на тихий відкат до Wi-Fi. Блокування — це задуманий результат, а не несправність, яку треба обходити.
Порядок вирішує результат частіше, ніж текст правила. Без quick pf продовжує оцінювати після збігу, і перемагає останнє відповідне правило, тому широкий пропуск унизу скасовує ретельні винятки вище. Позначення пропусків як quick робить перший збіг остаточним, і саме це зазвичай має на увазі автор політики.
Спершу прочитайте факти про інтерфейс і кінцеву точку
Бездротові інтерфейси нумеруються не однаково на кожному Mac, а пристрій тунелю отримує номер, який може змінюватися між завантаженнями. Правило, яке називає неіснуючий пристрій, падає під час розбору, що гучно й легко помітити, тоді як правило, яке називає неправильний наявний пристрій, розбирається чисто й пропускає трафік, який ви хотіли зупинити.
Збирайте факти, поки клієнт підключений, бо пристрій тунелю існує лише тоді. Вам потрібен інтерфейс, що тримає маршрут за замовчуванням, пристрій, створений клієнтом, і адреса та порт сервера, до якого він звертається. Саме це останнє значення більшість наборів правил пропускає, і через це скопійований набір блокує власний тунель.
route -n get default
ifconfig -l
scutil --nc list
Перша команда називає інтерфейс, який зараз перемагає, друга перелічує кожен пристрій, відомий ядру, а третя показує конфігурації VPN, які система може запустити. Запишіть ці відповіді, потім прочитайте адресу й порт сервера з власної конфігурації клієнта.
Напишіть набір правил навколо шляху тунелю
Файл нижче за замовчуванням відмовляє й знову пропускає п'ять речей: loopback, пристрій тунелю, шлях клієнта до його сервера, резолвер, який використовується до появи тунелю, і два обміни, що зберігають бездротове з'єднання придатним. Назви інтерфейсів і адреса сервера беруться з вашої машини, тож підставте підтверджені значення. Номер тунелю теж не збігатиметься з вашим.
set skip on lo0
block all
pass out quick on utun0
# maintain this line when the server address changes
pass out quick on en1 inet proto udp to 203.0.113.10 port 1194
# only the resolver the client uses before the tunnel exists
pass out quick on en1 inet proto udp to 192.0.2.53 port 53
pass out quick on en1 inet proto udp from any port 68 to any port 67
pass out quick on en1 inet proto udp to 224.0.0.251 port 5353
Рядок DHCP існує тому, що Mac запитує адресу раніше, ніж має її, тож запит виходить з порту 68 до порту 67 без придатної адреси джерела. Рядок multicast дозволяє системі вирішити, чи варто використовувати бездротове з'єднання, а його видалення дає машину, яка в робочій мережі повідомляє про відсутність зв'язку. Рядок кінцевої точки — це те, що OpenVPN взагалі дозволяє дістатися свого сервера; без нього block all відкидає зовнішнє рукостискання, і тунель ніколи не піднімається. Рядок резолвера вужчий за загальний дозвіл DNS, бо називає одну адресу й один порт замість кожного запиту, який робить машина.
Ці винятки для кінцевої точки й резолвера — ті два, що мусять існувати; усе інше лишається заблокованим. Якщо клієнт звертається до буквальної адреси, приберіть рядок резолвера й залиште рядок кінцевої точки. Якщо адреса сервера змінюється, оновіть цей рядок перед наступним підключенням або заповніть таблицю pf з власного хука клієнта й зіставляйте натомість таблицю.
Опустіть тунель, потім перезавантажтеся
Розбирайте перед завантаженням, бо синтаксична помилка дешева в сухому прогоні й дорога у віддаленій сесії. Потім завантажте файл, увімкніть фільтр, якщо він був вимкнений, і прочитайте, що насправді чинне. Зворотне читання — не церемонія: інший якір може додати правила, яких ви не писали, тож порівняйте надрукований набір зі своїм файлом.
sudo pfctl -n -v -f /etc/pf.conf
sudo pfctl -f /etc/pf.conf
sudo pfctl -e
sudo pfctl -s rules
sudo pfctl -s Anchors
sudo pfctl -a <anchor> -s rules
sudo pfctl -s info
Із завантаженими правилами опустіть тунель і спробуйте завантажити сторінку. Звичайний трафік має зупинитися й лишатися зупиненим після сну та пробудження машини, бо саме на цьому переході повертається застарілий стан. Підключіться знову й підтвердьте, що трафік відновлюється без втручання в набір правил. Якщо браузер усе ще працює з опущеним тунелем, якесь правило ширше, ніж ви думали, і зворотне читання зазвичай його називає.
Перезавантаження — та частина, яку люди пропускають. macOS читає /etc/pf.conf під час завантаження, але читання файлу не те саме, що ввімкнення фільтра, тому набір правил, який працює зараз, може бути неактивним після перезапуску. Потім виконайте sudo pfctl -s info і підтвердьте, що рядок стану повідомляє про ввімкнений фільтр.
Тримайте вихід і шлях перезапуску чесними
Набір правил, що блокує все, може також замкнути вас ззовні машини, якою ви керуєте віддалено. Редагуйте з локальної сесії, коли можете, тримайте попередній файл поруч із новим і знайте шлях повернення до того, як він знадобиться. Команди нижче вимикають фільтр і заново завантажують збережену копію, і це послідовність для консолі, а не через тунель, який ви щойно перерізали. П'ятисекундний відкат щоразу перемагає розумне правило.
sudo pfctl -d
sudo pfctl -f /etc/pf.conf.previous
sudo pfctl -s rules
Для стійкості потрібен launch daemon, який виконує pfctl -e і завантажує ваш файл під час старту. Ставтеся до нього як до будь-якого іншого привілейованого завдання: абсолютні шляхи, журнал, який можна прочитати потім, і тест на машині, до якої можна фізично дістатися. Демон, що тихо падає, лишає машину незахищеною й нормальною на вигляд.
Задокументуйте прогалини, почавши з другого клієнта VPN, який створює власний пристрій тунелю. Ваші правила називають один інтерфейс тунелю, тож другий лишається заблокованим або його ловить широке правило, додане пізніше. Інтерфейси tethering і точки доступу з'являються лише іноді й заслуговують тієї самої нотатки. Жодна з цих прогалин не є причиною пропускати політику; це умови, за яких вона ще діє.