プログラマーのメモ書き

伊勢在住のプログラマーが気になることを気ままにメモったブログです

Roundcube の立ち上げ:暗号化接続を有効化 (1/3)

あれこれ検討しましたが、こちらの記事でまとめたように、ブラウザベースのメールクライアントとして、 Roundcube を使うことにしました。

試用の際は、問題があったら避けるようにしたのですが、今度は試用ではないので、もうちょっとちゃんと対応して、しっかりと使えるようにしたいと思います。

まずは、メールサーバーに接続する際に暗号化を使うような設定をしたので、それについてメモっておきます。

なお、最終的に立ち上げる際の docker-compose.yml は、 Roundcube を試した際のものと基本的には同じです(コンテナ名、ポート番号が少し異なる)。また、 ident_switch を入れて、複数アカウントを登録して、複数の IMAP サーバーに接続できるようにします。

暗号化接続を有効化

まず、 IMAP や SMTP サーバーとの接続時に暗号化が有効にならないのを何とかしたいと思います(というか、メールサーバーによっては、 SSL での接続のみが許可されているので、これを有効にしないと話になりません)。

メールサーバー情報を設定する際に、サーバー名の先頭に

ssl://

を追加すると、 SSL/TLS での接続になるようです(デフォルトのサーバー設定および ident_switch での設定時とも)。

いまのところ、この状態でメールサーバー(mail.xxx.sakura.ne.jp)につないでみると

errors: <1494e41f> IMAP Error: Login failed for test@ドメイン名 against ssl://mail.xxx.sakura.ne.jp from 192.168.0.16. Could not connect to ssl://mail.xxx.sakura.ne.jp:993: Unknown reason in /var/www/html/program/lib/Roundcube/rcube_imap.php on line 211 (GET /?_task=mail&_action=list&_refresh=1&_layout=widescreen&_mbox=INBOX&_page=&_remote=1&_unlock=loading1690772721943&_=1690772721911)

のようなエラーが表示されます。で、これをネットをググってみると、どうも証明書関連の問題が原因のようです。

サーバー証明書の設定を確認

最初に見つけた、下記の記事を参考にいろいろと試してみました。

Could not connect to ssl://mail.ingentar.com:993: Unknown reason in /var/www/html/program/lib/Roundcube/rcube_imap.php on line 200 · Issue #7408 · roundcube/roundcubemail · GitHub

これを読むと、クライアント側でサーバー証明書を検証する際に、サーバー証明書が見つからないことが原因かもしれないと思われます。

なので、まずは現状を確認してみます。

[ユーザ名@NAS名 application]$ docker exec -it roundcubemailtest /bin/bash

として、コンテナに入って、証明書があることを確認します。

root@0c74afe74dd1:/var/www/html# apt list --installed                   
Listing... Done
(略)
ca-certificates/stable,now 20210119 all [installed]
(略)

ありますね。 php の設定も確認します。

root@0c74afe74dd1:/var/www/html# php --info
phpinfo()
PHP Version => 7.4.30

System => Linux 0c74afe74dd1 5.10.60-qnap #1 SMP Fri Jun 9 01:48:30 CST 2023 x86_64
Build Date => Jun 23 2022 08:44:46
(中略)
openssl

OpenSSL support => enabled
OpenSSL Library Version => OpenSSL 1.1.1n  15 Mar 2022
OpenSSL Header Version => OpenSSL 1.1.1n  15 Mar 2022
Openssl default config => /usr/lib/ssl/openssl.cnf

Directive => Local Value => Master Value
openssl.cafile => no value => no value
openssl.capath => no value => no value
(後略)

openssl.cafile および openssl.capath の設定が無いようです。設定が無い場合はどうなるのかな? さきほどの php --info の先頭に読み込んでいる php.ini に関する情報があるので、確認すると

root@0c74afe74dd1:/var/www/html# php --info
phpinfo()
PHP Version => 7.4.30

System => Linux 0c74afe74dd1 5.10.60-qnap #1 SMP Fri Jun 9 01:48:30 CST 2023 x86_64
Build Date => Jun 23 2022 08:44:46
Configure Command =>  './configure'  '--build=x86_64-linux-gnu' '--with-config-file-path=/usr/local/etc/php' '--with-config-file-scan-dir=/usr/local/etc/php/conf.d' '--enable-option-checking=fatal' '--with-mhash' '--with-pic' '--enable-ftp' '--enable-mbstring' '--enable-mysqlnd' '--with-password-argon2' '--with-sodium=shared' '--with-pdo-sqlite=/usr' '--with-sqlite3=/usr' '--with-curl' '--with-iconv' '--with-openssl' '--with-readline' '--with-zlib' '--disable-phpdbg' '--with-pear' '--with-libdir=lib/x86_64-linux-gnu' '--disable-cgi' '--with-apxs2' 'build_alias=x86_64-linux-gnu'
Server API => Command Line Interface
Virtual Directory Support => disabled
Configuration File (php.ini) Path => /usr/local/etc/php
Loaded Configuration File => (none)
Scan this dir for additional .ini files => /usr/local/etc/php/conf.d
Additional .ini files parsed => /usr/local/etc/php/conf.d/docker-php-ext-exif.ini,
/usr/local/etc/php/conf.d/docker-php-ext-gd.ini,
/usr/local/etc/php/conf.d/docker-php-ext-imagick.ini,
/usr/local/etc/php/conf.d/docker-php-ext-intl.ini,
/usr/local/etc/php/conf.d/docker-php-ext-ldap.ini,
/usr/local/etc/php/conf.d/docker-php-ext-opcache.ini,
/usr/local/etc/php/conf.d/docker-php-ext-pdo_mysql.ini,
/usr/local/etc/php/conf.d/docker-php-ext-pdo_pgsql.ini,
/usr/local/etc/php/conf.d/docker-php-ext-pspell.ini,
/usr/local/etc/php/conf.d/docker-php-ext-redis.ini,
/usr/local/etc/php/conf.d/docker-php-ext-sodium.ini,
/usr/local/etc/php/conf.d/docker-php-ext-zip.ini,
/usr/local/etc/php/conf.d/roundcube-defaults.ini

PHP API => 20190902
(略)

/usr/local/etc/php およびその下の conf.d にある php.ini などの設定ファイルを読み込んでいるようです。

このコンテナの場合 php.in-production と php.ini-development があるのですが、 openssl に関する記述は共通で

[openssl]
; The location of a Certificate Authority (CA) file on the local filesystem
; to use when verifying the identity of SSL/TLS peers. Most users should
; not specify a value for this directive as PHP will attempt to use the
; OS-managed cert stores in its absence. If specified, this value may still
; be overridden on a per-stream basis via the "cafile" SSL stream context
; option.
;openssl.cafile=

; If openssl.cafile is not specified or if the CA file is not found, the
; directory pointed to by openssl.capath is searched for a suitable
; certificate. This value must be a correctly hashed certificate directory.
; Most users should not specify a value for this directive as PHP will
; attempt to use the OS-managed cert stores in its absence. If specified,
; this value may still be overridden on a per-stream basis via the "capath"
; SSL stream context option.
;openssl.capath=

となっています。なので、この説明によるとパスが無い場合は、システムデフォルトが使われるとのことです。

じゃあ、システムデフォルトがどうなっているのか、下記の記事に従って確認してみると、

python - what is my openssl and ssl Default CA Certs Path? - Stack Overflow

root@0c74afe74dd1:/var/www/html# openssl version -a
OpenSSL 1.1.1n  15 Mar 2022
built on: Tue May 10 18:37:36 2022 UTC
platform: debian-amd64
options:  bn(64,64) rc4(16x,int) des(int) blowfish(ptr) 
compiler: gcc -fPIC -pthread -m64 -Wa,--noexecstack -Wall -Wa,--noexecstack -g -O2 -ffile-prefix-map=/build/openssl-iy042u/openssl-1.1.1n=. -fstack-protector-strong -Wformat -Werror=format-security -DOPENSSL_USE_NODELETE -DL_ENDIAN -DOPENSSL_PIC -DOPENSSL_CPUID_OBJ -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DKECCAK1600_ASM -DRC4_ASM -DMD5_ASM -DAESNI_ASM -DVPAES_ASM -DGHASH_ASM -DECP_NISTZ256_ASM -DX25519_ASM -DPOLY1305_ASM -DNDEBUG -Wdate-time -D_FORTIFY_SOURCE=2
OPENSSLDIR: "/usr/lib/ssl"
ENGINESDIR: "/usr/lib/x86_64-linux-gnu/engines-1.1"
Seeding source: os-specific
root@0c74afe74dd1:/var/www/html# 

となっています。この OPENSSLDIR がデフォルトのパスになるらしい。

で、ここを見てみると

root@0c74afe74dd1:/var/www/html# ls -laF /usr/lib/ssl/
total 16
drwxr-xr-x 3 root root 4096 Jun 23  2022 ./
drwxr-xr-x 1 root root 4096 Jun 30  2022 ../
lrwxrwxrwx 1 root root   14 May 10  2022 certs -> /etc/ssl/certs/
drwxr-xr-x 2 root root 4096 Jun 23  2022 misc/
lrwxrwxrwx 1 root root   20 May 10  2022 openssl.cnf -> /etc/ssl/openssl.cnf
lrwxrwxrwx 1 root root   16 May 10  2022 private -> /etc/ssl/private/
root@0c74afe74dd1:/var/www/html# 

/etc/ssl 以下を見に行っているようです。ここをみると、各種証明書が入っています。なので、証明書そのものは正しく検索できるんじゃないかな?と思われます。

(参考)

上記が正しいとすると、今回使っているコンテナの場合は証明書のパスを設定するのは不要と思われます。

ですが、もし、最初の記事にあるように、 certificateファイルへのパスを設定する場合は、 roundcube-add-cert-path.ini のようなファイル名を下記の内容で作成して、

[openssl]
; The location of a Certificate Authority (CA) file on the local filesystem
; to use when verifying the identity of SSL/TLS peers. Most users should
; not specify a value for this directive as PHP will attempt to use the
; OS-managed cert stores in its absence. If specified, this value may still
; be overridden on a per-stream basis via the "cafile" SSL stream context
; option.
openssl.cafile=/etc/ssl/certs/ca-certificates.crt

; If openssl.cafile is not specified or if the CA file is not found, the
; directory pointed to by openssl.capath is searched for a suitable
; certificate. This value must be a correctly hashed certificate directory.
; Most users should not specify a value for this directive as PHP will
; attempt to use the OS-managed cert stores in its absence. If specified,
; this value may still be overridden on a per-stream basis via the "capath"
; SSL stream context option.
openssl.capath=/etc/ssl/certs

このファイルを、さきほどの 設定ファイル用のディレクトリに保存しておけばOKです。

root@387123b8511b:/usr/local/etc/php/conf.d# ls
docker-php-ext-exif.ini  docker-php-ext-imagick.ini  docker-php-ext-ldap.ini     docker-php-ext-pdo_mysql.ini  docker-php-ext-pspell.ini  docker-php-ext-sodium.ini  roundcube-add-cert-path.ini
docker-php-ext-gd.ini    docker-php-ext-intl.ini     docker-php-ext-opcache.ini  docker-php-ext-pdo_pgsql.ini  docker-php-ext-redis.ini   docker-php-ext-zip.ini     roundcube-defaults.ini
root@387123b8511b:/usr/local/etc/php/conf.d# 

php --info を見てみると、

openssl

OpenSSL support => enabled
OpenSSL Library Version => OpenSSL 1.1.1n  15 Mar 2022
OpenSSL Header Version => OpenSSL 1.1.1n  15 Mar 2022
Openssl default config => /usr/lib/ssl/openssl.cnf

Directive => Local Value => Master Value
openssl.cafile => /etc/ssl/certs/ca-certificates.crt => /etc/ssl/certs/ca-certificates.crt
openssl.capath => /etc/ssl/certs => /etc/ssl/certs

ちゃんと設定できてますね。

IMAP 接続時のオプション

次に、下記の記事などを見ると、証明書の検証自体を無効にするようなことが書かれている。

Roundcube SSL connection IMAP Error: Login failed - Stack Overflow

Howto Get Roundcube To Use SSL/TLS To Connect @ ;; MYRTANA.SK ;;

証明書のパスに問題が無さそうだったので、これも試してみます。

現状の /var/www/html/config/config.inc.php および config.docker.inc.php を確認してみると、どこにも imap_conn_options の設定がありません。も少し調べると、同じフォルダにある defaults.inc.php 内に

// IMAP socket context options
// See http://php.net/manual/en/context.ssl.php
// The example below enables server certificate validation
//$config['imap_conn_options'] = [
//  'ssl'         => [
//     'verify_peer'  => true,
//     'verify_depth' => 3,
//     'cafile'       => '/etc/openssl/certs/ca.crt',
//   ],
// ];
// Note: These can be also specified as an array of options indexed by hostname
$config['imap_conn_options'] = null;

という記述があります(SMTPについても同様の記述があります)。まずは試しに一度、これを有効にしてみます。

まず、 config.docker.add_options.inc.php を下記の内容で作成します。

<?php

// IMAP socket context options
$config['imap_conn_options'] = [
  'ssl'         => [
    'verify_peer'  => true,
    'verify_depth' => 3,
  ],
];

// SMTP socket context options
$config['smtp_conn_options'] = [
  'ssl'         => [
    'verify_peer'  => true,
    'verify_depth' => 3,
  ],
];

/var/www/html はコンテナのボリュームとして、 NAS のフォルダに接続されているので、作成したファイルを NAS 上の File Station を使って当該フォルダにアップロードしてやります(コンテナ内に vi とかのエディタがないため)。

次に、設定ファイルを追加で読み込むように config.inc.php の最後に一行追加します。

root@0c74afe74dd1:/var/www/html/config# echo "    include(__DIR__ . '/config.docker.add_options.inc.php');" >> config.inc.php
root@0c74afe74dd1:/var/www/html/config# cat config.inc.php
<?php
    $config['plugins'] = [
        'archive',
        'zipdownload',
        'ident_switch',
];
    $config['log_driver'] = 'stdout';
    $config['zipdownload_selection'] = true;
    $config['des_key'] = 'mcmwPOc6YPMtTZs8quIcNaaW';
    $config['enable_spellcheck'] = true;
    $config['spellcheck_engine'] = 'pspell';
    include(__DIR__ . '/config.docker.inc.php');
    
    include(__DIR__ . '/config.docker.add_options.inc.php');
root@0c74afe74dd1:/var/www/html/config# 

この状態で、IMAPサーバーへの接続を試してみると、

[Mon Jul 31 06:10:04.626685 2023] [php7:warn] [pid 50] [client 192.168.0.16:57207] PHP Warning:  stream_socket_client(): Peer certificate CN=`*.sakura.ne.jp' did not match expected CN=`mail.xxx.sakura.ne.jp' in /var/www/html/program/lib/Roundcube/rcube_imap_generic.php on line 1060, referer: http://nas01:9004/?_task=mail&_mbox=INBOX
[Mon Jul 31 06:10:04.626890 2023] [php7:warn] [pid 50] [client 192.168.0.16:57207] PHP Warning:  stream_socket_client(): Failed to enable crypto in /var/www/html/program/lib/Roundcube/rcube_imap_generic.php on line 1060, referer: http://nas01:9004/?_task=mail&_mbox=INBOX
[Mon Jul 31 06:10:04.627211 2023] [php7:warn] [pid 50] [client 192.168.0.16:57207] PHP Warning:  stream_socket_client(): unable to connect to ssl://mail.xxx.sakura.ne.jp:993 (Unknown error) in /var/www/html/program/lib/Roundcube/rcube_imap_generic.php on line 1060, referer: http://nas01:9004/?_task=mail&_mbox=INBOX
errors: <1494e41f> IMAP Error: Login failed for test@ドメイン名 against ssl://mail.xxx.sakura.ne.jp from 192.168.0.16. Could not connect to ssl://mail.xxx.sakura.ne.jp:993: Unknown reason in /var/www/html/program/lib/Roundcube/rcube_imap.php on line 211 (GET /?_task=mail&_action=getunread&_page=1&_remote=1&_unlock=0&_=1690783804509)

のように Warning が出るようになりました。

で、この Warning の内容をよく見てみると、

Peer certificate CN=*.sakura.ne.jp' did not match expected CN=mail.xxx.sakura.ne.jp'

とあります。 CN が証明書と異なる?

実は、今回試している IMAP サーバーはさくらインターネットのレンタルサーバーで、 SSL は共有 SSL を使っています。改めて、さくらインターネットのメールの設定を調べてみると、例えば、下記のページにあるように

メール(Windows 10・11)の設定をしたい | さくらのサポート情報

メールサーバーとして mail.xxx.sakura.ne.jp ではなく、 xxx.sakura.ne.jp (初期ドメイン)を使えとあります。あ、これですね。

ということで、メールサーバーの設定を xxx.sakura.ne.jp に変更してもう一度試してみると、問題なく接続できました!

(参考)

共有 SSL は初期ドメインの部分を * にしたワイルドカード証明書になっているようです。このため、 mail.xxx.sakura.ne.jp は階層が異なるため、サーバー証明書の検証に失敗していたようです。

一方、独自ドメインに対して設定できる無料 SSL (Let's Encrypt)もありますが、下記の説明からすると、こちらはメールでは使えないとのことです。

無料SSL(Let’s Encrypt)を設定したい | さくらのサポート情報

別のメールサーバーへ接続

これで、問題ないかと思ったのですが、別のメールサーバーへの接続を試してみると

[Mon Jul 31 06:17:12.468482 2023] [php7:warn] [pid 58] [client 192.168.0.16:57252] PHP Warning:  stream_socket_client(): SSL operation failed with code 1. OpenSSL Error messages:\nerror:1414D172:SSL routines:tls12_check_peer_sigalg:wrong signature type in /var/www/html/program/lib/Roundcube/rcube_imap_generic.php on line 1060, referer: http://nas01:9004/?_task=mail&_mbox=INBOX
[Mon Jul 31 06:17:12.469031 2023] [php7:warn] [pid 58] [client 192.168.0.16:57252] PHP Warning:  stream_socket_client(): Failed to enable crypto in /var/www/html/program/lib/Roundcube/rcube_imap_generic.php on line 1060, referer: http://nas01:9004/?_task=mail&_mbox=INBOX
[Mon Jul 31 06:17:12.469673 2023] [php7:warn] [pid 58] [client 192.168.0.16:57252] PHP Warning:  stream_socket_client(): unable to connect to ssl://imap.xxx.xxx.jp:993 (Unknown error) in /var/www/html/program/lib/Roundcube/rcube_imap_generic.php on line 1060, referer: http://nas01:9004/?_task=mail&_mbox=INBOX
errors: <1494e41f> IMAP Error: Login failed for test2@別のドメイン名 against ssl://imap.xxx.xxx.jp from 192.168.0.16. Could not connect to ssl://imap.xxx.xxx.jp:993: Unknown reason in /var/www/html/program/lib/Roundcube/rcube_imap.php on line 211 (GET /?_task=mail&_action=getunread&_page=1&_remote=1&_unlock=0&_=1690784232338)

のように先ほどとは内容が違いますが Warning が出ます。

コマンドラインで検証

IMAP 接続時のオプションを試した際のさきほどの記事に書いてあった openssl s_client を試してみます。

root@0c74afe74dd1:/var/www/html/config# openssl s_client -connect imap.xxx.xxx.jp:993
CONNECTED(00000003)
depth=2 C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Global Root CA
verify return:1
depth=1 C = US, O = DigiCert Inc, CN = DigiCert TLS RSA SHA256 2020 CA1
verify return:1
depth=0 C = JP, ST = Tokyo, L = xxx 区, O = 会社名, CN = imap.xxx.xxx.jp
verify return:1
139802833319232:error:1414D172:SSL routines:tls12_check_peer_sigalg:wrong signature type:../ssl/t1_lib.c:1145:
---
Certificate chain
 0 s:C = JP, ST = Tokyo, L = xxx 区, O = 会社名, CN = imap.xxx.xxx.jp
   i:C = US, O = DigiCert Inc, CN = DigiCert TLS RSA SHA256 2020 CA1
 1 s:C = US, O = DigiCert Inc, CN = DigiCert TLS RSA SHA256 2020 CA1
   i:C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Global Root CA
 2 s:C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Global Root CA
   i:C = IE, O = Baltimore, OU = CyberTrust, CN = Baltimore CyberTrust Root
---
Server certificate
-----BEGIN CERTIFICATE-----
(略)
-----END CERTIFICATE-----
subject=C = JP, ST = Tokyo, L = xxx 区, O = 会社名, CN = imap.xxx.xxx.jp

issuer=C = US, O = DigiCert Inc, CN = DigiCert TLS RSA SHA256 2020 CA1

---
No client certificate CA names sent
Server Temp Key: ECDH, P-256, 256 bits
---
SSL handshake has read 4573 bytes and written 313 bytes
Verification: OK
---
New, (NONE), Cipher is (NONE)
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : 0000
    Session-ID: 4128E371AF8CFCDFCC3C079195546F513D3A1C5AACC87CB5CF8BD000A31E56AE
    Session-ID-ctx: 
    Master-Key: 
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    Start Time: 1690784373
    Timeout   : 7200 (sec)
    Verify return code: 0 (ok)
    Extended master secret: no
---
root@0c74afe74dd1:/var/www/html/config# 

とあります。ここでも、表示されるメッセージをよく見ると、

tls12_check_peer_sigalg:wrong signature type

とあります。これってなんだろうか?と思い、ググると

OpenSSL SECLEVELによるwrong signature typeエラーの概要 - designetwork

セキュリティ レベル

openssl のセキュリティレベルというのがあって、それがあってないときに出るエラーのようです。

ためしに、変更してみます。既存の /etc/ssl/openssl.cnf の最後の部分が

[system_default_sect]
MinProtocol = TLSv1.2
CipherString = DEFAULT@SECLEVEL=2

となっているので、これを

root@0c74afe74dd1:/etc/ssl# sed -i "s/DEFAULT@SECLEVEL=2/DEFAULT@SECLEVEL=1/" openssl.cnf

のように編集しておきます。

root@0c74afe74dd1:/etc/ssl# cat openssl.cnf
#
# OpenSSL example configuration file.
# This is mostly being used for generation of certificate requests.
#
(略)
[system_default_sect]
MinProtocol = TLSv1.2
CipherString = DEFAULT@SECLEVEL=1
root@0c74afe74dd1:/etc/ssl# 

変更されてますね。

この状態で一度、 roundcube を立ち上げなおして(コンテナを再起動して)アクセスしてみると、問題なくアクセスできました!

(参考)

セキュリティレベル変更後に openssl s_client を試すと

root@0c74afe74dd1:/var/www/html/config# openssl s_client -connect imap.xxx.xxx.jp:993
CONNECTED(00000003)
depth=2 C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Global Root CA
verify return:1
depth=1 C = US, O = DigiCert Inc, CN = DigiCert TLS RSA SHA256 2020 CA1
verify return:1
depth=0 C = JP, ST = Tokyo, L = xxx 区, O = 会社名, CN = imap.xxx.xxx.jp
verify return:1
---
Certificate chain
 0 s:C = JP, ST = Tokyo, L = xxx 区, O = 会社名, CN = imap.xxx.xxx.jp
   i:C = US, O = DigiCert Inc, CN = DigiCert TLS RSA SHA256 2020 CA1
 1 s:C = US, O = DigiCert Inc, CN = DigiCert TLS RSA SHA256 2020 CA1
   i:C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Global Root CA
 2 s:C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Global Root CA
   i:C = IE, O = Baltimore, OU = CyberTrust, CN = Baltimore CyberTrust Root
---
Server certificate
-----BEGIN CERTIFICATE-----
(略)
-----END CERTIFICATE-----
subject=C = JP, ST = Tokyo, L = xxx 区, O = 会社名, CN = imap.xxx.xxx.jp

issuer=C = US, O = DigiCert Inc, CN = DigiCert TLS RSA SHA256 2020 CA1

---
No client certificate CA names sent
Peer signing digest: SHA1
Peer signature type: RSA
Server Temp Key: ECDH, P-256, 256 bits
---
SSL handshake has read 4633 bytes and written 438 bytes
Verification: OK
---
New, TLSv1.2, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES256-GCM-SHA384
    Session-ID: BBC91ACC2D9F8838296555800F1670C7474EEC1DEDEBA315DE4635F7B9585238
    Session-ID-ctx: 
    Master-Key: 79531CB64488D4CC67211712D6491E1D8B4ACC5FFECB2C5C050BADAFDEBD387720E276E0C374191FFEEC6E768B9F0D26
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    Start Time: 1690785252
    Timeout   : 7200 (sec)
    Verify return code: 0 (ok)
    Extended master secret: no
---
* OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE AUTH=PLAIN AUTH=LOGIN] IMAP4 ready

となり、 Cipher のところが表示されるようになってました。なるほどね、 SSL の最初にある暗号化方式を決める、という部分で失敗していたんですね。

(おまけ)ポート番号の指定

さて、これで送受信とも暗号化されて通信できたのですが、いろいろと試すと、メールの送信ができないケースがありました。

というのは、 docker-compose.yml で

  roundcubemail:
    environment:
      - ROUNDCUBEMAIL_DB_TYPE=sqlite
      - ROUNDCUBEMAIL_SKIN=elastic
      - ROUNDCUBEMAIL_DEFAULT_HOST=ssl://メールサーバー名
      - ROUNDCUBEMAIL_SMTP_SERVER=ssl://メールサーバー名

としたときに、ログイン時に用いるメールアドレスについて、 IMAP はポート番号として 143 ではなく 993 を使っているようなのですが、 SMTP についてはデフォルトの値(587)をそのまま使っており、 SMTPS でよくある 465 には切り替わっていないようでした。

なので、 ident_switch で設定したメールアドレスではこの現象が起きずに、デフォルトのメールサーバーを使うログイン時のメールアカウントの場合にのみ、送信エラーが起きていました。

ということで、余計なトラブルを避けるため、

  roundcubemail:
    environment:
      - ROUNDCUBEMAIL_DB_TYPE=sqlite
      - ROUNDCUBEMAIL_SKIN=elastic
      - ROUNDCUBEMAIL_DEFAULT_HOST=ssl://メールサーバー名
      - ROUNDCUBEMAIL_DEFAULT_PORT=993
      - ROUNDCUBEMAIL_SMTP_SERVER=ssl://メールサーバー名
      - ROUNDCUBEMAIL_SMTP_PORT=465

のように、明示的にポート番号を指定するようにしておきます。

まとめ

実際は、ここに書いたようにスムーズに解決法が見つかったわけではなく、結構紆余曲折がありました。

特に、 imap_conn_options を設定するまでは、Warning メッセージも出てなくて、何を調べればいいのかわからず、行き当たりばっりでした。この Warning メッセージが出力されるようになってからは、比較的解決策を見つけるのが早くなりました。

メッセージ大事ですね。

にしても、imap_conn_options の設定がない場合に、 Warning が出ないのは何とかしてほしいものです。