概要

使っているMacBookProのローカルに立ち上がっているapacheのWebサーバに自己証明書を導入したくなりました。その構築するための手順などを残しておく。

環境

下記環境

  • OS macOS Monterey 12.6
  • httpd Apache/2.4.54
    macOSデフォルトのではなく、brew install apache2で導入したもの
  • TLS 1.2以上に限定したい

前提として

  • localhost:80httpdがすでに起動されている状態
  • opensslコマンドが使える

構築の流れ

VirtualHostが使えるようhttpd.confを変更

/usr/local/etc/httpd/httpd.confを編集し、下記それぞれの行をコメントアウトする

LoadModule vhost_alias_module lib/httpd/modules/mod_vhost_alias.so
...省略...
Include /usr/local/etc/httpd/extra/httpd-vhosts.conf
...省略...

VirtualHostを設定

/usr/local/etc/httpd/extra/httpd-vhosts.confを開き、下記部分だけになるよう編集。

<VirtualHost *:80>
   ServerName localhost
   DocumentRoot "/usr/local/var/www"

   <Directory "/usr/local/var/www">
       Options Indexes FollowSymLinks
       AllowOverride All
       Order allow,deny
       Allow from all
       Require all granted
   </Directory>
</VirtualHost>

Apache2を再起動できるか確認

$ sudo apachectl restart

http://localhostで確認して、 file になっているので問題ない。

SSLを設定

RSA秘密鍵を作成

$ mkdir -p /usr/local/etc/httpd/ssl
$ cd /usr/local/etc/httpd/ssl
$ sudo openssl genrsa 2048 > server.key

これで、RSA方式で2048 bit長の秘密鍵を作成できた。 今回はパスフレーズなしで秘密鍵を作成している例で、パスフレーズ付きで作成したい場合は、例えば、sudo openssl genrsa -aes256 2048 > server.keyのようにする。しかし、この場合は、秘密鍵を使った作業(CSRの作成、署名)やapache起動する際にはパスフレーズを求められるようになる。今回は自己証明書なので、パスフレーズなしのやり方にした。 参考)https://turningp.jp/network_and_security/openssl_a-challenge-password

CSRを作成

CSRはCertificate Signing Request、すなわち証明書署名要求のこと。今回は自己証明(オレオレ証明)なので、認証局(自分)にサーバの公開鍵に署名することになる。

$ openssl req -new -key server.key > server.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:JP
State or Province Name (full name) [Some-State]:Tokyo
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

CSRを作成する際、各項目に対して空欄回答で大丈夫。

サーバ証明書を作成

$ openssl x509 -req -days 3650 -signkey server.key < server.csr > server.crt
Certificate request self-signature ok
subject=C = JP, ST = Tokyo, O = Internet Widgits Pty Ltd

これでサーバ証明書を作成できた。

サーバ証明書をキーチェーンアクセスへ登録

$ sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain /usr/local/etc/httpd/ssl/server.crt
Password:

Password入力にmacOSにログイン時のパスワードを入力し、その後下記のようなダイヤログが表示されたが、Touch IDを使用した。 file

SSL用のVirtualHostを設定

/usr/local/etc/httpd/httpd.confを編集し、下記各行をコメントアウトする。

LoadModule socache_shmcb_module lib/httpd/modules/mod_socache_shmcb.so
LoadModule ssl_module lib/httpd/modules/mod_ssl.so
Include /usr/local/etc/httpd/extra/httpd-ssl.conf

httpd-vhosts.confを編集

/usr/local/etc/httpd/extra/httpd-vhosts.confを開き、SSL用の設定を追加。 将来、http://localhosthttps://localhostDocumentRootを区別させるために、httpsの場合のDocumentRoot/usr/local/var/wwsにした。

<VirtualHost *:443>
   ServerName localhost
   DocumentRoot "/usr/local/var/wws"

   SSLEngine on
   SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
   SSLCertificateFile /usr/local/etc/httpd/ssl/server.crt
   SSLCertificateKeyFile /usr/local/etc/httpd/ssl/server.key

   <Directory "/usr/local/var/wws">
       Options Indexes FollowSymLinks
       AllowOverride All
       Order allow, deny
       Allow from all
       Require all granted
   </Directory>
</VirtualHost>

httpd-ssl.confを設定

/usr/local/etc/httpd/extra/httpd-ssl.confを編集し、待受ポート番号とServerNameを以下になるよう変更する。

Listen 443
...省略...
DocumentRoot "/usr/local/var/wws"
...省略...
ServerName localhost
...省略...

また、サーバ証明書と秘密鍵を記述する場所を、上で作ったものになるよう変更する。

SSLCerificateFile "/private/etc/apache2/server.crt"
SSLCertificateKeyFile "/private/etc/apache2/server.key"
↓書き換える
SSLCerificateFile "/usr/local/etc/httpd/ssl/server.crt"
SSLCertificateKeyFile "/usr/local/etc/httpd/ssl/server.key"

Apacheを再起動

ここまで、SSL設定の手続きが一通り完了したので、apacheを再起動する。

$ sudo apachectl restart

ブラウザからhttps://localhostでアクセスすると、最初は安全な接続ではありませんの警告画面が出る(自己証明書なので想定内)。その後、承知した上で接続すると、問題なく表示できた。 file

ブラウザから証明書の詳細を確認

Firefox

file

Chrome

file

file

サーバ側でTLS1.2未満リクエストを遮断

サーバが対応しているSSL/TLSバージョンを確認

参考)https://kazuhira-r.hatenablog.com/entry/2020/11/19/020208

まずTLS1.2バージョンのリクエストが受けられるかを確認

$ echo | openssl s_client -connect localhost:443 -tls1_2
CONNECTED(00000005)
Can't use SSL_get_servername
depth=0 C = JP, ST = Tokyo, O = Internet Widgits Pty Ltd
verify error:num=18:self-signed certificate
verify return:1
depth=0 C = JP, ST = Tokyo, O = Internet Widgits Pty Ltd
verify return:1
---
Certificate chain
 0 s:C = JP, ST = Tokyo, O = Internet Widgits Pty Ltd
   i:C = JP, ST = Tokyo, O = Internet Widgits Pty Ltd
   a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA256
   v:NotBefore: Nov 16 14:31:37 2022 GMT; NotAfter: Nov 13 14:31:37 2032 GMT
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIDBzCCAe8CFCjYt/eQcMFIJW6CRIbwz/fo4Ar/MA0GCSqGSIb3DQEBCwUAMEAx
CzAJBgNVBAYTAkpQMQ4wDAYDVQQIDAVUb2t5bzEhMB8GA1UECgwYSW50ZXJuZXQg
V2lkZ2l0cyBQdHkgTHRkMB4XDTIyMTExNjE0MzEzN1oXDTMyMTExMzE0MzEzN1ow
QDELMAkGA1UEBhMCSlAxDjAMBgNVBAgMBVRva3lvMSEwHwYDVQQKDBhJbnRlcm5l
dCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
AQCW91nNc7umaUCNN7O9NP3r1DlEpu/MzWrqHFz5joGvnlX7s9HceMrN5lOxtcgN
7BNeGQZBXj5FKBdQcQBy4Db8D0XXuX9ZY3L4eBF6KT7fGOYjBjpfeFv+zjn719Y2
F/tiz03DlUk173xjaL9t1Pii3VOKQRDX8GO/RT8E2/U/cjdHqpdOgpKP0FdyKR9l
7hnrVsBuJNTWvU23jEhDq43ZRpaMESqXiRBvChiBMdSZSorMkkf/Erido33ViDXU
uQEr/jmfvfyDyqMFAOFAsVmM+KCAgEkBDMPDz7NXnsExfOAiQIgrB2/QG82PRDq3
Z39gIOm4UFzdLYEayf/QcUC9AgMBAAEwDQYJKoZIhvcNAQELBQADggEBAAEpVLWI
suk39uon9IMUo9hFSvTr4uNJCatz6Olig91pP9ubJ8Wune4NeUpoOJCATKHcvn0O
YsUrO6T1Bi0vyKvGaw97MiYEkLIcTXXjgMfEe4hSw7zRIudpLevGoQkdomMATQde
2LchsnLt1m5CLbO8cHSnEeKD9Hct0xY61vCzx+6UgN5Ywl1YCY4zrqdVyv3Po3su
DSPLuyfkflZLpsUajjh0Bz4YjdHfGWIg1Sfd0amTmlt1zANMHCyG6voxdaIn3jsd
Le3kXVifESHRnRlcmskbDrWoKQFQiWp7063fHPDNFHi8dL190Qir8Wg0JsUkm7Av
JqyUfGcCXAFb+Mw=
-----END CERTIFICATE-----
subject=C = JP, ST = Tokyo, O = Internet Widgits Pty Ltd
issuer=C = JP, ST = Tokyo, O = Internet Widgits Pty Ltd
---
No client certificate CA names sent
Peer signing digest: SHA256
Peer signature type: RSA-PSS
Server Temp Key: X25519, 253 bits
---
SSL handshake has read 1436 bytes and written 281 bytes
Verification error: self-signed certificate
---
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: AC509E77972734E3D291365A36E657F35271CDF3BDEA2515A70D36116398BA33
    Session-ID-ctx:
    Master-Key: 3B863598DB03087EFF35E42485126B21C6B8832594EA40F915664E82BEE0B44EB35E292795C7F5569A124F4DADC4B488
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    TLS session ticket lifetime hint: 300 (seconds)
    TLS session ticket:
    0000 - af c3 66 dd d7 18 04 12-df 77 07 63 ee 17 f3 88   ..f......w.c....
    0010 - db 1c 23 22 04 be 69 6d-be 5b aa 85 e9 b3 ae 72   ..#"..im.[.....r
    0020 - 93 34 fd 13 ef c9 91 38-91 cb 08 48 73 5b b4 99   .4.....8...Hs[..
    0030 - b0 f4 b6 c8 c0 c9 e5 eb-12 7a a0 05 e7 53 a8 3f   .........z...S.?
    0040 - 63 ad a6 40 1c 04 75 22-23 7a 65 56 a4 df aa 4e   [email protected]"#zeV...N
    0050 - f5 d5 03 f6 c1 d9 ac d4-7f 64 ab 8a 9a 2f 5a af   .........d.../Z.
    0060 - 69 f5 01 1b 2e 32 1a 0a-71 87 cb 62 5e a5 e9 6f   i....2..q..b^..o
    0070 - c3 22 9e 33 d7 93 a8 10-b2 85 34 f1 1d a1 29 f7   .".3......4...).
    0080 - 16 0d 9c aa 32 8f 14 b8-29 48 1d e7 50 7a 00 63   ....2...)H..Pz.c
    0090 - 64 3a bd 25 7e 01 99 01-17 d5 47 cb a9 c0 6e 54   d:.%~.....G...nT
    00a0 - 1d f0 8a db 71 3c 2c 31-f4 dd f8 12 30 8a e4 45   ....q<,1....0..E
    00b0 - 4b 85 0b 55 c4 ae 06 98-67 6e 26 e9 bb 4f 89 aa   K..U....gn&..O..

    Start Time: 1668617406
    Timeout   : 7200 (sec)
    Verify return code: 18 (self-signed certificate)
    Extended master secret: yes
---
DONE

TLS1.2に対応していることが分かる。オプションを以下のように変更して実行する

  • -tls1_3
  • -tls1_1
  • -tls1
  • -ssl3
  • -ssl2

結果として、TLSv1以上に対応していることが分かった(いつの間にか-ssl3-ssl2のオプションはサポートされなくなった模様)。 ちなみに、この時に、 /usr/local/etc/httpd/extra/httpd-ssl.confの中では、以下の記述があるので、辻褄があうことになる。

SLProtocol all -SSLv3
SSLProxyProtocol all -SSLv3

TLSv1.2以上のみ許可するように設定

/usr/local/etc/httpd/extra/httpd-ssl.confを編集して、TLSv1.2の接続のみ許可するように設定変更する。

#SSLProtocol all -SSLv3
#SSLProxyProtocol all -SSLv3
SSLProtocol +TLSv1.2 +TLSv1.3
SSLProxyProtocol +TLSv1.2 +TLSv1.3

参考)https://httpd.apache.org/docs/current/mod/mod_ssl.html#sslprotocol

設定変更したら、`apache`を再起動しておく。

### 検証
TLSv1.1での接続では失敗↓
```sh
$ echo | openssl s_client -connect localhost:443 -tls1_1
CONNECTED(00000005)
00D6B10701000000:error:0A00042E:SSL routines:ssl3_read_bytes:tlsv1 alert protocol version:ssl/record/rec_layer_s3.c:1584:SSL alert number 70
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 7 bytes and written 104 bytes
Verification: OK
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.1
    Cipher    : 0000
    Session-ID:
    Session-ID-ctx:
    Master-Key:
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    Start Time: 1668617975
    Timeout   : 7200 (sec)
    Verify return code: 0 (ok)
    Extended master secret: no
---

TLSv1での接続も失敗↓

$ echo | openssl s_client -connect localhost:443 -tls1
CONNECTED(00000005)
0076FC1301000000:error:0A00042E:SSL routines:ssl3_read_bytes:tlsv1 alert protocol version:ssl/record/rec_layer_s3.c:1584:SSL alert number 70
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 7 bytes and written 104 bytes
Verification: OK
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1
    Cipher    : 0000
    Session-ID:
    Session-ID-ctx:
    Master-Key:
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    Start Time: 1668618050
    Timeout   : 7200 (sec)
    Verify return code: 0 (ok)
    Extended master secret: no
---

念の為、TLSv1.2TLSv1.3は問題なく受けられることがも確認した。 検証が無事に予定通りに完了した。

まとめ

  • apacheサーバにSSLの自己証明書を導入できた。
  • サーバが対応しているSSL/TLSのバージョンの確認方法を実行できた。
  • 特定なSSL/TLSバージョンを指定(+/-)する方法を検証できた。
  • 最終的にTLSv1.2以上のみ許可する方法を設定ができた。

参考資料(特別THX!)