添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
というソフトで Let’s Encrypt にサーバ証明書を要求して使っているのですが、 Lego はデフォルトで ECDSA の証明書を要求するようになっていて ( -k ec384 )、これがたまに問題を起こしていました。

昨日もそれにひっかかったあげく、さらに深入りして時間を浪費してしまったので、ブログの記事にしておきたいと思います。

Exchange と ECDSA

今回ひっかかったのは 1 年以上前に構築して使っているメールサーバ ( Postfix StartTLS に使うサーバ証明書で、Lego と cron による自動更新を続けて特にトラブルなく使えていたものです。

昨日 Exchange Online のとあるテナントをいじって Office 365 → Postfix の送信コネクタ (TLS 接続) を作ったところ、 451 4.4.0 Security status IllegalMessage という接続エラーが出てうまくいきませんでした。

そして Postfix 側では次のようなログが残されていました。

Nov 29 20:20:16 mail-000 postfix/smtpd[16423]: connect from mail-pu1apc01lp2056.outbound.protection.outlook.com[104.47.126.56]
Nov 29 20:20:16 mail-000 postfix/smtpd[16423]: SSL_accept error from mail-pu1apc01lp2056.outbound.protection.outlook.com[104.47.126.56]: -1
Nov 29 20:20:16 mail-000 postfix/smtpd[16423]: warning: TLS library problem: error:1408A0C1:SSL routines:ssl3_get_client_hello:no shared cipher:s3_srvr.c:1417:
Nov 29 20:20:16 mail-000 postfix/smtpd[16423]: lost connection after STARTTLS from mail-pu1apc01lp2056.outbound.protection.outlook.com[104.47.126.56]
Nov 29 20:20:16 mail-000 postfix/smtpd[16423]: disconnect from mail-pu1apc01lp2056.outbound.protection.outlook.com[104.47.126.56] ehlo=1 starttls=0/1 commands=1/2

原因がわかりづらいエラーメッセージですが、適当に検索してみると類似の症例が見つかります。

  • https://moocat.me/words/server/smtp-error1408a0c1-no-shared-cipher-ecc-support
  • これを見て、Office 365 の Exchange Server は Lego が要求した ECDSA の証明書に対応していないに違いない、 と早々に結論して RSA の証明書に切り替えて終わらせようとしていたのですが、 では実際に Exchange はどういう暗号をサポートしているのだろうと気になったので、調べてみました。

    原因の調査

    それには TLS のハンドシェイクで Exchange から送られてくる Client Hello の中身を見る必要があるのですが、 Postfix のデバッグログ機能ではペイロードの 16 進ダンプしか表示できないようなので、 結局 tshark を使うことになりました。

    以下が Exchange が送ってきた Client Hello と、それに対して Postfix が返した Alert(失敗) です。

    Secure Sockets Layer
        TLSv1.2 Record Layer: Handshake Protocol: Client Hello
            Content Type: Handshake (22)
            Version: TLS 1.2 (0x0303)
            Length: 346
            Handshake Protocol: Client Hello
                Handshake Type: Client Hello (1)
                Length: 342
                Version: TLS 1.2 (0x0303)
                Random: 5de27a6ca121e22b2abd6df1ee9ac689fe51042ccbfc99bc...
                    GMT Unix Time: Nov 30, 2019 23:19:24.000000000 JST
                    Random Bytes: a121e22b2abd6df1ee9ac689fe51042ccbfc99bc0beea610...
                Session ID Length: 0
                Cipher Suites Length: 32
                Cipher Suites (16 suites)
                    Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (0xc02c)
                    Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (0xc02b)
                    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)
                    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
                    Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 (0xc024)
                    Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 (0xc023)
                    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (0xc028)
                    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (0xc027)
                    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (0xc014)
                    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (0xc013)
                    Cipher Suite: TLS_RSA_WITH_AES_256_GCM_SHA384 (0x009d)
                    Cipher Suite: TLS_RSA_WITH_AES_128_GCM_SHA256 (0x009c)
                    Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA256 (0x003d)
                    Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA256 (0x003c)
                    Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA (0x0035)
                    Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA (0x002f)
                Compression Methods Length: 1
                Compression Methods (1 method)
                    Compression Method: null (0)
                Extensions Length: 269
                Extension: supported_groups (len=4)
                    Type: supported_groups (10)
                    Length: 4
                    Supported Groups List Length: 2
                    Supported Groups (1 group)
                        Supported Group: secp256r1 (0x0017)
                Extension: ec_point_formats (len=2)
                    Type: ec_point_formats (11)
                    Length: 2
                    EC point formats Length: 1
                    Elliptic curves point formats (1)
                        EC point format: uncompressed (0)
                Extension: signature_algorithms (len=20)
                    Type: signature_algorithms (13)
                    Length: 20
                    Signature Hash Algorithms Length: 18
                    Signature Hash Algorithms (9 algorithms)
                        Signature Algorithm: rsa_pkcs1_sha256 (0x0401)
                            Signature Hash Algorithm Hash: SHA256 (4)
                            Signature Hash Algorithm Signature: RSA (1)
                        Signature Algorithm: rsa_pkcs1_sha384 (0x0501)
                            Signature Hash Algorithm Hash: SHA384 (5)
                            Signature Hash Algorithm Signature: RSA (1)
                        Signature Algorithm: rsa_pkcs1_sha1 (0x0201)
                            Signature Hash Algorithm Hash: SHA1 (2)
                            Signature Hash Algorithm Signature: RSA (1)
                        Signature Algorithm: ecdsa_secp256r1_sha256 (0x0403)
                            Signature Hash Algorithm Hash: SHA256 (4)
                            Signature Hash Algorithm Signature: ECDSA (3)
                        Signature Algorithm: ecdsa_secp384r1_sha384 (0x0503)
                            Signature Hash Algorithm Hash: SHA384 (5)
                            Signature Hash Algorithm Signature: ECDSA (3)
                        Signature Algorithm: ecdsa_sha1 (0x0203)
                            Signature Hash Algorithm Hash: SHA1 (2)
                            Signature Hash Algorithm Signature: ECDSA (3)
                        Signature Algorithm: SHA1 DSA (0x0202)
                            Signature Hash Algorithm Hash: SHA1 (2)
                            Signature Hash Algorithm Signature: DSA (2)
                        Signature Algorithm: rsa_pkcs1_sha512 (0x0601)
                            Signature Hash Algorithm Hash: SHA512 (6)
                            Signature Hash Algorithm Signature: RSA (1)
                        Signature Algorithm: ecdsa_secp521r1_sha512 (0x0603)
                            Signature Hash Algorithm Hash: SHA512 (6)
                            Signature Hash Algorithm Signature: ECDSA (3)
                Extension: SessionTicket TLS (len=218)
                    Type: SessionTicket TLS (35)
                    Length: 218
                    Data (218 bytes)
                Extension: extended_master_secret (len=0)
                    Type: extended_master_secret (23)
                    Length: 0
                Extension: renegotiation_info (len=1)
                    Type: renegotiation_info (65281)
                    Length: 1
                    Renegotiation Info extension
                        Renegotiation info extension length: 0
    Secure Sockets Layer
        TLSv1.2 Record Layer: Alert (Level: Fatal, Description: Handshake Failure)
            Content Type: Alert (21)
            Version: TLS 1.2 (0x0303)
            Length: 2
            Alert Message
                Level: Fatal (2)
                Description: Handshake Failure (40)
    

    ご覧の通り、暗号スイートには ECDSA のものをひととおり対応しているように見えます。 ではなにがダメだったのかというと、 それは楕円曲線群が secp256r1 ひとつしか使えないことだったようです。

                Extension: supported_groups (len=4)
                    Type: supported_groups (10)
                    Length: 4
                    Supported Groups List Length: 2
                    Supported Groups (1 group)
                        Supported Group: secp256r1 (0x0017)
    

    そこで Lego のデフォルトである secp384r1 ( -k ec384 ) ではなく secp256r1 ( -k ec256 ) で証明書を作り直してみたところ、 無事に Exchange Online の送信コネクタで Postfix に TLS 接続することができるようになりました。

    ということで、実際には Exchange Online は ECDSA をサポートしており、 ECDSA をあきらめて RSA にしなくてもよいことがわかりました。 もっとも、ECDSA 全般に対応していないサーバやクライアントはまだあるみたいなので、 結局のところサーバ証明書は RSA で作る ( -k rsa4096 ) のが一番安全なのかもしれません。

    その他の ECDSA トラブル事例

    これより前に遭遇した ECDSA がらみのトラブルとしては、 GitLab Pages の独自ドメインサイトに設定するサーバ証明書が RSA でないと受け付けられないということがありました。 これには自分もコメントしていました。

    https://gitlab.com/gitlab-org/gitlab-pages/issues/35#note_177010927

    なお、今は ECDSA も対応しているそうです。これは純粋に GitLab Pages の Ruby のコードの問題だったようです。

    また先月には Windows Server の ADFS と Lego による ECDSA 証明書ではまっている方がいらっしゃいました。 Windows Server がらみということで、今回と根が同じ問題なのかもしれないと思っています。