在nginx服务器上配置ssl代理https以及wss的一些笔记

1、前言

    因为微信小程序在与服务器通信时必须使用ssl协议,所以准备着手在nginx服务器上配置好ssl

 

2、初步想法

    之前有看过一点关于实现wss连接的文章,大致了解到ssl是一个在运作在传输层的安全通信协议,他的通讯流程大致为:

服务器认证阶段:

1)客户端向服务器发送一个开始信息“Hello”以便开始一个新的会话连接;

2)服务器根据客户的信息确定是否需要生成新的主密钥,如需要则服务器在响应客户的“Hello”信息时将包含生成主密钥所需的信息;

3)客户根据收到的服务器响应信息,产生一个主密钥,并用服务器的公开密钥加密后传给服务器;

4)服务器回复该主密钥,并返回给客户一个用主密钥认证的信息,以此让客户认证服务器。

    以我的理解来看,主密钥即每次的会话密钥,公开密钥即网站的证书,然后在服务器回复主密钥时,实际上是拿自己的私钥来先解开公钥加密的会话密钥,然后再利用证书中的公钥加密一段回复信息给客户。在这个过程中需要注意的是会话密钥是由客户产生的。

    知道了ssl是怎么运作了,然后我开始的想法是,直接在服务器的python代码中直接实现ssl通信,但是因为我的小程序端使用的是需要ssl加密的websocket,而PC端则是裸奔的socket通信,而ssl又是一个传输层协议,所以对客户端的识别是一个小问题,我的第一个想法是开辟两个端口,一个用于处理小程序端,另一个处理PC端,这样也就需要继承两次socketserver.BaseRequestHandler,重写两次handle函数,准备的参考代码:Python3+ssl实现加密通信,其中大致说的是,在得到一个socket后,利用ssl模块中的SSLContext上下文的wrap_socket()函数来得到一个带ssl的socket,然后用这个新的socket进行通信,这其实已经是一个挺简便的方法了。

    然后在查阅了其他资料后,我又决定在PC客户端也干脆实现好ssl好了,紧接着我发现一些文章上所说的根证书我并没有,虽然可能和普通证书没有什么区别,而且网络上关于这个的代码很少,由此我找到了一份ssl官方的开发者文档翻译版,虽然是机翻:Python 联网 | Networking ssl,不过此时我也不准备用python代码直接实现ssl了,还是用nginx直接代理ssl比较实在吼吼吼。

 

3、获取证书

    证书我并没有选择自己生成,而是准备使用各大云平台的免费ssl证书,开始时选择了阿里云的Symantec免费单域名版ssl,结果没通过安全审核,域名没什么敏感词,哔了狗了。。。然后死马当活马医,又去了腾讯云的ssl里弄了的Symantec免费ssl,结果居然成功了,然后拿到了nginx的证书,一份是crt文件,一份是key文件

 

4、配置nginx

    接下来就是配置nginx中的ssl了,就不说中间的探索和试错过程了,直接说结论

    我的nginx配置目录为/etc/nginx/conf.d   就我的了解,nginx服务器启动时会挨个运行这里面的.conf文件,这些conf文件中一般会有server字段,例如:在nginx服务器上配置ssl代理https以及wss的一些笔记_第1张图片

    server中开始有listen参数,填的当然是监听端口443啦,然后是server_name,这就是url,两个结合一起就是url:listen, 然后配置要配置ssl的话就又ssl,ssl_certificate,ssl_certificate_key参数,比较一目了然,ssl一般填写on。再后面就是一些协议细节配置了。

    接着是location字段,后面会接一个小字段,这个就是当客户访问指定端口时使用的协议标识,wss就是/wss,http直接是/,根据标识的不同,定位到的代码段就不同,比如当识别为http标识时就会到下面的location代码段当中,代码块中有相关的处理根目录,默认文档日志等等设置,需要注意的是proxy_pass参数,这个填的是http://$upstram$/,其中upstream需要事先定义例如:

    这里的upstream就是“web”,这里面只有一段地址串,可以理解为一个出口,之前的proxy_pass参数就是作为一个代理将当前的请求跳转到另一个出口,我的代码中将其跳转为8080端口,然后nginx又会继续将url:8080作为一个请求来处理(但是ssl已经转载好了)。

    然后我又在这个配置文件夹里创建了一个新的配置文件http2https.conf,,其监听的端口就是8080,在这里我就配置好正经的http请求该配置的东西, 然后为了让普通的http请求也能够跳转到https,我在原先监听80端口的代码段,中加上了

return      301 https://$server_name$request_uri;

  或者

rewrite ^(.*)$  https://$host$1 permanent; 

    也可以,前者是新的写法,这样普通的http也就是80端口的请求就被转成了443端口的请求了,随后就会调用之前第一个文件中的代码进行多次跳转将客户的请求变成https请求。

    经过后续的调试,我发现用https访问时页面会显示不全,查询资料得知是因为浏览器选择了不加载不安全的http资源,因为网站并非所有资源都是以http协议请求的,某些图片,css布局就会被一些浏览器屏蔽掉(因为经测试手机浏览器都没有屏蔽掉http资源),如果要让https网站显示完全可能还得进一步设置,不过鉴于今天的主题是配置wss,所以不讨论后续问题了。

   WSS配置

        wss配置略微有点曲折,开始是使用域名:端口号作为上游的,后来看到有人说不行,然后自己又在一个wss接口测试网站栽跟头,所以改成了ip:端口号,也不行。然后用小程序测试,测试出错,返回码200,查资料说什么的都有,感觉又都不靠谱,说到这里就要讲到一个题外话了——搜索,做这个项目愈多,愈发现搜索的重要性,我指的是搜索关键词的选取,这个问题我开始的搜索方法是直接搜索错误信息 “Error during WebSocket handshake: Unexpected response code: 200”,搜出来的结果鱼龙混杂,说什么拦截器,stuts,handle什么鬼这是,搜的我怀疑人生,这些东西基本不懂,没听过并且用的部署方案跟我也不同。然后我换了一种关键词序列  “nginx wss 200”  ,结果第一个结果就是我要的,这个搜索其实很讲究,描述事件的几大要素——时间,地点,人物,事件,这对关键词占了其三,nginx相当于地点,wss相当于人物,200相当于事件,虽然好像有点扯,但是就是有道理!这样搜索就剔除了之前错误信息的冗余,从一个精准的角度去搜索问题。然后得知之前的location字段那个是指。。。唉说不清楚直接放图

在nginx服务器上配置ssl代理https以及wss的一些笔记_第2张图片在nginx服务器上配置ssl代理https以及wss的一些笔记_第3张图片

至此,问题解决。

参考代码:Nginx配置https和wss

你可能感兴趣的:(笔记)