HTTPS的双向认证(七)

上一篇文章讲解了容器的使用方法,这篇文章使用这个容器,启动容器里的nginx服务,并使用容器里自带的curl命令访问nginx服务,看一下「https双向认证」的实际过程。

首先启动并且登录这个容器:

$ docker run -it  alchemystudio/nginx-ssl-bidirection sh

登录进容器以后,启动nginx服务:

$ nginx

然后查看nginx是否正确启动了:

$ ps -ef | grep nginx

此时使用curl命令访问nginx服务:

$ curl https://localhost

执行上面的命令,可以看到curl的报错信息:

如上所示,可以看到curl在访问服务端的时候,说服务端提供的证书是self signed certificate,就是自签名证书,因此无法验证这张证书。

因为我们的「服务端证书」不是第三方权威机构签名的,所以curl无法进行验证。我们有两个方案可以解决这个问题:

因为我们的「服务端证书」是自签名的,因此「服务端证书」的签名证书就是它自己。

上面两种方案我们都执行一下看看,首先是使用-k选项跳过对「服务端证书」的签名验证:

$ curl -k https://localhost

可以看到这回curl命令从nginx服务这边返回了内容,说明curl跳过了对「服务端证书」的验证,建立了和nginx服务的连接,并取得了服务端返回的内容。

如果不跳过验证,那么就要在curl访问nginx服务的时候挂上「服务端证书」作为验证用的「CA证书」。命令如下:

$ curl --cacert /cert/server.crt https://localhost

执行上面命令的结果和跳过验证是一致的:

可以看到挂上「服务端证书」作为「CA证书」以后,curl验证通过了服务端提供的证书,并且成功和服务端建立了连接,并且返回了nginx提供的页面。

接下来看一下返回页面的内容。可以看到返回的内容是400 Bad Request,错误信息也给出了:

No required SSL certificate was sent

也就是说「服务端」要「客户端」提供证书,但是我们在curl中没有提供「客户端证书」,因此nginx服务无法验证「客户端」的身份。

因此我们要在curl请求服务端的时候,挂上「客户端证书」。方法是使用curl--cert选项:

$ curl --cacert /cert/server.crt --cert /cert/client.crt https://localhost

以下是命令的执行结果:

可以看到,虽然在curl的请求命令挂上了--cert选项,但是这个证书curl无法使用,因为curl作为「客户端证书」的拥有者,还需要拥有「客户端证书」的「私钥」。这样,服务端使用「客户端证书」的「公钥」把一些加密数据发还给「客户端」的时候,「客户端」才能使用「私钥」正确解密。

这一点其实和nginx服务这边的配置文件里,同时配置了「服务端证书」和「服务端证书私钥」的形式,是对等的。

因此在使用curl访问「服务端」的时候,还要加上--key选项,挂上「客户端」的「私钥文件」:

$ curl --cacert /cert/server.crt --cert /cert/client.crt --key /cert/client.key https://localhost

以下是命令的执行结果:

可以看到这次连接,curlnginx服务端取回了Hello, world!的页面数据。也就是说这次基于「ssl双向认证握手」的连接成功了。

因为在之前的文章里面已经看过,给「客户端证书」签名的「CA证书」是配置在nginx服务的「配置文件」里的。所以curl出示的「客户端证书」是被「服务端」所信任的。

本篇文章就写到这里,下一篇讲解这个容器的另一种使用方法,也就是通过docker-compose启动容器,并在host端访问容器里面nginx服务的方法。

My Github Page: https://github.com/liweinan

Powered by Jekyll and Theme by solid

If you have any question want to ask or find bugs regarding with my blog posts, please report it here:
https://github.com/liweinan/liweinan.github.io/issues