トップ 履歴 一覧 カテゴリ ソース 検索 ヘルプ RSS ログイン

OpenBSD/httpd/68(relayd+tsl)

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) を参照。

自己証明書で 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へ。