LoginSignup
0
0

ろうとるがPythonを扱う、、(その23:ScapyでDNSフィルタリング)

Posted at

ScapyでDNSフィルタリング

Scapyでネットワークブリッジを構築し、ブリッジ内でDNSフィルタリングを実施してみた。

ネットワーク

image.png
ubuntu上にScapyによるネットワークブリッジを設け、そこでDNSフィルタリングを行う。ClientからはRouterをとおしてインターネットへアクセスする。(なお、ClientはRouter上で動作しているDHCPサーバーからIPアドレスを取得する。)

DNSフィルタリング

フィルタリングとして、特定ドメインをブロックするもの。いわゆるブラックリストを作成し、Webアクセスなどが行えないよう制御する。

ソースコード

ブラックリスト

”blacklist.txt”というファイルにアクセスを許可しないドメインを記載する。なお、”.”(ピリオド)ではじまる場合、ワイルドカード的に扱うこととした。

blacklist.txt
yahoo.com
.zm
www.bbc.co.uk

上記の2行目では、”www.abc.zm”や”xdu.zm”もマッチ(適用)するものとする。”.”(ピリオド)ではじまらない場合は、完全一致した場合のみ適用する。

コード本体

dns_filter.py
from scapy.all import *
import datetime

blk_list = []

def cb_filter(p):
    found = 0
    if p.haslayer(DNS):
        dns = p.getlayer(DNS)
        qname = dns.qd.qname
        #print(qname.decode('utf-8'))
        chk_domain = qname.decode('utf-8').rstrip('.')
        for blk_domain in blk_list:
            if blk_domain.startswith('.'):
                if chk_domain.endswith(blk_domain):
                    found = 1
                    break
            else:
                if chk_domain == blk_domain:
                    found = 1
                    break
    if found == 1:
        now = datetime.datetime.now()
        d = now.strftime('%Y/%m/%d-%H:%M:%S')
        msg = d + ' ' + chk_domain + ' is dropped.'
        print(msg)
        msg += '\n'
        flog.write(msg)
        return False
    else:
        return True

with open('blacklist.txt') as f:
  for line in f:
    blk_list.append(line.rstrip())

flog = open('dns.log', 'a')

bridge_and_sniff('enp3s0', 'enp1s0f0', xfrm12=cb_filter, xfrm21=cb_filter)

#do not call flog.close()
  • blk_list: ブロックするドメインのリスト
  • cb_filter: ブリッジ時にCallされる関数
    • DNSパケットのみを対象
    • ブリッジを通過するDNSのドメイン名を取得(最後のピリオド”.”削除)
    • ブロックするドメイン名がピリオド”.”で始まっている場合、取得したドメイン名が後方一致するかチェック
    • ピリオド”.”で始まっていない場合、取得したドメイン名が完全一致するかチェック
    • 一致した場合、コンソール表示およびログへの書き込み
    • 一致した場合、Trueを返す(転送する)
    • 一致しない場合、Falseを返す(転送しない)
  • ブラックリストファイル(blacklist.txt)に格納されているドメイン名をblk_listに格納
  • ログファイル(dns.log)をオープン
  • bridge_and_sniff(): 2つのネットワークI/F("enp3s0","enp1s0f0")のブリッジ化およびブリッジ時にCallされる関数(cb_filter)の定義

検証

ほぼ自明なので、クライアントの状況は省略。上記コードで記載したログファイル(一部)は下記のとおりとなる。

access.log

2023/12/31-14:37:05 www.bbc.co.uk is dropped.
2023/12/31-14:37:05 www.bbc.co.uk is dropped.
2023/12/31-14:37:14 www.cabinet.gov.zm is dropped.
2023/12/31-14:37:14 www.cabinet.gov.zm is dropped.

終わりに

パフォーマンス的には今ひとつかもしれない。とにかく、Scapyは便利である。関連して、「ろうとるがPythonを扱う、、(その20:Scapyで改ざん)」でも一部実施したが、本格的なSpoofingもできそう(気が向いたらトライしてみる)。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0