IPTables - 16進文字列ブロックDNSクエリ

IPTables - 16進文字列ブロックDNSクエリ

私のDNSサーバーの特定のドメインに多くのクエリを送信するクライアントがあります。そのクエリをブロックしたいのですが、これを行う16進文字列を見つけました。それは文字列です:

iptables -I INPUT 1 -p udp --dport 53 --match string --algo kmp --hex-string '|77 70 61 64 2e 64 6f 6d 61 69 6e 2e 6e 61 6d 65|' -j DROP

-

0     0 DROP       udp  --  *      *       0.0.0.0/0            0.0.0.0/0            udp dpt:53 STRING match  "wpad.domain.name" ALGO name kmp TO 65535

しかし、その名前に対してサーバーを照会すると、応答が表示され、カウンターがゼロのままであるため、機能しないようです。

root@banana:~# dig @5.172.120.59 wpad.domain.name

; <<>> DiG 9.8.4-rpz2+rl005.12-P1 <<>> @5.172.120.59 wpad.domain.name
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 29891
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;wpad.domain.name.              IN      A

;; Query time: 136 msec
;; SERVER: 5.172.120.59#53(5.172.120.59)
;; WHEN: Thu Nov 26 22:55:30 2015
;; MSG SIZE  rcvd: 34

いくつかのエラーを見つけることができますか?

ありがとう

ベストアンサー1

これをしないでください。

...少なくともこの特定のDNS要求には適用されません。なぜできないの?まあ、まず、自分とCPUを実際に簡単にするのではなく、クライアントにとっては状況をさらに悪化させています。すべてのプラットフォームのほぼすべてのブラウザは、DHCPアドレスを取得するときに「自動プロキシ検出」を使用します。この自動検出は、ホスト名のDNSエントリを見つける方法で機能しますwpad.subdomain.subdomain.currentdomain.xxwpad.currentdomain.xx第二に、ブラウザはOSにDNSを取得するように要求し、OS(さまざまなTCP / UDPパラメータに従って)努力し続ける応答を受信するまで、DNSサーバーに要求が行われます。入力をブロックすると、DNSサーバーはまったく答えを提供できないため、クライアントはもう一度お試しください続けて。これをブロックすることによって、クライアントが要求の送信を停止するように「訓練」することはありません。応答が得られない場合は、プロキシの使用試行を停止し、直接接続を使用します。同時にユーザーはただ待つブラウザが直接接続を試みることができます。ブラウザが応答する前に15秒間待つこともできます。このメカニズムはすべてのAndroidおよびiOSデバイスに組み込まれているため、すべてのiPad、AppleTV、Samsungスマートフォンがインターネットに接続するのに長い時間がかかります。だから基本的にあなたはコックを取得します。

実行方法(ベスト、正確)

しかし、QN​​AMEに基づいてDNSクエリをブロックしたいとしましょう。 QNAMEには「タグ」セットが含まれています。しかし、私たちドット表記のタグをご覧ください。クエリパケット内の各タグの前には対応する長さ(バイト)が付き、すべてのタグはNULで終了します。1

1 OPではこの部分を調べましたが、16進文字列に関連しているように聞こえます。

1.4.9iptablesのソースコードを見て確認したように、その動作を適切に説明するマニュアルが見つからないため、hex文字列は(quasi-BNF)形式になっています。

HEXSTRING := SUBSTRING [ SUBSTRING ... ]

それぞれは次SUBSTRINGのいずれかです。

'\' CHAR
'|' HEXDIGIT HEXDIGIT [ SPACE ] '|'
CHAR

ここで CHAR は入力が処理できるほぼすべてのものであり、 HEXDIGIT は isxdigit() が言うようにsscanf(s,"%x",buf)"16 進数パターン" をバイパスし、リテラル文字列 "|" と一致させることができるように .escape 文字と結合されます。そうでなければ特別なことはありません。現在のSUBSTRINGが16進文字列の最後の場合、末尾は|必ずしも必要ではありません。

次に、検索を最適化します。クエリ部分は、DNS要求の13番目のバイトよりも早く開始されません。つまり、バイト 40( 20(IP) + 8(UDP) + 13 - 1 ) から始まります。パケットがクエリであるかどうかをテストできる場合(それを行う必要がある場合)、検索制限について心配する必要はありません。パケットの最後まで検索してください。クエリであるかどうかをテストするには、パケット内のバイト31の上位5ビットをテストします。また、IPヘッダーの微妙な違いを考慮することもできます。まれに、20ではなく24 +バイトなので、テストするバイトは35(または39)になります。

bm(Boyer-Moore)アルゴリズムを使用して追加の最適化が実行されます。何の問題もありませんが、kmp全体的にBoyer-Mooreはより高速でより少ないリソースを使用します。

それらを組み合わせると、次のような結果が得られます。

-A INPUT -s 5.172.121.170/32 -p udp -m udp --dport 53 \
-m u32 --u32 "28 & 0xF8 = 0" \
-m string --algo bm --from 40 \
--hex-string "|04|wpad|08|mydomain|03|isa|04|dick" 

この--u32部分は、「パケットの28番目(0インデックス)バイトから始めて4バイトを取得します...つまり、バイト28、29、30、31をつかみ、32ビット値を0x000000F8でマスクします...これは単なる例です。のためです。 上位 5 バイト 31 のビット…前述のように、この--fromセクションではパケットの「問題」部分で文字列検索を開始します。これにより、偽の肯定を防ぐことができます。

RHEL 6.5 iptables 1.4.7でテストされました。

賢明に言えば、IPヘッダーフィールドバイト0のヘッダー長をテストし、バイト32で始まるDNSクエリに一致する別のルールを作成します。

おすすめ記事