<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>双向认证 on 勇气</title><link>https://courages.us/tag/%E5%8F%8C%E5%90%91%E8%AE%A4%E8%AF%81/</link><description>Recent content in 双向认证 on 勇气</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><lastBuildDate>Wed, 12 Apr 2023 21:33:27 +0800</lastBuildDate><atom:link href="https://courages.us/tag/%E5%8F%8C%E5%90%91%E8%AE%A4%E8%AF%81/index.xml" rel="self" type="application/rss+xml"/><item><title>mTLS 认证</title><link>https://courages.us/mtls-%E8%AE%A4%E8%AF%81/</link><pubDate>Wed, 12 Apr 2023 21:18:30 +0800</pubDate><guid>https://courages.us/mtls-%E8%AE%A4%E8%AF%81/</guid><description>&lt;p&gt;有时候虽然我们部署一个服务到了公网，但只想提供给部分用户而不想其他人（黑客/robot）使用，比如webhook或者跨机房的服务调用。虽然我们可以使用密码/token保护这些服务，但是程序可以被直接扫描到，仍然存在被攻击的风险。而如果把这些服务放在某个认证服务器后面，又存在二次登陆的问题。如何标识目标用户又不影响请求过程？答案是mTLS认证。&lt;br&gt;&#10;TLS认证是当前WEB通信的基石，没有加密的通信无异于裸奔：任何中间人都可以查看/串改通信内容。mTLS认证，亦即双向TLS认证，不但客户端校验服务器证书，服务器亦校验客户端证书，这意味着如果客户端证书不在服务器的信任列表里面，那么客户端也访问不了服务。请求认证过程如下&lt;br&gt;&#10;&lt;a class="link" href="https://courages.us/wp-content/uploads/2023/04/how_mtls_works-what_is_mutual_tls.png" target="_blank" rel="noopener"&#10; &gt;&lt;img class="gallery-image" data-flex-basis="654px" data-flex-grow="272" height="110" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://courages.us/wp-content/uploads/2023/04/how_mtls_works-what_is_mutual_tls-300x110.png" width="300"&gt;&lt;/a&gt;&lt;br&gt;&#10;mTLS可以用来保护私有服务，加强通信过程，减少服务器攻击。由于客户端也需要提供证书，证书里面可以携带用户或者设备信息，可以识别仅授信用户，才授权访问 。由于服务器需要校验客户端信息，所以未提供有效证书用户不能访问，就算盗取了用户的密码/token也不可以。因为双方都互相校验证书，所以也可以抵抗中间人攻击。这样子我们便可以公开服务，但又限制某些用户使用了。&lt;br&gt;&#10;mTLS认证有别于应用程序认证。mTLS仅涉及证书校验，在网关出就可以进行，不需要涉及应用程序逻辑/数据库。mTLS也不依赖于请求头/请求体里面的内容，所以不会影响已有程序。&lt;br&gt;&#10;mTLS认证限制某些用户/设备访问，也有别于传统VPN网络。VPN总是要求服务端/客户端先建立连接，才能在同一内网内访问。一旦连接建立，便可以访问所有服务。而采用mTLS认证，则每一个服务都可以使用不同的客户端证书，限制不同的用户访问。零信任（ZeroTrust）亦建立在mTLS之上，即对每个请求都做双向认证。&lt;br&gt;&#10;mTLS并不是什么新鲜事物，许多互联网软件都支持，比如浏览器、SSH，SSH采用私钥登陆的过程，即双向认证：客户端先将自己的公钥上传至服务器，建立连接时，客户端询问是否信任服务器，服务器亦校验客户端。Git使用SSH key登陆也是类似双向认证。开发者调用Google云服务，除了app认证信息，也是需要双向认证的。有些互联网公司也采用双向认证来保护自己的应用，比如支付功能，甚至是所有页面-只允许自己的APP查看，其他免谈。&lt;br&gt;&#10;Nginx早已支持mTLS认证，除了服务器本身的证书，还需要配置客户端证书或其签发root CA证书。关于服务器证书获取之前已介绍&lt;a class="link" href="https://courages.us/lets-encrypt/" target="_blank" rel="noopener"&#10; &gt;基于DNS自动获取证书&lt;/a&gt;了，同样的方法也可以用来生成客户端证书，比如基于用户id来生成不同域名username.id.example.com的证书给客户端使用。这里介绍另外一种基于&lt;a class="link" href="https://github.com/go-acme/lego" target="_blank" rel="noopener"&#10; &gt;LEGO ACME&lt;/a&gt;在本地生成客户端证书的方法。&lt;br&gt;&#10;首先安装lego程序，如果有golang环境直接就好了，或者下载对应平台的&lt;a class="link" href="https://github.com/go-acme/lego/releases" target="_blank" rel="noopener"&#10; &gt;程序&lt;/a&gt;。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ go install github.com/go-acme/lego/v4/cmd/lego@latest&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;然后就可以基于&lt;a class="link" href="https://go-acme.github.io/lego/dns/" target="_blank" rel="noopener"&#10; &gt;DNS厂商&lt;/a&gt;来生成证书，这里以腾讯云DNS，注意它的APP Key是不同于DNSPod的。如果网络不加，建议延长TIMEOUT时间。这里一并生成浏览器/系统可用的PKCS12文件(.pfx)&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ TENCENTCLOUD_SECRET_ID&lt;span style="color:#f92672"&gt;=&lt;/span&gt;*** TENCENTCLOUD_PROPAGATION_TIMEOUT&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;120&lt;/span&gt; TENCENTCLOUD_POLLING_INTERVAL&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;5&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;\ &lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;TENCENTCLOUD_SECRET_KEY&lt;span style="color:#f92672"&gt;=&lt;/span&gt;***&lt;span style="color:#ae81ff"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;lego --email username@exmaple.com --pem --pfx --pfx.pass *** --cert.timeout &lt;span style="color:#ae81ff"&gt;120&lt;/span&gt; --dns tencentcloud --domains user1.idt.exmaple.com run&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2023/04/08 11:42:46 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;INFO&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;user1.idt.exmaple.com&lt;span style="color:#f92672"&gt;]&lt;/span&gt; acme: Obtaining bundled SAN certificate&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2023/04/08 11:42:47 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;INFO&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;user1.idt.exmaple.com&lt;span style="color:#f92672"&gt;]&lt;/span&gt; AuthURL: https://acme-v02.api.letsencrypt.org/acme/authz-v3/217627103547&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2023/04/08 11:42:47 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;INFO&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;user1.idt.exmaple.com&lt;span style="color:#f92672"&gt;]&lt;/span&gt; acme: Could not find solver &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt;: tls-alpn-01&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2023/04/08 11:42:47 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;INFO&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;user1.idt.exmaple.com&lt;span style="color:#f92672"&gt;]&lt;/span&gt; acme: Could not find solver &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt;: http-01&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2023/04/08 11:42:47 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;INFO&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;user1.idt.exmaple.com&lt;span style="color:#f92672"&gt;]&lt;/span&gt; acme: use dns-01 solver&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2023/04/08 11:42:47 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;INFO&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;user1.idt.exmaple.com&lt;span style="color:#f92672"&gt;]&lt;/span&gt; acme: Preparing to solve DNS-01&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2023/04/08 11:42:50 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;INFO&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;user1.idt.exmaple.com&lt;span style="color:#f92672"&gt;]&lt;/span&gt; acme: Trying to solve DNS-01&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2023/04/08 11:42:50 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;INFO&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;user1.idt.exmaple.com&lt;span style="color:#f92672"&gt;]&lt;/span&gt; acme: Checking DNS record propagation using &lt;span style="color:#f92672"&gt;[&lt;/span&gt;127.0.0.53:53&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2023/04/08 11:42:55 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;INFO&lt;span style="color:#f92672"&gt;]&lt;/span&gt; Wait &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; propagation &lt;span style="color:#f92672"&gt;[&lt;/span&gt;timeout: 2m0s, interval: 5s&lt;span style="color:#f92672"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2023/04/08 11:42:55 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;INFO&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;user1.idt.exmaple.com&lt;span style="color:#f92672"&gt;]&lt;/span&gt; acme: Waiting &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; DNS record propagation.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2023/04/08 11:43:01 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;INFO&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;user1.idt.exmaple.com&lt;span style="color:#f92672"&gt;]&lt;/span&gt; acme: Waiting &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; DNS record propagation.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2023/04/08 11:43:06 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;INFO&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;user1.idt.exmaple.com&lt;span style="color:#f92672"&gt;]&lt;/span&gt; acme: Waiting &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; DNS record propagation.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2023/04/08 11:43:11 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;INFO&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;user1.idt.exmaple.com&lt;span style="color:#f92672"&gt;]&lt;/span&gt; acme: Waiting &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; DNS record propagation.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2023/04/08 11:43:17 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;INFO&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;user1.idt.exmaple.com&lt;span style="color:#f92672"&gt;]&lt;/span&gt; acme: Waiting &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; DNS record propagation.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2023/04/08 11:43:22 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;INFO&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;user1.idt.exmaple.com&lt;span style="color:#f92672"&gt;]&lt;/span&gt; acme: Waiting &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; DNS record propagation.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2023/04/08 11:43:35 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;INFO&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;user1.idt.exmaple.com&lt;span style="color:#f92672"&gt;]&lt;/span&gt; The server validated our request&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2023/04/08 11:43:35 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;INFO&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;user1.idt.exmaple.com&lt;span style="color:#f92672"&gt;]&lt;/span&gt; acme: Cleaning DNS-01 challenge&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2023/04/08 11:43:37 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;INFO&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;user1.idt.exmaple.com&lt;span style="color:#f92672"&gt;]&lt;/span&gt; acme: Validations succeeded; requesting certificates&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;2023/04/08 11:43:39 &lt;span style="color:#f92672"&gt;[&lt;/span&gt;INFO&lt;span style="color:#f92672"&gt;]&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;user1.idt.exmaple.com&lt;span style="color:#f92672"&gt;]&lt;/span&gt; Server responded with a certificate.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ ls -la .lego/certificates&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;total &lt;span style="color:#ae81ff"&gt;40&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;drwx------ &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; channing channing &lt;span style="color:#ae81ff"&gt;4096&lt;/span&gt; 4月 &lt;span style="color:#ae81ff"&gt;8&lt;/span&gt; 11:43 .&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;drwx------ &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt; channing channing &lt;span style="color:#ae81ff"&gt;4096&lt;/span&gt; 4月 &lt;span style="color:#ae81ff"&gt;8&lt;/span&gt; 10:58 ..&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw------- &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; channing channing &lt;span style="color:#ae81ff"&gt;5341&lt;/span&gt; 4月 &lt;span style="color:#ae81ff"&gt;8&lt;/span&gt; 11:43 user1.idt.exmaple.com.crt&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw------- &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; channing channing &lt;span style="color:#ae81ff"&gt;3751&lt;/span&gt; 4月 &lt;span style="color:#ae81ff"&gt;8&lt;/span&gt; 11:43 user1.idt.exmaple.com.issuer.crt&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw------- &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; channing channing &lt;span style="color:#ae81ff"&gt;244&lt;/span&gt; 4月 &lt;span style="color:#ae81ff"&gt;8&lt;/span&gt; 11:43 user1.idt.exmaple.com.json&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw------- &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; channing channing &lt;span style="color:#ae81ff"&gt;227&lt;/span&gt; 4月 &lt;span style="color:#ae81ff"&gt;8&lt;/span&gt; 11:43 user1.idt.exmaple.com.key&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw------- &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; channing channing &lt;span style="color:#ae81ff"&gt;5568&lt;/span&gt; 4月 &lt;span style="color:#ae81ff"&gt;8&lt;/span&gt; 11:43 user1.idt.exmaple.com.pem&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-rw------- &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; channing channing &lt;span style="color:#ae81ff"&gt;2992&lt;/span&gt; 4月 &lt;span style="color:#ae81ff"&gt;8&lt;/span&gt; 11:43 user1.idt.exmaple.com.pfx&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;由于这个证书的CA是Let’s Encrypt的，而Let’s Encrypt本身的证书又是Internet Security Research Group签发。而当Nginx配置ssl_client_certificate CA证书时只能是Root CA，也就是ISRG的证书，而不是中间厂商的证书，也就是不能用Let’s Encrypt的CA证书。ISRG的证书可以从浏览器导出或者网上&lt;a class="link" href="http://www.certificate.fyicenter.com/11138_ISRG_Root_X1_Certificate-79B459E67BB6E5E40173800888C81A58F6E99B6E.html" target="_blank" rel="noopener"&#10; &gt;下载&lt;/a&gt;，然后保存到服务器上&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ mv isrg_root.crt /etc/nginx/certs/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ chomd &lt;span style="color:#ae81ff"&gt;400&lt;/span&gt; etc/nginx/certs/isrg_root.crt&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Nginx配置如下，可以将日志级别设置为debug,调试/观察认证&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ vim /etc/nginx/conf.d/site-available/100-mtls.example.com&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;server &lt;span style="color:#f92672"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; listen 80;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; server_name mtls.example.com;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;301&lt;/span&gt; https://$host$request_uri;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;server &lt;span style="color:#f92672"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; listen &lt;span style="color:#ae81ff"&gt;443&lt;/span&gt; ssl;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; server_name mtls.example.com;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ssl_client_certificate /etc/nginx/conf.d/certs/isrg_root.crt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ssl_verify_client on;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ssl_verify_depth 2;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ssl_session_cache builtin:1000 shared:SSL:10m;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ssl_protocols TLSv1 TLSv1.1 TLSv1.2;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ssl_prefer_server_ciphers on;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# error_log /var/log/nginx/error.log debug;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; location / &lt;span style="color:#f92672"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; root /var/www/mtls.example.com/html;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; index index.html index.htm;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; error_page &lt;span style="color:#ae81ff"&gt;500&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;502&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;503&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;504&lt;/span&gt; /50x.html;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; location &lt;span style="color:#f92672"&gt;=&lt;/span&gt; /50x.html &lt;span style="color:#f92672"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; root /usr/share/nginx/html;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;使用curl测试一下，提示需要客户端证书&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl https://mtls.example.com&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;html&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;head&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;title&amp;gt;400 No required SSL certificate was sent&amp;lt;/title&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/head&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;body bgcolor&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;white&amp;#34;&lt;/span&gt;&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;center&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;h1&amp;gt;400 Bad Request&amp;lt;/h1&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/center&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;center&amp;gt;No required SSL certificate was sent&amp;lt;/center&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;hr&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;center&amp;gt;nginx/1.14.0&amp;lt;/center&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;lt;/body&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/html&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;当带上证书的时候就可以了&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl --cert user1.idt.exmaple.com.crt --key user1.idt.exmaple.com.key https://mtls.example.com&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;html&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;head&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;title&amp;gt;Welcome to mtls.example.com!&amp;lt;/title&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/head&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;body&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;h1&amp;gt;Success! The mtls server is working!&amp;lt;/h1&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/body&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/html&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;使用浏览器访问目标网站需要安装.pfx文件，否则也会报错，禁止访问。通常Windows/Mac双击.pfx文件即可自动安，也可以通过浏览器配置来安装。使用Chrome需要在从菜单设置-&amp;gt;隐私设置和安全性-&amp;gt;安全-&amp;gt;管理设备证书-&amp;gt;个人-&amp;gt;导入。使用Firefox则是从从菜单设置-&amp;gt;隐私与安全-&amp;gt;安全-&amp;gt;查看证书-&amp;gt;您的证书-&amp;gt;导入。iOS和Android可以通过邮件的方式将.pfx文件传输到手机上，点击.pfx文件按照系统提示安装即可。最后使用浏览器打开https://mtls.example.com，会提示使用刚才配置好的证书，选择即可。&lt;br&gt;&#10;上面Nginx配置的是公共CA的根证书（isrg_root.crt），这意味着所有该CA签发的证书都将可以访问https://mtls.example.com，这有点太开放了。如果我们自己生成Root CA证书，便可以做进一步的控制。&lt;br&gt;&#10;首先生成Root CA证书&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ openssl genrsa -des3 -out ca.key &lt;span style="color:#ae81ff"&gt;4096&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Enter PEM pass phrase:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Verifying - Enter PEM pass phrase:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ openssl req -new -x509 -days &lt;span style="color:#ae81ff"&gt;3650&lt;/span&gt; -key ca.key -out ca.crt39:06&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Enter pass phrase &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; ca.key:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;You are about to be asked to enter information that will be incorporated&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;into your certificate request.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;What you are about to enter is what is called a Distinguished Name or a DN.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;There are quite a few fields but you can leave some blank&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;For some fields there will be a default value,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;If you enter &lt;span style="color:#e6db74"&gt;&amp;#39;.&amp;#39;&lt;/span&gt;, the field will be left blank.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-----&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Country Name &lt;span style="color:#f92672"&gt;(&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; letter code&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;AU&lt;span style="color:#f92672"&gt;]&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;State or Province Name &lt;span style="color:#f92672"&gt;(&lt;/span&gt;full name&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;Some-State&lt;span style="color:#f92672"&gt;]&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Locality Name &lt;span style="color:#f92672"&gt;(&lt;/span&gt;eg, city&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;[]&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Organization Name &lt;span style="color:#f92672"&gt;(&lt;/span&gt;eg, company&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;Internet Widgits Pty Ltd&lt;span style="color:#f92672"&gt;]&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Organizational Unit Name &lt;span style="color:#f92672"&gt;(&lt;/span&gt;eg, section&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;[]&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Common Name &lt;span style="color:#f92672"&gt;(&lt;/span&gt;e.g. server FQDN or YOUR name&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;[]&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Email Address &lt;span style="color:#f92672"&gt;[]&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ cat ca.key &amp;gt; ca.pem &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ cat ca.crt &amp;gt;&amp;gt; ca.pem&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ ls&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ca.crt ca.key ca.pem&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;然后使用CA证书生成客户端&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ openssl genrsa -out user1.key&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Enter PEM pass phrase:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ openssl req -new -key user1.key -out user1.csr&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;You are about to be asked to enter information that will be incorporated&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;into your certificate request.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;What you are about to enter is what is called a Distinguished Name or a DN.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;There are quite a few fields but you can leave some blank&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;For some fields there will be a default value,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;If you enter &lt;span style="color:#e6db74"&gt;&amp;#39;.&amp;#39;&lt;/span&gt;, the field will be left blank.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-----&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Country Name &lt;span style="color:#f92672"&gt;(&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; letter code&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;AU&lt;span style="color:#f92672"&gt;]&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;State or Province Name &lt;span style="color:#f92672"&gt;(&lt;/span&gt;full name&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;Some-State&lt;span style="color:#f92672"&gt;]&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Locality Name &lt;span style="color:#f92672"&gt;(&lt;/span&gt;eg, city&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;[]&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Organization Name &lt;span style="color:#f92672"&gt;(&lt;/span&gt;eg, company&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;Internet Widgits Pty Ltd&lt;span style="color:#f92672"&gt;]&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Organizational Unit Name &lt;span style="color:#f92672"&gt;(&lt;/span&gt;eg, section&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;[]&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Common Name &lt;span style="color:#f92672"&gt;(&lt;/span&gt;e.g. server FQDN or YOUR name&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;[]&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Email Address &lt;span style="color:#f92672"&gt;[]&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Please enter the following &lt;span style="color:#e6db74"&gt;&amp;#39;extra&amp;#39;&lt;/span&gt; attributes&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;to be sent with your certificate request&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;A challenge password &lt;span style="color:#f92672"&gt;[]&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;An optional company name &lt;span style="color:#f92672"&gt;[]&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ openssl x509 -req -days &lt;span style="color:#ae81ff"&gt;365&lt;/span&gt; -in user1.csr -CA ca.crt -CAkey ca.key -set_serial &lt;span style="color:#ae81ff"&gt;01&lt;/span&gt; -out user1.crt&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Certificate request self-signature ok&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Enter pass phrase &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; ca.key:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ openssl pkcs12 -export -out user1.pfx -inkey user1.key -in user1.crt -certfile ca.crt&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Enter Export Password:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Verifying - Enter Export Password:&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;然后将ca.crt上传至服务器/etc/nginx/certs/下面并配置ssl_client_certificate使用该证书即可。使用curl测试一下&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl --cert user1.crt --key user1.key https://mtls.example.com&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;html&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;head&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;title&amp;gt;Welcome to mtls.example.com!&amp;lt;/title&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/head&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;body&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;h1&amp;gt;Success! The mtls server is working!&amp;lt;/h1&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/body&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/html&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;同样可以成功访问。不过刚才生成的.pfx文件只有Firefox可以导入使用，其他系统/浏览器不可以，那么可以从Firefox中重新备份导出该文件，Chrome/其他系统就可以使用了。或者重新转换一下&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;openssl pkcs12 -in user1.pfx -out user1.pem -nodes &lt;span style="color:#75715e"&gt;#pfx证书转换为x.509格式的pem证书&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;openssl pkcs12 -in user1.pfx -nocerts -nodes -out user1.key &lt;span style="color:#75715e"&gt;#pfx证书中提取密钥对&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;openssl rsa -in user1.key -out user1_private.key &lt;span style="color:#75715e"&gt;#密钥对提取私钥&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;openssl pkcs12 -export -in user1.pem -inkey user1_private.key -out user1.pfx &lt;span style="color:#75715e"&gt;#使用x.509+私钥转换为win10可用的pfx证书&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;使用自定义CA可以有效控制证书的签发，也可以免CA直接签发客户端证书&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ openssl req -x509 -nodes -days &lt;span style="color:#ae81ff"&gt;9999&lt;/span&gt; -newkey rsa:2048 -keyout user2.key -out user2.crt&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;..+...+...&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-----&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;You are about to be asked to enter information that will be incorporated&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;into your certificate request.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;What you are about to enter is what is called a Distinguished Name or a DN.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;There are quite a few fields but you can leave some blank&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;For some fields there will be a default value,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;If you enter &lt;span style="color:#e6db74"&gt;&amp;#39;.&amp;#39;&lt;/span&gt;, the field will be left blank.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;-----&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Country Name &lt;span style="color:#f92672"&gt;(&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; letter code&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;AU&lt;span style="color:#f92672"&gt;]&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;State or Province Name &lt;span style="color:#f92672"&gt;(&lt;/span&gt;full name&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;Some-State&lt;span style="color:#f92672"&gt;]&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Locality Name &lt;span style="color:#f92672"&gt;(&lt;/span&gt;eg, city&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;[]&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Organization Name &lt;span style="color:#f92672"&gt;(&lt;/span&gt;eg, company&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;Internet Widgits Pty Ltd&lt;span style="color:#f92672"&gt;]&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Organizational Unit Name &lt;span style="color:#f92672"&gt;(&lt;/span&gt;eg, section&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;[]&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Common Name &lt;span style="color:#f92672"&gt;(&lt;/span&gt;e.g. server FQDN or YOUR name&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;[]&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Email Address &lt;span style="color:#f92672"&gt;[]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;无CA签名的证书，就直接将user2.crt上传至服务器/etc/nginx/certs/下面并配置ssl_client_certificate使用该证书即可。如果生成了多个，就合并成一个上传服务器就好了。使用curl测试一下，也是可以的&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl --cert user2.crt --key user2.key https://mtls.example.com&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;html&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;head&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;title&amp;gt;Welcome to mtls.example.com!&amp;lt;/title&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/head&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;body&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;h1&amp;gt;Success! The mtls server is working!&amp;lt;/h1&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/body&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&amp;lt;/html&amp;gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Nginx还支持将客户端证书及CA的DN传递给后端程序，再配合访问控制，便可以精细控制用户访问了。Nginx配置如下，注意这里ssl_verify_client是optional,认证失败不再返回400而是403&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ vim /etc/nginx/conf.d/site-available/100-mtls.example.com&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;server &lt;span style="color:#f92672"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; listen &lt;span style="color:#ae81ff"&gt;443&lt;/span&gt; ssl;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; server_name mtls.example.com;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ssl_certificate /etc/letsencrypt/live/example.comfullchain.pem;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ssl_client_certificate /etc/nginx/conf.d/certs/ca.crt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ssl_verify_client optional;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ssl_verify_depth 2;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ssl_session_cache builtin:1000 shared:SSL:10m;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ssl_protocols TLSv1 TLSv1.1 TLSv1.2;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ssl_prefer_server_ciphers on;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# error_log /var/log/nginx/error.log debug;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; location / &lt;span style="color:#f92672"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# if ($ssl_client_i_dn != &amp;#34;/C=EX/CN=Client/emailAddress=user1@example.com&amp;#34;) {&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# return 403;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# }&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#f92672"&gt;(&lt;/span&gt;$ssl_client_verify !&lt;span style="color:#f92672"&gt;=&lt;/span&gt; SUCCESS&lt;span style="color:#f92672"&gt;)&lt;/span&gt; &lt;span style="color:#f92672"&gt;{&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; 403; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header SSL_Client_Issuer $ssl_client_i_dn;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header SSL_Client $ssl_client_s_dn;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_set_header SSL_Client_Verify $ssl_client_verify;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; proxy_pass http://127.0.0.1:3000/;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; error_page &lt;span style="color:#ae81ff"&gt;500&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;502&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;503&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;504&lt;/span&gt; /50x.html;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; location &lt;span style="color:#f92672"&gt;=&lt;/span&gt; /50x.html &lt;span style="color:#f92672"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; root /usr/share/nginx/html;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;➜&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;NodeJS代码如下&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;express&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;require&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;express&amp;#39;&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;port&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;3000&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;host&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;127.0.0.1&amp;#39;&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;options&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; { };&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;app&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;express&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;app&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;get&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;/&amp;#39;&lt;/span&gt;, (&lt;span style="color:#a6e22e"&gt;req&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;res&lt;/span&gt;) =&amp;gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;res&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;status&lt;/span&gt;(&lt;span style="color:#ae81ff"&gt;200&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;json&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;`Hello &lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;req&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;header&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;ssl_client&amp;#34;&lt;/span&gt;)&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;, your certificate was issued by &lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;req&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;header&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;SSL_Client_Issuer&amp;#34;&lt;/span&gt;)&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;!`&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;});&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;app&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;listen&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;port&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;host&lt;/span&gt;, () =&amp;gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;listening&amp;#34;&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;})&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;使用curl测试一下便会输出客户端DN。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ curl --cert user1.crt --key user1.key https://mtls.example.com/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;Hello emailAddress=user1@example,CN=exmaple,OU=server,C=exmaple, your certificate was issued by emailAddress=user1@example,CN=exmaple,OU=user1,C=exmaple!&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;事实上不仅Nginx支持设置客户端认证，&lt;a class="link" href="https://github.com/Kong/kong" target="_blank" rel="noopener"&#10; &gt;Kong网关&lt;/a&gt;，云原生应用传输&lt;a class="link" href="https://github.com/traefik/traefik" target="_blank" rel="noopener"&#10; &gt;traefik&lt;/a&gt;等也早已支持，编程语言层面更是支持开发mTLS应用了。&lt;/p&gt;&#10;&lt;p&gt;参考链接：&lt;br&gt;&#10;&lt;a class="link" href="https://www.cloudflare.com/learning/access-management/what-is-mutual-tls/" target="_blank" rel="noopener"&#10; &gt;What is mutual TLS (mTLS)?&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="http://dapenti.com/blog/index.asp" target="_blank" rel="noopener"&#10; &gt;Mutual authentication&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://github.com/haoel/mTLS" target="_blank" rel="noopener"&#10; &gt;mTLS Golang Example&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://datacadamia.com/web/server/nginx/client_authentication" target="_blank" rel="noopener"&#10; &gt;How to configure certification based client authentication with Nginx ?&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://dev.to/darshitpp/how-to-implement-two-way-ssl-with-nginx-2g39" target="_blank" rel="noopener"&#10; &gt;How To Implement Two Way SSL With Nginx&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://github.com/pandashavenobugs/mTLS-with-node-blogpost" target="_blank" rel="noopener"&#10; &gt;mTLS with node&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://medium.com/geekculture/mtls-with-nginx-and-nodejs-e3d0980ed950" target="_blank" rel="noopener"&#10; &gt;mTLS with NGINX and NodeJS&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://go-acme.github.io/lego/" target="_blank" rel="noopener"&#10; &gt;LEGO&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://www.infinisign.com/faq/firefox-pfx-import-windows10-error-password" target="_blank" rel="noopener"&#10; &gt;Firefox导出PFX证书在Win10导入提示密码错误&lt;/a&gt;&lt;br&gt;&#10;&lt;a class="link" href="https://stackoverflow.com/questions/8431528/nginx-ssl-certificate-authentication-signed-by-intermediate-ca-chain" target="_blank" rel="noopener"&#10; &gt;NGinx SSL certificate authentication signed by intermediate CA (chain)&lt;/a&gt;&lt;/p&gt;&#10;</description></item></channel></rss>