
Я пытался сделать 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
вариант розетки.