自签发证书配置 HTTPS 单向双向验证
好久以前阅读《HTTP/2 in Action》一书起了个头,又重新放回了书架。近来再次对 HTTPS/TLS 来了劲,自己的博客用的是 Let's Encrypt 签发的证书,这次实践一下自签发证书的过程与配置,并实现单向和双向的认证方式。
如果是配置单向认证的过程需要有以下三个证书
证书是含有组织与域名或(CA) 信息以及公钥的文件, root.key 和 root.crt 将被用于签发其他的证书。这里的 crt 证书是 x509 格式的。
浏览器只会信任某些 CA 机构签发的证书,如 DigiCert, GlobalSign, GoDaddy, Amazon Root CA,Let's Encrypt 等。如果是不被信任 CA 签发的证书,我们在浏览器中打开相应的 HTTPS url 就会看到 'Not Secure - Your connection is not private' 的提示,要继续访问需自行承担可能的安全责任。
如果是公司内部,或相互信任的公司之间的通信,用自签发的证书也不成问题。不过直接用浏览器或其他 HTTPS 客户端信任又免费的 Let's Encrypt 来签发证书可免去浏览器的警告或某些特殊配置。
根证书,服务端证书或后面将要讲到的客户端证书的完整生成过程都是三步
根据不同的情景,以上某些步骤可以合并操作。
1. 生成根私钥 root.key
虽然 openssl genrsa 支持最小的长度是 512,但 Nginx 要求最短长度为 2048。
2. 生成根证书请求文件 root.csr
生成证书请求文件是一个中间步骤,目的是准备组织和域名信息,再加上私钥用于签发最后的证书文件(包含公钥)
3. 生成自签发的根证书 root.crt
CA 就是自己,所以不用指定 -CA 参数
其实最终只需要 root.key 和 root.csr 文件,所以 #2, #3 两步可合而为一,并且不生成中间过程的 root.csr 请求文件,只生成 root.crt 文件
** 由于是自签发根证书,只需一条命令便能生成需要的 root.key 和 root.crt 文件
如果是在 macOS 中可用命令
或者用 openssl 查看,下面显示了部分信息
1. 生成服务端私钥与证书请求文件
这里用一条命令同时生成 server.key 和 server.csr 两文件
2. 用根证书签发服务端证书
到现在我们就有了 server.key 和 server.crt 文件,同样的方式可以查看 server.crt 的信息。
比如我们查看前面生成的 key, csr, crt 文件内部如下:
覆盖 /usr/shar/nginx/html/index.html 的内容为 "Ok", 以免后的 curl 命令输出过长。
编辑 /etc/nginx/nginx.cfg, 在 http 块中加上
然后启动 nginx 或重新启动 nginx -s reload
用 curl 测试
已在 /etc/hosts 中配置了 127.0.0.1 server.local 映射。或可在另一个 Docker 容器中测试(docker run -it --net host ubuntu:24.04)
控制台输出明确显示了完整的 TLS 握手过程
点击地址栏 "Not Secure" 可查看服务端证书以及 CA 的信息。点 "Advanced" -> "Processed to server.local (unsafe)" 自担安全的信任该网站 server.local 而访问它的内容
还能用
用
再编辑 default-ssl.conf,配置一个 443 虚拟机
apachectl -k restart 重启即可
相关的配置项有
从中我们发现
试着在 application.properties 中加上
启动 SpringBoot Web 项目,看到控制台输出
如果采用 key-store 的配置方式则要用 Java 的 keytool 命令把 openssl 生成的 server.key, server.crt 生成 keystore.jks 文件,或者直接用 keytool 替代 openssl 来生成它所需的 keystore.jks 文件。
生成客户端 client1.key, client1.crt
编辑 /etc/nginx/nginx.cfg, server {} 块
nginx -s reload
现在用 curl -k 完全信息服务端也没用,服务端可不买这个账
400 Bad Request, 因为 No required SSL certificate was sent
主动带上 client1.key 和 client1.crt 就行,只要服务端的证书是不被广泛接受的,就要用
除了用命令 curl,同样可用
那浏览器该怎么办呢?
我们可用 openssl 由 client1.crt 和 client1.key 生成 PKCS#12 格式的客户端证书上,然后导入到浏览器当中
如果不想设置的密码的话在两次提示输入密码时直接回车跳过,生成 client1.p12
比如在 Chrome 浏览器,可找到 Settings/Privacy and security/Security/Advanced/Manage certificates/Personal/Imports..., 然后导入前面生成的 client1.p12 文件,有密码的话就输入相同的密码。再浏览 https://server.local 就没问题了。
用 Postman 直接浏览 https://server.local 也同样得到 400 Bad Request 的错误,也需要配置客户端证书才能正常访问。Postman 同时支持 client1.crt,client1.key 组合,和 client1.p12(有密码则输入), 请看下方的截图
完后 Postman 就能看到 https://server.local 的正确输出了。
curl 也可以用 p12 格式的证书
可分别用下面的 curl 进行测试
链接:
永久链接 https://yanbin.blog/self-certs-https-tls-mtls-config/, 来自 隔叶黄莺 Yanbin's Blog
[版权声明]
本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。
如果是配置单向认证的过程需要有以下三个证书
- 根(CA) 证书: root.crt
- 服务端私钥文件: server.key
- 服务端公钥证书: server.crt
证书是含有组织与域名或(CA) 信息以及公钥的文件, root.key 和 root.crt 将被用于签发其他的证书。这里的 crt 证书是 x509 格式的。
浏览器只会信任某些 CA 机构签发的证书,如 DigiCert, GlobalSign, GoDaddy, Amazon Root CA,Let's Encrypt 等。如果是不被信任 CA 签发的证书,我们在浏览器中打开相应的 HTTPS url 就会看到 'Not Secure - Your connection is not private' 的提示,要继续访问需自行承担可能的安全责任。
如果是公司内部,或相互信任的公司之间的通信,用自签发的证书也不成问题。不过直接用浏览器或其他 HTTPS 客户端信任又免费的 Let's Encrypt 来签发证书可免去浏览器的警告或某些特殊配置。
根证书,服务端证书或后面将要讲到的客户端证书的完整生成过程都是三步
- openssl genrsa 生成私钥 xxx.key
- openssl req -new -out xxx.csr -key xxx.key 产生证书请求文件
- openssl x509 -req in xxx.csr -out xxx.crt -signkey xxx.key -CAcreateserial -days 365 生成相应证书文件。生成根证书时无需指定 -CA 参数,因为自己就是 CA,其他证书则需用 -CA root.crt 让根证书予以签发
根据不同的情景,以上某些步骤可以合并操作。
生成根(CA)证书
最终要得到的 root.key, root.crt 用于签发服务端或客户端证书。如果对中间过程没有兴趣的,可用该节最后的openssl req -x509... 一条命令完成所有。1. 生成根私钥 root.key
1openssl genrsa -out root.key 2048虽然 openssl genrsa 支持最小的长度是 512,但 Nginx 要求最短长度为 2048。
2. 生成根证书请求文件 root.csr
1openssl req -new -out root.csr -key root.key \
2 -subj "/C=US/ST=Illinois/L=Chicago/O=CA Company/CN=RootCA"-subj 参数指定所有组织相关的信息,免得按提示要多次输入,C, ST, O 分别是国家,省(州), 组织名,这里省略了 OU 部门名称,根据实际进行输入即可。最后 CN,此处是根证书,可随便指定,无需真正的域名。生成证书请求文件是一个中间步骤,目的是准备组织和域名信息,再加上私钥用于签发最后的证书文件(包含公钥)
3. 生成自签发的根证书 root.crt
CA 就是自己,所以不用指定 -CA 参数
1openssl x509 -req -in root.csr -out root.crt -signkey root.key -CAcreateserial -days 3651openssl req -x509 -new -nodes -key root.key -days 365 -out root.crt \
2 -subj "/C=US/ST=Illinois/L=Chicago/O=CA Company/CN=RootCA"** 由于是自签发根证书,只需一条命令便能生成需要的 root.key 和 root.crt 文件
1openssl req -x509 -newkey rsa:2048 -nodes -keyout root.key -out root.crt \
2 -subj "/C=US/ST=Illinois/L=Chicago/O=CA Company/CN=RootCA"如果是在 macOS 中可用命令
open root.crt 查看,默认会用 Keychain Access/Add Certificates 打开,然后可看到信息
或者用 openssl 查看,下面显示了部分信息 1openssl x509 -noout -text -in root.crt
2Certificate:
3 Data:
4 Version: 3 (0x2)
5 Serial Number:
6 34:10:b8:8a:00:86:76:c3:e0:b5:23:4c:0a:79:30:1f:f9:aa:79:17
7 Signature Algorithm: sha256WithRSAEncryption
8 Issuer: C=US, ST=Illinois, L=Chicago, O=CA Company, CN=RootCA
9 Validity
10 Not Before: Nov 27 04:48:07 2024 GMT
11 Not After : Dec 27 04:48:07 2024 GMT
12 Subject: C=US, ST=Illinois, L=Chicago, O=CA Company, CN=RootCA
13 Subject Public Key Info:
14 Public Key Algorithm: rsaEncryption
15 Public-Key: (2048 bit)
16 Modulus:
17 00:b0:84:85:c5:95:aa:f6:ae:e4:e4:97:43:7c:cb:生成服务端私钥与证书
正常的过程是要先有私钥 server.key,证书请求文件 server.csr, 然后用前面的根(CA)证书 root.key 和 root.crt 签发服务端证书,可参考上节中生成 root.key 和 root.csr 的步骤。1. 生成服务端私钥与证书请求文件
这里用一条命令同时生成 server.key 和 server.csr 两文件
1openssl req -newkey rsa:2048 -nodes -keyout server.key -out server.csr \
2 -subj "/C=US/ST=Illinois/L=Chicago/O=X Company/CN=server.local"-subj 参数要留意 CN 必须与服务器的访问方式对应,如果将用 IP 地址(如 192.168.86.101) 访问, 则 CN=192.168.86.101。这里假设将用 server.local 域名来访问,所以设置 CN=server.local,后面在客户端将通过 /etc/hosts 中配置 127.0.0.1 server.local 来访问本地的 https://server.local 服务。 2. 用根证书签发服务端证书
1openssl x509 -req -in server.csr -out server.crt -CA root.crt -CAkey root.key -CAcreateserial -days 365到现在我们就有了 server.key 和 server.crt 文件,同样的方式可以查看 server.crt 的信息。
私钥,证书请求文件和证书的内容格式
不管是私钥,公钥还是证书,或更多我们常见到 key, csr, crt, cer, der, pem, pfx, p12, jks 等扩展名,其实它们内部的格式都差不多,基本像下面那样-----BEGIN XXX-----以上扩展名的缩写为
<ASCII 字符串, 通常是 BASE64 格式>
-----END XXX-----
- PEM(Privacy-Enhanced Mail)
- DER(Distinguished Encoding Rules)
- CRT/CER(Certificate), KEY(key)
- P12(PKCS#12)
- PFX(Predecessor of PKCS#12)
- JKS(Java Key Storage)
比如我们查看前面生成的 key, csr, crt 文件内部如下:
cat server.key在 csr, crt 文件中内容进行 Base64 解码可看到组织及域名信息。有时候我们看到的 *.pem 文件,它可能就是一个 *.crt 文件,比如愿意的外把上面的 server.crt 改名成 server.pem 也行,关键看其中的内容是 BEGIN xxx。
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCnGmYO71gf4bQF
......
3TFxXQvsM5LjL/JCckYRscUiVQiaZzkNi044XeTRLKLrrsEKxOKJ+Dn7R5c4lBIQ
+kP41vHSScLrhltkjKZfQiHQ
-----END PRIVATE KEY----- cat server.csr
-----BEGIN CERTIFICATE REQUEST-----
MIICpDCCAYwCAQAwXzELMAkGA1UEBhMCVVMxETAPBgNVBAgMCElsbGlub2lzMRAw
......
jr3ySo1hczjdhn4TiYR7AtLMTQj4X8aTnSfDBpn95+/jR1x9KjeCwLBgCJWXmtwo
Fu5hcsQXfjc=
-----END CERTIFICATE REQUEST----- cat server.crt
-----BEGIN CERTIFICATE-----
MIIDhzCCAm+gAwIBAgIUb2sb3c3BaZk+z1fOprzKO6Zcu18wDQYJKoZIhvcNAQEL
......
4YXaB54t+I8x/eiYu1W77hJjAG52SsVb/2QiJdbFT0VDwcVrMdMRutMjlg==
-----END CERTIFICATE-----
配置 Nginx 支持 HTTPS 单向验证 (TLS)
有了前面生成的服务端私钥 server.key, 证书 server.crt 后,首先应用到 Nginx Web 服务中。以 Docker 启用的 Ubuntu:24.04 容器为例, 假定 server.key, server.crt 在当前目录中1docker run -it -v ${PWD}:/certs -p 443:443 ubuntu:24.04
2
3root@3010925dc0b1:/# apt update && apt install -y nginx
4root@3010925dc0b1:/# echo Ok > /usr/share/nginx/html/index.html覆盖 /usr/shar/nginx/html/index.html 的内容为 "Ok", 以免后的 curl 命令输出过长。
编辑 /etc/nginx/nginx.cfg, 在 http 块中加上
1 server {
2 listen 443 ssl;
3 server_name server.local;
4 ssl_certificate server.crt;
5 ssl_certificate_key server.key;
6 }然后启动 nginx 或重新启动 nginx -s reload
用 curl 测试
已在 /etc/hosts 中配置了 127.0.0.1 server.local 映射。或可在另一个 Docker 容器中测试(docker run -it --net host ubuntu:24.04)
root@docker-desktop:~# curl https://server.local因为服务器端的证书是自签发的,默认不被信任,需用 -k 信任证书,重试,顺便加上 -v 参数
curl: (60) SSL certificate problem: unable to get local issuer certificate
More details here: https://curl.se/docs/sslcerts.html curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
1root@docker-desktop:~# curl -kv https://server.local
2* Host server.local:443 was resolved.
3* IPv6: (none)
4* IPv4: 127.0.0.1
5* Trying 127.0.0.1:443...
6* Connected to server.local (127.0.0.1) port 443
7* ALPN: curl offers h2,http/1.1
8* TLSv1.3 (OUT), TLS handshake, Client hello (1):
9* TLSv1.3 (IN), TLS handshake, Server hello (2):
10* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
11* TLSv1.3 (IN), TLS handshake, Certificate (11):
12* TLSv1.3 (IN), TLS handshake, CERT verify (15):
13* TLSv1.3 (IN), TLS handshake, Finished (20):
14* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
15* TLSv1.3 (OUT), TLS handshake, Finished (20):
16* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 / X25519 / RSASSA-PSS
17* ALPN: server accepted http/1.1
18* Server certificate:
19* subject: C=US; ST=Illinois; L=Chicago; O=Demo Server; CN=server.local
20* start date: Nov 27 05:34:22 2024 GMT
21* expire date: Nov 27 05:34:22 2025 GMT
22* issuer: C=US; ST=Illinois; L=Chicago; O=CA Company; CN=RootCA
23* SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
24* Certificate level 0: Public key type RSA (2048/112 Bits/secBits), signed using sha256WithRSAEncryption
25* using HTTP/1.x
26> GET / HTTP/1.1
27> Host: server.local
28> User-Agent: curl/8.5.0
29> Accept: */*
30>
31* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
32* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
33* old SSL session ID is stale, removing
34< HTTP/1.1 200 OK
35< Server: nginx/1.24.0 (Ubuntu)
36< Date: Wed, 27 Nov 2024 06:41:10 GMT
37< Content-Type: text/html
38< Content-Length: 3
39< Last-Modified: Wed, 27 Nov 2024 06:38:57 GMT
40< Connection: keep-alive
41< ETag: "6746be81-3"
42< Accept-Ranges: bytes
43<
44Ok控制台输出明确显示了完整的 TLS 握手过程
* TLSv1.3 (OUT), TLS handshake, Client hello (1):用浏览器访问,同样因为我们自己的 rootCA 是不被浏览器信任的,所以看到的是这样
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
点击地址栏 "Not Secure" 可查看服务端证书以及 CA 的信息。点 "Advanced" -> "Processed to server.local (unsafe)" 自担安全的信任该网站 server.local 而访问它的内容还能用
openssl s_client 命令访问 1$ openssl s_client -connect server.local:443
2Connecting to 127.0.0.1
3CONNECTED(00000003)
4depth=0 C=US, ST=Illinois, L=Chicago, O=Demo Server, CN=server.local
5verify error:num=20:unable to get local issuer certificate
6verify return:1
7depth=0 C=US, ST=Illinois, L=Chicago, O=Demo Server, CN=server.local
8verify error:num=21:unable to verify the first certificate
9verify return:1
10depth=0 C=US, ST=Illinois, L=Chicago, O=Demo Server, CN=server.local
11verify return:1
12---
13Certificate chain
14 0 s:C=US, ST=Illinois, L=Chicago, O=Demo Server, CN=server.local
15 i:C=US, ST=Illinois, L=Chicago, O=CA Company, CN=RootCA
16 a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA256
17 v:NotBefore: Nov 27 05:34:22 2024 GMT; NotAfter: Nov 27 05:34:22 2025 GMT
18---
19Server certificate
20-----BEGIN CERTIFICATE-----
21MIIDhzCCAm+gAwIBAgIUaVkSmjyS/M/82njsEW5Dgy2Pg8EwDQYJKoZIhvcNAQEL
22BQAwWDELMAkGA1UEBhMCVVMxETAPBgNVBAgMCElsbGlub2lzMRAwDgYDVQQHDAdD
23aGljYWdvMRMwEQYDVQQKDApDQSBDb21wYW55MQ8wDQYDVQQDDAZSb290Q0EwHhcN
24MjQxMTI3MDUzNDIyWhcNMjUxMTI3MDUzNDIyWjBfMQswCQYDVQQGEwJVUzERMA8G
25A1UECAwISWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28xFDASBgNVBAoMC0RlbW8g
26U2VydmVyMRUwEwYDVQQDDAxzZXJ2ZXIubG9jYWwwggEiMA0GCSqGSIb3DQEBAQUA
27A4IBDwAwggEKAoIBAQDJasqYBxyiMjL6DW6MpiKDloStV4tkFonYaVUMm2fr7ZiY
28Lj5A+rNXcLBvZlaf93hC11EdZljom9l2aIybRRR0ml0NEycE+sGHbOs0PFqtN2nB
29gV/15J5gqTeCO7HpBWkhg3R0+PPj46WK03idz4f0M2Dz9qgnJC+/j3enMX32/t4X
30KG8/lwiah1bAcBq4OU6N6syfpAA10ISljLjg8ztnb0u0WMNOLYgWd6/aOlZk2Wp6
31k7AJrKRiTfjz7Pi3aDMjaTTziQ0Erz+ngD8RYbUhuZIIFDZNGPiJMDSoaj0ffzNz
32fuqVN4TqvMBwGWtKmQ/ofC93cVGXcjZNIUvjSqLrAgMBAAGjQjBAMB0GA1UdDgQW
33BBQzMRYTcWvhMTsRDN4Av2J3Vga6nTAfBgNVHSMEGDAWgBQ5N633VoXMBr+O0TH3
34P8m/B/hHnzANBgkqhkiG9w0BAQsFAAOCAQEAo4cjfmljrr/m9Vsuzw+yD5sp1TPb
35sIp+OF7DWKhRn7CxPv/wnmpexx3RVgBFpJ3erpgFSH+Zu8tP7vRf0t6mqUaWmkMG
36w/iBAJ46tnVlaeiPWEnjkvOUHNb9V1OXFOXQMad0NfyAMulJBHMJiyl73JGqziVP
37fI9U5NgHVWLUtWlvGkdAiukg+RDGSPQYrxaDuwYnsl+vdbmFRw9Yn7I3BxRTqtHo
38FkbWIgTt0URil7dc5t775ZIFVKusH+XC+Kt+wk2Mjp1KCkZ0Kk7auQHfdbjm9mNp
39OJjjwmVs1QeBnuMfdMqLsvEn2FG4pJZ4blq/Z/coLDUHoXo0tk3FDc9vEA==
40-----END CERTIFICATE-----
41subject=C=US, ST=Illinois, L=Chicago, O=Demo Server, CN=server.local
42issuer=C=US, ST=Illinois, L=Chicago, O=CA Company, CN=RootCA
43---
44No client certificate CA names sent
45Peer signing digest: SHA256
46Peer signature type: RSA-PSS
47Server Temp Key: X25519, 253 bits
48---
49SSL handshake has read 1467 bytes and written 403 bytes
50Verification error: unable to verify the first certificate
51---
52New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
53Protocol: TLSv1.3
54Server public key is 2048 bit
55This TLS version forbids renegotiation.
56Compression: NONE
57Expansion: NONE
58No ALPN negotiated
59Early data was not sent
60Verify return code: 21 (unable to verify the first certificate)
61---
62---
63Post-Handshake New Session Ticket arrived:
64SSL-Session:
65 Protocol : TLSv1.3
66 Cipher : TLS_AES_256_GCM_SHA384
67 Session-ID: 0B11B6BFDDB73E9DD08C3FC42AECF250348B22D3E0EB16A3129AD8D527C0A8F4
68 Session-ID-ctx:
69 Resumption PSK: 002B9CD5B0A52362F873BA3D665106A9FD736FB0A50AA330948984FB1E73EDCEC62CEEAAE44710F409008D73911DAFBE
70 PSK identity: None
71 PSK identity hint: None
72 SRP username: None
73 TLS session ticket lifetime hint: 300 (seconds)
74 TLS session ticket:
75 0000 - 9c 74 9e 82 50 ea 6a 63-98 fc b0 d9 d7 53 01 6b .t..P.jc.....S.k
76 0010 - 8d 91 b5 e9 0e 48 97 5c-51 d0 a1 3a 0a 61 b0 79 .....H.\Q..:.a.y
77 0020 - 71 9a 59 1d 7f f4 74 9b-aa 3c f3 52 0b 1f 17 c8 q.Y...t..<.R....
78 0030 - 25 cf 37 bf fc f8 93 55-e4 65 fd 5a 5e dc 66 4c %.7....U.e.Z^.fL
79 0040 - aa 8b 42 a9 46 4f 92 a2-32 25 35 94 ca ad fc 54 ..B.FO..2%5....T
80 0050 - 73 cd 1f 9b ef 31 d3 c8-5d 30 7d c7 28 9e 66 cb s....1..]0}.(.f.
81 0060 - e9 99 c7 f9 f3 a6 05 04-dc 7e 77 5c 4b f3 d0 e2 .........~w\K...
82 0070 - 1f 7a cd 9c f8 d5 ab c4-dd 20 3e 86 4d ff ce 1a .z....... >.M...
83 0080 - 4a 88 8e 50 53 e7 74 1a-96 87 c6 02 af 35 7f 4e J..PS.t......5.N
84 0090 - f5 f3 a8 0f 0d 97 3b 73-d5 ca 22 bf 56 de 60 db ......;s..".V.`.
85 00a0 - 38 13 e1 bd ac c4 42 1d-58 df f2 eb 84 91 4d 21 8.....B.X.....M!
86 00b0 - 13 2f a3 f6 4f 9f 61 18-44 1f f1 d2 82 88 03 95 ./..O.a.D.......
87 00c0 - f0 5d 88 f7 ee a5 b6 68-7f 73 4f db c8 52 34 84 .].....h.sO..R4.
88 00d0 - a5 ae 39 c3 0f 05 b0 e6-d7 3e 76 32 43 29 54 8f ..9......>v2C)T.
89 00e0 - 0c 57 af dc a4 ac 08 45-3c 33 85 9a df 59 47 6b .W.....E<3...YGk
90
91 Start Time: 1733008466
92 Timeout : 7200 (sec)
93 Verify return code: 21 (unable to verify the first certificate)
94 Extended master secret: no
95 Max Early Data: 0
96---
97read R BLOCK
98---
99Post-Handshake New Session Ticket arrived:
100SSL-Session:
101 Protocol : TLSv1.3
102 Cipher : TLS_AES_256_GCM_SHA384
103 Session-ID: 224F519D21BCA495AE6008B2EA2322BAFD83FC8D05B93849CA4AF31F74662DD9
104 Session-ID-ctx:
105 Resumption PSK: 31A997D5DE3B4AD430063FC9C2E5EAC9251ED7C6E8B546BCEAC4E6E6364E9897D7119F837639206D344EBBEE6666217A
106 PSK identity: None
107 PSK identity hint: None
108 SRP username: None
109 TLS session ticket lifetime hint: 300 (seconds)
110 TLS session ticket:
111 0000 - 9c 74 9e 82 50 ea 6a 63-98 fc b0 d9 d7 53 01 6b .t..P.jc.....S.k
112 0010 - f0 db 7b cc e0 30 87 b4-ad 38 35 d8 94 6f dd 90 ..{..0...85..o..
113 0020 - f3 95 f3 99 94 60 c4 db-57 fd 6f 15 d5 d4 97 7a .....`..W.o....z
114 0030 - b6 2b db f5 aa f1 31 0b-fd 48 87 e1 66 c9 47 cb .+....1..H..f.G.
115 0040 - f0 1a da 02 b3 db e5 c1-8a 63 74 e6 23 6b 99 09 .........ct.#k..
116 0050 - 9a b4 f2 38 58 65 ab 13-6c c5 3e 56 7b 10 cd cb ...8Xe..l.>V{...
117 0060 - 05 b2 70 e0 17 4d 06 fc-b3 65 d9 65 a6 1b 74 8b ..p..M...e.e..t.
118 0070 - a1 fa e8 92 78 4d b8 5a-ef 02 24 6e 9a 1c 05 61 ....xM.Z..$n...a
119 0080 - 35 a6 4d 6a a0 08 bb 7e-48 f5 c9 71 4c 11 34 b9 5.Mj...~H..qL.4.
120 0090 - 39 36 77 69 3b bf 25 33-fd ca 19 5a 07 0a cd d3 96wi;.%3...Z....
121 00a0 - ae 5c 45 66 7d 16 6c 7d-3c 60 fd 96 1a c3 56 52 .\Ef}.l}<`....VR
122 00b0 - 43 75 cf 70 d2 b0 4f f3-99 08 15 35 41 6f 34 ad Cu.p..O....5Ao4.
123 00c0 - c9 a0 69 6c ed 60 70 c3-19 62 0c 43 4d 1d 1a 36 ..il.`p..b.CM..6
124 00d0 - be e8 5a e9 a5 1a 93 ef-11 db 10 9a 03 a2 71 55 ..Z...........qU
125 00e0 - fa 3e 59 d5 89 c2 88 8b-94 a3 47 00 66 6f 96 d6 .>Y.......G.fo..
126
127 Start Time: 1733008466
128 Timeout : 7200 (sec)
129 Verify return code: 21 (unable to verify the first certificate)
130 Extended master secret: no
131 Max Early Data: 0
132---
133read R BLOCK用
openssl s_client 更有助于我们理解 TLS 握手的详细过程。Apache2 中的配置 HTTPS
和 Nginx 差不多,先要启用相应的模块和站点1a2enmod ssl
2a2ensite default-ssl再编辑 default-ssl.conf,配置一个 443 虚拟机
1<VirtualHost *:443>
2 ServerName server.local
3 DocumentRoot /var/www/html
4
5 SSLEngine on
6 SSLCertificateFile /etc/ssl/certs/server.crt
7 SSLCertificateKeyFile /etc/ssl/private/server.key
8 ....
9</VirtualHost>apachectl -k restart 重启即可
SpringBoot Tomcat 中的配置
如果开发的一个 SpringBoot Web 应用直接面对客户,它的前面没有 Nginx/Apache 或其他的 Load Balancer, 这一节或许对我们会有所帮助。所有的关于server.ssl 的配置可参考 SpringBoot 官方文档 Common Application Properties / Server Properties。相关的配置项有
1server.ssl.bundle: The name of a configured SSL bundle.
2server.ssl.certificate: Path to a PEM-encoded SSL certificate file.
3server.ssl.certificate-private-key: Path to a PEM-encoded private key file for the SSL certificate.
4server.ssl.ciphers: Supported SSL ciphers.
5server.ssl.client-auth: Client authentication mode. Requires a trust store.
6server.ssl.enabled: Whether to enable SSL support. default: true
7server.ssl.enabled-protocols: Enabled SSL protocols.
8server.ssl.key-alias: Alias that identifies the key in the key store.
9server.ssl.key-password: Password used to access the key in the key store.
10server.ssl.key-store: Path to the key store that holds the SSL certificate (typically a jks file).
11server.ssl.key-store-password: Password used to access the key store.
12server.ssl.key-store-provider: Provider for the key store.
13server.ssl.key-store-type: Type of the key store.
14server.ssl.protocol: SSL protocol to use. default: TLS
15server.ssl.server-name-bundles: Mapping of host names to SSL bundles for SNI configuration.
16server.ssl.trust-certificate: Path to a PEM-encoded SSL certificate authority file.
17server.ssl.trust-certificate-private-key: Path to a PEM-encoded private key file for the SSL certificate authority.
18server.ssl.trust-store: Trust store that holds SSL certificates.
19server.ssl.trust-store-password: Password used to access the trust store.
20server.ssl.trust-store-provider: Provider for the trust store.
21server.ssl.trust-store-type: Type of the trust store.从中我们发现
server.ssl.certificate 和 server.ssl.certificate-private-key 可实现与 Nginx/Apache 类似的配置试着在 application.properties 中加上
1server.ssl.certificate=/certs/server.crt
2server.ssl.certificate-private-key=/certs/server.key启动 SpringBoot Web 项目,看到控制台输出
Tomcat started on port 8080 (https) with context path '/'测试
curl -kv https://server.local:8080/没问题,一样的效果,需要注意的是 SpringBoot Tomcat 不同时启动 HTTP 和 HTTPS 服务,配置了相应的 server.ssl 则只启动 HTTPS 服务,并且端口号复用
server.port 的配置。如果采用 key-store 的配置方式则要用 Java 的 keytool 命令把 openssl 生成的 server.key, server.crt 生成 keystore.jks 文件,或者直接用 keytool 替代 openssl 来生成它所需的 keystore.jks 文件。
配置 Nginx 支持 HTTPS 双向验证 (mTLS)
为配置 mTLS(mutual TLS),除了前面的 root.key, root.crt, server.key, server.crt 外,还需要为客户端生成相应的 key 与证书。何谓双向验证是除了传统的客户端信任服务端,服务端还要检查客户端的证书,决定是否信任,是否提供服务给该客户端。我们可以为不同的客户生独立的客户端私钥与证书,或多个客户可共享。服务端单向验证在客户端可选择信任或不信任,即使不信任也可以使用服务; 而双向认证让服务端更有主动权,服务认为是一个非法的客户(未提供客户端证书或提供了非法的客户端证书)能够拒绝服务。双向认证让 HTTPS 通信更安全,不易被中间人攻击,以至于让无比缺德的 zscaler 都会无能为力。生成客户端 client1.key, client1.crt
1openssl req -newkey rsa:2048 -nodes -keyout client1.key -out client1.csr -subj "/C=US/ST=Illinois/L=Chicago/O=Company 1/CN=client1"
2openssl x509 -req -in client1.csr -out client1.crt -CA root.crt -CAkey root.key -CAcreateserial -days 365编辑 /etc/nginx/nginx.cfg, server {} 块
1 server {
2 listen 443 ssl;
3 server_name server.local;
4 ssl_certificate server.crt;
5 ssl_certificate_key server.key;
6
7 ssl_client_certificate /certs/root.crt;
8 ssl_verify_client on;
9 }nginx -s reload
现在用 curl -k 完全信息服务端也没用,服务端可不买这个账
1root@docker-desktop:~# curl -kv https://server.local
2* Host server.local:443 was resolved.
3* IPv6: (none)
4* IPv4: 127.0.0.1
5* Trying 127.0.0.1:443...
6* Connected to server.local (127.0.0.1) port 443
7* ALPN: curl offers h2,http/1.1
8* TLSv1.3 (OUT), TLS handshake, Client hello (1):
9* TLSv1.3 (IN), TLS handshake, Server hello (2):
10* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
11* TLSv1.3 (IN), TLS handshake, Request CERT (13):
12* TLSv1.3 (IN), TLS handshake, Certificate (11):
13* TLSv1.3 (IN), TLS handshake, CERT verify (15):
14* TLSv1.3 (IN), TLS handshake, Finished (20):
15* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
16* TLSv1.3 (OUT), TLS handshake, Certificate (11):
17* TLSv1.3 (OUT), TLS handshake, Finished (20):
18* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 / X25519 / RSASSA-PSS
19* ALPN: server accepted http/1.1
20* Server certificate:
21* subject: C=US; ST=Illinois; L=Chicago; O=Demo Server; CN=server.local
22* start date: Nov 27 05:34:22 2024 GMT
23* expire date: Nov 27 05:34:22 2025 GMT
24* issuer: C=US; ST=Illinois; L=Chicago; O=CA Company; CN=RootCA
25* SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
26* Certificate level 0: Public key type RSA (2048/112 Bits/secBits), signed using sha256WithRSAEncryption
27* using HTTP/1.x
28> GET / HTTP/1.1
29> Host: server.local
30> User-Agent: curl/8.5.0
31> Accept: */*
32>
33* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
34* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
35* old SSL session ID is stale, removing
36< HTTP/1.1 400 Bad Request
37< Server: nginx/1.24.0 (Ubuntu)
38< Date: Wed, 27 Nov 2024 06:41:48 GMT
39< Content-Type: text/html
40< Content-Length: 246
41< Connection: close
42<
43<html>
44<head><title>400 No required SSL certificate was sent</title></head>
45<body>
46<center><h1>400 Bad Request</h1></center>
47<center>No required SSL certificate was sent</center>
48<hr><center>nginx/1.24.0 (Ubuntu)</center>
49</body>
50</html>
51* Closing connection
52* TLSv1.3 (IN), TLS alert, close notify (256):
53* TLSv1.3 (OUT), TLS alert, close notify (256):400 Bad Request, 因为 No required SSL certificate was sent
主动带上 client1.key 和 client1.crt 就行,只要服务端的证书是不被广泛接受的,就要用
-k 来手动接受证书,即使是服务端与客户端相互承认也不能省略 -k 1root@docker-desktop:~# curl --cert client1.crt --key client1.key -kv https://server.local
2* Host server.local:443 was resolved.
3* IPv6: (none)
4* IPv4: 127.0.0.1
5* Trying 127.0.0.1:443...
6* Connected to server.local (127.0.0.1) port 443
7* ALPN: curl offers h2,http/1.1
8* TLSv1.3 (OUT), TLS handshake, Client hello (1):
9* TLSv1.3 (IN), TLS handshake, Server hello (2):
10* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
11* TLSv1.3 (IN), TLS handshake, Request CERT (13):
12* TLSv1.3 (IN), TLS handshake, Certificate (11):
13* TLSv1.3 (IN), TLS handshake, CERT verify (15):
14* TLSv1.3 (IN), TLS handshake, Finished (20):
15* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
16* TLSv1.3 (OUT), TLS handshake, Certificate (11):
17* TLSv1.3 (OUT), TLS handshake, CERT verify (15):
18* TLSv1.3 (OUT), TLS handshake, Finished (20):
19* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 / X25519 / RSASSA-PSS
20* ALPN: server accepted http/1.1
21* Server certificate:
22* subject: C=US; ST=Illinois; L=Chicago; O=Demo Server; CN=server.local
23* start date: Nov 27 05:34:22 2024 GMT
24* expire date: Nov 27 05:34:22 2025 GMT
25* issuer: C=US; ST=Illinois; L=Chicago; O=CA Company; CN=RootCA
26* SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
27* Certificate level 0: Public key type RSA (2048/112 Bits/secBits), signed using sha256WithRSAEncryption
28* using HTTP/1.x
29> GET / HTTP/1.1
30> Host: server.local
31> User-Agent: curl/8.5.0
32> Accept: */*
33>
34* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
35* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
36* old SSL session ID is stale, removing
37< HTTP/1.1 200 OK
38< Server: nginx/1.24.0 (Ubuntu)
39< Date: Wed, 27 Nov 2024 06:42:04 GMT
40< Content-Type: text/html
41< Content-Length: 3
42< Last-Modified: Wed, 27 Nov 2024 06:38:57 GMT
43< Connection: keep-alive
44< ETag: "6746be81-3"
45< Accept-Ranges: bytes
46<
47Ok除了用命令 curl,同样可用
openssl s_clinet 携带 client1.key 和 client1.crt 来访问openssl s_client -connect server.local:443 -key client1.key -cert client1.crt
1openssl s_client -connect server.local:443 -key client1.key -cert client1.crt
2Connecting to 127.0.0.1
3CONNECTED(00000003)
4depth=0 C=US, ST=Illinois, L=Chicago, O=Demo Server, CN=server.local
5verify error:num=20:unable to get local issuer certificate
6verify return:1
7depth=0 C=US, ST=Illinois, L=Chicago, O=Demo Server, CN=server.local
8verify error:num=21:unable to verify the first certificate
9verify return:1
10depth=0 C=US, ST=Illinois, L=Chicago, O=Demo Server, CN=server.local
11verify return:1
12---
13Certificate chain
14 0 s:C=US, ST=Illinois, L=Chicago, O=Demo Server, CN=server.local
15 i:C=US, ST=Illinois, L=Chicago, O=CA Company, CN=RootCA
16 a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA256
17 v:NotBefore: Nov 27 05:34:22 2024 GMT; NotAfter: Nov 27 05:34:22 2025 GMT
18---
19Server certificate
20-----BEGIN CERTIFICATE-----
21MIIDhzCCAm+gAwIBAgIUaVkSmjyS/M/82njsEW5Dgy2Pg8EwDQYJKoZIhvcNAQEL
22BQAwWDELMAkGA1UEBhMCVVMxETAPBgNVBAgMCElsbGlub2lzMRAwDgYDVQQHDAdD
23aGljYWdvMRMwEQYDVQQKDApDQSBDb21wYW55MQ8wDQYDVQQDDAZSb290Q0EwHhcN
24MjQxMTI3MDUzNDIyWhcNMjUxMTI3MDUzNDIyWjBfMQswCQYDVQQGEwJVUzERMA8G
25A1UECAwISWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28xFDASBgNVBAoMC0RlbW8g
26U2VydmVyMRUwEwYDVQQDDAxzZXJ2ZXIubG9jYWwwggEiMA0GCSqGSIb3DQEBAQUA
27A4IBDwAwggEKAoIBAQDJasqYBxyiMjL6DW6MpiKDloStV4tkFonYaVUMm2fr7ZiY
28Lj5A+rNXcLBvZlaf93hC11EdZljom9l2aIybRRR0ml0NEycE+sGHbOs0PFqtN2nB
29gV/15J5gqTeCO7HpBWkhg3R0+PPj46WK03idz4f0M2Dz9qgnJC+/j3enMX32/t4X
30KG8/lwiah1bAcBq4OU6N6syfpAA10ISljLjg8ztnb0u0WMNOLYgWd6/aOlZk2Wp6
31k7AJrKRiTfjz7Pi3aDMjaTTziQ0Erz+ngD8RYbUhuZIIFDZNGPiJMDSoaj0ffzNz
32fuqVN4TqvMBwGWtKmQ/ofC93cVGXcjZNIUvjSqLrAgMBAAGjQjBAMB0GA1UdDgQW
33BBQzMRYTcWvhMTsRDN4Av2J3Vga6nTAfBgNVHSMEGDAWgBQ5N633VoXMBr+O0TH3
34P8m/B/hHnzANBgkqhkiG9w0BAQsFAAOCAQEAo4cjfmljrr/m9Vsuzw+yD5sp1TPb
35sIp+OF7DWKhRn7CxPv/wnmpexx3RVgBFpJ3erpgFSH+Zu8tP7vRf0t6mqUaWmkMG
36w/iBAJ46tnVlaeiPWEnjkvOUHNb9V1OXFOXQMad0NfyAMulJBHMJiyl73JGqziVP
37fI9U5NgHVWLUtWlvGkdAiukg+RDGSPQYrxaDuwYnsl+vdbmFRw9Yn7I3BxRTqtHo
38FkbWIgTt0URil7dc5t775ZIFVKusH+XC+Kt+wk2Mjp1KCkZ0Kk7auQHfdbjm9mNp
39OJjjwmVs1QeBnuMfdMqLsvEn2FG4pJZ4blq/Z/coLDUHoXo0tk3FDc9vEA==
40-----END CERTIFICATE-----
41subject=C=US, ST=Illinois, L=Chicago, O=Demo Server, CN=server.local
42issuer=C=US, ST=Illinois, L=Chicago, O=CA Company, CN=RootCA
43---
44Acceptable client certificate CA names
45C=US, ST=Illinois, L=Chicago, O=CA Company, CN=RootCA
46Requested Signature Algorithms: ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512:Ed25519:Ed448:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA+SHA256:RSA+SHA384:RSA+SHA512:ECDSA+SHA224:RSA+SHA224
47Shared Requested Signature Algorithms: ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512:Ed25519:Ed448:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA+SHA256:RSA+SHA384:RSA+SHA512
48Peer signing digest: SHA256
49Peer signature type: RSA-PSS
50Server Temp Key: X25519, 253 bits
51---
52SSL handshake has read 1632 bytes and written 1624 bytes
53Verification error: unable to verify the first certificate
54---
55New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
56Protocol: TLSv1.3
57Server public key is 2048 bit
58This TLS version forbids renegotiation.
59Compression: NONE
60Expansion: NONE
61No ALPN negotiated
62Early data was not sent
63Verify return code: 21 (unable to verify the first certificate)
64---
65---
66Post-Handshake New Session Ticket arrived:
67SSL-Session:
68 Protocol : TLSv1.3
69 Cipher : TLS_AES_256_GCM_SHA384
70 Session-ID: C60065DBCD8AFF88C350CB29F9076F57A95E7290534C518EBB9BF617EBFF0863
71 Session-ID-ctx:
72 Resumption PSK: 6D54823943FE7170A07CE3A7770B014EB6182BCD336B43D8A8AFEFB41E424CAD149143C0D6D5E04A793F0E40A47411FB
73 PSK identity: None
74 PSK identity hint: None
75 SRP username: None
76 TLS session ticket lifetime hint: 300 (seconds)
77 TLS session ticket:
78 0000 - 38 07 5a 8e ad d0 49 f4-67 f0 aa a2 e2 82 ae 57 8.Z...I.g......W
79 0010 - 0d e8 fc 3a 97 ad eb 17-f0 1c 1b 30 d7 13 47 c5 ...:.......0..G.
80 0020 - 6c 08 7b 91 f6 51 b0 2d-82 05 c6 04 9e f4 a4 1f l.{..Q.-........
81 0030 - 31 ef 95 6f 9e b3 ed 15-25 31 59 00 bc 11 d8 b9 1..o....%1Y.....
82 0040 - 58 00 e3 d7 54 92 77 8e-59 5e 02 f1 11 e7 32 d9 X...T.w.Y^....2.
83 0050 - 97 03 1e b5 ec ed 4a 6f-1b 2b 44 6b 0d b2 a0 6b ......Jo.+Dk...k
84 0060 - 27 10 ae 11 e4 66 6e 55-1d 69 95 05 72 0d cc 63 '....fnU.i..r..c
85 0070 - cc 36 df 05 06 c6 d0 73-48 af 83 eb 12 de a9 73 .6.....sH......s
86 0080 - 51 1c ff a1 2a ed e6 4f-25 11 03 9d 6c a0 28 e4 Q...*..O%...l.(.
87 0090 - d7 b3 c9 c9 8f 45 da d1-53 c5 63 2e 90 25 67 e0 .....E..S.c..%g.
88 00a0 - b4 77 dc 42 99 25 9d 9a-10 ab c5 79 30 bd 42 e2 .w.B.%.....y0.B.
89 00b0 - 1c 71 90 40 d9 09 70 8d-61 7b a3 e8 c5 41 95 43 .q.@..p.a{...A.C
90 00c0 - 10 b6 d1 45 c1 61 02 29-b7 28 80 65 53 3b 8f 79 ...E.a.).(.eS;.y
91 00d0 - cc fa 1a 61 bb 32 e1 8b-e3 c3 7e 38 38 f0 d7 8c ...a.2....~88...
92 00e0 - 3b d3 79 23 1c 3b 99 f0-8f 86 2f 09 50 cc 6f 97 ;.y#.;..../.P.o.
93 00f0 - a8 a4 63 00 c8 9e a5 25-d0 0b 18 b8 92 5f 2c 65 ..c....%....._,e
94 0100 - 3f b8 7c 91 1d a6 7b 72-c9 a9 8b 00 e0 e3 ce cb ?.|...{r........
95 0110 - c1 74 34 78 e6 42 08 57-20 77 2f 70 45 79 bd 63 .t4x.B.W w/pEy.c
96 0120 - 0a f3 60 08 da 37 c3 6b-b3 07 8f c8 7e 8e a5 a1 ..`..7.k....~...
97 0130 - a2 f4 6d f4 f2 3f 97 e5-75 1a 30 19 d2 14 7a 76 ..m..?..u.0...zv
98 0140 - 53 3e e6 75 a0 23 50 c5-39 05 60 c7 8f 44 b0 de S>.u.#P.9.`..D..
99 0150 - 25 3f 06 86 23 19 a4 54-d5 da b2 45 29 c4 3e f0 %?..#..T...E).>.
100 0160 - 98 36 6c 62 6c 74 20 b8-7a 8c f6 08 a0 15 81 1e .6lblt .z.......
101 0170 - 40 07 62 7d f9 cf 9e 93-55 fe 1d 4f 22 b9 e1 1d @.b}....U..O"...
102 0180 - 98 78 fe 64 50 31 fb 0c-a8 5d 1a 7a 89 22 da 06 .x.dP1...].z."..
103 0190 - bf 98 28 5d 60 ff a9 2d-76 70 8a 6b 24 11 27 77 ..(]`..-vp.k$.'w
104 01a0 - d1 02 8d 32 ca fd f3 53-0a 1f cd 63 63 b3 92 c7 ...2...S...cc...
105 01b0 - 7c ba 2d cf f8 bf 7e d2-39 f3 19 cf c1 3b 1f 0b |.-...~.9....;..
106 01c0 - 8c a5 be 4a 64 d5 b7 f6-43 f2 fe fe d8 90 42 cf ...Jd...C.....B.
107 01d0 - e5 86 1c c6 41 b3 2f 8f-3f cb 7e 27 1e 47 3c 88 ....A./.?.~'.G<.
108 01e0 - ca 00 20 e7 f6 ac ef 25-63 7e f1 59 15 d3 b9 6c .. ....%c~.Y...l
109 01f0 - b4 99 f5 f3 4e 0b 32 f2-3d 71 36 3e 30 fb e4 5a ....N.2.=q6>0..Z
110 0200 - 90 74 ae 32 8a 6d eb 05-cf 44 69 dd ba bc 9c 89 .t.2.m...Di.....
111 0210 - 6e 66 61 85 81 42 d6 ad-89 2d be b2 59 d7 d2 15 nfa..B...-..Y...
112 0220 - 6e 2d fe f4 b0 24 7c 15-ff d9 a7 70 f0 af fb f0 n-...$|....p....
113 0230 - 50 53 93 34 d6 58 26 7d-2f d7 2b 03 33 78 37 20 PS.4.X&}/.+.3x7
114 0240 - 21 50 1a 49 d7 aa 28 5f-4d ef d5 ea 39 c7 0b a2 !P.I..(_M...9...
115 0250 - fc e7 4f b1 6f 26 cc cc-e9 59 69 ab 22 dd 5f 5b ..O.o&...Yi."._[
116 0260 - 38 aa 06 f5 d4 7e be 8d-42 83 7c 30 e0 5d 61 4a 8....~..B.|0.]aJ
117 0270 - c9 78 32 c9 e0 54 1e 64-3e 85 41 96 e0 be ed 4c .x2..T.d>.A....L
118 0280 - ff 3e 82 fe 87 88 3d 90-b0 33 5a 0a 9c 43 c4 75 .>....=..3Z..C.u
119 0290 - 82 31 4e c7 a1 c9 86 73-8e 38 84 38 73 0e aa 48 .1N....s.8.8s..H
120 02a0 - 50 bd db 58 e9 8d 84 2b-f6 b1 4e 2d b4 08 04 ab P..X...+..N-....
121 02b0 - 05 26 22 89 7a 91 a1 fc-11 a6 c2 98 19 3c 8e 56 .&".z........<.V
122 02c0 - 29 6d 44 99 1a a3 a5 94-8a f4 8b ea 60 c0 27 01 )mD.........`.'.
123 02d0 - ee 37 c4 e4 30 2d f2 68-fd a2 44 72 d8 af ad 96 .7..0-.h..Dr....
124 02e0 - 65 28 7c 47 b7 15 69 39-7a 02 64 d6 44 33 37 70 e(|G..i9z.d.D37p
125 02f0 - e7 33 61 ae 0a 62 97 89-01 b2 3b 33 57 71 48 fc .3a..b....;3WqH.
126 0300 - 05 97 b2 2a c7 ec ca d1-87 ec de 5e b9 2d 3e 3a ...*.......^.->:
127 0310 - 24 9b e7 b4 b5 17 9c 33-9d 9b 52 21 9e 9b 2f 66 $......3..R!../f
128 0320 - 85 9d 85 1c 1e ce 83 ab-c6 92 1d da 7b 1c fc 25 ............{..%
129 0330 - 84 29 a8 f0 fd 4c c4 26-d8 d5 db 85 e5 03 a4 86 .)...L.&........
130 0340 - ef 0f 8b ed ce 40 57 06-34 3d 23 81 bc 56 67 06 .....@W.4=#..Vg.
131 0350 - 4c 18 ba eb eb 3c 5d b9-ca 9d 7e 4d 61 99 70 98 L....<]...~Ma.p.
132 0360 - e9 9e e0 6c 7e 92 bd 81-ff f3 b1 0a 50 9d 85 3c ...l~.......P..<
133 0370 - af 25 35 f0 ba 9f 06 b5-21 46 0e 14 8a d0 fe c7 .%5.....!F......
134 0380 - 56 53 97 55 ad d7 9a e6-ea e1 a9 95 17 56 0a 6e VS.U.........V.n
135 0390 - 46 61 42 6d 29 14 3a 59-78 b7 6f 30 aa 4d a5 e0 FaBm).:Yx.o0.M..
136 03a0 - f4 f7 ec 21 11 ee fa 80-08 61 9c 53 86 ea 7b 02 ...!.....a.S..{.
137 03b0 - d8 69 fb 39 50 13 dc ad-07 86 86 e4 f6 17 18 af .i.9P...........
138 03c0 - f2 d9 60 f2 66 eb 58 50-b7 2f 41 73 b1 2b c0 b1 ..`.f.XP./As.+..
139 03d0 - 54 48 b9 e4 35 95 10 fc-4d b2 7d 2b 2d d0 ca 68 TH..5...M.}+-..h
140 03e0 - be 04 02 11 14 65 08 c7-c4 fe 98 cd 2d 3e 13 48 .....e......->.H
141 03f0 - f1 2c 69 42 a5 d3 ac ec-03 4a f9 2e ad 27 7b 96 .,iB.....J...'{.
142 0400 - 81 b4 aa 74 d0 23 6b f8-1c c0 fd 70 00 cc 7f 5b ...t.#k....p...[
143 0410 - 1e cb bd df b3 c1 83 61-af 2f 81 1d fe f4 de 95 .......a./......
144 0420 - 37 6e 8c 67 2a 8a 27 cc-6c 9b 70 db 7f a4 96 d4 7n.g*.'.l.p.....
145 0430 - 65 ef 07 68 17 df 86 8e-9b ac 27 e8 d0 3c 21 78 e..h......'..<!x
146 0440 - 7b 61 2e 71 3b 99 4b 4c-81 4d 54 5c 67 a7 45 38 {a.q;.KL.MT\g.E8
147 0450 - a0 04 d9 3b c8 0a f2 8b-50 4c 2c d7 a2 5d c0 48 ...;....PL,..].H
148 0460 - fd 38 ca 75 c1 50 53 80-48 64 eb 22 62 7e 62 14 .8.u.PS.Hd."b~b.
149
150 Start Time: 1733008819
151 Timeout : 7200 (sec)
152 Verify return code: 21 (unable to verify the first certificate)
153 Extended master secret: no
154 Max Early Data: 0
155---
156read R BLOCK
157---
158Post-Handshake New Session Ticket arrived:
159SSL-Session:
160 Protocol : TLSv1.3
161 Cipher : TLS_AES_256_GCM_SHA384
162 Session-ID: EEFDEAF0CA2B63A2C27D92CCBFF99004E2FBC173147833C923060155B7F066CD
163 Session-ID-ctx:
164 Resumption PSK: 0DA3469A6889259B9E4D679C94DE33ED35B749E75CBA7D9BC30BD4718A84FFFECB8CE825CE012FCD56A1FE4AD1F7256E
165 PSK identity: None
166 PSK identity hint: None
167 SRP username: None
168 TLS session ticket lifetime hint: 300 (seconds)
169 TLS session ticket:
170 0000 - 38 07 5a 8e ad d0 49 f4-67 f0 aa a2 e2 82 ae 57 8.Z...I.g......W
171 0010 - 2b db e4 2a 84 d0 dc 89-75 5d 9e 3a d2 b2 95 bf +..*....u].:....
172 0020 - e1 40 be 1b 1f fb bf 10-ab 8b 6c 02 62 cc 91 64 .@........l.b..d
173 0030 - de 97 13 a4 52 2d 55 35-f6 96 af 15 37 c0 c3 ff ....R-U5....7...
174 0040 - b6 3b f3 85 1c 26 b2 84-cf f6 14 85 f8 5d 47 fd .;...&.......]G.
175 0050 - 29 aa 71 3e 36 af 75 3f-5c 5c 3a d4 41 f3 fc fd ).q>6.u?\\:.A...
176 0060 - b4 57 73 6d 4f c4 91 f3-7b 3f 8f 14 ac de f3 12 .WsmO...{?......
177 0070 - 8b 53 27 b8 bc eb 85 c3-c7 5e 62 63 7f c6 c6 44 .S'......^bc...D
178 0080 - 3e 06 79 9e 75 b9 84 7a-d9 73 7f e9 e5 f2 ce a9 >.y.u..z.s......
179 0090 - 7e c4 ed 98 d1 ec a0 11-22 d5 2e c3 43 ed 17 ca ~......."...C...
180 00a0 - ed 2d 6e c6 92 55 ff 38-69 b1 75 54 8c e1 8a b9 .-n..U.8i.uT....
181 00b0 - c8 c1 7f 54 90 46 c0 cb-d2 1e f0 b4 41 de d3 27 ...T.F......A..'
182 00c0 - b3 2e 2c 6d ff 7c c0 5e-f7 75 31 c3 e1 4b 8d e4 ..,m.|.^.u1..K..
183 00d0 - 85 05 a9 d1 f7 14 e7 45-60 f8 86 d8 e7 1e f2 83 .......E`.......
184 00e0 - 66 b6 52 4c fb 81 48 be-f6 24 5f 94 31 91 e3 d8 f.RL..H..$_.1...
185 00f0 - 5f 56 f1 7d 2d f0 b4 6f-d1 04 fa 5a 5c cd d8 03 _V.}-..o...Z\...
186 0100 - f0 2f a4 7e af ee ae 0c-69 71 b6 22 b1 af 0f be ./.~....iq."....
187 0110 - 15 7a 0b 78 55 6c 8b 09-6b e2 9f 39 e3 2f a1 0d .z.xUl..k..9./..
188 0120 - 5f b1 ac 81 ff 50 43 f0-32 5d 14 1b 82 3c c6 5e _....PC.2]...<.^
189 0130 - 7b 1b 27 81 a0 62 77 6c-ae 12 56 b8 85 d5 a8 f2 {.'..bwl..V.....
190 0140 - c7 db ef bc 3e 63 8d 58-82 50 16 a5 9d a4 e7 c4 ....>c.X.P......
191 0150 - 3c c1 21 87 41 eb 17 b9-7e 55 10 e5 d4 8e e1 72 <.!.A...~U.....r
192 0160 - b3 2c 28 3d 98 a8 51 96-63 7c 15 6d 06 6b e8 74 .,(=..Q.c|.m.k.t
193 0170 - a4 2e 6c 38 ab cb 93 94-d4 f8 c0 84 20 5a db ce ..l8........ Z..
194 0180 - f8 79 88 6f fc 67 58 8b-09 23 6b 2f 6b 99 08 85 .y.o.gX..#k/k...
195 0190 - cb 1b ac f8 64 31 eb 91-e1 74 d1 da 64 2f 0f 9f ....d1...t..d/..
196 01a0 - 2b df 97 ca 3e 12 f6 54-41 84 0e 26 0b af 5f 6f +...>..TA..&.._o
197 01b0 - 7f fd 16 a2 f4 7f 1a af-b4 9d b5 58 46 09 d5 7c ...........XF..|
198 01c0 - 79 6b 16 9a 4a f3 d4 9d-10 ac 18 c2 ae eb a2 24 yk..J..........$
199 01d0 - 8e 4c 45 26 57 82 fb d5-9a 24 c3 08 9b cd e1 b7 .LE&W....$......
200 01e0 - 30 85 73 71 09 5d d1 78-0d 16 33 11 0d 10 63 8e 0.sq.].x..3...c.
201 01f0 - ed d3 3b d8 2a 04 72 ac-76 1d 6c 83 b3 8e e8 25 ..;.*.r.v.l....%
202 0200 - aa da ad c5 24 17 04 c1-0a ef 10 41 a5 25 0d d7 ....$......A.%..
203 0210 - 12 8c 68 e8 10 e8 41 8c-92 07 8f 08 97 1f 8e 1a ..h...A.........
204 0220 - a5 fa 47 b7 96 f9 29 d6-00 71 6e e4 bb 90 6e 4a ..G...)..qn...nJ
205 0230 - 31 f8 af de a7 b0 34 c3-68 d2 a4 5c c6 42 6a 14 1.....4.h..\.Bj.
206 0240 - 9e d4 85 ee 11 b7 8e b2-58 d1 55 ac 5c cd 9b 36 ........X.U.\..6
207 0250 - 82 f1 dd 0e bb fe 5b 9c-14 b9 51 2b 9a 8d e3 28 ......[...Q+...(
208 0260 - 9f f6 e1 67 a3 9a 9c 93-27 54 7c ce 0f 54 18 c5 ...g....'T|..T..
209 0270 - 4a 00 95 0c 75 ee df ef-29 1b 2c 3d c5 f3 d9 50 J...u...).,=...P
210 0280 - 4d 91 3d 07 81 63 6e e0-5c 79 b8 bc 56 c9 b5 eb M.=..cn.\y..V...
211 0290 - 10 95 70 48 46 f5 4c 20-48 ef 43 a8 fc 58 ae 08 ..pHF.L H.C..X..
212 02a0 - 80 0e 3d ee 37 eb be 55-61 80 50 22 f2 34 5a bf ..=.7..Ua.P".4Z.
213 02b0 - 12 08 9a d9 44 c0 a3 2c-08 32 96 c5 62 7b 97 15 ....D..,.2..b{..
214 02c0 - 7f c8 07 48 ad 4f 01 83-60 bf d6 90 54 3f e3 c4 ...H.O..`...T?..
215 02d0 - 3d 2e b6 18 33 ad b0 09-a8 db e5 1e 94 98 7c 71 =...3.........|q
216 02e0 - 5d 91 84 a9 93 2f d1 87-cf dc cd fc 3e 80 4b ff ]..../......>.K.
217 02f0 - 97 4b e7 d1 fd 29 59 69-7c 46 b3 86 48 ec bd 40 .K...)Yi|F..H..@
218 0300 - 89 4b 74 c7 2d eb 19 16-ca b6 8c 0c 88 39 fa c9 .Kt.-........9..
219 0310 - b2 ca f9 b6 d6 c8 58 c1-b5 f5 20 c1 33 6e 1f ee ......X... .3n..
220 0320 - 8a 32 e3 51 9d 1f a7 f7-14 58 a8 c8 6f c6 0d 6f .2.Q.....X..o..o
221 0330 - dd b5 5f 44 29 bd 17 fc-cd f9 d1 78 ad 92 7b 8b .._D)......x..{.
222 0340 - 36 5d ce f0 8a 9d b8 94-9e f7 2d 7e 7e 95 59 c8 6]........-~~.Y.
223 0350 - 43 7b 8c fd ed 3e cf dd-37 8b 24 32 62 24 ac 64 C{...>..7.$2b$.d
224 0360 - 4d 16 cf c2 13 19 7d 67-0e 25 57 31 47 e4 ed 2c M.....}g.%W1G..,
225 0370 - f7 93 64 61 b9 98 1f 11-53 69 75 1d 85 3c 54 48 ..da....Siu..<TH
226 0380 - c8 69 a6 be d7 d0 1e 9c-e4 41 30 53 f4 96 a6 34 .i.......A0S...4
227 0390 - 38 f0 98 00 17 d0 fa cf-26 b9 15 3f 20 d9 d9 80 8.......&..? ...
228 03a0 - 3a f4 e0 f6 19 da 69 99-e9 8f 4d 1e ba d5 27 8b :.....i...M...'.
229 03b0 - 4c 13 51 1f 99 bc 82 ff-cf 0f 73 97 7f 35 61 d1 L.Q.......s..5a.
230 03c0 - 1b 5d 80 6b 0b fd 4c 95-33 74 9a bb 33 a5 6a fe .].k..L.3t..3.j.
231 03d0 - 3c 68 77 58 bd 00 9e 93-db 6c 62 95 3b c8 0b 3a <hwX.....lb.;..:
232 03e0 - 25 9d c2 7f 7f ba 19 7d-a5 f5 19 c8 cd db a6 f6 %......}........
233 03f0 - d0 cb 23 c7 c8 cb 5e e2-25 7f 25 88 82 2e b6 19 ..#...^.%.%.....
234 0400 - 11 a3 70 63 e3 8e 5b 79-08 4e ab e8 c8 47 5c 0f ..pc..[y.N...G\.
235 0410 - 03 4e 18 47 8b c9 9c e4-e5 16 f7 77 90 fe 70 f8 .N.G.......w..p.
236 0420 - ad 4b b4 a2 2a 92 55 5c-0e 52 e4 67 dd d1 84 0c .K..*.U\.R.g....
237 0430 - 90 cc 82 3c 47 90 c7 46-02 46 7f 34 07 2d cf 4a ...<G..F.F.4.-.J
238 0440 - 72 f0 d3 3a 4c 5c dd ee-13 a9 7b ca ad e2 28 71 r..:L\....{...(q
239 0450 - 90 2f 98 1c ea 61 05 16-58 f0 f6 ad 72 9d 5b 94 ./...a..X...r.[.
240 0460 - ae 27 ec 83 05 b0 92 e9-5a 0a a5 b6 84 91 f3 2d .'......Z......-
241
242 Start Time: 1733008819
243 Timeout : 7200 (sec)
244 Verify return code: 21 (unable to verify the first certificate)
245 Extended master secret: no
246 Max Early Data: 0
247---
248read R BLOCK
249closed那浏览器该怎么办呢?
我们可用 openssl 由 client1.crt 和 client1.key 生成 PKCS#12 格式的客户端证书上,然后导入到浏览器当中1openssl pkcs12 -export -in client1.crt -inkey client1.key -out client1.p12
2Enter Export Password:
3Verifying - Enter Export Password:如果不想设置的密码的话在两次提示输入密码时直接回车跳过,生成 client1.p12
比如在 Chrome 浏览器,可找到 Settings/Privacy and security/Security/Advanced/Manage certificates/Personal/Imports..., 然后导入前面生成的 client1.p12 文件,有密码的话就输入相同的密码。再浏览 https://server.local 就没问题了。
用 Postman 直接浏览 https://server.local 也同样得到 400 Bad Request 的错误,也需要配置客户端证书才能正常访问。Postman 同时支持 client1.crt,client1.key 组合,和 client1.p12(有密码则输入), 请看下方的截图
完后 Postman 就能看到 https://server.local 的正确输出了。curl 也可以用 p12 格式的证书
1curl --cert-type P12 --cert client1.p12 -kv https://server.local
2
3# 如有密码
4curl --cert-type P12 --cert client1.p12:<password> -kv https://server.localApache2 中的 mTLS 双向认证配置
类似的在 Apache2 中的配置就是在启用 HTTPS 单向验证的基础上于 default-ssl.conf 中再加上1# 指定 CA 证书
2SSLCACertificateFile /certs/root.crt
3
4# 启用客户端认证
5SSLVerifyClient require
6# SSLVerifyDepth 2SpringBoot Tomcat 的 mTLS 双向认证
在启用了 HTTPS 单身验证的情况下加上 server.ssl.trust-certificate 和 server.ssl.client-auth 配置,完整的相关配置是1server.ssl.certificate=/certs/server.crt
2server.ssl.certificate-private-key=/certs/server.key
3server.ssl.trust-certificate=/certs/root.crt
4server.ssl.client-auth=need可分别用下面的 curl 进行测试
$ curl -k https://server.local:8080
curl: (56) LibreSSL SSL_read: LibreSSL/3.3.6: error:1404C412:SSL routines:ST_OK:sslv3 alert bad certificate, errno 0
$ curl --cert client1.crt --key client1.key -k https://server.local:8080
Ok
其他相关内容
以下相关内容在本文中不作详细展开,具体做法可参考 基于证书的双向认证(mTLS)技术方案。比- keytool 替代 openssl 生成证书,在 crt, jdk, p12 之间的证书转换
- Tomcat 中如何使用 key-store 方式配置 HTTPS
- Tomcat 中启用了 HTTPS 后,@EnableWebSecurity 之后如何信任 x509 证书
- Java 作为客户端调用相应服务,如何处理 TLS 和 mTLS
- Nginx 作反向代理时作为 HTTPS 客户端时的配置
链接:
永久链接 https://yanbin.blog/self-certs-https-tls-mtls-config/, 来自 隔叶黄莺 Yanbin's Blog
[版权声明]
本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。