去年用tomcat、jboss配置過HTTPS雙向認證,那時候主要用的是JDK自帶的keytool工具。此次是用httpd + openssl,區別比較大
在網上搜索了不少文章,發現全面介紹的很少,或者就是版本比較舊了。因此把我配置的過程完整地記錄下來,以供參考
首先要說明一下,HTTPS涉及到的內容很是繁雜,包括各類術語、命令、算法,我如今也沒有徹底搞清楚。本文會盡可能把我知道的解釋一下,可是深刻的內容,暫時不打算深究了
1、環境
httpd: 2.4.4
openssl:1.0.1
os:ubuntu 12.04 LTS
2、場景
我準備在httpd上配置一個HTTPS雙向認證,既向客戶端代表本身的身份,也只容許特定的客戶端訪問。本文說的主要是做爲server的角色的配置,至於做爲client的配置,最後也會稍微介紹一下,可是不會詳細說明
通常來講,互聯網站不會去配置雙向認證,由於客戶端證書的分發和管理會比較麻煩,會把用戶擋在門外,因此通常是不能這麼作的。固然,像銀行等對安全要求很高的網站,也會採用雙向認證,好比U盾、安全控件什麼的,其實就是固化的客戶端證書
可是對於企業應用來講,客戶通常是固定的,好比兩個已知的系統對接、內部系統集成等。因此在企業應用領域,雙向認證仍是比較常見的
3、背景知識
證書(Certificate)是HTTPS的核心,可是其實證書並非一個單一的東西,而是幾種技術的綜合
爲了網絡傳輸的安全,有不少種技術,最主要的是如下3種:
一、加密/解密
避免消息明文傳輸,對消息進行加密。早期通常是用對稱加密算法,如今通常都是不對稱加密,最多見的算法就是RSA。在後面的介紹中,也會屢次看到RSA這個詞
二、消息摘要
這個技術主要是爲了不消息被篡改。消息摘要是把一段信息,經過某種算法,得出一串字符串。這個字符串就是消息的摘要。若是消息被篡改(發生了變化),那麼摘要也必定會發生變化(通常是這樣的。若是2個不一樣的消息生成的摘要是同樣的,那麼這就叫發生了碰撞)
消息摘要的算法主要有MD5和SHA,在證書領域,通常都是用SHA(安全哈希算法)
三、數字簽名
數字簽名是爲了驗證雙方的身份,避免身份僞造
以上三個技術結合起來,就是在HTTPS中普遍應用的證書(certificate),證書自己攜帶了加密/解密的信息,而且能夠標識本身的身份,也自帶消息摘要
4、在httpd中配置單向HTTPS
首先在%HTTPD_HOME%/conf/目錄下,修改httpd.conf文件,加載必要的模塊 html
這裏的前提是,在編譯httpd的時候,已經編譯了ssl模塊。這個步驟看另外一篇文檔:
http://kyfxbl.iteye.com/blog/1902299
而後再導入默認的SSL配置文件,固然也能夠選擇不導入,在httpd.conf直接配置。可是導入默認的能夠節省不少時間,而且默認的文件是用vhost配置的,不會跟main server衝突,能夠算是一種最佳實踐 linux
而後打開%HTTPD_HOME%/conf/extra/目錄,看一下httpd-ssl.conf,主要有如下幾個配置 算法
只要開啓前3個,單向的HTTPS認證就配置好了。後面3個目前先註釋掉,是後面雙向認證纔用到
而後重啓一下httpd,會發現報錯:
AH00526: Syntax error on line 106 of /usr/local/httpd/conf/extra/httpd-ssl.conf:
SSLCertificateFile: file '/usr/local/httpd/conf/server.cer' does not exist or is empty
這是由於httpd須要一個服務端的私鑰(.key.pem),和一個服務端證書(.cer)。前面已經配置了這2個文件的路徑,可是尚未建立。下一步就要建立這些文件
5、建立CA(Certificate Authority)
這個CA,也叫「根證書」
服務端作了一個證書,可是這是沒有法律效力的,誰均可以本身作證書,就根本達不到安全的目的。因此就要有一個機構,負責來確認服務端的身份,而後統一的簽發證書。這樣纔能有權威性
當瀏覽器經過HTTPS協議訪問一個網站,網站首先會發過來一個本身的證書(certificate)。接下來瀏覽器就會到權威機構(CA),去 驗證一下這個證書是否是它簽發的。若是是的話,就信任這個網站的證書,繼續訪問;若是不是的話,要怎麼處理就依賴於實現了。通常的瀏覽器會彈出一個警告, 讓用戶本身決定要不要繼續訪問。固然直接拒絕也是能夠的
如今國際上有3大CA機構,若是是要本身作一個網站的話,如上所述,通常是須要請這些權威機構幫忙簽發證書的。如今全部的主流瀏覽器,默認都安裝 了這些CA的根證書,因此若是網站的證書是這些權威機構簽發的,瀏覽器就不會發出警告了。好比支付寶,它的證書是由VeriSign簽發的,因此訪問支付 寶,瀏覽器不會發出警告
這裏還有一個鏈條的關係,好比我有10個子網站,若是每一個都要去找CA簽發證書,就很麻煩。我能夠找CA給我簽發一個次級根證書,而後再用這個次 級根證書給本身簽發10個證書。那麼只要客戶的瀏覽器裏有CA根證書就能夠了,這10個證書均可以經過認證,不要求客戶安裝次級根證書,原文見下:
apache
若是是企業應用,那徹底能夠本身給本身當CA,由於能夠要求目標用戶(系統)安裝本身的CA根證書,效果是同樣的,還能夠省下請權威CA簽發證書的費用(互聯網應用分發本身的CA到無數的互聯網用戶上,難度很大)
下面就介紹如何建立本身的CA
一、準備工做
先在隨便一個目錄,建立如下幾個子目錄:
/private
/certificates
其中private放的是私鑰和CSR(後面會介紹),certificates裏放的就是證書了
二、建立CA私鑰 ubuntu
最後的參數是RSA密鑰的長度,默認是512。2048其實長了一點,老的瀏覽器稍後會不支持,不過如今的主流瀏覽器都是支持的,因此問題不大
經過這個命令,私鑰就建立好了,文件名是ca.key.pem
用這個命令,能夠看一下剛纔建立的這個私鑰的信息 瀏覽器
不過基本上,看也是白看,反正我是看不懂。只知道私鑰裏其實有2組數字,是用來造成公鑰的,最後也會包含在證書裏
tomcat
另外,最後的.pem擴展名,是表示該私鑰用PEM編碼。實際上私鑰和證書都是用PEM編碼的,PEM只是一種編碼格式,不須要太在乎。 httpd能夠直接處理這種編碼格式,可是瀏覽器和JAVA都不行,因此在須要的時候,會把編碼從PEM改爲PKCS,後面會介紹。只要知道證書和私鑰都 有編碼,只是編碼是PEM仍是PKCS的區別而已。就像"你好"能夠用UTF-8編碼,也能夠用GBK編碼同樣,內容是不變的
三、建立CA簽名請求 安全
這裏要注意的是,若是不用-subj參數,那麼就會在命令行交互輸入簽發目標的身份識別信息,這叫DN(Distinguished Name)。其中別的都沒關係,最重要的是CN那一行,由於我這裏是根證書,因此我設置爲*.kyfxbl.net,這樣我後面用這個CA簽發的 www.kyfxbl.net、game.kyfxbl.net、news.kyfxbl.net……,全都是有效的
生成的簽名請求文件,是ca.csr 服務器
同上,看不懂
四、本身簽發CA根證書 網絡
這裏參數很複雜,我也不太清楚準確的意思是什麼,能夠用openssl x509 -help本身研究一下
生成的ca.cer,就是最終的根證書了!這個文件很是重要,由於後續的服務端證書、客戶端證書,都是用這個CA簽發的,也要把它分發給客戶,讓他們導入到本身的瀏覽器或者系統中
查看的命令是:
五、把根證書從PEM編碼轉爲PKCS編碼
這步其實不是必選的,可是前面說過,JAVA環境是不能直接用PEM編碼的證書的,不少瀏覽器也不行,因此有時候也須要轉一下編碼
獲得的ca.p12就是轉碼後的CA根證書,在不能直接用ca.cer的時候,就用ca.p12代替
6、簽發服務端證書
如今CA根證書和私鑰都有了,就能夠開始簽發服務端證書了(簽發請求ca.csr是過程文件,有了cer就再也不須要它了,要刪掉也能夠)。下面的命令和簽發CA證書時都差很少,可是參數上有區別
一、建立服務端私鑰
二、建立服務端證書籤發請求
和ca.csr的區別在於,這裏的CN不是*.kyfxbl.net,而是www.kyfxbl.net,由於我如今是在爲www.kyfxbl.net申請證書
三、利用CA根證書,簽發服務端證書
這裏和前面本身簽發CA證書時,參數區別就比較大了,最後獲得的server.cer,就是服務端證書
7、測試單向認證
把server.key.pem和server.cer拷貝到%HTTPD_HOME%/conf/目錄下,而後從新啓動httpd,會要求輸入一個密碼
而後訪問http://localhost:443/,會報400錯誤:
接下來用https://localhost:443來訪問,瀏覽器報警:
這裏就是前面建立CSR時,輸入的CN的做用,這個證書是爲www.kyfxbl.net申請的,這裏請求的地址倒是localhost,不匹配因此報錯。爲了能用www.kyfxbl.net這個主機名來訪問,就須要改一下/etc/hosts文件:
127.0.0.1 localhost
192.168.1.102 www.kyfxbl.net
而後就能夠用www.kyfxbl.net來訪問了,再試一下:https://www.kyfxbl.net/
此次瀏覽器仍是告警,可是告警信息變了:
證書信息以下:
能夠看到這個證書是由*.kyfxbl.net這個CA頒發的,瀏覽器不認識,因此不信任由這個CA簽發的全部證書。接下來就須要把ca.cer 導入瀏覽器。這裏直接導入server.cer也是能夠的,可是後面若是又建立一個網站好比說www2.kyfxbl.net,那麼又不行了。因此最好的 辦法是直接導入CA根證書,那麼後續只要是用這個根證書籤發的證書,瀏覽器都會信任
導入前:
導入後:
再次訪問,能夠看到成功了,瀏覽器不告警,而且URL欄前面打了一個綠勾
8、配置雙向認證
若是要配置服務器只容許合法的用戶訪問,就須要配置雙向認證
配置爲雙向認證以後,除了服務端要發證書給客戶端以外,客戶端也要發客戶端證書到服務端,服務端認證經過,才容許訪問
在單項認證的基礎上,再配置以上3個參數
SSLCACertificateFile,這個意思是當客戶端發來客戶端證書的時候,httpd用哪一個CA根證書校驗它
配置好了,還不能重啓,由於如今客戶端證書還沒作好
這裏要說明一下,客戶端證書是怎麼來的
有2種方式:
第一種,客戶端也本身CA,而後簽發證書給本身。把客戶端的CA根證書發過來,配置成SSLCACertificateFile。這在互聯網應用裏基本是不可能的,安全和管理都是問題。可是在企業應用裏,仍是比較常見的,雙方互相交換CA根證書
第二種,就用剛纔服務端的CA根證書,簽發一個客戶端證書,發給用戶,用戶每次用這個證書來發請求,像銀行,支付寶等等,用的是這種方式
固然理論上其實還有一種辦法,就是客戶本身去找權威CA簽證書,可是這個是不可能的,由於很麻煩,找CA籤也很是貴
本文用的是第2種方法。其實都是同樣的。關鍵仍是在CA根證書上,因此前面也說過了,CA根證書很是重要
9、簽發客戶端證書
一、建立客戶端私鑰
二、建立客戶端證書籤發請求
這裏的不一樣在於,這裏的CN不是*.kyfxbl.net,也不是www.kyfxbl.net,隨便填一個kyfxbl就行了,或者乾脆叫user都沒問題,反正是一個客戶端證書
三、利用CA根證書,簽發客戶端證書
這裏和簽發server.cer基本是同樣的
四、把客戶端證書轉換成p12格式
這步是必須的,由於稍後就須要把客戶端證書導入到瀏覽器裏,可是通常瀏覽器都不能直接使用PEM編碼的證書
10、測試雙向認證
把ca.cer拷貝到%HTTPD_HOME%/conf/目錄下,重啓httpd
而後再次訪問https://www.kyfxbl.net/,結果此次不是警告,而是直接報錯:
接下來要把client.p12導入到瀏覽器裏
導入前:
導入的時候會要求輸入密碼,這是爲了不有人偷偷拷貝了別人的客戶端證書,假裝成合法用戶:
導入後:
而後再次訪問,瀏覽器會要求選擇證書。這個步驟是經過雙向認證訪問網站時必須的,可是平時訪問銀行、支付寶的時候貌似沒有,這是由於這些網站爲了簡化用戶的操做,都會要求用戶安裝什麼「安全控件」,控件自動選擇了證書
點擊肯定,訪問成功!
11、JKS等
到這裏,用httpd配置雙向HTTPS認證就完成了
本文說的是做爲server的角色,要如何配置。可是在JAVA環境下,若是要以client的角色,經過雙向認證發起請求,則還有些不一樣
這裏其實是要充當一個相似瀏覽器的角色,須要校驗server certificate,還須要在發起請求的時候,把client certificate發過去
在JAVA裏,是經過keystore和truststore來實現的,不在本文的討論範圍內。能夠看一下其餘的幾篇博客,在HTTPS分類裏
12、參考資料
http://httpd.apache.org/docs/2.4/en/ssl/
http://linux.chinaunix.net/techdoc/net/2008/01/08/976172.shtml 《JAVA加密與解密的藝術》——做者樑棟