基於OpenSSL自建CA和頒發SSL證書

關於SSL/TLS介紹見文章 SSL/TLS原理詳解
關於證書受權中心CA以及數字證書等概念,請移步 OpenSSL 與 SSL 數字證書概念貼html

openssl是一個開源程序的套件、這個套件有三個部分組成:一是libcryto,這是一個具備通用功能的加密庫,裏面實現了衆多的加密庫;二是libssl,這個是實現ssl機制的,它是用於實現TLS/SSL的功能;三是openssl,是個多功能命令行工具,它能夠實現加密解密,甚至還能夠當CA來用,可讓你建立證書、吊銷證書。linux

默認狀況ubuntu和CentOS上都已安裝好openssl。CentOS 6.x 上有關ssl證書的目錄結構:nginx

/etc/pki/CA/
            newcerts    存放CA簽署(頒發)過的數字證書(證書備份目錄)
            private     用於存放CA的私鑰
            crl         吊銷的證書

/etc/pki/tls/
             cert.pem    軟連接到certs/ca-bundle.crt
             certs/      該服務器上的證書存放目錄,能夠房子本身的證書和內置證書
                   ca-bundle.crt    內置信任的證書
             private    證書密鑰存放目錄
             openssl.cnf    openssl的CA主配置文件

1. 頒發證書

1.1 修改CA的一些配置文件

CA要給別人頒發證書,首先本身得有一個做爲根證書,咱們得在一切工做以前修改好CA的配置文件、序列號、索引等等。git

vi /etc/pki/tls/openssl.cnfweb

...
[ CA_default ]

dir             = /etc/pki/CA           # Where everything is kept
certs           = $dir/certs            # Where the issued certs are kept
crl_dir         = $dir/crl              # Where the issued crl are kept
database        = $dir/index.txt        # database index file.
#unique_subject = no                    # Set to 'no' to allow creation of
                                        # several ctificates with same subject.
new_certs_dir   = $dir/newcerts         # default place for new certs.

certificate     = $dir/cacert.pem       # The CA certificate
serial          = $dir/serial           # The current serial number
crlnumber       = $dir/crlnumber        # the current crl number
                                        # must be commented out to leave a V1 CRL
crl             = $dir/crl.pem          # The current CRL
private_key     = $dir/private/cakey.pem # The private key
RANDFILE        = $dir/private/.rand    # private random number file
...
default_days    = 3650                  # how long to certify for
...
# For the CA policy
[ policy_match ]
countryName             = match
stateOrProvinceName     = optional
localityName            = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional
...
[ req_distinguished_name ]
countryName                     = Country Name (2 letter code)
countryName_default             = CN
countryName_min                 = 2
countryName_max                 = 2

stateOrProvinceName             = State or Province Name (full name)
stateOrProvinceName_default     = GD
...
[ req_distinguished_name ] 部分主要是頒證時一些默認的值,能夠不動

必定要注意[ policy_match ]中的設定的匹配規則,是有可能由於證書使用的工具不同,致使即便設置了csr中看起來有相同的countryName,stateOrProvinceName等,但在最終生成證書時依然報錯:docker

Using configuration from /usr/lib/ssl/openssl.cnf
Check that the request matches the signature
Signature ok
The stateOrProvinceName field needed to be the same in the
CA certificate (GuangDong) and the request (GuangDong)

touch index.txt serial
在CA目錄下建立兩個初始文件:shell

# touch index.txt serial
# echo 01 > serial

1.2 生成根密鑰

# cd /etc/pki/CA/
# openssl genrsa -out private/cakey.pem 2048

爲了安全起見,修改cakey.pem私鑰文件權限爲600或400,也可使用子shell生成( umask 077; openssl genrsa -out private/cakey.pem 2048 ),下面再也不重複。apache

1.3 生成根證書

使用req命令生成自簽證書:ubuntu

# openssl req -new -x509 -key private/cakey.pem -out cacert.pem

會提示輸入一些內容,由於是私有的,因此能夠隨便輸入(以前修改的openssl.cnf會在這裏呈現),最好記住能與後面保持一致。上面的自簽證書cacert.pem應該生成在/etc/pki/CA下。segmentfault

1.4 爲咱們的nginx web服務器生成ssl密鑰

以上都是在CA服務器上作的操做,並且只需進行一次,如今轉到nginx服務器上執行:

# cd /etc/nginx/ssl
# openssl genrsa -out nginx.key 2048

這裏測試的時候CA中心與要申請證書的服務器是同一個。

1.5 爲nginx生成證書籤署請求

# openssl req -new -key nginx.key -out nginx.csr
...
Country Name (2 letter code) [AU]:CN
State or Province Name (full name) [Some-State]:GD
Locality Name (eg, city) []:SZ
Organization Name (eg, company) [Internet Widgits Pty Ltd]:COMPANY
Organizational Unit Name (eg, section) []:IT_SECTION
Common Name (e.g. server FQDN or YOUR name) []:your.domain.com
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
...

一樣會提示輸入一些內容,其它隨便,除了Commone Name必定要是你要授予證書的服務器域名或主機名,challenge password不填。

1.6 私有CA根據請求來簽署證書

接下來要把上一步生成的證書請求csr文件,發到CA服務器上,在CA上執行:

# openssl ca -in nginx.csr -out nginx.crt

另外在極少數狀況下,上面的命令生成的證書不能識別,試試下面的命令:
# openssl x509 -req -in server.csr -CA /etc/pki/CA/cacert.pem -CAkey /etc/pki/CA/private/cakey.pem -CAcreateserial -out server.crt

上面簽發過程其實默認使用了-cert cacert.pem -keyfile cakey.pem,這兩個文件就是前兩步生成的位於/etc/pki/CA下的根密鑰和根證書。將生成的crt證書發回nginx服務器使用。

到此咱們已經擁有了創建ssl安全鏈接所須要的全部文件,而且服務器的crt和key都位於配置的目錄下,剩下的是如何使用證書的問題。

2. 使用ssl證書

2.1 通常瀏覽器

瀏覽器做爲客戶端去訪問https加密的服務器,通常不用去手動作其餘設置,如https://www.google.com.hk,這是由於Chrome、FireFox、Safari、IE等瀏覽器已經內置了大部分經常使用的CA的根證書,但自建CA的根證書就再也不瀏覽器的信任列表中,訪問時會提示以下:
IE瀏覽器
openssl-https-browser-ie

谷歌瀏覽器
openssl-https-browser

安裝網站證書後(同時也有信任的根證書),地址欄通常會顯示綠色小鎖
openssl-https-12306

證書信息
openssl-https-browser-cert

導入證書到瀏覽器的方法:http://cnzhx.net/blog/self-signed-certificate-as-trusted-root-ca-in-windows/

2.2 爲linux系統添加根證書

這一步不是必須的,通常出如今開發測試環境中,並且具體的應用程序應該提供添加證書的方法。

curl工具能夠在linux上模擬發送請求,但當它去訪問https加密網站時就會提示以下信息:

# curl https://sean:sean@registry.domain.com:8000/
curl: (60) Peer certificate cannot be authenticated with known CA certificates
More details here: http://curl.haxx.se/docs/sslcerts.html
curl performs SSL certificate verification by default, using a "bundle"
 of Certificate Authority (CA) public keys (CA certs). If the default
 bundle file isn't adequate, you can specify an alternate file
 using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
 the bundle, the certificate verification probably failed due to a
 problem with the certificate (it might be expired, or the name might
 not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
 the -k (or --insecure) option.

提示上面的信息說明curl在linux的證書信任集裏沒有找到根證書,你可使用curl --insecure來不驗證證書的可靠性,這隻能保證數據是加密傳輸的但沒法保證對方是咱們要訪問的服務。使用curl --cacert cacert.pem能夠手動指定根證書路徑。咱們也能夠把根證書添加到系統(CentOS 5,6)默認的bundle:

# cp /etc/pki/tls/certs/ca-bundle.crt{,.bak}    備份以防出錯
# cat /etc/pki/CA/cacert.pem >> /etc/pki/tls/certs/ca-bundle.crt

# curl https://sean:sean@registry.domain.com:8000
"docker-registry server (dev) (v0.8.1)"

2.3 nginx

在nginx配置文件(多是/etc/nginx/sites-available/default)的server指令下添加:

ssl on;
  ssl_certificate /etc/nginx/ssl/nginx.crt;
  ssl_certificate_key /etc/nginx/ssl/nginx.key;

同時注意 server_name 與證書申請時的 Common Name 要相同,打開443端口。固然關於web服務器加密還有其餘配置內容,如只對部分URL加密,對URL重定向實現強制https訪問,請參考其餘資料。

3 關於證書申請

注意,若是對於通常的應用,管理員只需生成「證書請求」(後綴大多爲.csr),它包含你的名字和公鑰,而後把這份請求交給諸如verisign等有CA服務公司(固然,連同幾百美金),你的證書請求經驗證後,CA用它的私鑰簽名,造成正式的證書發還給你。管理員再在web server上導入這個證書就好了。若是你不想花那筆錢,或者想了解一下原理,能夠本身作CA。從ca的角度講,你須要CA的私鑰和公鑰。從想要證書的服務器角度將,須要把服務器的證書請求交給CA。

若是你要本身作CA,別忘了客戶端須要導入CA的證書(CA的證書是自簽名的,導入它意味着你「信任」這個CA簽署的證書)。而商業CA的通常不用,由於它們已經內置在你的瀏覽器中了。

參考


原文連接地址:http://seanlook.com/2015/01/18/openssl-self-sign-ca

相關文章
相關標籤/搜索