読者です 読者をやめる 読者になる 読者になる

らくがきちょう

なんとなく

openssl コマンドで SSL/TLS バージョンを指定した HTTPS 接続テストを実施する

Linux

openssl コマンドは様々なことが実行できますが、HTTPS の接続テストに使うことも出来ます。今回は openssl を使って SSL/TLS バージョンを明示的に指定した接続テストの方法をメモします。

目次

Apache のインストール

テスト用のサーバは AWS 上に CentOS7 で構築しました。

$ cat /etc/redhat-release
CentOS Linux release 7.2.1511 (Core)

yumhttpd と mod_ssl をインストールします。

sudo yum install -y httpd mod_ssl

Apache のバージョンは 2.4.6、コンパイルオプションは以下でした。

$ httpd -V
Server version: Apache/2.4.6 (CentOS)
Server built:   May 12 2016 10:27:23
Server's Module Magic Number: 20120211:24
Server loaded:  APR 1.4.8, APR-UTIL 1.5.2
Compiled using: APR 1.4.8, APR-UTIL 1.5.2
Architecture:   64-bit
Server MPM:     prefork
  threaded:     no
    forked:     yes (variable process count)
Server compiled with....
 -D APR_HAS_SENDFILE
 -D APR_HAS_MMAP
 -D APR_HAVE_IPV6 (IPv4-mapped addresses enabled)
 -D APR_USE_SYSVSEM_SERIALIZE
 -D APR_USE_PTHREAD_SERIALIZE
 -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT
 -D APR_HAS_OTHER_CHILD
 -D AP_HAVE_RELIABLE_PIPED_LOGS
 -D DYNAMIC_MODULE_LIMIT=256
 -D HTTPD_ROOT="/etc/httpd"
 -D SUEXEC_BIN="/usr/sbin/suexec"
 -D DEFAULT_PIDLOG="/run/httpd/httpd.pid"
 -D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
 -D DEFAULT_ERRORLOG="logs/error_log"
 -D AP_TYPES_CONFIG_FILE="conf/mime.types"
 -D SERVER_CONFIG_FILE="conf/httpd.conf"

インストール直後は Apache が停止しているので、開始しておきます (本格的に運用するなら自動起動設定も実施しておくと良いと思いますが、今回はテスト環境なので省略しています)。

sudo systemctl start httpd.service

デフォルトで有効になっている SSL/TLS バージョン

CentOS7 標準構成で yum から Apache をインストールした場合、SSL/TLS バージョンに関する設定は以下のようになっていました。

$ cat /etc/httpd/conf.d/ssl.conf | grep ^SSLProtocol
SSLProtocol all -SSLv2

「all を有効化し」「SSLv2 を無効化(マイナス)」しているので、結果的には以下となります。SSL 1.0 は仕様が存在するものの、実装されなかったプロトコルですので N/A としています。

プロトコル&バージョン 有効(○) or 無効(X)
SSL 1.0 N/A
SSL 2.0
SSL 3.0
TLS 1.0
TLS 1.1
TLS 1.2

OpenSSL を使った HTTPS 接続テスト

openssl を使って HTTPS の接続テストを実施する場合、以下のように実行します。

openssl s_client -connect EXAMPLE.LOCAL:443

opensslHTTPS 接続すると、通常は標準入力を待ちます(=切断されません)。これを避け、切断されるようにするには /dev/null をリダイレクトしてやります。具体的には以下のように実行します。

openssl s_client -connect EXAMPLE.LOCAL:443 < /dev/null

SSL/TLS バージョンを指定した接続テスト

opensslSSL/TLS バージョンを指定した接続テストを実施するには以下のように指定します。SSL 3.0 〜 TLS 1.0 までは良いのですが、「TLS 1.1 は -tls1_1」「TLS 1.2 は -tls1_2」になる(ドットでは無く、アンダースコア)のがポイントです。

SSL 1.0

SSLNetscape 社が生み出したプロトコルですが、リリース前に Netscape 社の社内レビューで脆弱性が見つかった為、(仕様は存在するものの)実装されることは無かったそうです。よって、SSL 1.0 を使った接続テストを実施することは出来ません。

SSL 2.0

openssl s_client -connect EXAMPLE.LOCAL:443 -ssl2

SSL 3.0

openssl s_client -connect EXAMPLE.LOCAL:443 -ssl3

TLS 1.0

openssl s_client -connect EXAMPLE.LOCAL:443 -tls1

TLS 1.1

openssl s_client -connect EXAMPLE.LOCAL:443 -tls1_1

TLS 1.2

openssl s_client -connect EXAMPLE.LOCAL:443 -tls1_2

実行結果

openssl を使って接続テストした場合、「接続失敗した際の出力」と「接続成功した際の出力」を見てみます。

SSL/TLS バージョンが一致せず、接続に失敗したケース

プロトコルは「Protocol : SSLv2」ですが、暗号スイートが「Cipher : 0000」と有効な値では無い為、接続に失敗していることが分かります。

$ openssl s_client -connect EXAMPLE.LOCAL:443 -ssl2 < /dev/null
CONNECTED(00000003)
140059824203680:error:1407F0E5:SSL routines:SSL2_WRITE:ssl handshake failure:s2_pkt.c:429:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 0 bytes and written 39 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : SSLv2
    Cipher    : 0000
    Session-ID:
    Session-ID-ctx:
    Master-Key:
    Key-Arg   : None
    Krb5 Principal: None
    PSK identity: None
    PSK identity hint: None
    Start Time: 1468084877
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)
---

SSL/TLS バージョンが一致し、接続に成功したケース

プロトコルは「 Protocol : TLSv1.2」、暗号スイートは「Cipher : ECDHE-RSA-AES256-GCM-SHA384」が選択され、その他の値もサーバから応答されたことで HTTPS 通信の確率に成功しています。

$ openssl s_client -connect EXAMPLE.LOCAL:443 -tls1_2 < /dev/null
    ( 省略 )
---
SSL handshake has read 1889 bytes and written 441 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES256-GCM-SHA384
    Session-ID: 661313629E1DB0ABF1B8A150E580E9B3C5AB3B8A957A0EAE3D7E590A5156C543
    Session-ID-ctx:
    Master-Key: 1F41EE645294FBFAF90AA95C5E74F7BD0169B35BDD05246979899E05DB46A6C48559B9777C38D708D27CD665A244A5EB
    Key-Arg   : None
    Krb5 Principal: None
    PSK identity: None
    PSK identity hint: None
    TLS session ticket lifetime hint: 300 (seconds)
    TLS session ticket:
    0000 - 23 b9 fa ef a9 75 e0 81-87 75 d9 16 cf 04 d5 96   #....u...u......
    ( 省略 )
    00b0 - 71 63 dc ed 7d 92 55 d5-9e ae 82 a8 10 7b 7b f6   qc..}.U......{{.

    Start Time: 1468084918
    Timeout   : 7200 (sec)
    Verify return code: 21 (unable to verify the first certificate)
---
DONE

ApacheSSL 3.0 を無効にしてみる

ApacheSSL/TLS のバージョン毎に有効化/無効化を指定するには /etc/httpd/conf.d/ssl.confSSLProtocol 設定を書き換えます。試しに SSL 3.0 を無効化してみます。

変更前

SSLProtocol all -SSLv2

変更後

SSLProtocol all -SSLv2 -SSLv3

設定変更を反映する為に Apache を再起動します。

sudo systemctl restart httpd.service

SSL 3.0 で接続出来なくなったことを確認する

ApacheSSL 3.0 を無効化したので、意図した通り、接続に失敗します。

$ openssl s_client -connect EXAMPLE.LOCAL:443 -ssl3 < /dev/null
CONNECTED(00000003)
140443742128032:error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure:s3_pkt.c:1259:SSL alert number 40
140443742128032:error:1409E0E5:SSL routines:SSL3_WRITE_BYTES:ssl handshake failure:s3_pkt.c:598:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 7 bytes and written 0 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : SSLv3
    Cipher    : 0000
    Session-ID:
    Session-ID-ctx:
    Master-Key:
    Key-Arg   : None
    Krb5 Principal: None
    PSK identity: None
    PSK identity hint: None
    Start Time: 1468085332
    Timeout   : 7200 (sec)
    Verify return code: 0 (ok)
---