
我試圖將系統解析為遠端 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 重新導向到 IP 127.0.0.53 的 192.168.1.2 lo 裝置上託管的 systemd-resolved?
答案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
套接字選項。