背景:
之前項目都是爲集團內部提供服務的,很多接口都是內網訪問,網絡安全方面考慮不多。但是隨着業務發展,可能要對外提供互聯網服務了,一些安全方面的因素也要逐步考慮計劃。
這次,就從最基本的域名安裝SSL證書開始,將http協議升級爲https協議。
一、購買申請SSL證書
直接進阿里雲官網購買證書,暫時選擇免費版本測試。
購買後進入證書控制檯,需要進行證書申請。
需要注意的是我們的ssl證書是和域名綁定的,所以需要提供域名。並且阿里雲免費證書只支持綁定一個域名,收費版支持多個域名(通配符)
關於這個域名驗證方式,它提示我綁定的域名已在阿里雲的雲解析服務中,這個其實是假的,我的域名是在騰訊雲買的,在阿里雲並沒有雲解析服務。
但是沒關係,我們依舊可以選擇自動DNS驗證,以及csr生成方式也是選擇自動。
上面的DNS解析驗證比較關鍵,需要我們去域名解析處配置,我是騰訊雲買的域名,所以我去騰訊雲解析配置。
新增一條域名解析策略,將記錄類型:TXT、主機記錄:_dnsauth、記錄值:201911060000000ajcb4f4配置完畢後,等其生效。
然後去阿里雲證書申請處點擊驗證,會提示驗證成功。
之後就可以看到我們的證書變成已簽發的了。
然後就可以下載證書了。我選擇的是Nginx版本證書。
下載到本地的壓縮文件包解壓後包含:
.crt文件:是證書文件,crt是pem文件的擴展名。
.key文件:證書的私鑰文件(申請證書時如果沒有選擇自動創建CSR,則沒有該文件)。
二、通過nginx配置SSL證書
先按阿里雲的nginx證書幫助文檔操作:
1.在Nginx的安裝目錄(我的是/usr/local/nginx
默認目錄,注意不是解壓目錄)下創建cert
目錄,並且將下載的全部文件拷貝到cert目錄中。如果申請證書時是自己創建的CSR文件,請將對應的私鑰文件放到cert目錄下並且命名爲a.key;
2.添加nginx.conf
配置:
server {
listen 443;
server_name localhost;
ssl on;
root html;
index index.html index.htm;
ssl_certificate cert/a.pem;
ssl_certificate_key cert/a.key;
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
location / {
root html;
index index.html index.htm;
}
}
然後nginx -s reload
重啓,就發現報錯了,在error.log
中:
2019/11/07 15:21:41 [emerg] 6649#0: unknown directive "ssl" in /usr/local/nginx/conf/nginx.conf:115
我開始以爲是cert文件路徑不對(其實確實不對。。但不是報錯的主要原因),然後嘗試各種路徑變幻相對絕對都還是報錯。
我只能認爲我的nginx默認沒有安裝ssl模塊了。然後去嘗試安裝,發現果然如此。
nginx安裝配置SSL模塊:
1.先確保linux服務器安裝了ssl組件:
yum -y install openssl openssl-devel
2.再去nginx解壓目錄(不是安裝目錄)下執行:
./configure --with-http_ssl_module
注意:此處如果你之前安裝nginx時不是用的默認配置,那此處還得添加當時的其他各種configure
3.執行make編譯
4.將原來/usr/local/nginx/sbin/
下的nginx執行文件備份一下,以防萬一
cp /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.bak
然後將解壓目錄下新的編譯後的nginx文件複製到安裝目錄原位置
cp objs/nginx /usr/local/nginx/sbin/nginx
5.測試 nginx配置是否正確
/usr/local/nginx/sbin/nginx -t
發現報錯方式換了:
BIO_new_file("/usr/local/nginx/conf/cert/a.pem") failed (SSL: error:02001002:
system library:fopen:No such file or directory:fopen('/usr/local/nginx/conf/cert/a.pem','r') error:2006D080:BIO routines:BIO_new_file:no such file)
哦 ~ 原來路徑錯誤是這樣報錯的呀!
可以發現,我們nginx.conf裏配置的ssl_certificate cert/a.pem;
其實運行時是去/usr/local/nginx/conf/cert/a.pem
下找的文件,即以nginx.conf所在的conf目錄爲相對路徑,這也符合常理。
那麼阿里雲這個幫助文檔裏寫的 在Nginx的安裝目錄下創建cert目錄
是啥意思,根本不能匹配上nginx.conf裏的配置嘛?!
算了,不計較啥了,我們重新將/usr/local/nginx下的cert目錄移動到/usr/local/nginx/conf下,再重啓nginx,發現成功了。
三、將以前的http請求重定向到https
下面問題來了,配置好 https後,我們以什麼方式訪問才能跳轉 https?之前的 http路徑都要怎麼處理?瀏覽器會如何切換?
測試後發現:
1.如果我們在瀏覽器中直接輸入aaa.com
,其實會自動去跳轉到http://aaa.com
,還是80端口的普通http流量
2.我們輸入https://aaa.com
,這下成功利用到了ssl證書,符合期望
3.我們輸入http://aaa.com:443/
行麼,這種方式其實就是強行將http流量轉移到https,會導致400錯誤,所以這條路也行不通
400 Bad Request
是由於明顯的客戶端錯誤(例如,格式錯誤的請求語法,太大的大小,無效的請求消息或欺騙性路由請求),服務器不能或不會處理該請求。
所以,我們或許需要將http請求都重定向到https?
如何重定向呢,用常用的proxy_pass
麼?
server {
listen 80;
server_name localhost;
location / {
proxy_pass https://localhost/;
}
}
發現依舊是跳轉到:http://aaa.com/
,並不行。而且多次嘗試不同寫法後還是不行。
我們放棄proxy_pass試試return
:
server {
listen 80;
server_name localhost;
location / {
return https://localhost/;
}
}
發現302重定向到了https://localhost/
,並沒有自動將localhost轉化爲域名,這樣也不行。
至於爲啥使用return,可以看看nginx官網的wiki:
所以我們直接寫域名:
server {
listen 80;
server_name localhost;
location / {
return https://aaa.com/;
}
}
發現OK!
我們觀察下百度是怎麼做的:
清除緩存後 (F12勾選 disable cache
),瀏覽器輸入baidu.com
:
看來方式和我們差不多。都是從80端口302重定向到443的https端口。
四、要考慮的還有很多
所以,這麼簡單就完成了https的升級嗎?
em,這是我阿里雲的個人機器,沒有啥項目運行,確實很隨意。
但是我們真正的業務環境是比較複雜的,項目可能涉及多臺服務器,每個服務器上可能有多個項目,這些項目也可能屬於不同項目組、不同業務,但是卻共用同一個Nginx服務器。
同一個nginx裏可能配置了複雜的策略,其中有靜態資源映射、負載均衡、各種維度的請求轉發等。我們要將哪些http請求重定向到https?改造的過程中會不會對其他東西產生干擾?
所以,這裏一定要深思熟慮,儘量減少不必要的麻煩。