SPFのDNSルックアップ制限厳しすぎな話
こんにちは。
ECシステム開発チームのいまづです。
みなさん、DMARC対応してますか。
対応と言っても、基本的にはDKIMやSPFが設定されていればDMARCのDNSレコード追加するだけよね、くらいに思っていたんですが、SPFは曲者なんですね、というお話です。
DKIMやSPFの設定は以前からされていたし、DMARCのレコードもあちこちドキュメントを見ながら設定していたのですが、社長から「設定ちゃんとやってね」というメッセージとともにこんなスクショが。
https://dmarcian.com/domain-checker/?domain=switch-science.com (当時とは表示が異なります。)
DMARCポリシーは理由を見ると、当初様子見るために p=none
にしていたためで、設定自体は変えるつもりだったのはいいのですが、問題はSPFです。
DNSルックアップが10回までしかダメなところを15回やってるぞ(スクショ忘れ)と。
なんのこっちゃねんと思いましたが、RFC 4480のこの部分ですね。
https://datatracker.ietf.org/doc/html/rfc4408#section-10
当社は、AWSの他にメール送信を行う外部サービスをいくつか使っています。
当社ドメイン switch-science.com
のTXTレコードには、それら外部サービスで指定されたSPFレコードのincludeを複数書いています。
これがダメと言われてもなあ、と思いながら詳細を見ると FreshDesk が8回も消費しているじゃないですか。
これを全部取り込めるようにしようと思ったら、Freshdeskで使っているもの以外のメールアドレスをサブドメインのものに変更しないと無理なのでは?
仕様を読む限りは、include先自体には意味がなく、IPアドレスのリストさえ同様に整えられれば良さそうです。
先人がいらっしゃいました。 https://zenn.dev/monicle/articles/9b9aad63b89a54
自動化まではまだしていませんが、とりあえずPythonでこんな関数を書いてIPアドレスのリストを得ました。
PTN_SPF = re.compile(r'^v=spf1')
PTN_INCLUDE = re.compile(r'include:([^ ]+)')
PTN_IPADDR = re.compile(r'(?Pip[46]:[\d\w\.:/]+)')
def flatten(domain):
results = []
# 指定ドメインのTXTレコードを取得する
for answer in resolver.resolve(domain, 'TXT'):
v = answer.strings[0].decode('ascii')
if not PTN_SPF.match(v): # SPFレコードではない場合は無視
continue
# `include` を再帰的に処理する
for include in PTN_INCLUDE.findall(v):
flattened = flatten(include)
if flattened:
results.extend(flattened)
# IPアドレス記述があれば返す
for ipaddr in PTN_IPADDR.findall(v):
results.append(ipaddr)
return results
あとは適当にDNSレコードの長さ制約を気にしながら、SPFレコードの書式に組み立ててみたところ、3レコードに納めることができました。自社のDNSサーバーにレコードを作成して、それらをincludeするように変更しました。
15 - 8 + 3 = 10
でギリギリクリアですね。
DNSのルックアップ制限が必要だということはわかるんですが、外部サービスを利用していると結構厳しいなあというのが実感です。
メールを送る外部サービスの利用については、SPFのことを意識しつつ使う送信元メールアドレスなどを工夫していく必要がありそうです。
それはともかく、今回他のサービスとかどうなってんのかなと思ってあちこち dig
コマンドでDNSレコードを見ましたが、割と興味深くて面白いですよ! :D
システムエンジニア募集中です!
興味のある方はぜひカジュアル面談へ!お待ちしています。