SMTPを知る
文 :
佐久間 浩彰
Write :
Hiroaki Sakuma
概要
Eメール(電子メール,以下メール)は,SMTP(Simple Mail Transfer Prorocol)という仕組みで通信します.
メールは,インターネット誕生以前から存在する化石のようなプロトコルです.SMTP誕生以前にも,UNIXのシステム内で,ユーザ間の連絡用として使われていました.
もちろん,時代に合わせ,様々な改良,拡張が行われていますが,基本となるSMTPの仕組みは,1982年にRFC821で,ARPAネット用メールプロトコルとして公開されて以来ほとんど変わっていません.
SMTPはテキストベースのとてもシンプルなステートフルなプロトコルですが,後述する理由から動作はとても複雑となっています.
UUCP
現在のインターネットは,TCP/IPという仕組みで成り立っています,インターネット誕生以前には,広域なネットワークとしてUUCPという仕組みが使われていました.
詳細は割愛しますが,UUCPはモデムと電話線を使ったダイヤルアップで相互のコンピュータを接続していました.当然,電話代が掛かりますから,常時接続ではなく,必要な際に接続する形を取ります.
しかし,例えばメールを送信しようと思っても,相手が接続中であるとは限りません.相手が接続してなくてもメールを送れるようにするため考え出されたのが,バケツリレー方式です.メールの宛先に関係なく,とりあえず接続中のマシンにメールを送っておき,接続中のマシンはもらったメールをまた他のマシンに送っていく,ということを繰り返し,最終的な目的地へ行き着くことを期待する仕組みになっていました.
メールのヘッダを見ると,必ず
Message-Id という項目があると思いますが,これは当時の仕組みの名残です.バケツリレーでは,途中でメールが失われたり,また複数の経路から同じメールが届くことがありました.そこで,送信時にメールごとに一意であるMessage-Idを付加する事で,メールを特定できるようにしました.
仕組み上,配信経路中でメールの内容を盗み見たり,改ざんする,なりすますといったことが可能になっていますが,この弱点は今でも引き継がれており,これが昨今のスパムメール,フィッシング詐欺メールが蔓延する原因となっています.
MUAとMTA
Eメールを使用する際,MUA(Mail User Agent)とMTA(Mail Transfer Agent)が,それぞれ役割分担をします.
MUAはEメールの作成と閲覧を担い,MTAが送信と受信という配信を請け負います.
Eメールは通常,送信元のMUAからMTAに送られ,いくつかのMTAを経た後,受信者のMTAに届けられ,最後は受信者のMUAに送られます.
ここで,最後の受信者のMTAとMUAの間は,POP3(Post Office Protocol version 3)やIMAP(Internet Message Access Protocol)が使われますが,それ以外の通信はSMTPが使われます.
MUA-MTA間,MTA-MTA間のどちらでもSMTPが使われるため,混乱しやすいのですが,動作を考えれば自然な実装です.
MUA-MTA間
MUAはEメールの作成や閲覧に特化しているため,宛先のホストを探すなどの処理は全てMTAに任せるようになっています.
これは,Eメールの配信には,例えば宛先のホストが一時的にダウンしていた場合に改めて再送を行う,バウンスメールを処理するなど,常時起動して常時接続している必要があるためです.
MUAが動く環境は,常時接続とは限りませんし,また常時起動しているとも限りません.
MUAは設定したMTA(多くのMUAはSMTPサーバと呼びます)に対し,SMTPでEメールを送ることで,その後の配信の一切を任せるようになっています.
MTA-MTA間
MTAの主な動作は,自分のホスト宛のEメールを受け取ったらユーザに配送し,他のホスト宛なら,適当なホストへ転送するという2種類の動きがあります.
自分のホスト宛のEメールかどうかは,SMTPのRCPT To: Envelope(エンベロープ)を見て判断します.
他のホスト宛のEメールをどう取り扱うかなのですが,通常はその宛先の最終的な配送先と思われるホストを探し,そこへ送ります.設定などにより,無条件で特定のホストへ送る場合もあります.
ここで一つの問題に気付きましたか?自分のホスト宛以外のEメールは転送する,ということは全く自分に関係のないEメールであっても取り扱うことになります.これが,今スパムメールで問題になっているメールリレーの脆弱性です.
対策として,
自分のホスト宛以外のEメールは受け取り拒否する
特定のホスト以外からのEメールは受け取り拒否する
パスワードを使って送信者を認証する
といったものがあります.プロバイダなどでは,(2)を使うことで,自社のユーザ以外からの利用はできないようにしています.また,POP before SMTPという仕組みを使い,一時的に接続可能な特定のホストを作る方法もよく使われます.
(3)はSMTP Auth(SMTP認証)という仕組みです.
MTAになりましょう
自分がMTAになったつもりで,実際に通信してみます.
ここでは,というアドレスからのEメールを,に送る場合を考えます.
宛先のホストを探すためのresolver(リゾルバ)の代用でdigコマンド,通信クライアントとしてtelnetを使います.
telnetクライアントは本来,telnetというプロトコルのためのクライアントですが,とてもシンプルなプロトコルのため,TCP/IPの低レベルなプロトコルを手動でシミュレートする際によく用いられます.
太字で示したところは実際に入力するアドレスです.[CRLF]は改行のことで,リターンキーを押すことを示しています.
まず,ホスト名からIPアドレスを求めます.
kakuo@TOJO /home/kakuo% dig MX bitcoffee.com[CRLF]
; <<>> DiG 9.3.1 <<>> MX bitcoffee.com
;; global options: printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 50889
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 2, ADDITIONAL: 4
;; QUESTION SECTION:
;bitcoffee.com. IN MX
;; ANSWER SECTION:
bitcoffee.com. 10 IN MX 10 mail.bitcoffee.com.
bitcoffee.com. 10 IN MX 20 mail2.bitcoffee.com.
;; AUTHORITY SECTION:
bitcoffee.com. 12583 IN NS ns1.bitcoffee.net.
bitcoffee.com. 12583 IN NS ns2.bitcoffee.net.
;; ADDITIONAL SECTION:
mail.bitcoffee.com. 10 IN A 210.167.148.251
mail2.bitcoffee.com. 10 IN A 210.167.148.252
ns1.bitcoffee.net. 144632 IN A 210.167.148.1
ns2.bitcoffee.net. 84900 IN A 210.167.148.2
;; Query time: 16 msec
;; SERVER: 203.141.128.33#53(203.141.128.33)
;; WHEN: Wed Mar 8 15:53:29 2006
;; MSG SIZE rcvd: 187
ここでは,Eメールの宛先のホストとして,DNSで宛先のアドレスのホストのMXレコードを探します.
この結果では,2つのホスト,
mail.bitcoffee.com と
mail2.bitcoffee.com が返ってきましたが,これは冗長構成になっています.もし1台のホストが止まっても,もう1台のホストがEメールを受け取ることで,Eメールのロストを防ぐようになっています.いわばバックアップと言えます.
ホスト名の前の,
10 や
20 はサーバとの距離と表しており,小さいほど近くを意味します.
複数のホストが返ってきた場合,通常は距離が小さい方(今回はmail.bitcoffee.com)へ接続します.
digコマンドは,対象となるホストのIPアドレス(Aレコード)も自動で検索してくれます.
次に,telnetで接続してみます.
kakuo@TOJO /home/kakuo% telnet[CRLF]
telnet> open 210.167.148.251 25[CRLF]
Trying 210.167.148.251...
Connected to 210.167.148.251.
Escape character is '^]'.
220 san.bitcoffee.net Mail server at BitCoffee, Inc. ESMTP
HELO kakuo.com[CRLF]
250 san.bitcoffee.net Mail server at BitCoffee, Inc.
MAIL From: <kakuo@kakuo.com>[CRLF]
250 ok
RCPT To: <hogehoge@bitcoffee.com>[CRLF]
250 ok
DATA[CRLF]
354 go ahead
From: "Kakuo TOJO" <kakuo@kakuo.com>[CRLF]
To: hogehoge@bitcoffee.com[CRLF]
Subject: This is test mail[CRLF]
[CRLF]
Hello.[CRLF]
How are you?[CRLF]
.[CRLF]
250 ok 1141833743 qp 81053
QUIT[CRLF]
221 san.bitcoffee.net Mail server at BitCoffee, Inc.
Connection closed by foreign host.
これは最も簡単なSMTPです.
宛先のホストの25ポートに接続したら,まずHELOコマンドで自分を名乗ります.通常は自分のホスト名などを名乗りますが,あまり意味は持っていません.
次に,MAILコマンドで,送信元のアドレスを名乗ります.その後,RCPTコマンドで宛先のアドレスを指定します.
この時点で,MAILコマンドとRCPTコマンドの組み合わせで不備があると,メールリレーなどと判断されて,エラーが返される事があります.
DATAコマンドが,Eメールの本文です.ここでいう本文というのは,Header(ヘッダ)とBody(ボディ)のことです.
ヘッダとボディは,[CRLF][CRLF](つまり改行のみの行を含む)で分離します.ヘッダは,項目名: 値という組み合わせになっています.
MUAで見たときに表示される,From(送信元)やTo(宛先),CC(同報),Subject(題名,タイトル)などは全てこのヘッダで指定します.
ピリオドと[CRLF]のみの行が,本文の終わりを示します.
最後に,QUITコマンドで接続を切断します.
FromやToは信用できない
上記の流れを見ても分かるとおり,MUAで示されるFromやToというのは,Eメールを送る際に自由に指定することができます.つまり,MUAでEメールを見ただけでは,本当の送り主や,宛先は分からないということになります.
また,MTAは他のホストに転送する際に,ヘッダにReceivedという経路を示す項目を追加しますが,これも自分が追加するもの以外は,前のホストが送ってきたものをそのまま使うので,同様に信頼性はありません.