LoginSignup
0
0

CentOS 5.9のqmailをDKIMやTLSv1.3に対応させてみた

Last updated at Posted at 2024-01-29

今更ながらではあるのだけど、CentOS 5.9などという古のの環境で動くqmail-1.3を今話題のGoogleが突きつけてきた難題「メール送信者のガイドライン」に対応させる必要が出てしまったのでざっくりとその手順を。

結論から言えばqmail-1.3に色々とパッチを当てまくってみたけど、オリジナルのqmailでの対応には失敗して、TLSv1.3対応パッチが施されたnetqmail-1.06のコンパイルとインストールを行うこととなった。
以下の手順はインストール直後のすっぴんなCentOS 5.9で実施した際の手順なので、利用環境によってはそのままでは適用できないかもなのでご容赦を。

Cent OSのリポジトリを修正

※もう随分と昔にCentOS 5はEOLを迎えているのでまずはyumのリポジトリを現在でも生きている環境へと向けてあげる必要があります。

参考データとして自分が使ったyumのリポジトリ設定をあげておきます。
基本はftp.jaist.ac.jpから取得し、epelはftp.iij.ad.jpから取得するようにしました
※yumが古くなり過ぎてssl通信(https//)で取得しようとするとエラーになるので、暗号化なし(https://)で通信可能なミラーサイトから取得するのがミソです

/etc/yum.repos.d/CentOS-Base.repo
# CentOS-Base.repo
#
# The mirror system uses the connecting IP address of the client and the
# update status of each mirror to pick mirrors that are updated to and
# geographically close to the client.  You should use this for CentOS updates
# unless you are manually picking other mirrors.
#
# If the mirrorlist= does not work for you, as a fall back you can try the
# remarked out baseurl= line instead.
#
#

[base]
name=CentOS-$releasever - Base
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=os
#baseurl=http://mirror.centos.org/centos/$releasever/os/$basearch/
baseurl=http://ftp.jaist.ac.jp/pub/Linux/CentOS-vault/5.9/os/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5

#released updates
[updates]
name=CentOS-$releasever - Updates
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=updates
#baseurl=http://mirror.centos.org/centos/$releasever/updates/$basearch/
baseurl=http://ftp.jaist.ac.jp/pub/Linux/CentOS-vault/5.9/updates/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5

#additional packages that may be useful
[extras]
name=CentOS-$releasever - Extras
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=extras
#baseurl=http://mirror.centos.org/centos/$releasever/extras/$basearch/
baseurl=http://ftp.jaist.ac.jp/pub/Linux/CentOS-vault/5.9/extras/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5

#additional packages that extend functionality of existing packages
[centosplus]
name=CentOS-$releasever - Plus
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=centosplus
#baseurl=http://mirror.centos.org/centos/$releasever/centosplus/$basearch/
baseurl=http://ftp.jaist.ac.jp/pub/Linux/CentOS-vault/5.9/centosplus/$basearch/
gpgcheck=1
enabled=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5

#contrib - packages by Centos Users
[contrib]
name=CentOS-$releasever - Contrib
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=contrib
#baseurl=http://mirror.centos.org/centos/$releasever/contrib/$basearch/
baseurl=http://ftp.jaist.ac.jp/pub/Linux/CentOS-vault/5.9/contrib/$basearch/
gpgcheck=1
enabled=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5
/etc/yum.repos.d/epel.repo
[epel]
name=Extra Packages for Enterprise Linux 5 - $basearch
baseurl=http://ftp.iij.ad.jp/pub/linux/Fedora/archive/epel/5/$basearch
#mirrorlist=http://mirrors.fedoraproject.org/mirrorlist?repo=epel-5&arch=$basearch
failovermethod=priority
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL

[epel-debuginfo]
name=Extra Packages for Enterprise Linux 5 - $basearch - Debug
baseurl=http://ftp.iij.ad.jp/pub/linux/Fedora/archive/epel/5/$basearch/debug
#mirrorlist=http://mirrors.fedoraproject.org/mirrorlist?repo=epel-debug-5&arch=$basearch
failovermethod=priority
enabled=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL
gpgcheck=1

[epel-source]
name=Extra Packages for Enterprise Linux 5 - $basearch - Source
baseurl=http://ftp.iij.ad.jp/pub/linux/Fedora/archive/epel/5/SRPMS
#mirrorlist=http://mirrors.fedoraproject.org/mirrorlist?repo=epel-source-5&arch=$basearch
failovermethod=priority
enabled=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL
gpgcheck=1

yumでCentOS 5.9環境標準のperlをインストール

自分の環境では諸々の作業にとりあえずperlとc++が足りないと言われたのでyumでの追加インストールが必要でしたが、環境によっては他にも色々と足りないと言われるでしょうから、適時インストールします

yum install perl

yumでgcc-c++をインストール

sudo yum install gcc-c++

patchの新しいバージョンをインストール

※標準のpachが古くてパッチが充てられない
patchのソースコードはGNU Projectの公式FTPサイトからダウンロードしています。
https://ftp.gnu.org/gnu/patch/

tar -zvxf patch-2.7.6.tar.gz
cd patch-2.7.6
./configure
make
sudo make install

perl-5.10.1をインストール

※なぜならnetqmailのTLSv1.3対応版のコンパイルに必要なopenssl-1.1.1wのビルドに以下の通り新しいperlを要求されるので…
Perlのソースコードも公式サイトのアーカイブ(https://www.cpan.org/src/5.0/)からダウンロードしました
https://www.cpan.org/src/5.0/

openssl-1.1.1wのビルドをするのにConfigureを実行するとperlが古いと言われる

cd openssl-1.1.1w
./Configure
Perl v5.10.0 required--this is only v5.8.8, stopped at ./Configure line 12.
BEGIN failed--compilation aborted at ./Configure line 12.

今のところopensslのConfigureでしか使わないし、面倒なので設定は全てデフォルトで

tar -zvxf perl-5.10.1.tar.gz
cd perl-5.10.1
sh Configure -de
make
make test
sudo make install

最後にmake testでテストをするとたぶんこんな感じにエラーが出るけど無視してインストールする

t/pod/pod2usage2..............................................ok
t/pod/podchkenc...............................................ok
t/pod/poderrs.................................................ok
t/pod/podselect...............................................ok
t/pod/special_seqs............................................ok
t/pod/twice...................................................ok
t/x2p/s2p.....................................................ok
Failed 1 test out of 1609, 99.94% okay.
	../lib/Time/Local.t
### Since not all tests were successful, you may want to run some of
### them individually and examine any diagnostic messages they produce.
### See the INSTALL document's section on "make test".
### You have a good chance to get more information by running
###   ./perl harness
### in the 't' directory since most (>=80%) of the tests succeeded.
### You may have to set your dynamic library search path,
### LD_LIBRARY_PATH, to point to the build directory:
###   setenv LD_LIBRARY_PATH `pwd`; cd t; ./perl harness
###   LD_LIBRARY_PATH=`pwd`; export LD_LIBRARY_PATH; cd t; ./perl harness
###   export LD_LIBRARY_PATH=`pwd`; cd t; ./perl harness
### for csh-style shells, like tcsh; or for traditional/modern
### Bourne-style shells, like bash, ksh, and zsh, respectively.
u=3.33  s=3.62  cu=215.65  cs=41.03  scripts=1609  tests=226458
make[2]: *** [_test_tty] エラー 1
make[2]: ディレクトリ `/usr/local/src/perl-5.10.1' から出ます
make[1]: *** [_test] エラー 2
make[1]: ディレクトリ `/usr/local/src/perl-5.10.1' から出ます
make: *** [test] エラー 2

エラーは無視してインストール

sudo make install

本題のopenssl-1.1.1wのインストール

OpenSSLも公式サイトから1.1.1系の最新をダウンロードしましたダウンロードしました
https://www.openssl.org/source/

※Configure(perlスクリプト)の実行には先程ビルドした/usr/local/bin/perlを使う

cd openssl-1.1.1w
/usr/local/bin/perl ./Configure shared linux-x86_64
make
sudo make install

インストールしたopenssl-1.1.1wの共有ライブラリが使われるようにld.so.confを調整

/etc/ld.so.conf.d/openssl.conf
/usr/local/lib64

ld.so.confの設定を反映

sudo /sbin/ldconfig

TLS対応パッチ適用ずみのnetqmail-1.06(smtp-auth + qmail-tls + forcetls patch for qmail)をインストール

smtp-auth + qmail-tls + forcetls patch for qmailをインストール
ソースコードはGithubのリポジトリより取得
https://notes.sagredo.eu/qmail-notes-185/smtp-auth-qmail-tls-forcetls-patch-for-qmail-84.html

cd /usr/local/src
unzip qmail-auth-tls-forcetls-main.zip
cd qmail-auth-tls-forcetls-main

qmailのユーザーとグループを作成

すでにqmailを導入済みの環境ではユーザーとグループは存在するはずなので不要な作業だが、もし新規にインストールする場合にはqmailをビルドするのに先立ちユーザーとグループを作っておかないとビルドに失敗する

sudo mkdir /var/qmail 
sudo /usr/sbin/groupadd nofiles
sudo /usr/sbin/useradd -g nofiles -d /var/qmail/alias alias
sudo /usr/sbin/useradd -g nofiles -d /var/qmail qmaild
sudo /usr/sbin/useradd -g nofiles -d /var/qmail qmaill
sudo /usr/sbin/useradd -g nofiles -d /var/qmail qmailp
sudo /usr/sbin/groupadd qmail
sudo /usr/sbin/useradd -g qmail -d /var/qmail qmailq
sudo /usr/sbin/useradd -g qmail -d /var/qmail qmailr
sudo /usr/sbin/useradd -g qmail -d /var/qmail qmails

先にビルドしておいたopenssl-1.1.1wが使われるようにnetqmailのビルド設定を変更

conf-cc
cc -O2 -g -DEXTERNAL_TODO -DTLS=20231230 -I/usr/local/include

This will be used to compile .c files.
conf-ld
cc -s -L/usr/local/lib64

This will be used to link .o files into an executable.

ビルドしたqmailをインストール

make
sudo make setup check
sudo ./install
sudo ./instcheck

qmailの初期設定ファイルを/var/qmail/controlに設定

sudo ./config-fast <送信元ドメイン名>
Your fully qualified host name is hoge.hoge.net.
Putting hoge.hoge.net into control/me...
Putting hoge.net into control/defaultdomain...
Putting hoge.net into control/plusdomain...
Putting hoge.hoge.net into control/locals...
Putting hoge.hoge.net into control/rcpthosts...
Now qmail will refuse to accept SMTP messages except to hoge.hoge.net.
Make sure to change rcpthosts if you add hosts to locals or virtualdomains!
[root@msl-backup qmail-auth-tls-forcetls-2024.01.15]#

qmailをサービス化するためのucspi-tcpを(tcpserver)インストール

ucspi-tcpはこちらからダウンロード
http://cr.yp.to/ucspi-tcp/ucspi-tcp-0.88.tar.gz

tcpserverをSSLに対応させるパッチを追加
tcpserverをSSLに対応させるパッチはこちらのサイト(NRG4U)からダウンロードしてきます

パッチファイルはこちらからダウンロードしました
http://www.nrg4u.com/qmail/ucspi-tcp-ssl-20050405.patch.gz

以下の3本のパッチファイルはnetqmail-1.06のソースツリーのother-patchesディレクトリ以下に入っている

  • ucspi-tcp-0.88.a_record.patch
  • ucspi-tcp-0.88.errno.patch
  • ucspi-tcp-0.88.nodefaultrbl.patch

ソースコードを展開しSSL対応パッチ他を適用

cd /usr/local/src
tar -zvxf ucspi-tcp-0.88.tar.gz
cd ucspi-tcp-0.88
patch -p1 < ../ucspi-tcp-0.88.a_record.patch
patch -p1 < ../ucspi-tcp-0.88.errno.patch
patch -p1 < ../ucspi-tcp-0.88.nodefaultrbl.patch
zcat ../ucspi-tcp-ssl-20050405.patch.gz | patch -p0

Makefileで先にインストールしたopenssl-1.1.1wが使われるように修正

Makefile
--- Makefile.old	2024-01-26 18:36:51.000000000 +0900
+++ Makefile	2024-02-02 18:46:15.000000000 +0900
@@ -4,8 +4,8 @@
 #add -DWITH_SSL to enable ssl support

 # LIBS for additional libraries and INCS for additional includes
-LIBS=-lcrypto -lssl
-#INCS=-I/usr/local/include
+LIBS=-L/usr/local/lib64 -lcrypto -lssl
+INCS=-I/usr/local/include
 OPENSSLBIN=openssl

 SHELL=/bin/sh

ビルドしてインストール

make
sudo make setup check 

tcpserver用の設定ファイルを作成
※設定内容は自身の環境に合わせて!

/etc/tcp.smtp
192.168.:allow,RELAYCLIENT=""
127.:allow,RELAYCLIENT=""

tcpserver用の設定ファイルを反映

sudo /usr/local/bin/tcprules /etc/tcp.smtp.cdb /etc/tcp.smtp.tmp < /etc/tcp.smtp

tcpserver用のSSL証明書を準備

tcpserver(ucspi-tcp-ssl)では秘密鍵と証明書(CAの証明書があればそれも)を一つにまとめたファイルを読み込んで利用するのでこれを用意します
自分の環境ではLet's Encryptで発行したSSL証明書を使っているので以下のように秘密鍵とCAの証明書、自局の証明書をcatで一つに結合して作成しました

秘密鍵と証明書を結合

sudo cat /etc/letsencrypt/live/mydomain.domain.tld/privkey.pem /etc/letsencrypt/live/mydomain.domain.tld/fullchain.pem > servercert.pem

servercert.pemを所定の場所(デフォルトではqmailの設定ディレクトリ)に移動
※作成したservercert.pemには機密情報である秘密鍵が含まれているのでコピーではなくmvで移動しています
またchownとchmodを使い、rootとqmail以外からは読み取れないようにしました

sudo mv servercert.pem /var/qmail/control/servercert.pem
sudo chown root:qmail /var/qmail/control/servercert.pem
sudo chmod 640 /var/qmail/control/servercert.pem

qmailの起動スクリプトを(存在しないなら)作成
※たぶん普通はすでにどこかにある

この起動スクリプトの場合には/var/qmail/boot/homeファイルへのシンボリックリンクを/var/qmail/rcとして作成済みを想定しているので、以下のようにシンボリックリンクを/var/qmail/rcに作成した

sudo ln -sf /var/qmail/boot/home /var/qmail/rc

サービス起動スクリプト

/etc/rc.d/init.d/qmail
#!/bin/sh
#
# qmail: /var/qmail
PATH=/var/qmail/bin:/usr/local/bin:/bin:/usr/bin
#FORCETLS=0
[ -f /var/qmail/rc ] || exit 0
case "$1" in
  start)
        # Start daemons.
        echo "Starting qmail."
        csh -cf '/var/qmail/rc &'
        tcpserver -v -u <qmaildのUID> -g <nofilesのGID> -x /etc/tcp.smtp.cdb \
       0 smtp /var/qmail/bin/qmail-smtpd 2>&1 | /var/qmail/bin/splogger smtpd 3 &
        echo
        touch /var/lock/qmail
        ;;
  stop)
        # Stop daemons.
        echo "Shutting down qmail."
        PID=`/bin/ps -aefw | grep qmail | awk '{print $2}'`
        if [ ! -z "$PID" ] ;  then
            /bin/kill ${PID} 1> /dev/null 2>&1
        fi
        echo
        rm -f /var/lock/qmail
        ;;
   *)
        echo "Usage: S99qmail {start|stop}"
        exit 1
esac
exit 0

qmailとtcpserverをサービスとして起動する

sudo /sbin/service qmail start

opensslを使いtcpserverで設定したSSL証明書が使われているか確認する

(192.168.xxx.xxxはqmailサービスを起動したサーバーのIPアドレス)

openssl s_client -connect 192.168.xxx.xxx:25 -starttls smtp -ign_eof

コンソールにSSL証明書の内容(有効期限やコモンネームなど)が表示されれば正しくSSL証明書が読み込まれている

CONNECTED(00000004)
Can't use SSL_get_servername
depth=2 C = US, O = Internet Security Research Group, CN = ISRG Root X1
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=1 C = US, O = Let's Encrypt, CN = R3
verify return:1
depth=0 CN = mydomain.domain.tld
verify return:1
---
...などなど...

※コンソールにread R BLOCKが出たら^Cなどで停止

testssl.shを使ったTLSの動作確認

念を入れるなら、この記事で紹介されているtestssl.shなどを使い、サポートされているプロトコルのバージョンなども要求通りになっているか確認しておくと良いでしょう
自分の場合はtestssl.shGithubのリポジトリから最新版をmacOS上で取得して利用しました

(192.168.xxx.xxxはqmailサービスを起動したサーバーのIPアドレス)

git clone --depth 1 https://github.com/drwetter/testssl.sh.git
cd testssl.sh
./testssl.sh -t smtp 192.168.xxx.xxx:25
kazu@VM-Host testssl.sh % ./testssl.sh -t smtp 192.168.xxx.xxx:25

###########################################################
    testssl.sh       3.2rc3 from https://testssl.sh/dev/
    (c30e541 2024-02-02 20:25:46)

      This program is free software. Distribution and
             modification under GPLv2 permitted.
      USAGE w/o ANY WARRANTY. USE IT AT YOUR OWN RISK!

       Please file bugs @ https://testssl.sh/bugs/

###########################################################

 Using "OpenSSL 1.0.2-bad (1.0.2k-dev)" [~183 ciphers]
 on VM-Host:./bin/openssl.Darwin.x86_64
 (built: "Sep  3 14:46:36 2022", platform: "darwin64-x86_64-cc")


 Start 2024-02-04 09:13:37                -->> 192.168.xxx.xxx:25 (192.168.xxx.xxx) <<--

 rDNS (192.168.xxx.xxx):  --
 Service set:            STARTTLS via SMTP

 Testing protocols via sockets

 SSLv2      not offered (OK)
 SSLv3      likely not offered (OK), received 4xx/5xx after STARTTLS handshake, rerun with DEBUG>=2 or --ssl-native
 TLS 1      offered (deprecated)
 TLS 1.1    offered (deprecated)
 TLS 1.2    offered (OK)
 TLS 1.3    offered (OK): final

wget-1.21をインストール

これはメール送信のローカルテストに便利なのでインストールしたけど、運用には必要はないです
wgetもGNU Projctの公式FTPサイトからダウンロードしました
(CentOS 5.9の標準でインストールできるwgetではsslの暗号化プロトコルが合わないのでhttp://でのダウンリロードが必要でした)

cd /usr/local/src
tar -zvxf wget-1.21.tar.gz
cd wget-1.21
./configure --with-ssl=openssl --with-libssl-prefix=/usr/local
make CFLAGS=-std=c99
sudo make install

Let,s encryptなどのCA証明書(中間認証局の証明書)が必要なサイトの中間証明書が記録されたファイルの最新版を以下のサイトからダウンロード
https://curl.se/docs/caextract.html

先程インストールされたwgetを使うが、今まさにダウンロードするファイルがないと相手側を信頼できないのでオプションに--no-check-certificateを付けて検証をスキップ

/usr/local/bin/wget --no-check-certificate https://curl.se/ca/cacert-2023-12-12.pem

ダウンロードしたCA証明書を所定の場所に移動

sudo mkdir -p /usr/local/ssl/certs/
sudo mv cacert-2023-12-12.pem /usr/local/ssl/certs/ca-certificates.crt

インストールしたwgetがCA証明書を使うように設定

~/.wgetrc
ca_certificate=/usr/local/ssl/certs/ca-certificates.crt

curl-8.5.0をインストール

これもローカルテストに便利なのでインストールしたけど、運用には必要はないです
ソースコードはcurlの公式サイト(https://curl.se/download.html)からダウンロードしました

cd /usr/local/src
tar -zvxf curl-8.5.0
cd curl-8.5.0
./configure --with-openssl=/usr/local --with-ca-bundle=/usr/local/ssl/certs/ca-certificates.crt
make
sudo make install

インストールしたcurlを使ってメール送信のテストをしてみる

cd ~/qmail_dkim_test
 /usr/local/bin/curl -v --url 'smtp://<qmailサーバー>' --mail-from <送信元メールアドレス> --mail-rcpt <送信元メールアドレス> --upload-file mail_txt

mail_txtにはこんな感じでテストメールの中身を書き込む
※メール本文は改行コードがCRLFであることに注意! (nkf -Lwとかで変換すると良い)

From:  <送信元メールアドレス>
To: <送信元メールアドレス>
Subject: an msl-build example email
Date: Thu Jan 25 22:30:47 PST 2024

Dear Joe,
Welcome to this example email. What a lovely day.

もし送信相手がDKIMやSFP、DMARCなどの情報を設定済みでDNSのレスポンスが512バイトを超えるようだとqmailがエラー'CNAME_lookup_failed_temporarily..,'を吐くのでログを確認してみる

/var/log/maillog
Jan 25 22:38:35 msl-build qmail: 1706251115.405085 info msg 585532: bytes 415 from <john_doe@my.domain.dom> qp 11617 uid 491
Jan 25 22:38:35 msl-build qmail: 1706251115.410840 starting delivery 1: msg 585532 to remote someone@remote.domain.dom
Jan 25 22:38:35 msl-build qmail: 1706251115.410975 status: local 0/10 remote 1/20
Jan 25 22:38:35 msl-build qmail: 1706251115.905974 delivery 1: deferral: CNAME_lookup_failed_temporarily._(#4.4.3)/
Jan 25 22:38:35 msl-build qmail: 1706251115.906140 status: local 0/10 remote 0/20
Jan 25 22:41:05 msl-build qmail: 1706251265.400220 status: exiting
Jan 25 22:41:09 msl-build qmail: 1706251269.030761 status: local 0/10 remote 0/20

この問題(DNSのレスポンスが512バイトを超えるとエラーになる)を解消するためのパッチqmail-103.patchが存在するので、これをqmail-auth-tlsに適用する
http://www.ckdhr.com/ckd/qmail-103.patch

qmail-103.patch (DNSのレスポンスが512バイトを超えてもエラーにならないようにする)を充ててqmailを再ビルド、インストール

cd qmail-auth-tls-forcetls-main
/usr/local/bin/patch -p1 < ../qmail-103.patch
make
sudo service qmail stop
sudo make setup check
sudo service qmail start

もう一度テストメールを送ってちゃんと送れればOK

cd qmail_dkim_test
/usr/local/bin/curl -v --url 'smtp://<qmailサーバー>' --mail-from <送信元メールアドレス> --mail-rcpt <送信元メールアドレス> --upload-file mail_txt

メール送信テストをqmailをインストールしたサーバーで行うなら、以下のようなスクリプトを使い(手動でもOKですか)qmail-inject経由でメール送信をテストすることもできます

qmail-inject経由でのメール送信をテスト

send_test_mail.sh
#!/bin/sh

smtp_host=`hostname`
from_user=`whoami`
from_domain=`cat /var/qmail/control/defaultdomain | head -1`
to_mail_address=[テストメール送信先]
send_date=`LANG=C date`
date_string=`date '+%Y%m%d'`
meessage_id=${date_string}${from_user}\@${from_domain}
mail_txt=`mktemp -p /tmp -t mail.XXXXXXXXXXXXXXX`

cat << EOT > ${mail_txt}
From: ${from_user}@${from_domain}
Reply-To: noreply-appledev@${from_domain}
To: ${to_mail_address}
Subject: an msl-build example email
Date: ${send_date}
Message-ID: <${meessage_id}>

Dear Joe,
Welcome to this example email. What a lovely day.

EOT

cat ${mail_txt} | /var/qmail/bin/qmail-inject
rm -f ${mail_txt}

ここまでがTLSv1.3をサポートするqmail(netqmail)のインストールなので、ここまでの動作が確認できればあとはDNSへのTXTレコードの設定や証明書の取得、DKIMを有効化するスクリプトの設定を行えばDKIMも有効になります

DKIMへの対応

qmail(netqmail)のDKIM対応についてはGithubのこちらの記事を参考にさせて頂きました。
Githubの参考記事
https://github.com/corokada/return-qmail/blob/master/qmail-dkim.md

具体的な手順としては「2.perlのDKIMモジュールをインストール」は記事のとおりyumを使いperl-Mail-DKIMのインストールを行います。

sudo yum install perl-Mail-DKIM --nogpgcheck

※自分の環境では証明書の期限切れでインストールにはyumのオプション--nogpgcheckが必要でした

openssl-1.0.2uのインストール

ここまでの手順ですでに新しいopenssl-1.1.1wがインストール済みなのだけどlibdomainkeysとの互換性がないので手を抜いて古いopenssl-1.0.2uもインストールします
古いOpenSSLのアーカイブ
https://ftp.openssl.org/source/old/1.0.2/

(ここでは個人的好みで/usr/local/opensslにインストールした)

cd /usr/local/src
tar -zvxf openssl-1.0.2u.tar.gz
cd openssl-1.0.2u
./Configure shared linux-x86_64 --prefix=/usr/local/openssl
make

出来上がったライブラリをインストール

sudo make install
ls /usr/local/openssl/
bin  certs  include  lib  man  misc  openssl.cnf  private

#### 「3.libdomainkeysをインストール」

cd /usr/local/src
tar -zvxf libdomainkeys-0.69.tar.gz
cd libdomainkeys-0.69

先ほどインストールしたちょっとバージョンの古いopenssl-1.0.2uが使われるようにMakefileを一部修正します

libdomainkeys-0.69-Makefile.patch
--- Makefile.orig	2006-01-17 16:28:58.000000000 -0800
+++ Makefile	2024-01-21 22:43:26.000000000 -0800
@@ -2,8 +2,8 @@
 CFLAGS=-DBIND_8_COMPAT -O2
 #CFLAGS += -DDK_DEBUG -DDK_HASH_BUFF -Wall
 #CFLAGS += -DUNIXWARE
-INCS=-I.
-LIBS=-L. -ldomainkeys -lcrypto
+INCS=-I. -I/usr/local/openssl/include
+LIBS=-L. -L/usr/local/openssl/lib -ldomainkeys -lcrypto
 MAKE=make

 dktest: dktest.o libdomainkeys.a dns.lib socket.lib
patch -p0 < libdomainkeys-0.69-Makefile.patch
echo -lresolv > dns.lib
make
sudo install -m 644 libdomainkeys.a /usr/local/lib
sudo install -m 644 domainkeys.h dktrace.h /usr/local/include
sudo install -m 755 dknewkey /usr/local/bin

「4.libdkimをインストール」

ここではいくつか注意が必要で、Makefileと設定ファイルの一部を直さないとソースコードと互換性のあるライブラリが使われないので修正します

cd /usr/local/src
unzip libdkim-1.0.19.zip
cd libdkim/src/
/usr/local/bin/patch -p2 --binary < ../../libdkim-1.0.19-linux.patch
/usr/local/bin/patch -p2 --binary < ../../libdkim-1.0.19-extra-options.patch
libdkim-1.0.19-Makefile.patch
--- Makefile.prev	2024-01-28 23:41:41.000000000 -0800
+++ Makefile	2024-01-29 00:00:58.000000000 -0800
@@ -1,9 +1,9 @@
 # libdkim makefile for UNIX
 #

-DESTDIR ?= /
+DESTDIR ?= /usr/local

-CFLAGS  += -fPIC
+CFLAGS  += -fPIC -I/usr/local/openssl/include
 LIBS    = -lcrypto -lresolv

 INCL	=  -I /usr/include/openssl/
@@ -30,7 +30,7 @@

 libdkimtest : libdkim.so.1 libdkimtest.o
 	$(CXX) -o$@ $(LDFLAGS) \
-	       -L. libdkimtest.o $(LIBS) -ldkim
+	       -L. libdkimtest.o  -L/usr/local/openssl/lib $(LIBS) -ldkim

 libdkimtest.o: libdkimtest.cpp $(HDRS)

@@ -39,10 +39,10 @@
 	rm -f *.o libdkim.{a,so,so.1} libdkimtest

 install: all
-	install -D -m 0755 libdkim.so.1 $(DESTDIR)/usr/lib/libdkim.so.1
-	ln -s libdkim.so.1 $(DESTDIR)/usr/lib/libdkim.so
-	ln -s libdkim.so.1 $(DESTDIR)/usr/lib/libdkim.so.1.1
-	install -D -m 0644 dkim.h $(DESTDIR)/usr/include/dkim.h
-	install -D -m 0755 libdkimtest $(DESTDIR)/usr/bin/libdkimtest
+	install -D -m 0755 libdkim.so.1 $(DESTDIR)/lib/libdkim.so.1
+	ln -s libdkim.so.1 $(DESTDIR)/lib/libdkim.so
+	ln -s libdkim.so.1 $(DESTDIR)/lib/libdkim.so.1.1
+	install -D -m 0644 dkim.h $(DESTDIR)/include/dkim.h
+	install -D -m 0755 libdkimtest $(DESTDIR)/bin/libdkimtest

patch -p0 < libdkim-1.0.19-Makefile.patch
make
sudo make install

「5.DKIM署名・検証スクリプトをダウンロード」

DKIM署名・検証スクリプトのダウンロードも参考記事のはそのままで問題ありませんが、自分の場合は以下のようにwgetで一旦作業ディレクトリへと必要なファイルをダウンロードしてから所定の場所へとそれをコピーする手順に変更しました
また、オリジナルではwgetにオプション--no-check-certificateを付加して証明書の検証をスキップしていますが、せっかく新しいwgetとCAの証明書リストをインストールしたのでそれ(/usr/local/bin/wget)を使い--no-check-certificateは削除しています

cd /usr/local/src
mkdir qmail_dkim_scripts
cd qmail_dkim_scripts
/usr/local/bin/wget https://github.com/corokada/return-qmail/raw/master/dkimsign.pl
/usr/local/bin/wget https://github.com/corokada/return-qmail/raw/master/dkimverify.pl
sudo cp ./dkimsign.pl /var/qmail/bin/dkimsign.pl
sudo chmod +x /var/qmail/bin/dkimsign.pl
sudo chgrp qmail /var/qmail/bin/dkimsign.pl
sudo cp ./dkimverify.pl /var/qmail/bin/dkimverify.pl
sudo chmod +x /var/qmail/bin/dkimverify.pl
sudo chgrp qmail /var/qmail/bin/dkimverify.pl
sudo sed -i -e "s/example.com/hogehoge.jp/" /var/qmail/bin/dkimverify.pl

「6.DKIM署名をする際の作業ディレクトリを作成」

参考記事のままで問題ありませんでした

sudo mkdir -p /var/domainkeys
sudo chown qmailr:qmail /var/domainkeys
sudo chmod 0700 /var/domainkeys

「7.DKIM検証をする際の作業ディレクトリを作成」

ではディレクトリのオーナーをrootではなくqmaildに変更しないとこの後インストールするqmail-dkimverifyでの受信したメールのDKIM署名の確認に失敗します

sudo mkdir -p /var/domainkeys-verify
sudo chown qmaild.root /var/domainkeys-verify
sudo chmod 0700 /var/domainkeys-verify

「8.メール送信時にDKIM署名を行うwrapperをダウンロード」

ここも参考記事のままで問題ありませんでしたが、自分の場合は以下のようにwgetで一旦作業ディレクトリへと必要なファイルをダウンロードしてから所定の場所へとそれをコピーする手順に変更しました
※また、1行目のmv /var/qmail/bin/qmail-remote /var/qmail/bin/qmail-remote.orig の処理は単なるオリジナルのqmail-remoteのバックアップではなく、新しくコピーされるWarapperスクリプトからこのオリジナルファイルが呼び出されるので、移動の先は必ず/var/qmail/bin/qmail-remote.origである必要があります

sudo mv /var/qmail/bin/qmail-remote /var/qmail/bin/qmail-remote.orig
/usr/local/bin/wget https://github.com/corokada/return-qmail/raw/master/qmail-remote
sudo cp ./qmail-remote /var/qmail/bin/qmail-remote 
sudo chown root:qmail /var/qmail/bin/qmail-remote
sudo chmod 0755 /var/qmail/bin/qmail-remote

余談ですが、mv/var/qmail/bin/qmail-remote/var/qmail/bin/qmail-remote.origへと移動するのに先立ってfileコマンドなどで/var/qmail/bin/qmail-remoteがすでにWarapperスクリプトに置き換えられていないか確認した方が良いでしょう

sudo file /var/qmail/bin/qmail-remote
/var/qmail/bin/qmail-remote: ELF 64-bit LSB executable, AMD x86-64, version 1 (SYSV), for GNU/Linux 2.6.9, dynamically linked (uses shared libs), stripped

となれば/var/qmail/bin/qmail-remoteはオリジナルのファイルですが、

sudo file /var/qmail/bin/qmail-remote
/var/qmail/bin/qmail-remote: Bourne shell script text executable

となってしまったらすでに/var/qmail/bin/qmail-remoteはWarapperスクリプトに置き換えられてしまっているので、これを/var/qmail/bin/qmail-remote.origへと移動してしまうと元の実行ファイルが無くなってしまいます

追記:

DKIM署名をするためのperlスクリプト(qmail-remote)に不具合あり送信元メールアドレスがサブドメインだと署名されないようです

こんな感じにWarapperスクリプトqmail-remoteにデバッグを仕込んで試してみました

qmail-remote
#!/bin/sh

#
# DKIM signing for qmail
#
# permissions must be 0755
#
# Author: Joerg Backschues
#

[ "$DKSIGN" ]   || DKSIGN="/etc/domainkeys/%/default"
[ "$DKREMOTE" ] || DKREMOTE="/var/qmail/bin/qmail-remote.orig"

# parent domains (see RFC 4871 3.8)

FQDN=${2##*@}
TLD=`echo $FQDN | awk 'BEGIN {FS = "."} {print $NF}'`
DOM=`echo $FQDN | awk 'BEGIN {FS = "."} {print $(NF-1)}'`
echo FQDN=$FQDN
echo TLD=$TLD
echo DOM=$DOM

# get domainkey file

if [[ $DKSIGN == *%* ]] ; then
    DOMAIN=$DOM.$TLD
    DKSIGN="${DKSIGN%%%*}${DOMAIN}${DKSIGN#*%}"
fi
echo DOMAIN=$DOMAIN
echo DKSIGN=$DKSIGN

if [ -f "$DKSIGN" ] ; then
  echo GO

サブドメインがなければOK

./qmail-remote remote.mail.dom me@domain.dom you@your.domain.dom
FQDN=domain.dom
TLD=dom
DOM=domain
DOMAIN=domain.dom
DKSIGN=/etc/domainkeys/domain.dom/default
GO

サブドメインがあると動かない

./qmail-remote remote.mail.dom me@sub.domain.dom you@your.domain.dom
FQDN=sub.domain.dom
TLD=dom
DOM=domain
DOMAIN=domain.dom
DKSIGN=/etc/domainkeys/domain.dom/default

qmail-remoteの修正箇所

qmail-remote.patch
--- qmail-remote	2024-01-22 23:29:22.000000000 -0800
+++ /var/qmail/bin/qmail-remote	2024-01-24 17:23:07.000000000 -0800
@@ -12,17 +12,23 @@
 [ "$DKREMOTE" ] || DKREMOTE="/var/qmail/bin/qmail-remote.orig"

 # parent domains (see RFC 4871 3.8)
-
-FQDN=${2##*@}
-TLD=`echo $FQDN | awk 'BEGIN {FS = "."} {print $NF}'`
-DOM=`echo $FQDN | awk 'BEGIN {FS = "."} {print $(NF-1)}'`
+# 多分RFC 4871の解釈が間違っていて送信元メールアドレスにサブドメインがあると
+# 送信元メールアドレスからドメインがうまく取れない
+#FQDN=${2##*@}
+#TLD=`echo $FQDN | awk 'BEGIN {FS = "."} {print $NF}'`
+#DOM=`echo $FQDN | awk 'BEGIN {FS = "."} {print $(NF-1)}'`

 # get domainkey file

 if [[ $DKSIGN == *%* ]] ; then
-    DOMAIN=$DOM.$TLD
+    # 先のコメントと同様
+    #DOMAIN=$DOM.$TLD
+    DOMAIN=${2##*@}
     DKSIGN="${DKSIGN%%%*}${DOMAIN}${DKSIGN#*%}"
 fi
+# デバック用なので消して!
+echo DOMAIN=$DOMAIN >> /tmp/qmail_args.log
+echo DKSIGN=$DKSIGN >> /tmp/qmail_args.log

 if [ -f "$DKSIGN" ] ; then

ただし、RFC 4871の節3.8に書かれているようにサブドメインの場合には「親ドメインによる署名」を行うのであれば私の修正でも問題はあるのだが、その場合でもこのコードのTLDとDOMの取得方法は間違っていて、これだとdom.co.jpのようなドメイン(ccTLD)には対応できない

3.8. Signing by Parent Domains
3.8. 親ドメインによる署名
In some circumstances, it is desirable for a domain to apply a signature on behalf of any of its subdomains without the need to maintain separate selectors (key records) in each subdomain. By default, private keys corresponding to key records can be used to sign messages for any subdomain of the domain in which they reside; e.g., a key record for the domain example.com can be used to verify messages where the signing identity ("i=" tag of the signature) is sub.example.com, or even sub1.sub2.example.com. In order to limit the capability of such keys when this is not intended, the "s" flag may be set in the "t=" tag of the key record to constrain the validity of the record to exactly the domain of the signing identity. If the referenced key record contains the "s" flag as part of the "t=" tag, the domain of the signing identity ("i=" flag) MUST be the same as that of the d= domain. If this flag is absent, the domain of the signing identity MUST be the same as, or a subdomain of, the d= domain. Key records that are not intended for use with subdomains SHOULD specify the "s" flag in the "t=" tag.

状況によっては、ドメインがサブドメインごとに個別のセレクター(キーレコード)を維持する必要なしに、サブドメインの代わりに署名を適用することが望ましい場合があります。デフォルトでは、鍵レコードに対応する秘密鍵を使用して、それらが存在するドメインの任意のサブドメインのメッセージに署名できます。たとえば、ドメインexample.comのキーレコードを使用して、署名ID(署名の「i =」タグ)がsub.example.com、さらにはsub1.sub2.example.comであるメッセージを検証できます。これが意図されていない場合にこのようなキーの機能を制限するには、キーレコードの「t =」タグに「s」フラグを設定して、レコードの有効性を署名IDのドメインに限定します。参照されたキーレコードに "t ="タグの一部として "s"フラグが含まれている場合、署名IDのドメイン( "i ="フラグ)はd =ドメインのドメインと同じである必要があります。このフラグが存在しない場合、署名IDのドメインは、d =ドメインと同じか、そのサブドメインでなければなりません(MUST)。サブドメインでの使用を目的としていないキーレコードは、「t =」タグに「s」フラグを指定する必要があります(SHOULD)。

「9.メール受信時にDKIM検証を行うwrapperをダウンロード」

参考記事のままで問題ありませんでしたが、自分の場合は以下のようにwgetで一旦作業ディレクトリへと必要なファイルをダウンロードしてから所定の場所へとそれをコピーする手順に変更しました

/usr/local/bin/wget https://raw.githubusercontent.com/corokada/return-qmail/master/qmail-dkimverify
sudo cp qmail-dkimverify /var/qmail/bin/qmail-dkimverify
sudo chown root:qmail /var/qmail/bin/qmail-dkimverify
sudo chmod 0755 /var/qmail/bin/qmail-dkimverify

「10.QMAILQUEUEを利用できるようにする」

QMAILQUEUEの利用についてはパッチずみのnetqmail-1.06(smtp-auth + qmail-tls + forcetls patch for qmail)ではすでに適用済みなのでスキップしました

「11.QMAILQUEUEを設定する」

QMAILQUEUEを利用する設定は先にインストール済みのucspi-tcp-0.88(tcpserver)の設定にメール受信時に受信メールのDKIM署名検証スクリプト/var/qmail/bin/qmail-dkimverifyを呼び出す設定を追加します

tcpserver用の設定ファイルを作成

最後の1行が受信したメールのDKIM署名を検証してその結果をキューに入れるのに必要
※そのほかの設定内容は自身の環境に合わせて!

/etc/tcp.smtp
192.168.:allow,RELAYCLIENT=""
127.:allow,RELAYCLIENT=""
:allow,QMAILQUEUE="/var/qmail/bin/qmail-dkimverify"
tcpserver用の設定ファイルを反映
sudo /usr/local/bin/tcprules /etc/tcp.smtp.cdb /etc/tcp.smtp.tmp < /etc/tcp.smtp

「12.DKIM署名用の秘密鍵を保存するディレクトリを作成」

参考記事のままで問題ありませんでした

sudo mkdir -p /usr/local/etc/domainkeys
sudo ln -s /usr/local/etc/domainkeys /etc/domainkeys

「13.DKIM署名用の秘密鍵を作成するShellをダウンロード」

これも参照記事のとおりですが、自分の場合は以下のようにwgetで一旦作業ディレクトリへと必要なファイルをダウンロードしてから所定の場所へとそれをコピーする手順に変更しました

cd /usr/local/src
cd qmail_dkim_scripts
/usr/local/bin/wget https://github.com/corokada/return-qmail/raw/master/dkim_keygen.sh
chmod +x ./dkim_keygen.sh

「14.秘密鍵を作成」

これも参照記事のままで問題ないのでスクリプトを実行しDKIM署名用の秘密鍵を生成します

sudo ./dkim_keygen.sh [ドメイン名]

以下のような感じでDNSサーバーにDKIM署名のレコードを追加するように指示されるのでそれを実行し、

example.domain.tld DNS records adding sample
default._domainkey	IN	TXT	"k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8…"
_adsp._domainkey	IN	TXT	"dkim=unknown"

あとは参考記事のとおりメールの送受信テストをすれば完了です

0
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0