博客搬家: https搭建(自簽名證書)
上一篇博客探究了https(ssl)的原理,為了貫徹理論落實於實踐的宗旨,本文將記錄我搭建https的實操流程,使用Apache2+ubuntu+opensssl
1.使用自簽證書配置https
一般來講,正式的上線項目都需要購買域名,並且向權威機構申請證書。但本次工作屬於測試環境,所以一切從簡,我們使用openssl工具生自簽名的CA證書以及服務器證書,來搭建https。具體步驟如下:
(1)安裝apache2、openssl(ubuntu16.04)
安裝過程此處不做贅述,很簡單。Apache2安裝完成並啟動后,通過http://ipaddress 來測試,如下圖所示,說明安裝成功
(2)制作證書
生成自簽CA證書
- 生成CA私鑰
openssl genrsa -out ca.key 2048
- 生成CA證書
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt -config /etc/ssl/openssl.cnf
openssl.cnf的路徑注意填對。最后在當前目錄下生成的ca.key即為CA私鑰,ca.crt即為CA證書(包含CA公鑰)
生成服務器證書
- 生成服務器私鑰
openssl genrsa -out server.key 2048
- 生成服務器簽署申請文件
openssl req -new -out server.csr -key server.key -config /etc/ssl/openssl.cnf
需要填寫服務器信息,如實填寫即可。需要注意Common Name 需要與openssl.cnf 中配置的域名相對應(alt_names),否則客戶端無法驗證。該命令最后生成的server.csr即為申請文件。openssl.cnf的具體配置見下文。
- 在簽署證書之前需要確認openssl.cnf中的配置,如下所示:
#根據實際情況修改,將match改成optional,否則ca.crt必須與server.csr中的各個字段值一致才能簽署
[ policy_match ]
countryName = optional
stateOrProvinceName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
# 確保req下存在以下2行(默認第一行是有的,第2行被注釋了)
[ req ]
distinguished_name = req_distinguished_name
req_extensions = v3_req
# 確保req_distinguished_name下沒有 0.xxx 的標簽,有的話把0.xxx的0. 去掉
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = XX
countryName_min = 2
countryName_max = 2
stateOrProvinceName = State or Province Name (full name)
localityName = Locality Name (eg, city)
localityName_default = Default City
organizationName = Organization Name (eg, company)
organizationName_default = Default Company Ltd
organizationalUnitName = Organizational Unit Name (eg, section)
commonName = Common Name (eg, your name or your server\'s hostname)
commonName_max = 64
emailAddress = Email Address
emailAddress_max = 64
#添加一行subjectAltName=@alt_names
[ v3_req ]
# Extensions to add to a certificate request
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName=@alt_names
#新增alt_names,注意括號前后的空格,DNS.x 的數量可以自己加
#如果沒有IP這一項,瀏覽器使用IP訪問時驗證無法通過
[ alt_names ]
IP.1 = 192.168.50.115
DNS.1 = dfe.leida.org
DNS.2 = ex.abcexpale.net
- 使用CA證書和私鑰簽署服務器證書
openssl ca -in server.csr -out server.crt -cert ca.crt -keyfile ca.key -extensions v3_req -config /etc/ssl/openssl.cnf
直接運行該簽署命令,會報錯,提示缺少某些文件和目錄。在當前目錄下把相應的文件及文件夾創建上即可解決,如下
mkdir -p demoCA/newcerts
touch ./demoCA/index.txt ./demoCA/serial
echo "01">> ./demoCA/serial
創建完畢后,運行簽署命令即可完成服務器證書的制作。當前目錄下生成的server.crt即為服務器證書,server.key為服務器私鑰
(3)配置apache2
- 啟用ssl模塊(此處可使用a2enmod命令)
a2enmod ssl
- 啟用ssl站點
a2ensite default-ssl
- 加入監聽端口443(因為https默認采用443端口,有別於http的80)
listen 80 443
# /etc/apache2/ports.conf中修改成如上所示即可
- 配置證書以及私鑰的路徑
SSLCertificateFile /etc/ssl/certs/server.crt
SSLCertificateKeyFile /etc/ssl/private/server.key
# 在/etc/apache2/sites-available/default-ssl.conf中修改如上參數,確認證書和私鑰的路徑正確無誤
重啟apache2,搞定!
2.使用瀏覽器測試https
上述的制作證書步驟,已經是我測試結束、爬完坑后的正確教程,下文則是填坑記錄。
實際上,我一開始按照網上的方法搭建完https后,出現過一些問題。使用瀏覽器訪問https://ipaddress 會跳出如下提示界面
實際上此時瀏覽器已獲取到服務器證書server.crt,只是由於某些原因無法驗證它。若選擇高級選項中的“繼續瀏覽”時,同樣可以正常跳轉至對應的頁面,這時相當於強行讓瀏覽器接受該證書,同時接受服務器公鑰。在測試環境下,這樣完全OK。但是,強迫症的我還是想讓導航欄上出現安全的小鎖,紅叉叉看着很難受啊。
下面總結記錄一下使用瀏覽器(chrome)測試的過程中遇到的問題以及解決方法
(1)客戶端缺少CA證書
點擊導航欄左側的感嘆號,查看證書,如下圖所示
此時瀏覽器已獲取到server.crt,由於其對應的CA證書不存在於“受信任的根證書機構”中,所以無法驗證server.crt
我們需要將CA證書(上文使用OpenSSL生成的ca.crt)安裝至客戶端系統中的“受信任的根證書機構”中,保證瀏覽器可通過此CA證書來驗證服務器證書server.crt。安裝過程很簡單,雙擊如下所示安裝即可
安裝結束后,重啟瀏覽器,再次打開證書,如下所示
此時瀏覽器已經可以使用ca證書來驗證server.crt,已完成了很重要的一步,但我的chrome瀏覽器依然沒有出現小鎖
(2)缺少使用者備用名稱
完成上一步后,瀏覽器的導航欄依然顯示不安全,我打開開發者工具,查看security得知,是服務器證書缺少“使用者備用名稱”所導致,如下圖所示。
如何解決這個問題,我參考了這個博客(http://blog.51cto.com/colinzhouyj/1566438 ),即修改openssl.cnf的部分配置,前文“制作證書”步驟中已經整合過此處的配置內容。修改完,重新簽署證書,重啟apache2,再次運行,Subject Alternative Name missing的問題解決。
(3)IP驗證不通過
在上一步操作中,我添加完幾條DNS之后,發現chrome依然報錯,如下圖所示
我用的是虛擬機環境,沒有域名解析,而是直接通過IP來訪問站點的,又由於證書中不存在IP信息,是無法跟URL中的IP進行比對的,因此瀏覽器無法通過證書驗證。該問題有兩個解決方法
(1)在證書中添加IP地址。在openssl.cnf中配置使用者可選名稱時,添加一條IP地址,即可保證瀏覽器通過對IP的驗證,重新簽署配置運行后,結果如下
打開證書,使用者可用名稱字段如下
(2)使用域名訪問。在客戶機的host文件中配置域名與IP的映射,直接使用域名來訪問站點(證書中包含域名),即可通過驗證,如下所示
使用這兩種方法的其中一種,遲遲不肯露面的小鎖終於出現了,打開security也是一片綠色,大功告成。但是,要注意一點,不同瀏覽器對於證書的驗證方式可能存在差異。按照我的操作,firefox依然無法驗證,暫時沒細究,但chrome和edge瀏覽器都可以完美運行。