解决问题:使用nignx完成http转https和二级域名转发,将已有http通信的web前端转为https,包括主域和一个二级域名,这两个domain解析到同一ip。
Nginx作用:
(1)HTTP静态服务器:存储图片,文件等静态资源
(2)负载均衡:当一台web服务器不够用时,需要添置一台web服务器,这时候就需要nginx来 做负载均衡,把浏览器的访问量以特定的规则分发到两台web服务器上。
(3)反向代理:正常情况下客户端直接访问服务器。反向代理是客户端请求nginx,nginx请求服务器,然后返回数据给客户端。
(4)虚拟主机:例如将www.aaa.com和www.bbb.com两个网站部署在同一台服务器上,两个域名解析到同一个IP地址,但是用户通过两个域名却可以打开两个完全不同的网站,互相不影响,就像访问两个服务器一样,所以叫两个虚拟主机。个域名解析同一个IP地址。用nginx做反向代理将对不同域名的请求分别转发到该IP的不同端口。
解决上面的问题,用到nginx反向代理,虚拟主机
Nginx安装:选择使用docker,一键部署。具体可参考博客:http://www.ruanyifeng.com/blog/2018/02/nginx-docker.html。在此使用nginx做反向代理而不是web服务器,所以只需要修改nginx配置,将配置文件映射到本地,不需要映射网页html文件。
Nginx配置:
实现功能:
- 访问http://aa.com时,自动跳转到https://aa.com,然后再转发到http://10.8.5.5:8888
- 访问http://bb.aa.com时,自动跳转到https://bb.aa.com,然后再转发到https://10.8.5.5:5020/api/,转发时对客户端不透明,浏览器上仍显示https://bb.aa.com,实则请求https://10.8.5.5:5020/api/
以上可以实现的前提是DNS可以自动将domain解析到配置nginx的服务器ip上。
配置文件:
upstream upstream1 {
server 10.8.5.5:8888;
} #upstream 实现负载均衡,可在此配置多个服务器
#------------http 重定向到https上----------------------
server {
listen 80;
server_name aa.com; #主域名
return 301 https://$server_name; 重定向,浏览器向重定向后的地址重新请求
}
server {
listen 80;
server_name bb.aa.com; #二级域名
return 301 https://$server_name;
}
#------------------------https设置反向代理-----------------------
server {
listen 443 ssl http2;
server_name aa.com; #主域名
ssl on;
ssl_certificate /etc/nginx/certs/example.crt; #证书位置
ssl_certificate_key /etc/nginx/certs/example.key;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://upstream1 ;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
#proxy_buffer_size 64k;
#proxy_buffers 32 32k;
#proxy_busy_buffers_size 128k;
}
}
server {
listen 443 ssl http2;
server_name bb.aa.com; #二级域名
ssl on;
ssl_certificate /etc/nginx/apicerts/example.crt;
ssl_certificate_key /etc/nginx/apicerts/example.key;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
location / {
proxy_pass https://10.8.5.5:5020/api/; #被代理服务器地址
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
#proxy_buffer_size 64k;
#proxy_buffers 32 32k;
#proxy_busy_buffers_size 128k;
}
location /swaggerui/ {#二级目录转发
proxy_pass https://10.8.5.5:5020/swaggerui/; 需要转发的二级domain本身为https,
# 该路径下为web页面的静态文件css,js等,不设置的话网页无法正常展示
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
}
location /api/ {#二级目录转发
proxy_pass https://10.8.5.5:5020/api/;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
#proxy_buffer_size 64k;
#proxy_buffers 32 32k;
#proxy_busy_buffers_size 128k;
}
}
至此,所有配置均已完成,启动命令:
docker container run -d \
-p 10.8.5.5:80:80 -p 10.8.5.5:443:443 \
--rm \
--name mynginx \
--volume "/mnt/storage/nginx_docker_demo/conf":/etc/nginx \
nginx
-d 后台运行
-p 容器80端口映射到10.8.5.5:80
-- rm 停止运行后删除容器文件
-- name 自定义容器名称
-volumn nginx配置文件映射
Bingo Bingo ~~~~
docker ps 可以查看正在运行的容器,可以发现已经启动成功。
番外:配置过程中遇到的一些其他问题:
1.ssl 证书 ,我用的是openssl申请的免费版证书,只能用于一个domain,对二级domain无效(貌似免费的都是这样),因此在nginx配置的时候分别配置,制定各自证书,否则可以配置到一起。配置方法如下:
server {
listen 443 ssl http2;
server_name *.aa.com; #此处设置为泛域名
ssl on;
ssl_certificate /etc/nginx/certs/example.crt; ##一定是相同的证书
ssl_certificate_key /etc/nginx/certs/example.key;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
if ($http_host ~* "^(.*?)\.aa\.com$") {
set $domain $1;
}
location / {
if ($domain ~* "bb") {
proxy_pass https://10.8.5.5:5020/api/;#匹配到子域名时设置相应的转发
}
proxy_pass http://upstream1;#默认情况,也就是主域名时相应的转发
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
}
-
配置子域名时有些特殊,web页面是flask-restplus框架中封装的swagger UI,本来也是http通信,按照主域名的配置后,静态的页面找不到css,js文件。找到这些文件所在路径后在nginx中添加二级目录可以解决。
文件路径
此时又出现了另外一个问题,swagger读某些json文件时为http,这样就产生了https和http混合通信,无法正常工作。在网上找了些解决办法,都不生效。干脆在flask-restplus配置为https,这样就全部是https通信了,修改的代码在此记录下:
###需要安装模块 pip install pyOpenSSL
if __name__ == '__main__':
from werkzeug.contrib.fixers import ProxyFix
initialize_app(app)
app.wsgi_app = ProxyFix(app.wsgi_app) #手动修复代理
app.run(threaded=True, host='0.0.0.0', port=5020 ,ssl_context='adhoc')#此处一定是adhoc,使用python模块自动生成的证书
网友评论