解決問題:使用nignx完成http轉(zhuǎn)https和二級域名轉(zhuǎn)發(fā)浅萧,將已有http通信的web前端轉(zhuǎn)為https,包括主域和一個二級域名阶淘,這兩個domain解析到同一ip哈踱。
Nginx作用:
(1)HTTP靜態(tài)服務(wù)器:存儲圖片箩退,文件等靜態(tài)資源
(2)負載均衡:當一臺web服務(wù)器不夠用時丑罪,需要添置一臺web服務(wù)器传黄,這時候就需要nginx來 做負載均衡杰扫,把瀏覽器的訪問量以特定的規(guī)則分發(fā)到兩臺web服務(wù)器上。
(3)反向代理:正常情況下客戶端直接訪問服務(wù)器膘掰。反向代理是客戶端請求nginx章姓,nginx請求服務(wù)器,然后返回數(shù)據(jù)給客戶端识埋。
(4)虛擬主機:例如將www.aaa.com和www.bbb.com兩個網(wǎng)站部署在同一臺服務(wù)器上凡伊,兩個域名解析到同一個IP地址,但是用戶通過兩個域名卻可以打開兩個完全不同的網(wǎng)站窒舟,互相不影響系忙,就像訪問兩個服務(wù)器一樣,所以叫兩個虛擬主機惠豺。個域名解析同一個IP地址银还。用nginx做反向代理將對不同域名的請求分別轉(zhuǎn)發(fā)到該IP的不同端口风宁。
解決上面的問題,用到nginx反向代理蛹疯,虛擬主機
Nginx安裝:選擇使用docker,一鍵部署戒财。具體可參考博客:http://www.ruanyifeng.com/blog/2018/02/nginx-docker.html。在此使用nginx做反向代理而不是web服務(wù)器捺弦,所以只需要修改nginx配置饮寞,將配置文件映射到本地,不需要映射網(wǎng)頁html文件列吼。
Nginx配置:
實現(xiàn)功能:
- 訪問http://aa.com時,自動跳轉(zhuǎn)到https://aa.com骂际,然后再轉(zhuǎn)發(fā)到http://10.8.5.5:8888
- 訪問http://bb.aa.com時,自動跳轉(zhuǎn)到https://bb.aa.com,然后再轉(zhuǎn)發(fā)到https://10.8.5.5:5020/api/冈欢,轉(zhuǎn)發(fā)時對客戶端不透明歉铝,瀏覽器上仍顯示https://bb.aa.com,實則請求https://10.8.5.5:5020/api/
以上可以實現(xiàn)的前提是DNS可以自動將domain解析到配置nginx的服務(wù)器ip上。
配置文件:
upstream upstream1 {
server 10.8.5.5:8888;
} #upstream 實現(xiàn)負載均衡凑耻,可在此配置多個服務(wù)器
#------------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設(shè)置反向代理-----------------------
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/; #被代理服務(wù)器地址
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/ {#二級目錄轉(zhuǎn)發(fā)
proxy_pass https://10.8.5.5:5020/swaggerui/; 需要轉(zhuǎn)發(fā)的二級domain本身為https,
# 該路徑下為web頁面的靜態(tài)文件css,js等香浩,不設(shè)置的話網(wǎng)頁無法正常展示
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/ {#二級目錄轉(zhuǎn)發(fā)
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 可以查看正在運行的容器邻吭,可以發(fā)現(xiàn)已經(jīng)啟動成功餐弱。
番外:配置過程中遇到的一些其他問題:
1.ssl 證書 ,我用的是openssl申請的免費版證書囱晴,只能用于一個domain膏蚓,對二級domain無效(貌似免費的都是這樣),因此在nginx配置的時候分別配置畸写,制定各自證書驮瞧,否則可以配置到一起。配置方法如下:
server {
listen 443 ssl http2;
server_name *.aa.com; #此處設(shè)置為泛域名
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/;#匹配到子域名時設(shè)置相應(yīng)的轉(zhuǎn)發(fā)
}
proxy_pass http://upstream1;#默認情況枯芬,也就是主域名時相應(yīng)的轉(zhuǎn)發(fā)
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通信千所,按照主域名的配置后狂魔,靜態(tài)的頁面找不到css,js文件。找到這些文件所在路徑后在nginx中添加二級目錄可以解決淫痰。
此時又出現(xiàn)了另外一個問題最楷,swagger讀某些json文件時為http,這樣就產(chǎn)生了https和http混合通信,無法正常工作。在網(wǎng)上找了些解決辦法管嬉,都不生效皂林。干脆在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) #手動修復(fù)代理
app.run(threaded=True, host='0.0.0.0', port=5020 ,ssl_context='adhoc')#此處一定是adhoc,使用python模塊自動生成的證書