最近的小程序项目中需要服务器同时支持https/wss,而微信小程序要求https请求和wss请求必须使用默认端口号(443),这样就会造成端口冲突。也就是IIS(https)监听443端口号,websocket服务也要监听443端口号。
有一个不经济的方案,就是wss服务和https服务分别部署到不同服务器,成本稍微有些高了。
比较理想的方案是使用nginx做反向代理,wss和https的请求都到nginx上,nginx配置规则把不同的请求转发到IIS不同的服务程序上去。
另外,http强制跳转https也是nginx常规要求,一块都整理成一篇IIS+Nginx多网站多域名配置同时反向代理http/https/wss的解决方案
最佳解决方案
一、网站部署到IIS
配置Nginx反向代理后,用户访问网站会首先到nginx服务,然后再由nginx转发到iis,所以这种情况80和443端口就要预留给nginx。在IIS部署网站时需要指定其他端口,同时也不需要在IIS绑定域名。同理,在IIS部署网站也不需要绑定证书,用户无法直接访问到IIS网站。配置如下:
网站使用了8088端口,需要指定websocket监听其他端口,如8099
注意:IIS指定的网站端口号不需要开放给外网
二、NGINX安装与启动
NGINX是免安装的,直接下载就可以。下载地址:http://nginx.org/en/download.html
(Mainline version: 主力开发版本,Stable version:稳定版本,建议下载稳定版本)
下载完成后,解压的不带中文字符的路径既可。不建议双击启动nginx.exe,有时候会出现无法创建logs/nginx.pid文件的情况。nginx.pid是nginx和系统进程的对应关系文件,没有他nginx无法正常工作。
win + r 输入 cmd ,依次进入nginx的安装目录,比如D:\nginx-1.18.0。输入start nginx 就可以启动nginx了。检查logs目录下是否由相应的nginx.pid文件,如果没有,打开error.log看下报什么错。
其他nginx常用命令:
start nginx --启动nginx
nginx -s reload --修改配置文件后重新启动nginx
nginx -s quit --退出nginx
nginx -V --查看nginx版本信息 大写V
三、配置NGINX <多域名多网站>
3.1 重要科普:SNI
SNI 全程Server Name Indication,中文名:服务器名称指示,它是TLS协议一种扩展,就是用来解决一个服务器拥有多个域名的情况的。
为什么需要SNI?
在客户端和服务端建立 HTTPS 的过程中先建立SSL连接,再发送HTTP请求,建立SSL连接时nginx不知道所请求主机的名字(域名),就只会返回默认主机(nginx里面第一个server)的证书。所以在不支持SNI的nginx版本里面配置多个https网站,就会经常出现证书和域名不匹配的情况,只有访问第一个server配置的域名才正常。而SNI就是用来解决这个矛盾问题的。SNI要求客户端在与服务器握手时就携带需要访问的域名的host(域名)信息。这样,服务器就知道需要用哪个虚拟主机的证书与客户端握手并建立TLS连接。
检查当前版本nginx是否支持nginx,输入nginx -V ,出现TLS SNI support enabled就是支持,如下图:
3.2 配置 http 跳转 https
目前https越来越普及,绝大部分网站都要求使用https进行访问。为了在用户输入http的情况也能正常浏览https网站,就需要配置http自动跳转到https了。
nginx/conf/nginx.conf 配置如下:
server { listen 80; #监听80端口,就是监听http访问 server_name www.test.com; location / { proxy_ssl_server_name on; root html; index index.html index.htm; proxy_pass http://127.0.0.1:8080;#仅仅是代理跳转演示,没有跳转到https。 其中127.0.0.1:8080是在IIS绑定的网站端口 } } server { listen 80; #监听80端口,就是监听http访问 server_name api.test.com; location / { proxy_ssl_server_name on; root html; index index.html index.htm; rewrite ^(.*)$ https://${server_name}$1 permanent; #http://api.test.com自动跳转 https://api.test.com } }
3.3 配置 https
这两有两个要注意的地方,1是证书路径的配置 2是 开启SNI , proxy_ssl_server_name 需要配置为on
server { listen 443 http2 ssl; server_name www.test.com; ssl_certificate www.test.com.pem # 没有/开头路径是从nginx.conf所在的文件夹开始的,也就是conf ssl_certificate_key /nginx/conf/www.test.com.key #/开头的路径是从nginx所在盘符开始算起的 ssl_session_cache shared:SSL:1m; ssl_session_timeout 5m; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers ECDH:AESGCM:HIGH:RSA+3DES:!RC4:!DH:!MD5:!aNULL:!eNULL; ssl_prefer_server_ciphers on; #access_log cert/test.log; #网站访问日志 location / { proxy_ssl_server_name on; root html; index index.html index.htm; proxy_pass http://127.0.0.1:8090; #8090 是在IIS配置的端口号 8080 已经给http请求了 } }
3.4 配置 https + wss
server { listen 443 http2 ssl; server_name api.test.com; ssl_certificate cert/api.test.com.pem; # 没有/开头路径是从nginx.conf所在的文件夹开始的 ,也就是conf ssl_certificate_key cert/api.test.com.key; ssl_session_cache shared:SSL:1m; ssl_session_timeout 5m; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers ECDH:AESGCM:HIGH:RSA+3DES:!RC4:!DH:!MD5:!aNULL:!eNULL; ssl_prefer_server_ciphers on; #access_log cert/test.log; #https正常反向代理 location / { proxy_ssl_server_name on; root html; index index.html index.htm; proxy_pass http://127.0.0.1:8088; } #访问wss://api.test.com/wss时,会匹配下面规则,自动转发到8099端口 location /wss { proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; #重要 proxy_set_header Connection "Upgrade"; #重要 proxy_pass http://127.0.0.1:8099;#好像是上面两个重要配置会把http://127.0.0.1:8099转发为或者iis会识别为ws://127.0.0.1:8099 } }