fw4: Фільтрація трафіку за IP-наборами через DNS
Вступ
Цей посібник демонструє, як створити набір IP-адрес для фільтрації трафіку. Це еквівалент dns_ipset для nftables/fw4, які є типовими починаючи з OpenWrt 22.03.
Мета
Уникнути обходу DNS-фільтрації (наприклад, фільтрація DNS за допомогою блокувальників реклами або через DoH) шляхом прямого підключення до IP-адреси. Основний сценарій — обмеження доступу до Інтернету для пристроїв типу SmartTV, IoT та ін., яким потрібно дозволити лише певний набір сайтів.
Для цього створюється набір IP-адрес з дозволених або заборонених доменів. Потім додається правило фаєрволу для дозволу або блокування трафіку до цих IP. Приклад нижче — для дозволеного доступу через інтерфейс з назвою wildlan.
Передумови
- Необхідна зона фаєрволу без переспрямування (forwarding) у wan, щоб за замовчуванням не було доступу до Інтернету. У прикладі така зона позначена як wildlan.
- Встановлені утиліти dig та grep (потрібні лише для Випадку 2).
- Стандартна конфігурація fw4 з таблицею inet fw4.
Цей посібник охоплює два варіанти реалізації залежно від версії dnsmasq. Випадок 1 стосується лише dnsmasq 2.87 або новішої версії.
[ВИПАДОК 1] Налаштування через командний рядок
Встановіть dnsmasq-full наступним чином:
opkg update; cd /tmp/ && opkg download dnsmasq-full; opkg install ipset libnettle8 libnetfilter-conntrack3; opkg remove dnsmasq; opkg install dnsmasq-full --cache /tmp/; rm -f /tmp/dnsmasq-full*.ipk;
Перевірте, чи встановлено dnsmasq:
opkg list-installed dns*
Коректний результат: `dnsmasq-full - 2.88-1`
У файлі /etc/hotplug.d/iface/20-firewall додайте такий код для створення nft-набору IP-адрес. Приклад нижче охоплює лише IPv4, але його можна розширити для IPv6.
# Фільтрація wildlan за IP-адресами ## Створити набір у таблиці "inet fw4" з назвою "allowlist", що зберігає тип "ipv4_addr" nft add set inet fw4 allowlist { type ipv4_addr \;} nft insert rule inet fw4 forward_wildlan ip daddr @allowlist accept
Зона wildlan не має доступу до Інтернету, якщо IP-адреса не входить до набору allowlist. Починаючи з dnsmasq 2.87, розв’язані (resolved) DNS-імена можуть автоматично додаватися до набору.
Відредагуйте /etc/dnsmasq.conf, додавши:
# IP-адреси, що відповідають дозволеним доменам, будуть збережені у nftset ("/4#" — IPv4) nftset=/first.allowed.urls/4#inet#fw4#allowlist nftset=/second.allowed.urls/4#inet#fw4#allowlist ...
Якщо потрібно дозволити лише ті IP, що були отримані через ваш DNS-сервер, а не напряму, використовуйте символ `#` як шаблон:
nftset=/#/4#inet#fw4#allowlist
Щоб переглянути IP-адреси, що потрапили до дозволеного списку, виконайте:
nft list set inet fw4 allowlist
Зауваження: набір буде порожній, доки не буде здійснено DNS-запит до відповідних доменів через dnsmasq.
[ВИПАДОК 2] Налаштування через командний рядок
Цей варіант застосовується лише для OpenWrt 22.03, OpenWrt 22.03.1 та OpenWrt 22.03.2, які мають застарілу версію dnsmasq. У цьому випадку ми не можемо використовувати dnsmasq для автоматичного наповнення IP-адрес у наборі, тому це потрібно зробити через скрипт.
У файл /etc/hotplug.d/iface/20-firewall додайте наступний код для створення nft-набору, до якого ми додаватимемо IP-адреси. Наведений код охоплює лише IPv4, але його можна розширити для IPv6:
# Фільтрація wildlan за IP-адресами ## Створення набору "allowlist" у таблиці "inet fw4" для типу "ipv4_addr" nft add set inet fw4 allowlist { type ipv4_addr \;} ## Додавання елементів до "allowlist" з файлу wildlan-urls.list for address in $(dig a -f /etc/sets-ipdns/wildlan-urls.list +short | grep -v '\.$'); do nft add element inet fw4 allowlist {$address timeout 24h} done nft insert rule inet fw4 forward_wildlan ip daddr @allowlist accept
Список доменів, до яких дозволено трафік, зберігається в спеціальному файлі /etc/sets-ipdns/wildlan-urls.list. Для створення цього файлу виконайте:
cd /etc mkdir sets-ipdns cd sets-ipdns vim wildlan-urls.list
Усередині vim додайте список доменів, до яких слід дозволити доступ.
На основі цього правила в ланцюжку forward, буде дозволено лише трафік до IP-адрес із набору @allowlist.
Файл /etc/hotplug.d/iface/20-firewall виконується при кожній зміні стану інтерфейсів (зазвичай при завантаженні системи), тому список IP буде оновлений лише під час запуску. Цей набір потрібно періодично оновлювати з двох причин: 1. IP-адреси можуть змінюватись. 2. У разі використання DNS Load Balancing, запит у різний час може повертати різні (але всі валідні) IP.
Для цього налаштуйте планувальник (через LuCI або файл /etc/crontabs/root), щоб запускати скрипт оновлення кожні 15 хвилин:
15 * * * * /etc/sets-ipdns/update-sets.sh
У файлі /etc/sets-ipdns/update-sets.sh:
## Додати IP-адреси до allowlist з доменів у wildlan-urls.list for address in $(dig a -f /etc/sets-ipdns/wildlan-urls.list +short | grep -v '\.$'); do nft add element inet fw4 allowlist {$address timeout 24h} done
Зробіть скрипт виконуваним і перезавантажте систему:
chmod +x /etc/sets-ipdns/update-sets.sh reboot
Після перезавантаження перевірте вміст @allowlist, список має містити IP-адреси (IPv4):
nft list set inet fw4 allowlist
Фінальна перевірка — переконайтесь, що доступні лише домени, які є в /etc/sets-ipdns/wildlan-urls.list. Жодні інші не повинні відкриватися, якщо тільки ті самі IP не використовуються кількома доменами (це трапляється з CDN).
Обмеження
У ВИПАДКУ 1 дозволяються всі домени та піддомени, які зазначені у конфігурації. У ВИПАДКУ 2 — лише ті домени, які вказані явно. Тому цей варіант працює лише з сервісами, які не використовують багато піддоменів.
Крім того, у ВИПАДКУ 2 скрипт періодично виконує DNS-запити для всіх доменів із файлу /etc/sets-ipdns/wildlan-urls.list, тому список бажано тримати невеликим.
Можливі покращення
Команди в /etc/hotplug.d/iface/20-firewall виконуються лише при зміні стану інтерфейсів. Це не відбувається при внесенні змін у фаєрвол через UCI або LuCI, тому після таких змін правила з цього файлу не застосовуються. У результаті пристрої, які залежать від цих правил, втрачають підключення.
Правила буде повторно застосовано при наступній зміні стану інтерфейсу (наприклад, при перепідключенні). Це можна також зробити вручну, щоб “перезібрати” правила.
У майбутніх версіях OpenWrt може бути реалізовано підтримку спеціального файлу з NFT-командами, який викликатиметься при кожному оновленні конфігурації фаєрволу — це повністю вирішить проблему.