qmailで IPv6 + TLS + SMTP-AUTH + POP3S + IMAPS

Last Update: 2004/09/27 12:25:31

  1. めざすもの
  2. 変更
  3. OS
  4. daemontools
  5. ucspi-tcp(IPv6)
  6. qmail(TLS+IPv6)
  7. pop3
  8. pop3s
  9. smtp
  10. smtps
  11. smtp-auth
  12. imap
  13. imaps
  14. Antivirus
  15. さいごに

めざすもの

qmailを使って出来るだけ暗号化して覗きみられないように通信しようとする メールサーバを作る。IPv6にも当然対応。
間違いや、こうした方がいいぞなどあれば教えてください。
(注意) 内容が現在(2004/07/28)のバージョンでは通用しないものが多くなっています。 作ってみたportsとか パッチとかに新しいものがあるかもしれません (ないかもしれません)。

変更

OS

OSは FreeBSD 4.7-RELEASE-p1 の予定。 ただし、マシンがまだ調達出来ないので 4.6.2-RELEASE-p2 でテスト。
(2003/04/30): 4.8-RELEASE で vpopmail-5.3.20 を検証。問題なさそう。 (2003/02/18): 5.0-RELEASE-p1 で vpopmail-5.3.16 で検証。問題あり。tcpserver が IPv4 か IPv6 かどっちかでしか bind(2) しない。 (2002/11/15): 4.7-RELEASE-p2 が用意できたので、検証予定。

daemontools

ports の sysutils/daemontools をそのままインストール。 /usr/local/etc/rc.d/svscan.sh は自分で作ってたけど、 /usr/local/share/examples/daemontools/svscan.sh.sample にサンプルが あるので、これを使うことにします。 /service ではなくて /var/service を使うようです。

# cd ${PORTSDIR}/sysutils/daemontools
# make
# make install

ucspi-tcp(IPv6)

ports の sysutils/ucspi-tcp をそのままインストールすると、 IPv6 は使えないので、http://www.fefe.de/ucspi/ にある ucspi-tcp-0.88-ipv6.diff13.bz2 を当てて使います。

そのままだと make が通らなかったりするので、さらにパッチを当てます。 それを ports にしたのが以下のもの。

ports-ucspi-tcp+ipv6-20031001_01.tar.gz
MD5 (ports-ucspi-tcp+ipv6-20031001_01.tar.gz) = 4f690b0856270fa2fc2b7af635bc43c0

# ls
ports-ucspi-tcp+ipv6-20021106.tar.gz
# tar xfz ports-ucspi-tcp+ipv6-20021106.tar.gz
# cd ucspi-tcp+ipv6
# make
# make install

これで qmail を使う前準備完了。

qmail(TLS+IPv6)

ports の mail/qmail はそのままだと IPv6 も使えないし、TLS も使えないので、 IPv6 と TLS を使えるようにします。

ports に mail/qmail-tls というのがあるのでこれをベースにします。 そのままインストールすると TLSは使えるけど IPv6は使えないものが インストールされるが、まずは、TLSが使えることを確認するために そのままインストールします。 そして、qmail-smtpd で TLS が扱えるようになったかを試してみます。

# cd ${PORTSDIR}/mail/qmail-tls
# make
# make install

daemontools と ucspi-tcp を利用して qmail と qmail-smtpd を動かす。 動かす run スクリプトは、 qmail-sendsmtpd。 /usr/local/share/examples/daemontools/svscan.sh.sample を利用しているなら

# mkdir /var/service
# mkdir /var/service/qmail-send
# chmod +t /var/service/qmail-send
# mkdir /var/service/smtpd
# chmod +t /var/service/smtpd
# cp run.qmail-send /var/service/qmail-send/run
# chmod u+x /var/service/qmail-send/run
# cp run.smtpd /var/service/smtpd/run
# chmod u+x /var/service/smtpd/run

とします。 そして、/var/qmail/control/servercert.pem を作ります。

# cd ${PORTSDIR}/mail/qmail-tls
# make certificate

必要事項を入力すると /var/qmail/control/servercert.pem が インストールされます。 sh /usr/local/etc/rc.d/svscan.sh start で qmail一式と qmail-smtpd が 動きだします。 動いたら、telnet localhost 25 としてみて、EHLO localhost を叩くと 250-STARTTLS という行があれば取り敢えず動いていて、 他のホストからメールを受け取ったり、他のホストへメールを送ると、 メールの中に、

Received: from xxx.example.com (XXX.YYY.ZZZ.1)
  by yyy.example.com with DES-CBC3-SHA encrypted SMTP; 8 Nov 2002 08:00:24 -0000

のように、DES-CBC3-SHA encrypted が入っていれば TLS を利用しています。

sylpheed で、「アカウント設定」のSSL で送信(SMTP) を 「SMTPセッションの開始にSTARTTLSコマンドを使用」にチェックをつけて、 SMTPサーバをこの設定にしたホストにして、このホスト宛にメールを 出してみると DES-CBC3-SHA encrypted が入った Received: 行がみられる のではないかと思います。 うまくいかない場合は .sylpheed/sylpheed.log とかみれば原因がつかめるかも しれません。 ちなみに mozilla 1.2b の Mailを使うと、RC4-MD5 encrypted とか入りました。

TLS が利用できるようになったら次は IPv6 も使えるようにします。 qmail の IPv6パッチは qmail-1.03-v6-20021006.diff を利用します。 これを取ってきて、単純に

# cd ${PORTSDIR}/mail/qmail-tls
# make patch
# cd work/qmail-1.03
# patch -p1 < (どっか)/qmail-1.03-v6-20021006.diff

とすると、パッチがうまく当たらないファイルがあります。

# ls *.rej
dns.c.rej               ipalloc.h.rej           qmail-remote.c.rej

この3個のファイルは手パッチします。 そして、mail/qmail-tls/Makefile の中を編集して、

-CFLAGS+=       -I${OPENSSLBASE}/include -L${OPENSSLBASE}/lib -DTLS
+CFLAGS+=       -I${OPENSSLBASE}/include -L${OPENSSLBASE}/lib -DTLS -DINET6 -DTCPTO_REFUSED

IPv6 を有効にします。 これで make すれば TLS+IPv6 対応にはなるので、これを ports にします。

qmail-tls 状態のファイルからIPv6パッチが当たらなかった 3個のファイルの分だけ diff を取ります。そして、 qmail-1.03-v6-20021006.diff からこの3個のファイル分のパッチを 取り除きます。 そしてそれぞれを files の中に置きます。 そして Makefile をいじり slave-ports 側の files内のパッチも当たるように します。ついでに qmail-date-localtime.patch も当てるようにします。 そうして出来たのが、

ports-qmail-tls+ipv6-20021108.tar.gz
MD5 (ports-qmail-tls+ipv6-20021108.tar.gz) = 3a6a65cbf267a209e509120098dd9992

# ls
ports-qmail-tls+ipv6-20021108.tar.gz
# tar xfz ports-qmail-tls+ipv6-20021108.tar.gz
# (cd ${PORTSDIR}/mail && tar cf - qmail) | tar xf - 
# cd qmail-tls+ipv6
# cat distinfo >> ../qmail/distinfo
# make
# make install

そのままやると qmail-tls に上書きしてしまうので、pkg_delete qmail-tls して からやりましょう。

pop3

pop3s の前にまずは pop3 を試します。 ここでは ports の mail/vpopmail を使います。 pop3 before smtp は使わないので WITHOUT_ROAMING=yes に、 CRAM-MD5 とかも使う予定なので WITH_CLEAR_PASSWD=yes にします。 ここでは /etc/make.conf に書いておきます。

# cd ${PORTSDIR}/mail/vpopmail
# make 
# make install
# cd /usr/local/vpopmail/bin
# ./vadddomain mail.example.com XXXX
# ./vadduser hoge@mail.example.com XXXX

/var/service/pop3d/run を用意して、動いてるのを確認すれば pop3 サーバは出来上がり。普通に pop3 でアクセス出来る筈。

pop3s

pop3 ではパスワードはそのまま流れるし、中身もそのままということで、 今回は pop3s を使ってみることに。

pop3s はここでは courier-imap に入っている couriertls を使います。 ports を使って mail/courier-imap をインストールします。

# cd ${PORTSDIR}/mail/courier-imap
# make WITH_VPOPMAIL=yes
# make install

TLSで使う CERTファイルを作ります。 /usr/local/etc/courier-imap/pop3d.cnf.dist に雛型があるので、 それを元に pop3d.cnf を作成して、 /usr/local/share/courier-imap/mkpop3dcert を使って pop3d.pem を作ります。

# cd /usr/local/etc/courier-imap/
# cp pop3d.cnf.dist pop3d.cnf
# vi pop3d.cnf
# cd /usr/local/share/courier-imap/
# ./mkpop3dcert
# ls pop3d.pem
pop3d.pem

出来た pop3d.pem をここでは /var/qmail/control/pop3d.pem としますが、 別にどこに置いてもいいでしょう。 また、/var/qmail/control/servercert.pem を流用してもいいような気も しないではないけど、ここでは各種 CERTファイルは別々に作ります。

pop3s用の run ファイルを作ります。 couriertls が読むCERTファイルの位置や TLSのプロトコルなどの設定も ここに書きます。ここではapopはしてないので、ALLOWPLAIN も設定します。 出来た run ファイルは pop3d-ssl になります。 これをここでは /var/service/pop3d-ssl/run として置いて、 動いているか確認します。

pop3s は 995/tcp を使うので pop3s 対応メーラーで 995/tcp に アクセスするように設定してテストします。 /var/log/maillog に

Nov  8 15:31:09 mail vpopmail[28978]: vchkpw-pop3s: (PLAIN) login success hoge@mail.example.com:192.168.0.1

などのように残れば成功です。tcpdump などでみて、 内容を確認してみると暗号化されているのがわかると思います。

smtp

smtpは TLS を確認したときのと同じ設定でうまくいけると思います。

smtps

TLSに対応しているのでいらないような気もしますが、 ここでは smtps にも対応してみます。

pop3s と同じ方法で smtpd.pem を用意してます。 ただ、/usr/local/share/courier-imap/mksmtpdcert はないので、 ここでは mkpop3dcert を真似てでっちあげ、/usr/local/etc/courier-imap に smtpd.cnf も用意します。 出来た smtpd.pem をここでは /var/qmail/control/smtpd.pem に置きます。

次に couriertls を利用して smtps を実現します。 pop3s と同じように TLS_* の環境変数を設定します。 smtps のポートは 465/tcp を利用します。 couriertls から qmail-smtpd を読んで run ファイルの出来上がりです。 動作しているか確認を取って、smtps に対応しているメーラで ポートを 465/tcp に設定し、メール送信してみます。 うまくいくなら tcpdump などでみて暗号化されているかみて確認してください。

smtp-auth

smtp-auth で認証してみます。 認証モジュールには vpopmail の vchkpw を利用します。 最近のバージョンでは標準で smtp-auth での認証を意識した作りになっていて、 CRAM-MD5 にも対応しているようです。

qmail-smtpd を smtp-auth 対応にするのに、ここでは、 qmail-smtpd-auth-0.31.tar.gzを利用します。

これを TLS+IPv6 した qmail に適用することにする。 qmail-tls+ipv6 で、

# cd qmail-tls+ipv6
# make patch
# cd work/qmail-1.03
# patch -p1 < (どっか)/qmail-smtpd-auth-0.31/auth.patch

とすると、パッチがうまく当たらないファイルがあります。

# ls *.rej
Makefile.rej            qmail-smtpd.c.rej

これらを IPv6 パッチの時と同じように 手パッチして、 これら2個のみを対象にする diff を取って、 auth.patch からこれら2個のパッチを取り除きます。 そうして、それぞれを files にいれて、さらに、 base64.c と base64.h も files にいれます。

Makefile を変更して、 ${PKGDIR_LOCAL}/files/patch-* のパッチを当たるようにし、 base64.* は ${WRKSRC} にコピーするようにします。

それらを ports にして、出来たのが、

ports-qmail-tls-smtpd-auth+ipv6-20021108.tar.gz
MD5 (ports-qmail-tls-smtpd-auth+ipv6-20021108.tar.gz) = 090c9e842e89156b4f412d0fcbf5f5f9

# ls
ports-qmail-tls-smtpd-auth+ipv6-20021108.tar.gz
# tar xfz ports-qmail-tls-smtpd-auth+ipv6-20021108.tar.gz
# (cd ${PORTSDIR}/mail && tar cf - qmail) | tar xf - 
# cd qmail-tls-smtpd-auth+ipv6
# cat distinfo >> ../qmail/distinfo
# make
# make install

これで、smtp-auth に対応した qmail-smtpd が出来たので、 それを使って設定します。

ここでは、普通に 25/tcp で受けている qmail-smtpd はそのままにして、 8025/tcp で smtp-auth を受け付けます。 smtpd を元にして smtpd-auth用の run ファイルを作ります。

認証モジュールには vchkpw を使うので、 qmail-smtpd smtp.example.com vchkpw /bin/true のように run ファイルを 書き換えます。smtp は 8025 にして動かしてみます。

この状態で smtp-auth を利用しようとしてもうまく動作しません。 vchkpwに PATH が通っていないからなので、PATH に /usr/local/vpopmail/bin を 追加します。これでうまくいったかと思いきや、まだ何かが違うようで 調べてみると、vchkpw が 8025 で受けた時に smtp のセッションだということを 理解していないようです。これを理解させるために

--- vchkpw.c.orig       Sat Jun 22 01:05:59 2002
+++ vchkpw.c    Thu Nov  7 13:59:18 2002
@@ -103,45 +103,62 @@
 {
  char *tmpstr;
 
+ char *smtpstr;
+ int smtpPort;
+ char *pop3str;
+ int pop3Port;
+ char *imapstr;
+ int imapPort;
+ char *smtpsstr;
+ int smtpsPort;
+ char *imapsstr;
+ int imapsPort;
+ char *pop3sstr;
+ int pop3sPort;
+
   if ( (IpAddr = getenv("TCPREMOTEIP"))  == NULL) IpAddr="";
   if ( (tmpstr = getenv("TCPLOCALPORT")) == NULL) LocalPort = 110;
   else LocalPort = atoi(tmpstr);
 
+  if ( (smtpstr = getenv("SMTPPORT")) == NULL) smtpPort = 25;
+  else smtpPort = atoi(smtpstr);
+  if ( (pop3str = getenv("POP3PORT")) == NULL) pop3Port = 110;
+  else pop3Port = atoi(pop3str);
+  if ( (imapstr = getenv("IMAPPORT")) == NULL) imapPort = 143;
+  else imapPort = atoi(imapstr);
+  if ( (smtpsstr = getenv("SMTPSPORT")) == NULL) smtpsPort = 465;
+  else smtpsPort = atoi(smtpsstr);
+  if ( (imapsstr = getenv("IMAPSPORT")) == NULL) imapsPort = 993;
+  else imapsPort = atoi(imapsstr);
+  if ( (pop3sstr = getenv("POP3SPORT")) == NULL) pop3sPort = 995;
+  else pop3sPort = atoi(pop3sstr);
+
   /* Check which port they are coming in on and 
    * setup the log name and connection type
    */
-  switch(LocalPort) {
-    case 25:
+  if( LocalPort == 25 || LocalPort == smtpPort ) {
       strcpy(VchkpwLogName, "vchkpw-smtp");
       ConnType = SMTP_CONN;
-      break;
-    case 110:
+  } else if( LocalPort == 110 || LocalPort == pop3Port ) {
       strcpy(VchkpwLogName, "vchkpw-pop3");
       ConnType = POP_CONN;
-      break;
-    case 143:
+  } else if( LocalPort == 143 || LocalPort == imapPort ) {
       strcpy(VchkpwLogName, "vchkpw-imap");
       ConnType = IMAP_CONN;
-      break;
-    case 465:
+  } else if( LocalPort == 465 || LocalPort == smtpsPort ) {
       strcpy(VchkpwLogName, "vchkpw-smtps");
       ConnType = SMTP_CONN;
-      break;
-    case 993:
+  } else if( LocalPort == 993 || LocalPort == imapsPort ) {
       strcpy(VchkpwLogName, "vchkpw-imaps");
       ConnType = IMAP_CONN;
-      break;
-    case 995:
+  } else if( LocalPort == 995 || LocalPort == pop3sPort ) {
       strcpy(VchkpwLogName, "vchkpw-pop3s");
       ConnType = POP_CONN;
-      break;
-    default:
+  } else {
       strcpy(VchkpwLogName, "vchkpw-pop3");
       ConnType = POP_CONN;
-      break;
   }
 
-
   /* read in the user name and password from file descriptor 3 */
   read_user_pass();

として、環境変数 SMTPPORT を設定すれば、そのポートで接続した場合に smtpの接続だと理解出来るようにしました。 run ファイルに SMTPPORT=8025 を追加して試してみると、 まだ駄目なようです。 sylpheed を利用してみて .sylpheed/sylpheed.log を見ると、 認証出来ているように見えるのに何かデバッグメッセージのようなゴミが 記録されています。これを消すとうまくいくようなので

@@ -631,7 +648,6 @@
      h=digest[j] & 0x0f;
      digascii[(2*j)+1]=hextab[h];
    }   
-    printf("digascii: %s, response: %s", digascii, response);
    return(strcmp(digascii,response));
 }

と消してしまいました。先ほどのパッチと合わせたパッチを files にいれて、 作り直してみると、今度はうまくいきました。 そのパッチはpatch-vchkpw.c。 run ファイルは smtpd-auth

# ls
patch-vchkpw.c
# cp patch-vchkpw.c ${PORTSDIR}/mail/vpopmail/files/
# cd ${PORTSDIR}/mail/vpopmail/
# make
# make install

smtp-auth のテストをしてみます。 sylpheed だと 「アカウントの設定」の「送信」で、 認証のところの SMTP認証(SMTP AUTH) にチェックをつけて、 認証方法は自動なり CRAM-MD5 にして チェックをします。 .sylpheed/sylpheed.log をみるとAUTH を使って認証しているのが 分かります。

(2003/07/18): qmail-smtpd-auth-0.31.tar.gzが当たった qmail-smtpd を利用する時に、普通の smtpd なパラメータのままだと、open relay な状態になるらしい。 参考: セキュリティホール memoからpossible open relay hole in qmail-smtpd-auth patch。 なわけで、8025/tcpを利用する smtpd-auth を使う時は、smtp-auth の設定をしてないrunファイル(smtpd) を残しておくのはやめましょう。 smtpd-auth を 25/tcp で受ける用にしても普通のメールは受け取れますので、 8025/tcp でテストがうまくいけば、25/tcp で受けるように変更して、 smtpd-auth を smtpd と差し替えて使った方がよいでしょう。

(2003/11/05): vpopmail-5.3.29 では vchkpw の引数に true があれば smtp-auth。 imap があれば imap の認証 としてポートに関係なく動くようです。 また、不要な printf もコメントアウトされたようなので、 パッチは必要なしに。

次に、smtps でも smtp-auth をしてみます。 これは単に smtps で vchkpw で認証するように変更した run ファイルを用意します。 run ファイルは smtpd-ssl-auth

これも 同じようにテストをします。 smtps を使うように設定してここではポートを 8465 にして、 メールの送信を行なうと確認できます。

imap

courier-imap がすでにインストールされてますが、 vpopmailでの認証するための authvchkpw が cram-md5 に対応してないので、 パッチを 当てて対応させます。WITH_VPOPMAIL だけではなくて、WITH_CRAM も yes にして make します。

インストールが終ったら、動かすための run ファイルを作ります。 ここでは tcpserver を使い、 認証には vpopmail の authlib/authvchkpw を利用します。

作った run ファイルは imapd

動かすとどうもうまくいきません。 何が駄目かと調べると、/usr/local/libexec/courier-imap/authlib/ に authvchkpw がありません。courier-imap をインストールする時に、 WITH_VPOPMAIL=yes をつけたので作っている筈ですが インストールはされていないようです。 本来はパッチを当てて作り直すところですが、疲れてきたので、 cd ${PORTSDIR}/mail/courier-imap/work/courier-imap-1.5.3/authlib/ にある authvchkpw を /usr/local/libexec/courier-imap/authlib/ にコピーします。

# cd ${PORTSDIR}/mail/courier-imap/work/courier-imap-1.5.3/authlib/
# cp authvchkpw /usr/local/libexec/courier-imap/authlib/
# strip /usr/local/libexec/courier-imap/authlib/authvchkpw

これで試してみるとうまくいく筈です。

(2003/02/18): WITH_VPOPMAIL=yes をつけて、authdaemond を動かして、authdaemon で認証可。authvchkpw を作るには、CONFIGURE_ARGS に --without-authdaemon を付ける。

imaps

ここまでやってきたらどうするかはわかると思いますが、 pop3s と同じ方法で couriertls を前に入れて imap を動かします。 作った run ファイルは imapd-ssl

これで imaps 対応のメーラで接続出来ればほとんど完成。

Antivirus

現在、調査中。 参考ページ

さいごに

テストするのにクライアント側には sylpheed を利用するとほとんどのテストが 出来ると思います。自分で普段は使ってないけど。 t-gnus を使ってますが、これでほとんどチェック出来ました。 OutlookExpress とかは SSL を利用出来るけど、どのチェックを入れると 何を使うのかが良く分からない。 しかし、pop3s、imaps、smtps は使えるようです。 mozilla も取り敢えず SSL を使うのは使えそうだけどこれもどのチェックを いれればいいのかわからない。 Becky! は CRAM-MD5 は使えるけども、SSLが全然だめなので pop3 がちょっときつい。今回作ったのに APOP も追加出来ればまぁなんとか。 他は良く分からないけど、sylpheedぐらい他のメーラーも対応してくれて、 TLSを喋るサーバーが増えれば、メールはほとんど暗号化出来るのにと思います。