Назад | Перейти на главную страницу

Nftables - как не указать ip на интерфейсе (DNS)

Я искал, но не могу найти ответа на мою конкретную проблему. Сегодня у меня при предварительной маршрутизации действует следующее правило: iifname "br0" udp dport 53 counter dnat to 192.168.22.5:53

Однако у меня есть одна проблема: IP-адрес 192.168.22.5 также находится на «br0». Итак, возникает вопрос, как я могу заставить nftables игнорировать этот IP-адрес и разрешить ему доступ к порту 53 в сети (это мой pihole), но перенаправить на него все остальные данные udp порта 53?

Ценю ваши ответы!

Трафик, исходящий от самого хоста, не обрабатывается iifname $outgoing_interface (но iifname lo), поэтому вашей проблемы не существует.

Вам просто нужно добавить дополнительное условие, чтобы не совпадать с этим IP-адресом, таким образом, не выполняя NAT в конце:

iifname "br0" ip saddr != 192.168.22.5 udp dport 53 counter dnat to 192.168.22.5:53

НО... если и клиент, и DNS-сервер находятся в одной локальной сети, то ответ будет отправлен напрямую с DNS-сервера клиенту. Например, если клиент с адресом 192.168.22.101 настроен на использование общедоступного преобразователя Google (со всеми сопутствующими проблемами конфиденциальности), вы получите следующее:

запрос: от 192.168.22.101 до 8.8.8.8 -> routed and dnat-ed -> 192.168.22.5

ответ: 192.168.22.5 -> мостовой (или вообще не виден маршрутизатором в обоих случаях) не виден семья ip правила -> 192.168.22.101

Но поскольку 192.168.22.101 ожидает ответа от 8.8.8.8, а не от 192.168.22.5, он потерпит неудачу.

Так что вы также должны схватить запрос. Любой IP-адрес, по которому пакеты используют маршрутизатор, в порядке: внутренний IP-адрес маршрутизатора (masquerade), потому что маршрутизатор владеет этим IP-адресом или любым IP-адресом в Интернете (используя snat), потому что они маршрутизируются через маршрутизатор. Вы даже можете представить себе использование для этого IP-адреса TEST-NET (например: 192.0.2.2): IP-адрес в любом случае никогда не будет виден за пределами локальной сети. Недостатком является то, что DNS-сервер не может определить, какой IP-адрес сделал запрос. Новые ядра (грядущие 5.7 или еще 5.8) будут иметь эквивалент NETMAP от iptables доступно, если это действительно важно.

Давайте использовать masquerade здесь для простоты.

Итак, внутри эквивалентной цепочки постмаршрутизации, которая может быть создана с чем-то похожим (пожалуйста, адаптируйте свои собственные соглашения об именах):

nft add chain ip nat postrouting '{ type nat hook postrouting priority 100; policy accept; }'

правило будет таким:

ip daddr 192.168.22.5 udp dport 53 counter masquerade

Это не повлияет на обратный трафик, инициированный DNS-сервером, потому что его запись conntrack больше не будет в состоянии NEW, а это нац правило не будет нарушено.

Если вы хотите повлиять только на ранее полученный трафик из br0 и не откуда-либо еще, есть несколько вариантов:

  • проверьте, что исходный IP-адрес от 192.168.22.0/24 и dnat-ed

    ip saddr 192.168.22.0/24 ip daddr 192.168.22.5 udp dport 53 ct status dnat counter masquerade
    
  • Вместо этого с достаточно свежим ядром (> = 5.6) сопоставление на входящем интерфейсе (все еще в пост-маршрутизации) будет достаточно:

    iifname "br0" ip daddr 192.168.22.5 udp dport 53 ct status dnat counter masquerade
    
  • или же вы можете использовать метки в предварительной и последующей маршрутизации, если они не противоречат другим применениям:

    предварительная маршрутизация:

    iifname "br0" ip saddr != 192.168.22.5 udp dport 53 counter set mark 1 dnat to 192.168.22.5:53
    

    постмаршрутизация:

    mark 1 counter masquerade
    

И, наконец, поскольку DNS использует TCP, а также UDP, вам, вероятно, также следует применить все то же самое, используя tcp dport 53.