Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
メール認証とRuby
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
uvb_76
March 07, 2024
Programming
1.2k
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
2
1.7k
ユーザーにサブドメインの ECサイトを提供したい (あるいは) 2026年函館で一番熱くなるかもしれない言語の話
uvb_76
0
970
Rails 7.2 のリリースノートを見て思ったこと
uvb_76
0
1k
Rails Girls ガイドを使って社内で Rails 講座を開催した
uvb_76
0
180
問い合わせ調査との付き合い方
uvb_76
0
280
yawaraka zouzei
uvb_76
0
2.2k
開発環境(物理)を作る
uvb_76
0
1.8k
Other Decks in Programming
See All in Programming
선언형 햅틱 라이브러리 진동을 소개합니다
l2hyunwoo
1
310
Herb in Rails 8.2: Your ERB views, now HTML-aware @ Kaigi on Rails 2026, Tokyo, Japan
marcoroth
2
420
Claude Code ハーネスDeep Dive – 君はどこまで制御する? -
takateeen_knj
6
5.1k
DroidKnights 2026 Android A2UI Jetpack Compose 기반의 안전한 AI UI 렌더링 - 박제창
itsmedreamwalker
1
220
ActionController meets Protocol Buffers
sorah
1
800
Vapor Mode でアクセシビリティは 壊れないか検証した話
fuqda
1
340
まずはコードより業務と向き合う:テーブル解体のためにPdMを呼んだ話
sakawe_ee
0
210
AIが生成したコードは読むべきか?抽象化設計とコードの品質保証 / abstraction-design-and-quality
minodriven
16
9k
baseline으로 마이그레이션, 리팩토링 안전하게 맡기기
fornewid
1
970
社内AIエージェント「Askワンバン」における コストチューニングの取り組み
t0yohei
0
170
複数ドメインを一つのアプリに統合するFlutterの設計と運用_FlutterKaigi2026登壇資料(須永高弘)
takahirosunaga
0
170
全ての永続トークンを、生まれる前に消し去りたい!
sylph01
3
1.7k
Featured
See All Featured
Writing Fast Ruby
sferik
630
63k
We Analyzed 250 Million AI Search Results: Here's What I Found
joshbly
2
2.1k
Efficient Content Optimization with Google Search Console & Apps Script
katarinadahlin
PRO
1
980
New Earth Scene 8
popppiees
5
2.8k
Believing is Seeing
oripsolob
1
270
Designing Dashboards & Data Visualisations in Web Apps
destraynor
232
55k
How Software Deployment tools have changed in the past 20 years
geshan
3
35k
Statistics for Hackers
jakevdp
799
230k
Site-Speed That Sticks
csswizardry
13
1.6k
How to build a perfect <img>
jonoalderson
1
6.2k
How to audit for AI Accessibility on your Front & Back End
davetheseo
0
630
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
508
140k
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