Ubuntu 16.04(ECS),OpenSSL 1.0.2g 1 Mar 2016,Nginx 1.10.3 (Ubuntu),
瀏覽器:Chrome 67,Firefox 61,Edge 40,IE 11
序言
孤之前從來沒有建立過HTTPS網站,感覺很高級、很難,雖然也讀過不少博文、資料,十年前在大學時,也使用過OpenSSL操作過建立證書,但后來都忘記了。
前同事說建立HTTPS網站很容易的,當時自己是不信的,並發生了一些爭論,在此表示歉意。
由於自己搭建了網站,提供了注冊、登錄功能,因此,有安全方面的考慮。前兩日研究了前端加密、Base64編碼等方案(crypto-js),但都無法很好地保證用戶數據安全。
最付出不少精時后,最終決定將網站升級為HTTPS網站,本文記錄了試驗過程中的關鍵步驟——兩步:
1.自建CA並簽名Server證書
2.配置Nginx服務器
自建CA並並簽名Server證書
本步驟完全參考了自建CA並簽名server證書實現https by Andy____Li,只是對一些文件名、配置參數進行了修改。
注意:在執行此步驟之前,請確保Linux操作系統上安裝了OpenSSL。
可以分為下面的小步驟(拷貝了參考鏈接中的命令):
1.自建CA
生成CA私匙
openssl genrsa -out icatchtek.key 2048
執行結果:提示創建成功,可又提示unable to什么的,為什么?還需要dig,
Generating RSA private key, 2048 bit long modulus
................+++
...........................................................................................+++
unable to write 'random state'
e is 65537 (0x10001)
生成CA證書請求
openssl req -new -key icatchtek.key -out icatchtek.csr
PS:證書請求是對簽名的請求,需要使用私鑰進行簽名
此命令輸入后,需要填寫信息。
生成CA根證書
openssl x509 -req -in icatchtek.csr -extensions v3_ca -signkey icatchtek.key -out icatchtek.crt
PS:證書是自簽名或CA簽名過的憑據,用來進行身份認證
執行結果:
Signature ok
subject=/C=CN/ST=Guangdong/L=Shenzhen/OU=.../CN=.../emailAddress=xxxx@example.com
Getting Private key
unable to write 'random state'
2.自建server端證書
生成server私匙
openssl genrsa -out smarthome_server.key 2048
結果同上。
生成server證書請求
openssl req -new -key smarthome_server.key -out smarthome_server.csr
結果同上,需輸入參數。
生成server證書:下面命令的紫色部分就是上面建立的一系列文件,不用弄錯了。
生成server證書,需要一份配置文件,可參閱:vi openssl.cnf
openssl x509 -days 365 -req -in smarthome_server.csr -extensions v3_req -CAkey icatchtek.key -CA icatchtek.crt -CAcreateserial -out smarthome_server.crt -extfile openssl.cnf
關於生產Server證書這一步,孤是直接拷貝了參考鏈接中的內容,並進行了修改。關於此文件怎么寫,孤是不太熟悉的,還需要看更多資料,比如參考鏈接中的OpenSSL主配置文件openssl.cnf。
下面是自己的open.cnf(私密信息沒有)(在參考鏈接中,[req]下面的幾個section是有縮進的,不知道為什么):
[req] distinguished_name = req_distinguished_name req_extensions = v3_req [req_distinguished_name] countryName = Country Name (2 letter code) countryName_default = CN stateOrProvinceName = Guangdong stateOrProvinceName_default = Guangdong localityName = Shenzhen localityName_default = Shenzhen organizationalUnitName = ... organizationalUnitName_default = ... commonName = ... commonName_max = 64 [ v3_req ] # Extensions to add to a certificate request basicConstraints = CA:FALSE keyUsage = nonRepudiation, digitalSignature, keyEncipherment subjectAltName = @alt_names [alt_names] IP.1 = xxx.xxx.xxx.xxx DNS.1 = www.example.com
說明,上面的每一步都會在 執行命令的 當前目錄下 建立相應的文件!下面是孤試驗過程中建立的:
$ ls
ben_server.crt ben_server.key icatchtek.csr icatchtek.srl
ben_server.csr icatchtek.crt icatchtek.key openssl.cnf
配置Nginx服務器
按照參考鏈接的說法,是在server 塊內 listen 端口后添加下面的語句:
ssl on;
ssl_certificate /home/ubuntu/webvideo/nginx/conf/smarthome_server.crt;
ssl_certificate_key /home/ubuntu/webvideo/nginx/conf/smarthome_server.key;
注意,*.crt、*.key文件的路徑需要更改,孤是將它們放在/etc/nginx/conf.d/ca里面的。
作為Nginx新手,孤的Nginx配置文件中只有一個Server的,端口是80。可HTTPS網站的默認端口不是443嗎?
修改前的Nginx配置文件:
server { listen 80 default_server; listen [::]:80 default_server; # SSL configuration # # listen 443 ssl default_server; # listen [::]:443 ssl default_server; # # Note: You should disable gzip for SSL traffic. # See: https://bugs.debian.org/773332 # # Read up on ssl_ciphers to ensure a secure configuration. # See: https://bugs.debian.org/765782 # # Self signed certs generated by the ssl-cert package # Don't use them in a production server! # # include snippets/snakeoil.conf;
修改后的配置文件:
server { listen 80 default_server; listen [::]:80 default_server; # SSL configuration # listen 443 ssl default_server; listen [::]:443 ssl default_server; ssl on; ssl_certificate /etc/nginx/conf.d/ca/smarthome_server.crt; ssl_certificate_key /etc/nginx/conf.d/ca/smarthome_server.key; # # Note: You should disable gzip for SSL traffic. # See: https://bugs.debian.org/773332
分別訪問http、https對應的網頁,http的訪問失敗了、但https訪問成功:原因是,只有一個服務器,可自己監聽了兩個端口,還需要結合nginx的rewrite技術,將http請求轉到對應的https請求。
最后,建立了兩個Server:一個sever監聽80端口、一個監聽443端口,前者http鏈接被rewrite到后者的鏈接,配置文件如下:
80端口后面沒有default_server了——不知道自己為何如此配置;在只有一個server時,其server_name為_,現在有兩個了,怎么配置呢?能否相同?
server {
listen 80;
listen [::]:80;
rewrite ^(.*)$ https://$host$1 permanent;
}
server {
# SSL configuration
#
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
ssl on;
ssl_certificate /etc/nginx/conf.d/ca/ben_server.crt;
ssl_certificate_key /etc/nginx/conf.d/ca/ben_server.key;
上面的配置完畢后,就可以通過http、https訪問網站了,不過,http的是轉向了https,所以,頁面最后看到的是https。
但是,因為瀏覽器有證書安全校驗的機制,因此,不是所有瀏覽器都可以成功打開頁面,測試結果是,只有Firefox在設置后可以打開頁面,其它幾種瀏覽器都失敗了。
-Chrome瀏覽器
-Firefox瀏覽器:最終訪問成功。
IE瀏覽器:
網頁不能訪問,原因是瀏覽器認為 頒發證書的CA 不安全。參考鏈接說把自己的CA根證書加入到瀏覽器。
在嘗試過后,發現問題並沒有解決——Chrome、IE都試了試,不行啊!懷疑和自己建立證書的過程有關系,也可能和最新版本的瀏覽器的安全機制升級有關系,更可能的是前者。
而且,如上面所講,自己在建立key是出現了unable to write 'random state'錯誤!后面可以解決此問題后再做嘗試,繼續dig。
怎么導入呢?Chrome的設置-搜索“證書”,IE、Edge的Internet選項:其實兩者配置的是一個東西,其屬於操作系統。
后記
總算知道怎么讓自己的網站變為HTTPS的了,自建的證書既然無法正常使用,那么,去申請證書吧——知道一個免費申請的機構,當然,付費的就很多了。
Nginx配置不熟悉;
雖然本文用OpenSSL做了一些操作,可是,為何這么做呢?官方文檔在哪里呢?配置文件怎么寫呢?現在只能踩着先行者的腳步往前走,感謝!
路漫漫啊,
參考鏈接
自建CA並簽名server證書實現https by Andy____Li
OpenSSL主配置文件openssl.cnf by 園友 我為什么堅持寫博客
openssl簽署和自簽署證書的多種實現方式 by 園友 駿馬金龍 (Highlycommended,博主的相關文章也很棒,已讀兩篇)