本文へスキップ

たけぞうBLOG

「外部から受信できない」は誤診だった 〜MAP-E回線のメールサーバーをIPv6で正しく監視するまで〜

「外部から受信できない」は誤診だった MAP-E IPv6 mailmon HetrixTools

自宅のメールサーバー(docker-mailserver / Proxmox LXC)で「外部からメールが受信できない」という診断を2回下し、その2回とも誤診だった、という顛末の記録です。実際にはサーバーも経路も生きていて、悪かったのは僕の検証手法でした。原因はMAP-E回線の構造的な制約と、それを知らずに使ってしまったIPv4専用の外部ポートテスト。最終的に、実メールを一切送らずに送受信経路を常時監視する仕組み(mailmon)、外部4拠点からのIPv6監視(HetrixTools + AAAA専用サブドメイン)、そして監視対象のメールサーバーに依存しない通知経路を整備しました。同じ構成で悩んでいる人の参考になれば幸いです。

目次

広告

タイムライン: 何が起きていたのか

  • 10/24: LXC上にdocker-mailserverでメールサーバーを構築。Gmailとの送受信を実証済み(構築記)
  • 10/26: 第2ドメインexample.orgを追加。同日午前5時頃、DNS汚染が発生(後述)
  • 10/26〜31: 外部からのメールが静かに失われ続ける
  • 10/31: 汚染を発見・修復。しかしその後も「外部受信が死んでいる」と診断してしまう
  • 11/1: 再検証したらGmail実メールが2秒でINBOXに到達。診断は誤りだった

本当に起きていた事故: DNSのCNAME汚染

修復すべき実害はこれでした。mail.example.comのAレコードが、ある日を境に送信サービスのホスト名を指すCNAMEに置き換わっていたのです。MXレコードはmail.example.comを指しているので、外部のMTAからのメールは全部そのCNAME先へ飛んでいく。サーバー自身は健康なまま、玄関の表札だけが別の家を指し続ける状態です。10/26〜31に届くはずだった外部からのメールは、おそらく全て喪失しています。

10/31にAレコードを再作成し、AAAAも併せて設定、DDNSも復旧確認。ここまでは正しい対処でした。問題はこの後です。

誤診その1: MAP-E回線ではIPv4の低いポートが「そもそも存在しない」

修復後、外部からポート25(SMTP)や993(IMAPS)への接続テストをしたところ、すべてタイムアウト。「DNSは直ったのに外部から届かない=ルーターの転送が壊れた」と診断してしまいました。ところが調べていくと、この回線はtransix系のMAP-E(IPv4 over IPv6)で、構造的にIPv4のメールポートが使えないのでした。

MAP-Eでは、契約ごとにIPv4アドレスの一部とポート範囲の一部が割り当てられます。この回線の割当はPSIDLEN=8 / OFFSET=4で、これはポート0〜1023(ウェルノウンポート帯)は割り当て範囲に含まれないことを意味します。つまり:

  • ポート25 / 465 / 587(SMTP系)へのIPv4 inbound → 事業者側のBRで破棄。ルーターまで届かない
  • 143 / 993(IMAP系)も同様
  • 外部から見ると「ポートが閉じている」のではなく「そのポートは宇宙のどこにも存在しない」状態

実験でも確認できました。外部の複数拠点から同時に接続を試みてもルーターの検知カウンタはゼロのまま。自宅のグローバルIPv4アドレスへのリテラル接続もタイムアウトします。この回線ではIPv4のポートテストは健康でも永久にタイムアウトする。だから健全性判定に使ってはいけない、ということになります。

誤診その2: テスト手法自体の妥当性を検討していなかった

さらにまずかったのは、使った外部テストサービス(check-host.net等)のノードがすべてIPv4専用だったことです(後日の検証で、IPv6対応ノードは0/12と確認)。つまり:

  • テストが失敗するのは「経路が壊れたから」ではなく「この回線でこのテストは永遠に成功しないから」
  • 一方で実際の受信経路はIPv6で生きていた: GoogleのMTA(2a00:1450系)→ルーターwan6→IPv6許可ルール→LXC:25→SpamAssassin→LMTP→INBOX

ユーザー(家族)にGmailから実メールを送ってもらい、2秒でINBOXに到達するのをログで確認した瞬間、すべての辻褄が合いました。設定もルーターもずっと正常だったのに、テストの選択を誤ったことで2回も「障害」と診断してしまったわけです。

教訓はシンプルです:

  • トランスポート系の健全性は、経路を実物で通してから断定する
  • 外部テストを使う前に、回線種別(MAP-E / IPoE / PPPoE)と「その回線で成立するテストか」を先に判定する
  • 「テストが失敗する」ことと「経路が壊れている」ことは別の事実

監視の作り直し(1): 内部経路 mailmon(5分毎)

同じ轍を踏まないため、監視体制をゼロから作り直しました。まず内部経路のmailmon。設計条件は実際のメールを送らない・実用アドレスを対象にしないの2点。この制約の中で「送受信が本当に通る」ことを検証するには、ローカルループ配送テストが有効でした:

  • LXC内部から127.0.0.1:25へテストメッセージを投入(Fromは解決可能なテスト用ドメイン、Toはプレースホルダーアカウント。外部には一切出ない)
  • postscreen → SpamAssassin → LMTP(Dovecot) → INBOX配信までを本物の配送パイプラインで通す
  • タグ付き件名で到達を確認したら、テストメッセージを自動削除

はまりどころとしては、テストメッセージにDateとMessage-IDヘッダがないと、amavisがBAD-HEADER判定で黙って検疫に入れてしまうことがありました。「送信は成功するのにINBOXに届かない」という謎の現象として現れるので、初見では原因が掴みにくいやつです。

配送テスト以外に、約25項目を5分毎にチェックしています:

  • コンテナ状態・ポートlisten(25/465/587/143/993/4190)・SMTPバナー・587 STARTTLS・993 TLSハンドシェイク
  • 証明書の有効期限(14日以内でWARN)
  • 送信リレー(Brevo smtp-relay:587)へのTLS到達。認証はせず送信もしない
  • メールキューの状態、実メール流量の記録とdeferred/bouncedの即時FAIL
  • DNS: 両ドメインのMX、A(ルーターの実MAPE IPv4と照合=DDNSの健全性)、AAAA(実IPv6と照合)、SPF/DKIM/DMARC — CNAME汚染の再発を即検知するのが目的
  • ルーター(SSHで内部から): メールポートの転送ルール数、IPv6許可ルール数、wan6・MAPEトンネルの状態

監視の作り直し(2): 外部からのIPv6監視

内部監視だけでは、ISP→ルーターの最終ホップ(外部から本当に届くか)は検証できません。しかし匿名で使えるcheck-host.netは前述の通りIPv4専用ノードのみで、この回線では成立しません。そこで無料枠のあるHetrixToolsを採用しました(1分間隔・複数ロケーション)。

ここで一つ設計上の問題があります。ホスト名を監視対象にすると、そのサービスがIPv4とIPv6のどちらで接続してきたか分からないのです。v4はこの回線では永遠に失敗するので、監視が常時FAILで埋まるか、逆に「どちらかで成功していればOK」になってIPv6経路の死を見逃します。

解はシンプルで、AAAAレコードしか持たないサブドメイン(mail6.example.com)を作り、それを監視対象にすることでした。AAAAしかないので監視サービスは強制的にIPv6で接続します。すると「接続成功=IPv6経路が生きている確定証拠」になります。DDNSスクリプトもmail6.example.comを追従させ、mailmonに「mail6.example.comのAAAA=実IPv6」の一致チェックを追加しました。プレフィックスが変わったときに監視だけ古いアドレスを見ている、という事故も防げます。

構築後、ルーターのwan6でLXC宛のIPv6パケットが観測され(8秒で134パケット)、外部からの監視プローブが本当に届いていることを確認しました。併せてCloudflare Tunnel経由のwebmailも監視対象に加えています。

監視の作り直し(3): 通知はメールサーバーに依存させない

検知して終わりでは意味がないので通知も作りました。ルールは、連続2回失敗(≈10分継続)で初回通知、以後1時間に1回リマインダー、復旧時に復旧通知。単発の瞬断で鳴らないようにしています。

重要なのは、通知経路を監視対象のメールサーバーに依存させてはいけない、という点です。サーバーが止まったときに通知も止まっていては本末転倒なので、2系統に分けました:

  • 監視ホストから送信リレー(Brevo)へ直接SMTP接続してGmail宛に通知(メールサーバーを経由しない)
  • ntfy.shのプッシュ通知(トピック名が秘密鍵の代わり。スマホアプリでもブラウザでも受け取れる)

テスト送信で両経路の動作を実証済みです。監視ホストごと死んだ場合も、外部監視(HetrixTools)側が別系統で警報してくれるので二重になっています。

現在の監視カバレッジ

階層監視間隔
外部複数拠点 → ISP → ルーターHetrixTools(AAAA専用名・強制IPv6)1分
DNS(MX/A/AAAA/SPF/DKIM/DMARC)mailmon(汚染再発検知)5分
ルーター(転送・許可ルール・wan6・MAPE)mailmon(SSH)5分
コンテナ・ポート・TLS・証明書・キューmailmon5分
配送パイプライン実フロー(SA→LMTP→INBOX)mailmon ローカルループテスト5分
実メールのdeferred/bouncedmailmon5分

まとめ

  • MAP-E系の回線では、低ポートへのIPv4 inboundは構造的に存在しない。メールサーバーは最初からIPv6-onlyの受信で設計する(送信はリレー経由なので問題ない)
  • 外部テストは「その回線で成立するテストか」を先に判定する。IPv4専用ノードのポートテストは、この回線では永久にタイムアウトするだけ
  • 健全性の断定は実フローで。設定とログの読解だけでは誤診する
  • IPv6-only受信は正しく監視すれば十分実用になる。むしろ「IPv4のテストが永久に失敗する」特性を逆手に取ると、AAAA専用名への接続成功がIPv6経路の確定証拠になる。失敗が曖昧なテストより、成功が意味を持つテストを設計する

同じMAP-E回線でメールサーバーを運用・検討中の方の参考になれば幸いです。次は3日分の監視ログのレビューをして、しきい値の調整をします。

広告

この記事をシェア