openssl コマンドで SSL/TLS バージョンを指定した HTTPS 接続テストを実施する
sopenssl コマンドは様々なことが実行できますが、HTTPS の接続テストに使うことも出来ます。今回は openssl を使って SSL/TLS バージョンを明示的に指定した接続テストの方法をメモします。
Apache のインストール
テスト用のサーバは AWS 上に CentOS7 で構築しました。
| $ cat /etc/redhat-release
CentOS Linux release 7.2.1511 (Core)
|
yum で httpd と mod_ssl をインストールします。
| sudo yum install -y httpd mod_ssl
|
Apache のバージョンは 2.4.6、コンパイルオプションは以下でした。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 | $ 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 |
X |
SSL 3.0 |
○ |
TLS 1.0 |
○ |
TLS 1.1 |
○ |
TLS 1.2 |
○ |
OpenSSL を使った HTTPS 接続テスト
openssl を使って HTTPS の接続テストを実施する場合、以下のように実行します。
| openssl s_client -connect EXAMPLE.LOCAL:443
|
openssl で HTTPS 接続すると、通常は標準入力を待ちます(=切断されません)。これを避け、切断されるようにするには /dev/null をリダイレクトしてやります。具体的には以下のように実行します。
| openssl s_client -connect EXAMPLE.LOCAL:443 < /dev/null
|
SSL/TLS バージョンを指定した接続テスト
openssl で SSL/TLS バージョンを指定した接続テストを実施するには以下のように指定します。SSL 3.0 〜 TLS 1.0 までは良いのですが、「TLS 1.1 は -tls1_1」「TLS 1.2 は -tls1_2」になる(ドットでは無く、アンダースコア)のがポイントです。
SSL 1.0
SSL は Netscape 社が生み出したプロトコルですが、リリース前に 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」と有効な値では無い為、接続に失敗していることが分かります。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 | $ 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 通信の確率に成功しています。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 | $ 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
|
Apache で SSL 3.0 を無効にしてみる
Apache で SSL/TLS のバージョン毎に有効化/無効化を指定するには /etc/httpd/conf.d/ssl.conf の SSLProtocol 設定を書き換えます。試しに SSL 3.0 を無効化してみます。
変更前
変更後
| SSLProtocol all -SSLv2 -SSLv3
|
設定変更を反映する為に Apache を再起動します。
| sudo systemctl restart httpd.service
|
SSL 3.0 で接続出来なくなったことを確認する
Apache で SSL 3.0 を無効化したので、意図した通り、接続に失敗します。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 | $ 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)
---
|