
LinuxシステムからのすべてのDNSクエリをローカルキャッシュスタブリゾルバ(バインドされていない)にリダイレクトしようとしています。
iptables -t nat -A OUTPUT -p tcp --dport 53 -j DNAT --to 1.1.1.1:53
iptables -t nat -A OUTPUT -p udp --dport 53 -j DNAT --to 1.1.1.1:53
iptables -t nat -A POSTROUTING -j MASQUERADE
上記のルールを使用すると、すべての発信DNSクエリがブロックされ、1.1.1.1のDNSサーバーにリダイレクトされます。
ただし、「1.1.1.1」を「127.0.0.1」に置き換えると、すべてのDNSクエリが失敗し、ローカルスタブリゾルバにリンクされません。
以下のsysctlパラメータを渡しました。
sysctl -w net.ipv4.conf.eth0.route_localnet=1
しかし、私の問題はまだ同じです。どんなアドバイス?
答え1
strace
、および/を使用してnc
デバッグすると、元の出口に選択したアドレスが変更されないことsocat
が明らかになります。おそらく、まだ「ルーティング」するローカルアドレスと見なされるので、変更する必要はありません。ここでは、そのルールは機能しません。nat/POSTROUTING
MASQUERADE
lo
MASQUERADE
とにかくそのようなことが起こりました。だから返信するときUDPプロトコルクエリを実行すると、サーバーは実際にデータを送信したソースに再接続され、ターゲットとして使用されます。当然、その宛先、すなわち同じローカルアドレスに対して最良のソースが選択される。いいえ127.0.0.1。したがって、conntrack -E
ローカル IP 192.0.2.2 とターゲット 198.51.100.1 UDP ポート 53 の例を使用すると、次のような結果が得られます。
[NEW] udp 17 30 src=192.0.2.2 dst=198.51.100.1 sport=40037 dport=53 [UNREPLIED] src=127.0.0.1 dst=192.0.2.2 sport=53 dport=40037
[NEW] udp 17 30 src=192.0.2.2 dst=192.0.2.2 sport=53 dport=40037 [UNREPLIED] src=172.16.0.22 dst=172.16.0.22 sport=40037 dport=53
応答は最初のクエリとは関係がないため(ソースIPが127.0.0.1ではないため)、conntrackはそれを2番目のストリームとして扱います。同時に、クライアントはUDPソケットを接続モードに設定します。これは、誤った送信元IP(正しいポートでも)で受信されたUDPパケットが拒否され、サーバーがICMPエラーを受信することを意味します(これは目撃によって可能ですtcpdump -i lo
)。
修正はとても簡単です。MASQUERADE
butを使用しないでくださいSNAT
。もちろん、この特定のストリームに固有でなければならないので(SNAT
すべてを127.0.0.1に変換したくない)、MASQUERADE
この行を次に置き換えます。
iptables -t nat -A POSTROUTING -p udp --dport 53 -j SNAT --to-source 127.0.0.1
変更されたフローを使用すると、ローカルサーバーはconntrackの予想されるアドレスで応答します。これを前のフローに関連付け、正しくSNATを解放します。
[NEW] udp 17 30 src=192.0.2.2 dst=198.51.100.1 sport=38871 dport=53 [UNREPLIED] src=127.0.0.1 dst=127.0.0.1 sport=53 dport=38871
[UPDATE] udp 17 30 src=192.0.2.2 dst=198.51.100.1 sport=38871 dport=53 src=127.0.0.1 dst=127.0.0.1 sport=53 dport=38871
クライアントは期待ソース 198.51.100.1 を受信し、すべてが期待どおりに動作します。
伝送制御プロトコル192.0.2.2 と 127.0.0.1 の間に接続が確立されると、応答は確立された同じ接続内にあるため、同じ結果は発生しません。これはUDPのような新しい接続ではないため、既に予想されるソースがあり、正しく処理されます。 conntrackで。一貫性のために、以下を追加することをお勧めします。
iptables -t nat -A POSTROUTING -p tcp --dport 53 -j SNAT --to-source 127.0.0.1
2つの注意事項:
場合によっては、
route_localnet
すべてのパケットがローカルで残りますので必要ありませんlo
。逆に、127.0.0.1に送信されたパケットを転送するには(他のトリックと共に)必要です。DNSサーバーが外部にクエリを送信するDNSクライアントでもある場合(再帰DNSサーバーの場合)、または独自のクエリが独自に再ルーティングされてループを生成する場合は、追加の例外ルールが必要になることがあります。通常、サーバーを特定のユーザーとして実行し、iptablesを使用して解決します。
-m owner
マッチ。各ルールセット(nat/OUTPUT
およびnat/POSTROUTING
)の前に次の内容を挿入するのと同じです。iptables -t nat -I .... -m owner --uid-owner unbound -j RETURN