🔒

AlmaLinux 9 上の nginx で TLSv1, TLSv1.1 を有効にする

2023/03/03に公開

のっぴきならない事情により TLSv1.1, TLSv1.0 での接続をサポートする必要があったんだけど、あまり情報がなかったので記録しておきます。

※ 当然、安全でないので無効になっているので危険性を理解した上で読んでください。

先に結論

OS 全体の暗号化ポリシーの設定で TLSv1.1, TLSv1.0 を有効にする。

$ sudo vi /usr/share/crypto-policies/policies/modules/TLS1.pmod
protocol@TLS = TLS1.0 TLS1.1 TLS1.3 TLS1.2 DTLS1.2
$ sudo update-crypto-policies --set LEGACY:TLS1

nginx の設定ファイルに下記を追加する。

server {
  ...
  ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
  ssl_ciphers @SECLEVEL=0:ALL:!aNULL:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
  ...
}

設定を有効にするために systemctl restart nginx で nginx を再起動する。

詳細

OS の暗号化ポリシーの設定

AlmaLinux 9 (おそらく RHEL9、CentOS9 も) では OS 全体の暗号化ポリシーで TLSv1.1, TLSv1.0 を無効にしている。

RHEL 9 では、TLS 設定はシステム全体の暗号化ポリシーメカニズムを使用して実行されます。1.2 未満の TLS バージョンはサポートされなくなりました。
https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/9/html/securing_networks/security-considerations-for-tls-in-rhel_planning-and-implementing-tls

8 までは LEGACY (古いクライアントをサポートする設定) にしていれば使えたのだが、LEGACY でもサポートしなくなったので自分で設定する必要がある。

暗号化ポリシーはサブポリシーという、設定の一部を上書きする仕組みがあるのでこれを作る。

$ sudo vi /usr/share/crypto-policies/policies/modules/TLS1.pmod
protocol@TLS = TLS1.0 TLS1.1 TLS1.3 TLS1.2 DTLS1.2

この上で LEGACY に上記のサブポリシーを上書きして適用する。

$ sudo update-crypto-policies --set LEGACY:TLS1

上記コマンドを実行すると /etc/crypto-policies/back-ends/opensslcnf.config が更新される。
下記の記述があれば OK。

TLS.MinProtocol = TLSv1

nginx の設定

nginx でも ssl_protocols で TLSv1, TLSv1.1 を使う設定は必要。

server {
  ...
  ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
  ...
}

なのだが、OpenSSL 3 では TLSv1, TLSv1.1 が使う SHA1 が (当然安全上の理由で) デフォルトでは使えないようになっている。

The security strength of SHA1 and MD5 based signatures in TLS has been reduced.
This results in SSL 3, TLS 1.0, TLS 1.1 and DTLS 1.0 no longer working at the default security level of 1 and instead requires security level 0. The security level can be changed either using the cipher string with @SECLEVEL, or calling SSL_CTX_set_security_level(3) . This also means that where the signature algorithms extension is missing from a ClientHello then the handshake will fail in TLS 1.2 at security level 1. This is because, although this extension is optional, failing to provide one means that OpenSSL will fallback to a default set of signature algorithms. This default set requires the availability of SHA1.
https://www.openssl.org/docs/man3.0/man7/migration_guide.html

このため @SECLEVEL=0 つきで使用する暗号化スイートを指定する必要がある。

server {
  ...
  # 使用可能なすべての暗号化スイートを指定している。実際の運用では限定したほうがよい。
  ssl_ciphers @SECLEVEL=0:ALL:!aNULL:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
  ...
}

その他の情報

TLS の対応状況を確認するには sslscan が便利だった。macOS なら brew install sslscan でインストールできる。
curl のオプション --tls-max 1.1 で使用する TLS のバージョンを指定するのも便利。

接続できないとき nginx では下記のようなログが error_log に出力されていた。

# ssl_protocols が設定できていないとき
****/**/** **:**:** [info] 1406#1406: *1 SSL_do_handshake() failed (SSL: error:0A000102:SSL routines::unsupported protocol) while SSL handshaking, client: x.x.x.x, server: 0.0.0.0:443

# ssl_ciphers が設定できていないとき
****/**/** **:**:** [info] 864#864: *1 SSL_do_handshake() failed (SSL: error:0A000076:SSL routines::no suitable signature algorithm) while SSL handshaking, client: x.x.x.x, server: 0.0.0.0:443

Discussion