🔄

DNSルックアップの回数を調べる

2024/08/16に公開

DNSルックアップの制限

SPFレコードで include などがあるとDNSルックアップがカウントされます。
DNSルックアップが10回までという制限があります。

Google Workspaceを利用しててGmailを使ってるとドメインのSPFに
下記のレコードを設定しないといけないです。
include:_spf.google.com

dig txt +short _spf.google.com
"v=spf1 include:_netblocks.google.com include:_netblocks2.google.com include:_netblocks3.google.com ~all"

_spf.google.com がさらにincludeで3つのドメインを指定してます。
これでDNSルックアップ回数が4になります。

困ること

SPFレコードの中に外部のサービスを使っていたり、別の会社のドメインを指定していると
知らない内に回数制限を超えてしまいそうです。
そして知らない内に、SPFレコードが無効と見なされます。

対策方法

自分でコントロール出来ないので、自動で調べるように
AWS LambdaとAmazon API GatewayでAPIを作成しました。

https://dnslookup.tomomik210.work/?domain=対象のドメイン

APIなら自動で確認できますよね。

一応、Lambdaのコード

import json
import subprocess

call_count = None
list = None

def lambda_handler(event, context):
    global call_count
    global list
    call_count = 0
    list = []

    domain = event['domain']
    print(domain)
    output_list = {}
    output_list['result'] = {}
    output_list['result']['domain'] = domain

    run_dig(domain)
    output_list['result']['call_count'] = call_count
    list.append(output_list)

    return {
        'body': list
    }

def run_dig(domain):
    global call_count
    try:
        result = subprocess.run(['dig', domain, 'txt', '+short'], capture_output=True, text=True, check=True)
        output = result.stdout
        print(f"Output for {domain}:\n{output}")
        output_list = {}
        output_list['domain'] = domain
        output_list['txt_record'] = output
        list.append(output_list)

        # `include`が含まれている場合に再帰的に処理
        if "include" in output:
            included_domains = extract_included_domains(output, "include:")
            for included_domain in included_domains:
                call_count += 1
                run_dig(included_domain)

        # `a:` または `mx:` が含まれている場合にカウントを増加
        call_count += count_dns_records(output, ["a:", "+mx"])
    
    except subprocess.CalledProcessError as e:
        print(f"An error occurred: {e}")

# keywordの後のドメインを返す
def extract_included_domains(output, keyword):
    included_domains = []
    for line in output.splitlines():
        if keyword in line:
            parts = line.split()
            for part in parts:
                if part.startswith(keyword):
                    included_domains.append(part.split(':')[-1])  # `include:`の後にドメインがあると仮定

    return included_domains

# keywordsいある文字列が何回含まれているか
def count_dns_records(output, keywords):
    count = 0
    for keyword in keywords:
        count += output.count(keyword)

    return count

記事書いてるときに知ったんですけど、SPF Macro ってあるんですね。

Discussion