Как перенаправить DNS-запрос на удаленный systemd-resolved?

Я пытался разрешить систему как удаленный кэширующий сервер DNS (я знаю, что это не предназначено для так). Я добавил, что изменил net.ipv4.conf.br0.route_localnet на 1 и добавил следующие правила nftable:

table ip nat {
    chain prerouting {
        type nat hook prerouting priority 100; policy accept;
        iif "br0" udp dport 53 counter packets 6 bytes 366 dnat to 127.0.0.53
    }

    chain postrouting {
        type nat hook postrouting priority -100; policy accept;
        ip saddr 127.0.0.53 oif "br0" counter packets 0 bytes 0 snat to 192.168.1.2
    }
}

Кажется, что правило предварительной маршрутизации работает, поскольку есть пакеты, соответствующие правилам. Однако нет пакета из хоста, в чем проблема?

Как я могу перенаправить DNS-запрос с 192.168.1.0/24 на systemd-resolved, размещенный на устройстве 192.168.1.2 lo с IP 127.0.0.53?

0
задан 26 July 2021 в 17:04
1 ответ

systemd-resolved привязывается к интерфейсу lo:

# ss -aunp src == 127.0.0.53 sport == 53
State  Recv-Q Send-Q Local Address:Port  Peer Address:Port 
UNCONN 0      0      127.0.0.53%lo:53         0.0.0.0:*     users:(("systemd-resolve",pid=44157,fd=17))

Это ограничивает доступные маршруты даже один раз net.ipv4.conf.br0.route_localnet= 1 применяется к тем, которые установлены на интерфейсе lo:

$ ip -4 route show table all dev lo
broadcast 127.0.0.0 table local proto kernel scope link src 127.0.0.1 
local 127.0.0.0/8 table local proto kernel scope host src 127.0.0.1 
local 127.0.0.1 table local proto kernel scope host src 127.0.0.1 
broadcast 127.255.255.255 table local proto kernel scope link src 127.0.0.1 

Ни один не будет соответствовать.

Необходимо изменить исходный адрес. Хотя редко используемый тип цепочки type nat hook input позволил бы изменить исходный адрес до того, как приложение его получило, уже слишком поздно: это происходит после того, как маршрутизация была выполнена, а пакет уже отброшен. Таким образом, NAT с отслеживанием состояния не может справиться с этим случаем.


Вместо этого для этого можно использовать прокси (после удаления всех конкретных настроек nat). Вот пример использования socat. socat не является специализированным приложением, поэтому есть оговорки, особенно для UDP.

  • Обработка TCP (OP забыл, что DNS тоже использует TCP)

    socat TCP4-LISTEN:53,bind=192.168.1.2,reuseaddr,fork TCP4:127.0.0.53:53
    

    Невозможно выполнить привязку к IN_ADDR_ANY, поскольку 127.0.0.53:53 уже привязан, поэтому привяжите к указанному OP адресу (по неправильным причинам): 192.168.1.2. Помимо этого, это довольно просто.

  • Обработка UDP

    socat -T 20 UDP4-LISTEN:53,bind=192.168.1.2,reuseaddr,fork UDP4:127.0.0.53:53
    

    Тайм-аут в 20 секунд здесь, потому что socat нельзя остановить сразу после получения ответа на один пакет UDP, и все разветвленные команды socat будут накапливаться с течением времени.

    Хотя в этом случае UDP не обязательно привязываться к адресу, привязка к адресу с использованием UDP позволяет избежать предостережения, связанного с множественной адресацией и необходимостью использовать параметр сокета IP_PKTINFO .

0
ответ дан 8 August 2021 в 12:36

Теги

Похожие вопросы