Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
メール認証とRuby
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
uvb_76
March 07, 2024
Programming
1.1k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
メール認証とRuby
uvb_76
March 07, 2024
More Decks by uvb_76
See All by uvb_76
地元にいないローカルオーガナイザーの立ち回り
uvb_76
1
870
ユーザーにサブドメインの ECサイトを提供したい (あるいは) 2026年函館で一番熱くなるかもしれない言語の話
uvb_76
0
890
Rails 7.2 のリリースノートを見て思ったこと
uvb_76
0
950
Rails Girls ガイドを使って社内で Rails 講座を開催した
uvb_76
0
160
問い合わせ調査との付き合い方
uvb_76
0
250
yawaraka zouzei
uvb_76
0
2.1k
開発環境(物理)を作る
uvb_76
0
1.8k
Other Decks in Programming
See All in Programming
Agentic UI
manfredsteyer
PRO
0
110
Why Laravel apps break—Mastering the fundamentals to keep them maintainable
kentaroutakeda
1
340
tsserverとは何だったのか、これからどうなるのか
nowaki28
1
450
脅威をエンジニアリングの糧にして――現場編 / Turning Threats into Engineering Fuel — Field Edition
nrslib
0
250
Dataformのリポジトリを立ち上げるときにまずやること / dataform-day0-2026
snhryt
0
110
AI駆動開発で崩れていくコードベースを立て直す
kyoko_nr_nr
1
440
CSC307 Lecture 17
javiergs
PRO
0
310
Technical Debt: Understanding it Rightly, Engaging it Rightly #LaravelLiveJP
shogogg
0
200
jQueryをバージョンアップする前に使いたいjQuery Migrate
matsuo_atsushi
0
190
関係性から理解する"同一性"の型用語たち
pvcresin
2
640
Lessons from Spec-Driven Development
simas
PRO
0
140
肥大化するレガシーコードに立ち向かうためのインターフェース分離と依存の逆転 / JJUG CCC 2026 Spring
hirokunimaeta
0
500
Featured
See All Featured
Mind Mapping
helmedeiros
PRO
1
240
Public Speaking Without Barfing On Your Shoes - THAT 2023
reverentgeek
1
410
Data-driven link building: lessons from a $708K investment (BrightonSEO talk)
szymonslowik
1
1.1k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
360
30k
What Being in a Rock Band Can Teach Us About Real World SEO
427marketing
0
250
Fashionably flexible responsive web design (full day workshop)
malarkey
408
66k
Large-scale JavaScript Application Architecture
addyosmani
515
110k
Statistics for Hackers
jakevdp
799
230k
Navigating Team Friction
lara
192
16k
End of SEO as We Know It (SMX Advanced Version)
ipullrank
3
4.2k
Ruling the World: When Life Gets Gamed
codingconduct
0
250
Designing for humans not robots
tammielis
254
26k
Transcript
メール認証とRuby 2024/03/06 Gotanda.rb#57 ikaruga / Atsushi Katsuura 1
誰 ikaruga / Atsushi Katsuura GMOペパボ株式会社 EC事業部 CREチーム puts Resolv::DNS.new.getresources(
'me.ikaruga.org', Resolv::DNS::Resource::IN::TXT ).map(&:data) => ["GITHUB=ikaruga777", "TWITTER=@UVB_76", "WORK=GMO Pepabo Inc.", "
[email protected]
"] 2
https://support.google.com/a/answer/81126?hl=ja 3
4
メール認証のおさらい 色々要件はあったけど、基本SPF,DKIM,DMARC 全てはメールのなりすましを防ぐための仕組み 5
メールヘッダー 二種類のFrom ヘッダーFrom メールヘッダーの From エンベロープFrom メールヘッダーの Return-Path 6
(ちょうどいま来たメールを例に) Gmailだったらメールのメニューから「メッセージのソースを表示」をポチるとヘッダーを確 認できる # ヘッダーFrom From: Duolingo <
[email protected]
> # エンベロープFrom
Return-Path: <0100018e1341b06c-6b1b2b73-30d1-49fc-9788-8b3c5133d0c5-000000@bounces.duolingo.com> 7
SPF Sender Policy Framework メール送信元のドメインが許可されているかどうかをチェックする エンベロープFromのドメインでTXTレコード引くと v=spf1 から始まる値が取れる。 ip4: や
ip6: の後ろにIPアドレスが含まれているので、そこで送信元のIPアドレ スが引けたらPASS $ dig spf-external.shop-pro.jp TXT +short "v=spf1 ip4:210.175.7.1/32 include:srs0260.cuenote.jp ~all 8
SPF IPアドレス以外にも a , mx , include , redirect の
mechanism ではドメインを指定 できる。 ドメインに当たったらそのドメインで再帰的にTXTレコードを引いていく。 ルックアップの回数は10回まで。 https://tex2e.github.io/rfc-translater/html/rfc7208.html 4.6.4. DNS Lookup Limits にその話がある 9
(Googleから来てたメールを例に取る) メールヘッダー Return-Path: <3H5XiZRAKCgozk8wox32-xy1ozv8qyyqvo.mywsuk14qkHHHqwksv.myw@scoutcamp.bounces.google.com> Received: from mail-sor-f69.google.com (mail-sor-f69.google.com. [209.85.220.69]) From:
Google Payments <
[email protected]
> 209.85.220.69 が送信元のIPアドレス 10
Return-PathのドメインでSPFを引くと $ dig 3h5xizrakcgozk8wox32- xy1ozv8qyyqvo.mywsuk14qkhhhqwksv.myw@scoutcamp.bounces.google.com TXT +short "v=spf1 redirect=_spf.google.com" $
dig _spf.google.com TXT +short $ dig _spf.google.com TXT +short "v=spf1 include:_netblocks.google.com include:_netblocks2.google.com include:_netblocks3.google.com ~all" $ dig _netblocks.google.com TXT +short "v=spf1 ip4:35.190.247.0/24 ..( 中略).. ip4:209.85.128.0/17 .... ~all" 11
(Googleから来てたメールを例に取る) irb(main):003> IPAddr.new('209.85.128.0/17').include?('209.85.220.69') => true 12
DKIM DomainKeys Identified Mail メールを送信する際にメールの内容を用いて署名を作って認証する仕組み 送信されるメールサーバに秘密鍵を保存する 生成された署名は DKIM-Signature ヘッダーに付与される 受信者はメールヘッダーの
DKIM-Signature ヘッダーの d, s タグからレコードを見つ ける dはドメイン、sはセレクタ(鍵ローテのために複数認証系を用意してる) "#{s}._domainkey.#{d} でTXTレコードを引くと公開鍵が引けるので、それを使 って認証する。 13
(Googleから来てたメールを例に取る) メールヘッダー DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1709348127; x=1709952927;
dara=google.com; h=to:from:subject:message-id:feedback-id:reply-to:date:mime-version :from:to:cc:subject:date:message-id:reply-to; "#{s}._domainkey.#{d}" でTXTレコードを引く p= のあとが公開鍵 $ dig 20230601._domainkey.google.com TXT +short "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AM...( 略)" 14
DMARC Domain-based Message Authentication, Reporting and Conformance SPFとDKIMに加えて追加の認証をすることでなりすましを防ぐ SPFアライメント、DKIMアライメントを追加で認証する さらに、認証が通らなかったときのメールの監視の仕組みも定義されていて、送信元の
サーバー管理者が通告されたSPAMと判定されたメールの内容について把握することが できる。 設定もDNSレコードで行う 15
DMARCレコードの実例 $ dig _dmarc.google.com TXT +short "v=DMARC1; p=reject; rua=mailto:
[email protected]
" $
dig _dmarc.shop-pro.jp TXT +short "v=DMARC1; p=none; pct=100; adkim=r; aspf=r; rua=mailto:
[email protected]
; ruf=mailto:
[email protected]
;" 16
アライメント SPFアライメント エンベロープFromとヘッダーFromのドメインが一致しているかどうか DKIMアライメント ヘッダーFromのドメインと DKIM-Signature ヘッダーの d タグのドメインが一致している かどうか
17
ref: https://speakerdeck.com/azumakuniyuki/gu-iji-shu-nituite-smtpxian-dai-shi-qing- tumamishi-i?slide=14 YAPC::HiroshimaでされていたSMTPのセッションが簡潔にまとまっていて最高。 古い技術について—SMTP現代事情つまみ食い— - Speaker Deck 18
ブログ SendGrid, ベアメールのブログにわかりやすい記事がたくさんあって便利。 https://sendgrid.kke.co.jp/blog/ https://baremail.jp/blog/ 19
一応Rubyの話 20
設定されていることをどうやって確認するか SPF, DKIM, DMARCいずれもDNSレコードの内容を確認していく必要がある。 21
Resolv 標準ライブラリにDNS引いてくれるくんがいて便利。 https://github.com/ruby/resolv https://docs.ruby-lang.org/ja/3.3/library/resolv.html 22
誰 ikaruga / Atsushi Katsuura GMOペパボ株式会社 EC事業部 CREチーム puts Resolv::DNS.new.getresources(
# ← これ 'me.ikaruga.org', # ← これ Resolv::DNS::Resource::IN::TXT # ← これ ).map(&:data) # ← これ => ["GITHUB=ikaruga777", "TWITTER=@UVB_76", "WORK=GMO Pepabo Inc.", "
[email protected]
"] 23
パーサーがある https://github.com/trailofbits/spf-query SPFレコードのパーサーもいて便利 https://github.com/trailofbits/dkim-query DKIMレコードのパーサーもいて便利 https://github.com/trailofbits/dmarc DMARCレコードのパーサーもいて便利 24
spf-query 使ってみる require 'bundler/inline' gemfile do source 'https://rubygems.org' gem 'spf-query'
end domain = ARGV.first q = SPF::Query::Record.query(domain) def query(q, lookup_count) q.mechanisms.each do |mechanism| case mechanism.name when :ip4, :ip6 puts mechanism.value when :include, :redirect lookup_count += 1 return if lookup_count > 10 puts ">>" + mechanism.value # _spf サブドメインを暗黙的に引いてしまうらしい # https://github.com/trailofbits/spf-query/issues/10 records = Resolv::DNS.new.getresources(mechanism.value, Resolv::DNS::Resource::IN::TXT) spf_record = records.find do |record| record.strings.join.include?('v=spf1') end spf_record_value = spf_record.strings.join q = SPF::Query::Parser.parse(spf_record_value) query(q, lookup_count) when :a lookup_count += 1 # Resolv::DNS::Resource::IN::A でレコードを引く when :mx lookup_count += 1 # Resolv::DNS::Resource::IN::MX でレコードを引く when :ptr, :exsists lookup_count += 1 # 頑張って実装 end end end query(q, 0) 25
$ ruby parse_spf.rb _spf.google.com >>_netblocks.google.com 35.190.247.0/24 64.233.160.0/19 66.102.0.0/20 66.249.80.0/20 72.14.192.0/18
74.125.0.0/16 108.177.8.0/21 173.194.0.0/16 209.85.128.0/17 216.58.192.0/19 216.239.32.0/19 >>_netblocks2.google.com 2001:4860:4000::/36 2404:6800:4000::/36 2607:f8b0:4000::/36 2800:3f0:4000::/36 2a00:1450:4000::/36 2c0f:fb50:4000::/36 >>_netblocks3.google.com 172.217.0.0/19 172.217.32.0/20 172.217.128.0/19 172.217.160.0/20 172.217.192.0/19 172.253.56.0/21 172.253.112.0/20 108.177.96.0/19 35.191.0.0/16 130.211.0.0/22 26
まとめ 最近話題になっていたDNSを使ったメール認証のしくみのおさらいをしました Rubyでドメインに対して適切なレコードが設定されているかを確認するを1つ紹介しま した 懇親会で喋れたら喋りたい ワンクリック購読解除の適用範囲 27
仕事の話(宣伝) 3/15~の Ya8 2024 - ヤパチー 令和六年最新版(仮) で同僚が現場の話をする予定です(採択さ れていました) 以下のような現場の話が聞ける可能性があります
「メールサーバー」を自前で運用している 自前のメールサーバーやSaasを通して、ユーザーが設定した「独自ドメイン」でメール を送るための機能を提供している https://github.com/hachiojipm/ya8-2024-cfp/issues/32 28