Share
Embed
Transcript
32 slides
-
自己紹介 自己紹介 とみたまさひろ ←投げ銭はこちら MySQL / メール / 文字化け 富士通クラウドテクノロジーズ勤務
https://twitter.com/tmtms https://tmtms.hatenablog.com https://zenn.dev/tmtms 2 -
SMTP SMTP Simple Mail Transfer Protocol (1982) → (2001) →
(2008) メールメッセージ形式は → → ポート番号は 25 (smtp) RFC 821 2821 5321 RFC 822 2822 5322 3 -
% nc smtp.example.com 25 ← 220 smtp.example.com ESMTP Postfix →
EHLO client.example.net ← 250-smtp.example.com 250-PIPELINING 250-SIZE 102400000 250-VRFY 250-ETRN 250-STARTTLS 250-AUTH DIGEST-MD5 NTLM CRAM-MD5 PLAIN LOGIN 250-ENHANCEDSTATUSCODES 250-8BITMIME 250-DSN 250 SMTPUTF8 4 -
→ MAIL FROM:<[email protected]> ← 250 2.1.0 Ok → RCPT TO:<[email protected]>
← 250 2.1.5 Ok → RCPT TO:<[email protected]> ← 250 2.1.5 Ok → DATA ← 354 End data with <CR><LF>.<CR><LF> → From: [email protected] To: [email protected] Cc: [email protected] Subject: test message body . ← 250 2.0.0 Ok: queued as F074F9FB0E → QUIT ← 221 2.0.0 Bye 5 -
SMTP認証 SMTP認証 メール送信時に認証が必要な場合 PLAIN はユーザー名とパスワードを Base64 しただけの平文 CRAM-MD5 等を使えば Challenge-Response
方式の暗号化もできるけど サーバー内に平文のパスワードを保持しておかないといけないのがイマイチ → AUTH PLAIN dXNlcm5hbWUAdXNlcm5hbWUAcGFzc3dvcmQ= ← 235 2.7.0 Authentication successful 12 -
通信暗号化(STARTTLS) 通信暗号化(STARTTLS) SMTP 接続後に STARTTLS 命令を発行すると それ以降 TLS での暗号化通信になる (465番ポートは接続時からTLS)
← 220 smtp.example.com ESMTP Postfix → EHLO client.example.net ← 250-smtp.example.com 250-STARTTLS ... → STARTTLS ← 220 2.0.0 Ready to start TLS --- ここから TLS 通信 --- → EHLO client.example.net ← 250-smtp.example.com ... → AUTH PLAIN dXNlcm5hbWUAdXNlcm5hbWUAcGFzc3dvcmQ= ← 235 2.7.0 Authentication successful 13 -
暗号化通信は手動ではできないので openssl を使う % openssl s_client -connect smtp.example.com:587 -starttls smtp
...STARTTLS まで自動でやってくれる... --- ここから TLS 通信 --- → EHLO client.example.net ← 250-smtp.example.com ... 14 -
TLS証明書の検証 TLS証明書の検証 オレオレ証明書とか期限切れ証明書はエラーにしたい % openssl s_client -connect smtp.example.com:587 -starttls smtp
-verify_return_error ... Verification error: certificate has expired --- New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384 Secure Renegotiation IS NOT supported Compression: NONE Expansion: NONE No ALPN negotiated Early data was not sent Verify return code: 10 (certificate has expired) --- % 15 -
証明書ホスト名の検証 証明書ホスト名の検証 証明書が正しくても自分がアクセスしてるサーバー用の 証明書じゃないかもしれない 接続先に指定した文字列とは異なるサーバー名を 使いたいこともある(テストとかで) % openssl s_client -connect
smtp.example.com:587 -starttls smtp -verify_return_error -verify_hostname smtp.example.com % openssl s_client -connect 192.168.11.22:587 -starttls smtp -verify_return_error -verify_hostname smtp.example.com 16 -
Net::SMTP Net::SMTP めっちゃ簡単 require 'net/smtp' Net::SMTP.start('smtp.example.com', 25) do |smtp| smtp.send_message(<<EOS,
'[email protected]', '[email protected]', '[email protected]') From: [email protected] To: [email protected] Cc: [email protected] Subject: test message body EOS end 18 -
SMTP認証 SMTP認証 ユーザー名とパスワードを指定したいだけなのに EHLO 名を書かないといけないのがイマイチ 認証が必要なのは送信サーバーに送信するとき その場合は EHLO 名は重要ではないはず デフォルトだとTLSじゃないんだけど
デフォルトの認証方式は PLAIN = 平文 Net::SMTP.start('smtp.example.com', 587, 'client.example.net', 'username', 'password') do |smtp| ... end 19 -
STARTTLS STARTTLS Net::SMTP は start よりも前に enabel_starttls が必要なのがイマイチ smtp =
Net::SMTP.new('smtp.example.com', 587) smtp.enable_starttls smtp.start('client.example.com', 'username', 'password') do ... end 20 -
TLS(465番ポート) TLS(465番ポート) enabel_starttls じゃなくて enable_tls enable_starttls と enable_tls 両方指定するとエラー smtp
= Net::SMTP.new('smtp.example.com', 465) smtp.enable_tls smtp.start('client.example.com', 'username', 'password') do ... end 21 -
証明書の検証 証明書の検証 デフォルトでは検証しない かなりダメな感じになってきた… smtp = Net::SMTP.new('smtp.example.com', 587) context =
OpenSSL::SSL::SSLContext.new context.set_params(verify_mode: OpenSSL::SSL::VERIFY_PEER) smtp.enable_starttls(context) smtp.start('client.example.com', 'username', 'password') do ... end 22 -
証明書ホスト名の検証 証明書ホスト名の検証 デフォルトでは証明書の検証をしないのに なぜかホスト名の検証だけはしてる(バグっぽい) Net::SMTP は常に #start() の第1引数の文字列を使うので別のサーバ ー名を使うことはできない smtp
= Net::SMTP.new('192.168.11.22', 587) context = OpenSSL::SSL::SSLContext.new context.set_params(verify_mode: OpenSSL::SSL::VERIFY_PEER) smtp.enable_starttls(context) smtp.start('client.example.com', 'username', 'password') #=> hostname "192.168.11.22" does not match the server # certificate (OpenSSL::SSL::SSLError) 23 -
ということで の コミット権をもらった Net::SMTP は Ruby 2.7 から Gem になってる
https://github.com/ruby/net-smtp/ 24 -
キーワード引数化 キーワード引数化 ↓ EHLO名を指定しなくても認証情報を指定可能 Net::SMTP.start(hostname, port, helo_name, username, password, authtype)
Net::SMTP.start(hostname, port, helo: helo_name, user: username, password: password, authtype: authtype) 25 -
デフォルトで STARTTLS を使用 デフォルトで STARTTLS を使用 非互換! 非互換! サーバーが対応していれば自動的に STARTTLS
を使用 Net::SMTP.start(hostname, port) { ... } → EHLO client.example.net ← 250-smtp.example.com 250-PIPELINING 250-SIZE 102400000 250-VRFY 250-ETRN 250-STARTTLS 250-AUTH DIGEST-MD5 NTLM CRAM-MD5 PLAIN LOGIN 250-ENHANCEDSTATUSCODES 250-8BITMIME 250-DSN 250 SMTPUTF8 26 -
デフォルトでTLS証明書を検証 デフォルトでTLS証明書を検証 非互換! 非互換! 検証したくない場合(テストとか)は tls_verify: false を指定 Net::SMTP.start(hostname, port,
tls_verify: false) { ... } 28 -
net-smtp gem net-smtp gem Ruby 2.7 の人はこれで使える 正当な TLS 証明書を持ってないサーバーへの接続が
エラーになる可能性あり オレオレ証明書とか % gem install net-smtp 30