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

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

Я пытался сделать system-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, размещенный на устройстве lo 192.168.1.2 с IP-адресом 127.0.0.53?

решение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 (ОП забыл, что 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вариант розетки.

Связанный контент