INDEX
OpenBSD Webサーバ の SSL(TSL) 接続 (httpd on OpenBSD 6.8 7.0)
OpenBSD の Webサーバ httpd(relayd) で、SSL(TSL) 接続する。
自己証明書(オレオレ証明書) と ACME client を用いての Let's Encrypt の証明書の取得と更新をする。
httpd 自体を動かす設定は、OpenBSD/httpd/68(relayd) を参照。
- 関連 man → httpd(8), httpd.conf(5), openssl(1), acme-client(1)
自己証明書で SSL(TSL) 接続
秘密鍵と証明書の作成
LibreSSL の openssl コマンドを使って、サーバの秘密鍵と証明書(自己署名証明書)を作成する。
秘密鍵の作成
bbb# openssl genrsa -out /etc/ssl/private/server.key 2048 Generating RSA private key, 2048 bit long modulus ..........................+++++ ..............+++++ e is 65537 (0x10001)
証明書署名要求(CSR)の作成
-subj オプションの内容は、対象のサーバに合わせて変える。指定しなければ、対話形式で入力となる。特に CN については、実際のホスト名(URL の FDQN)に合わせる。
bbb# openssl req -new -key /etc/ssl/private/server.key -out /etc/ssl/private/server.csr -subj "/C=JP/ST=Tokyo/L=Chuo-Ku/CN=example.com"
証明書(CRT)の作成
bbb# openssl x509 -days 3650 -req -signkey /etc/ssl/private/server.key -in /etc/ssl/private/server.csr -out /etc/ssl/server.crt Signature ok subject=/C=JP/ST=Tokyo/L=Chuo-Ku/CN=example.com Getting Private key
秘密鍵ファイルの内容を確認
bbb# openssl rsa -text -noout -in /etc/ssl/private/server.key RSA Private-Key: (2048 bit) modulus: :以下略
証明書署名要求の内容を確認
bbb# openssl req -text -noout -in /etc/ssl/private/server.csr
Certificate Request:
Data:
Version: 0 (0x0)
Subject: C=JP, ST=Tokyo, L=Chuo-Ku, CN=example.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (2048 bit)
Modulus:
:以下略
証明書ファイルの内容を確認
bbb# openssl x509 -text -noout -in /etc/ssl/server.crt
Certificate:
Data:
Version: 1 (0x0)
Serial Number:
ac:fd:4f:7d:d5:52:9b:a0
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=JP, ST=Tokyo, L=Chuo-Ku, CN=example.com
Validity
Not Before: Dec 5 11:02:41 2021 GMT
Not After : Dec 3 11:02:41 2031 GMT
Subject: C=JP, ST=Tokyo, L=Chuo-Ku, CN=example.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (2048 bit)
Modulus:
:以下略
Webサーバ(httpd) の設定
/etc/httpd.conf に設定する。
TSL(HTTP over SSL/TLS)接続で待つポート番号と、作成したキーファイル /etc/ssl/private/server.key 、証明書 /etc/ssl/server.crt を指定する。
server "default" {
listen on * port 80
listen on * tls port 443
tls {
certificate "/etc/ssl/server.crt"
key "/etc/ssl/private/server.key"
}
# :中略
}
HTTPS通信の疎通確認
まぁ、ブラウザでアクセスして、期待するページが表示されれば OK なんだけど。
curl
curl コマンドでアクセスして確認する。自己証明書なので -k (--insecure) オプションをつけて、安全でないSSL接続も許可するようにする。
bbb$ curl -svk https://localhost:443/ 1> /dev/null
* Trying 127.0.0.1:443...
* Connected to localhost (127.0.0.1) port 8443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/cert.pem
CApath: none
* (304) (OUT), TLS handshake, Client hello (1):
} [314 bytes data]
* (304) (IN), TLS handshake, Server hello (2):
{ [122 bytes data]
* (304) (IN), TLS handshake, Unknown (8):
{ [10 bytes data]
* (304) (IN), TLS handshake, Certificate (11):
{ [795 bytes data]
* (304) (IN), TLS handshake, CERT verify (15):
{ [264 bytes data]
* (304) (IN), TLS handshake, Finished (20):
{ [36 bytes data]
* (304) (OUT), TLS handshake, Finished (20):
} [36 bytes data]
* SSL connection using unknown / AEAD-CHACHA20-POLY1305-SHA256
* ALPN, server did not agree to a protocol
* Server certificate:
* subject: C=JP; ST=Tokyo; L=Chuo-Ku; CN=example.com
* start date: Dec 5 11:02:41 2021 GMT
* expire date: Dec 3 11:02:41 2031 GMT
* issuer: C=JP; ST=Tokyo; L=Chuo-Ku; CN=example.com
* SSL certificate verify result: self signed certificate (18), continuing anyway.
> GET / HTTP/1.1
> Host: localhost:443
> User-Agent: curl/7.72.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Connection: keep-alive
< Content-Length: 170
< Content-Type: text/html
< Date: Fri, 14 Jan 2022 23:49:29 GMT
< Last-Modified: Wed, 13 Jan 2021 15:54:49 GMT
< Server: OpenBSD httpd
<
{ [170 bytes data]
* Connection #0 to host localhost left intact
また、--tlsv1(-1) または、--sslv2(-2)、--sslv3(-3) を指定することで、TLSv1.0 以上 または、SSLv2、SSLv3 で接続する。もっとも、LibreSSL は SSLv2 および SSLv3 をサポートしない。さらに、--tlsv1.0 や --tlsv1.1、--tlsv1.2、--tlsv1.3 で、TLSv1.0 以上、TLSv1.1 以上… となる。
bbb$ curl -svk -ssl3 https://localhost:443/ 1> /dev/null * Trying 127.0.0.1:443... * Connected to localhost (127.0.0.1) port 443 (#0) * LibreSSL was built without SSLv3 support * Closing connection 0 bbb$ bbb$ curl -svk -tsl1 https://localhost:443/ 1> /dev/null * Trying 127.0.0.1:443... * Connected to localhost (127.0.0.1) port 443 (#0) * ALPN, offering h2 * ALPN, offering http/1.1 * successfully set certificate verify locations: * CAfile: /etc/ssl/cert.pem :後略 bbb$ bbb$ curl -svk -tsl1.3 https://localhost:443/ 1> /dev/null * Trying 127.0.0.1:443... * Connected to localhost (127.0.0.1) port 443 (#0) * ALPN, offering h2 * ALPN, offering http/1.1 * successfully set certificate verify locations: * CAfile: /etc/ssl/cert.pem :後略
openssl s_client
LibreSSL の openssl コマンドの s_client を利用して、TSL接続を確認する。
-connect localhost:443 で接続先のホストとポート番号を指定し、-showcerts でサーバ証明書を表示する。また、SNI(Server Name Indication) の場合、-servername localhost でサーバ名も指定する。
s_client は、SSL/TSL通信クライアントなので、サーバにコマンドを送るために標準入力の入力待ちとなる。エンターキーを押すか、nullディバイスを標準入力に渡す(< /dev/null)。
bbb$ openssl s_client -showcerts -connect localhost:443 -servername localhost < /dev/null
CONNECTED(00000003)
depth=0 C = JP, ST = Tokyo, L = Chuo-Ku, CN = example.com
verify error:num=18:self signed certificate
verify return:1
write W BLOCK
---
Certificate chain
0 s:/C=JP/ST=Tokyo/L=Chuo-Ku/CN=example.com
i:/C=JP/ST=Tokyo/L=Chuo-Ku/CN=example.com
-----BEGIN CERTIFICATE-----
:中略
-----END CERTIFICATE-----
---
Server certificate
subject=/C=JP/ST=Tokyo/L=Chuo-Ku/CN=example.com
issuer=/C=JP/ST=Tokyo/L=Chuo-Ku/CN=example.com
---
No client certificate CA names sent
Server Temp Key: ECDH, X25519, 253 bits
---
SSL handshake has read 1326 bytes and written 369 bytes
---
New, TLSv1/SSLv3, Cipher is AEAD-CHACHA20-POLY1305-SHA256
Server public key is 2048 bit
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
Protocol : TLSv1.3
Cipher : AEAD-CHACHA20-POLY1305-SHA256
Session-ID:
Session-ID-ctx:
Master-Key:
Start Time: 1642210666
Timeout : 7200 (sec)
Verify return code: 0 (ok)
---
DONE
bbb$
使用するTLSのバージョン指定(-tls1 | -tls1_1 | -tls1_2 | -tls1_3)、制限(-no_tls1 | -no_tls1_1 | -no_tls1_2 | -no_tls1_3)、使用する暗号スイートを指定(-cipher cipherlist)(リストは ciphers コマンドで確認)ができる。
bbb$ openssl ciphers -v
AEAD-CHACHA20-POLY1305-SHA256 TLSv1.3 Kx=TLSv1.3 Au=TLSv1.3 Enc=ChaCha20-Poly1305 Mac=AEAD
:中略
AES256-SHA256 TLSv1.2 Kx=RSA Au=RSA Enc=AES(256) Mac=SHA256
:中略
AES128-SHA256 TLSv1.2 Kx=RSA Au=RSA Enc=AES(128) Mac=SHA256
:中略
bbb$
bbb$ openssl s_client -showcerts -connect localhost:443 -servername localhost -tls1_2 -cipher AES128-SHA256 < /dev/null
CONNECTED(00000003)
depth=0 C = JP, ST = Tokyo, L = Chuo-Ku, CN = example.com
verify error:num=18:self signed certificate
verify return:1
write W BLOCK
---
:中略
---
New, TLSv1/SSLv3, Cipher is AES128-SHA256
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
Protocol : TLSv1.2
Cipher : AES128-SHA256
Session-ID:
Session-ID-ctx:
Master-Key: 1335A8833AC1494CFE00E7D4B2633859D62CC5330268B4132E47E0C25FEDFB2A5F3123B28F10601CA706726E761B45B8
Start Time: 1642212400
Timeout : 7200 (sec)
Verify return code: 0 (ok)
---
DONE
bbb$
Let's Encrypt の証明書で SSL(TSL) 接続
OpenBSD 6.1 から追加された ACME クライアントを利用して、Let's Encrypt の取得・更新を行い、SSL(TSL) 接続する。
acme-client の設定
/etc/acme-client.conf に設定する。サンプルが /etc/examples/acme-client.conf にある。
bbb# cp -p /etc/examples/acme-client.conf /etc/
サンプルをコピーして、末尾の domain 部分の example.com 等を自分のドメインに変更する。複数のドメイン名に対応する Subject Alternative Names(SANs) を利用する場合は、alternative names にカンマまたはスペース区切りで列挙する。
domain example.com {
#alternative names { secure.example.com }
domain key "/etc/ssl/private/example.com.key"
domain full chain certificate "/etc/ssl/example.com.fullchain.pem"
sign with letsencrypt
#challengedir /var/www/acme
}
Webサーバ(httpd) の設定
/etc/httpd.conf に設定する。サンプルが /etc/examples/httpd.conf にある。
必要になるのは、ドメイン名の検証を行う HTTP-01 チャレンジ の応答を返すための設定と、取得した証明書(とその秘密鍵)ファイルを参照するようにする。
server "default" {
listen on * port 80
listen on * tls port 443
tls {
certificate "/etc/ssl/example.com.fullchain.pem"
key "/etc/ssl/private/example.com.key"
}
location "/.well-known/acme-challenge/*" {
root "/acme"
request strip 2
}
}
証明書の取得
acme-client を実行して、証明書が取得できたら、httpd を再起動して、秘密鍵と証明書を読み込み直す。
bbb# rcctl restart httpd httpd(ok) httpd(ok) bbb# acme-client -v example.com acme-client: /etc/acme/letsencrypt-privkey.pem: generated RSA account key acme-client: /etc/ssl/private/example.com.key: generated RSA domain key acme-client: https://acme-v02.api.letsencrypt.org/directory: directories acme-client: acme-v02.api.letsencrypt.org: DNS: 172.65.32.248 acme-client: dochngreq: https://acme-v02.api.letsencrypt.org/acme/authz-v3/00000000000 acme-client: challenge, token: **********, uri: https://acme-v02.api.letsencrypt.org/acme/chall-v3/00000000000/XXXXXX, status: 0 acme-client: /var/www/acme/**********: created acme-client: https://acme-v02.api.letsencrypt.org/acme/chall-v3/00000000000/XXXXXX: challenge acme-client: order.status 1 acme-client: https://acme-v02.api.letsencrypt.org/acme/finalize/111111111/22222222222: certificate acme-client: order.status 3 acme-client: https://acme-v02.api.letsencrypt.org/acme/cert/zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz: certificate acme-client: /etc/ssl/example.com.fullchain.pem: created bbb# rcctl restart httpd httpd(ok) httpd(ok) bbb#
証明書の自動更新
Let's Encrypt の証明書の有効期限は 90日 で作成される。このため、証明書を維持するには、定期的に更新が必要となる。
acme-client は、有効期限が30日を切ると更新を行うようになるので、 acme-client example.com && rcctl reload httpd とコマンドをつなげて、証明書の更新と再起動を行うように、cron に設定するか、/etc/daily.local や /etc/weekly.local にコマンドを記載して実行させる。
bbb# cat /etc/daily.local # update Let's Encrypt certificate. acme-client example.com && rcctl reload httpd bbb#
最終更新時間:2022年02月11日 23時03分51秒 指摘や意見などあればSandBoxのBBSへ。