1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Linux】SSL/TLS証明書作成

1
Last updated at Posted at 2024-12-04

拡張子がややこしくないですか?
SSL/TLSについての概要はこちらにまとめています。

■証明書作成の流れ(2パターン)

パターン1:外部CAに署名してもらう
パターン2:自前CAで署名する

■パターン1:外部CAに署名してもらう

CSRを作成して認証局(DigiCert / Let's Encryptなど)に提出し、署名済みのサーバ証明書を取得する方法。本番環境はこちらが基本。

① サーバ秘密鍵を作成

openssl genrsa -out server.key 2048

genrsa: RSA秘密鍵を生成
-out server.key: 出力先ファイルとしてserver.keyを指定(拡張子は.pemの場合もある)
2048: 鍵の長さを2048ビットに指定

参考:公開鍵抽出

秘密鍵が生成されるが、その中には対応する公開鍵の情報も含まれている。
keyとcertが一致しているかの確認や公開鍵のみ共有したい場合などで、公開鍵をエクスポートするには以下コマンド

openssl rsa -in server.key -pubout -out public-key.pem

rsa: RSAの秘密鍵や公開鍵の操作を行う
-in server.key: 入力ファイルとして秘密鍵を指定
-pubout: 公開鍵を出力するよう指定
-out public-key.pem: 公開鍵の出力先ファイルを指定

② CSRを作成

openssl req -new -key server.key -out server.csr

req: 証明書署名要求(CSR)を作成または処理する
-new: 新しいCSRまたは証明書を生成する.※ここでは-x509オプションがないため、CSRが作成される
-key server.key: CSR作成に使用する秘密鍵を指定
-out server.csr: 生成されたCSRの出力先ファイルを指定

③ 外部CAに提出

作成した server.csr を認証局に提出する。
審査後、CSRの内容に対して“署名する”ことでサーバ証明書が発行され、中間CA証明書と共に返却される。

server.crt
intermediate.crt(中間CA)

④ サーバ設定(例:Nginx)

クライアントは以下のようにチェーンを辿って信頼する。

サーバ証明書(server.crt)
   ↓
中間CA(intermediate.crt)
   ↓
ルートCA (クライアントのOSに最初から入ってる信頼の起点)

サーバ証明書(server.crt)だけでは信頼チェーンが成立しないため、中間CA証明書と連結したfullchain.pemを設定する必要がある。

cat server.crt intermediate.crt > fullchain.pem
/etc/nginx/nginx.conf など
server {
    listen 443 ssl;
    server_name example.com;

    ssl_certificate       /etc/nginx/certs/fullchain.pem;    #クライアントに提示する証明書チェーン。 fullchain.pem = server.crt + intermediate.crt
    ssl_certificate_key   /etc/nginx/certs/server.key;       #サーバ側だけが保持する秘密鍵

    location / {
        proxy_pass http://backend;
    }
}

⑤ クライアント設定は不要

公開されているCAの証明書を利用する場合、クライアントとなるPCやサーバOSは基本的にあらかじめ信頼しているルートCAを持っている。
⇒ 送られてきたサーバ証明書が信頼しているCA一覧(rootCA)で署名されていることを検証することができるため、基本的にはクライアント側での設定は不要。
またCAについてもLet's Encrypt などでは certbot 等により自動更新する構成が一般的

■パターン2:自前CAで署名する

自分でCA(認証局)を作り、そのCAでサーバ証明書に署名する方法。クライアントにCA配布必要。
外部公開しない、内で閉じたシステムでよく使われている。

① CA(認証局)を作成

秘密鍵(CA用)

openssl genrsa -out rootCA.key 4096

genrsa: RSA秘密鍵を生成する
-out rootCA.key: 出力先ファイルを指定
4096: 鍵長(CAは強めにするのが一般的)

ルートCA証明書

openssl req -x509 -new -nodes \
  -key rootCA.key \
  -sha256 -days 3650 \
  -out rootCA.pem

req: CSRまたは証明書を作成するコマンド
-x509: CSRではなく自己署名証明書を作成(=CAになる)
-new: 新規作成
-nodes: 秘密鍵をパスフレーズなしで扱う(自動処理向け)
-key rootCA.key: 使用する秘密鍵
-sha256: 署名アルゴリズム
-days 3650: 有効期限(約10年)
-out rootCA.pem: 出力ファイル

② サーバ秘密鍵を作成

パターン1と同じ

openssl genrsa -out server.key 2048

③ CSRを作成

パターン1と同じ

openssl req -new -key server.key -out server.csr

④ CAで署名してサーバ証明書を作成

openssl x509 -req \
  -in server.csr \
  -CA rootCA.pem \
  -CAkey rootCA.key \
  -CAcreateserial \
  -out server.crt \
  -days 365 \
  -sha256 \
  -extfile san.txt

x509: 証明書の生成・操作
-req: CSRを元に証明書を発行する
-in server.csr: 入力CSR
-CA rootCA.pem: 使用するCA証明書
-CAkey rootCA.key: CAの秘密鍵
-CAcreateserial: シリアル番号ファイルを自動生成
-out server.crt: 出力するサーバ証明書
-days 365: 有効期限
-sha256: 署名アルゴリズム
-extfile san.txt: 拡張設定(SAN)を読み込む

openssl x509 -text -in server.crt -noout

で証明書の情報を確認できる

⑤ SAN設定(重要)

san.txt
subjectAltName = @alt_names

[alt_names]
DNS.1 = example.com
DNS.2 = www.example.com

👉 SANがないと以下エラーになる場合あり:

ERRO[2024-08-08 23:02:14] Failed verifying certificate: x509: certificate relies on legacy Common Name field, use SANs instead 
ERRO[2024-08-08 23:02:14] An error occurred: x509: certificate relies on legacy Common Name field, use SANs instead 

⑥ クライアント側にCAを配布

自己署名証明書や内部CAの証明書を使用している場合、クライアント側はoptionで作成されたルートCA証明書を信頼済みリストに登録することで、システム上のアプリケーションがその証明書を信頼できるようにする。
※配置場所や実装しているシステム(Apache,Nginx等)により異なるので注意

RHEL/Rocky/CoreOS系

# CA配置
cp my-root-ca.crt /etc/pki/ca-trust/source/anchors/

# 反映
update-ca-trust extract

# 信頼リスト確認
trust list

ファイルとしては、
/etc/pki/tls/certs/ または /etc/ssl/certs/ ディレクトリの
ca-bundle.crt または ca-bundle.trust.crt
等にリストされる。(色んなところにあるな…)

Ubuntu/Debian系

# CA配置
cp my-root-ca.crt /usr/local/share/ca-certificates/

# 反映
update-ca-certificates

これで、curl,docker,podmanなどのアクセス含めそのサイトを信頼するようになる

Windows

ちなみにwindowsPCやサーバでは基本的に以下の方法で追加できる。

`certmgr.msc` または `mmc`
「証明書(ローカルコンピューター)」追加
"信頼されたルート証明機関"にインポート

image.png

(非推奨)サーバで直接署名して作成する場合

④については、-signkeyで指定することで、CAで署名せずにサーバ自身の秘密鍵を使って署名することもできる

openssl x509 -req \
  -days 365 \
  -in server.csr \
  -signkey server.key \   #サーバの秘密鍵
  -out server.crt \
  -extfile san.txt

CAが署名する場合は信頼されるが、自己署名になるため誰も信頼してない状態になる。
クライアント側からみてもそのCA信頼してる?→知らない、なのでエラーになるが、サーバ証明書をそのままCAとして登録することで対処は可能。
ただ、CAではrootCA.pem 1個配ればOKだが、この場合はサーバ証明書毎にひとつずつ登録することになるため、管理は煩雑になる

■作成例

ここでは上記非推奨の自己署名する場合の出力例

[root@host01 ~]# openssl genrsa -out private.key 2048    #秘密鍵作成
Generating RSA private key, 2048 bit long modulus
....................................+++
............................................................+++
e is 65537 (0x10001)
[root@host01 ~]# 
[root@host01 ~]# ls
private.key
[root@host01 ~]# 
[root@host01 ~]# cat private.key 
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAv9bwNG3hA
(略)
dczV46uEYrM/oUur95a1KZRSh
-----END RSA PRIVATE KEY-----
[root@host01 ~]# 
[root@host01 ~]# openssl req -new -key private.key -out server.csr   #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) [XX]:JP
State or Province Name (full name) []:Tokyo
Locality Name (eg, city) [Default City]:Raccoon City
Organization Name (eg, company) [Default Company Ltd]:Umbrella
Organizational Unit Name (eg, section) []:human experiment Unit                                                    
Common Name (eg, your name or your server's hostname) []:host01.local
Email Address []:hogehoge.co.jp

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
[root@host01 ~]# 
[root@host01 ~]# ls
private.key  server.csr
[root@host01 ~]# cat server.csr
-----BEGIN CERTIFICATE REQUEST-----
MIIC4zCCAcsCAQAwgZ0xCzAJBgNVBAYTAkpQMQ4wDAYDVQQIDAVUb2t5bzEVMBMG
(略)
obc/VkE6A/q7OJa6u5efANIn8Tcj4L4=
-----END CERTIFICATE REQUEST-----
[root@host01 ~]# 

[root@host01 ~]# vi san.txt
[root@host01 ~]# cat san.txt
subjectAltName = DNS:example.com
[root@host01 ~]#
[root@host01 ~]# openssl x509 -req -days 365 -in server.csr -signkey private.key -out server.crt -extfile san.txt     #秘密鍵で署名してサーバ証明書作成
Signature ok
subject=/C=JP/ST=Tokyo/L=Raccoon City/O=Umbrella/OU=human experiment Unit/CN=host01.local/emailAddress=hogehoge.co.jp
Getting Private key
[root@host01 ~]# 
[root@host01 ~]# ls
private.key  san.txt  server.crt  server.csr
[root@host01 ~]# 
[root@host01 ~]# cat server.crt
-----BEGIN CERTIFICATE-----
MIID2TCCAsGgAwIBAgIJAOy0I96HysgOMA0GCSqGSIb3DQEBCwUAMIGdMQswCQYD
(略)
gPh37FrGGL+hZnn8fSD2JlO4ENoDPkZhjP7Ywso=
-----END CERTIFICATE-----
[root@host01 ~]# 
[root@host01 ~]# openssl x509 -text -in server.crt -noout     #サーバ証明書確認
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            ec:b4:23:de:87:ca:c8:0e
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=JP, ST=Tokyo, L=Raccoon City, O=Umbrella, OU=human experiment Unit, CN=host01.local/emailAddress=hogehoge.co.jp
        Validity
            Not Before: Dec  4 14:31:37 2024 GMT
            Not After : Dec  4 14:31:37 2025 GMT
        Subject: C=JP, ST=Tokyo, L=Raccoon City, O=Umbrella, OU=human experiment Unit, CN=host01.local/emailAddress=hogehoge.co.jp
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:bf:d6:f0:34:6d:e1:01:c4:c6:ca:1e:e3:4e:5c:
                    1e:25:d1:52:eb:36:fb:bc:24:35:23:d9:a4:cd:4c:
                    ba:9d:6f:20:19:2c:4b:4c:11:2b:e8:6f:0f:80:8f:
                    aa:76:88:89:bc:1f:78:7f:a3:f8:f1:4a:01:1f:73:
                    71:52:aa:20:82:a1:38:93:ec:f6:cf:75:68:8f:ff:
                    ce:82:f6:4f:51:01:e3:bd:b6:b8:fc:98:9d:d0:80:
                    2f:29:3c:ac:54:ab:b1:c6:ee:5b:8f:f2:4d:0a:4a:
                    76:2b:cc:c1:9f:24:93:18:66:85:bb:3e:8b:80:b1:
                    d1:96:d9:3d:eb:dc:80:84:7d:71:d6:ef:c1:1e:cd:
                    6b:08:29:7c:6d:00:f9:51:ff:d8:8e:3b:77:26:0e:
                    66:ca:c9:17:c2:ff:a8:e3:1a:83:f8:24:24:4f:6a:
                    6f:0c:8d:71:e9:3d:c5:2f:80:4a:52:32:bf:dd:54:
                    2d:98:fd:47:21:09:51:59:07:36:13:2a:f0:e7:19:
                    ee:d1:39:f9:c3:d2:f6:bb:bc:d2:92:92:bc:10:27:
                    1c:6d:75:42:fc:68:50:f5:23:88:8d:de:0b:39:38:
                    64:b5:8b:6b:3d:dc:0c:bd:99:99:97:3f:86:ef:fa:
                    71:e4:c6:e3:08:f3:a7:0f:62:40:62:62:06:be:06:
                    cd:d3
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Alternative Name: 
                DNS:example.com
    Signature Algorithm: sha256WithRSAEncryption
         24:d5:3f:6c:d0:00:68:a2:8e:b1:fb:33:c2:53:ce:0e:af:96:
         b3:07:3b:81:96:bc:25:0c:a0:99:2a:8b:15:6e:0b:d5:46:46:
         72:0e:c1:dc:dc:be:04:f7:42:9f:f0:16:8d:06:4e:80:59:cb:
         13:17:d4:c0:a3:bd:fe:af:bb:83:51:e7:e8:18:84:ec:03:21:
         45:86:4a:a0:3a:69:30:76:69:06:e3:f6:c6:cb:6e:57:7f:58:
         a8:6e:4d:01:e5:7e:15:5c:50:e4:3f:c6:86:d0:5e:82:5d:2a:
         8a:3b:c7:01:bb:fc:90:ab:0d:8c:ea:67:0d:c2:ff:fe:28:47:
         88:02:e6:8e:4d:46:8e:90:24:0e:55:11:e7:cf:92:3b:82:03:
         54:f8:8b:30:dd:97:2d:5d:61:84:11:49:37:45:9f:a9:b2:aa:
         c2:ee:da:64:00:cf:09:67:95:58:23:2e:02:60:b9:9d:c1:d0:
         54:3f:df:17:09:f8:b1:f0:11:ed:dd:07:27:5a:09:02:53:0b:
         f5:14:cf:9f:db:23:81:e4:a6:a7:f0:91:b0:4a:3c:f1:9e:4e:
         fb:8a:ee:fd:db:37:27:f3:2b:40:0d:80:f8:77:ec:5a:c6:18:
         bf:a1:66:79:fc:7d:20:f6:26:53:b8:10:da:03:3e:46:61:8c:
         fe:d8:c2:ca

■HTTPS通信確認

openssl s_client -connect xxxx.com:443

openssl s_client: OpenSSLコマンドでSSL/TLSクライアントを起動
-connect xxxx.com:443: 接続先のホスト名とポート番号を指定

このコマンドを実行すると、指定されたホストとポート上のサーバーに対してSSL/TLS接続が試みられる。
接続が成功すると、サーバーの証明書情報や使用されるSSL/TLSバージョンなどの詳細な情報が表示される。

証明書ファイルの内容を表示したい場合は以下

openssl x509 -in xxxx.crt -text -noout

■cURL確認(おまけ)

curl http://xxxx.com

-L:リダイレクトがあればリダイレクト先の情報を取得
-s:進捗状況を非表示。-sSとすることが多い
-S:エラーは表示。-sSとすることが多い
-v:詳細ログを出力
-I:HTTPレスポンスヘッダを取得
-k:SSL接続で証明書エラーをスキップ

1
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?