引用文章 - OpenSSL 操作指南
來自 https://github.com/k8sp/tls/blob/master/openssl.md
OpenSSL操作指南
生成RSA秘鑰對
以下OpenSSL的genrsagenrsa命令生成一個2048 bit的公鑰私 鑰對,輸出到文件server.key里gist:
openssl genrsa -out server.key 2048
server.key是PEM格式pem的:
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,DB98A9512DD7CBCF
yKTM+eoxBvptGrkEixhljqHSuE+ucTh3VqYQsgO6+8Wbh1docbFUKzLKHrferJBH
...
-----END RSA PRIVATE KEY-----
雖說文件頭尾都標注著RSA PRIVATE KEY,但實際上這個文件里既包括公鑰也 包括私鑰genrsa。
生成身份證申請
以下OpenSSL的req命令req以上文中的 server.key 為輸 入,生成一個身份證申請(CSR)文件 server.csr。
openssl req -nodes -new -key server.key -subj "/CN=localhost" -out server.csr
這個 CSR 里的公鑰是從 server.key 里提取出來的,域名是 localhost。 需要注意的是,如果將來我們啟動一個 HTTPS 服務,使用這個 CSR 簽署的身份 證,那么客戶端必須可以通過域名 locahost 訪問到這個 HTTPS 服務。
server.csr文件也是PEM格式的,文件頭尾標注為 CERTIFICATE REQUEST:
-----BEGIN CERTIFICATE REQUEST-----
MIIC0TCCAbkCAQAwgYsxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTERMA8GA1UE
...
-----END CERTIFICATE REQUEST-----
簽署身份證
以下OpenSSL的x509命令x509用指定的私鑰 server.key 簽署 server.csr,輸出身份證 server.crt:
openssl x509 -req -sha256 -days 365 -in server.csr -signkey server.key -out server.crt
server.crt也是PEM格式的。文件頭尾的標記為CERTIFICATE:
-----BEGIN CERTIFICATE-----
MIIDlDCCAnwCCQDQ1UvQyFD7jDANBgkqhkiG9w0BAQsFADCBizELMAkGA1UEBhMC
...
-----END CERTIFICATE-----
在這個例子里,用來簽署CSR的私鑰和 CSR 里的公鑰是一對兒。也就是說這是一 個自簽名(self-sign)的例子。
通常情況下,我們會用一個CA的私鑰來簽署一個CSR。在這個為 Kubernetes apiserver 簽署身份證的例子sign里,apiserver 的身份 證是用一個自簽署的CA的私鑰來簽署的:
$ openssl genrsa -out ca-key.pem 2048
$ openssl req -x509 -new -nodes -key ca-key.pem -days 10000 -out ca.pem -subj "/CN=kube-ca"
$ openssl genrsa -out apiserver-key.pem 2048
$ openssl req -new -key apiserver-key.pem -out apiserver.csr -subj "/CN=kube-apiserver" -config openssl.cnf
$ openssl x509 -req -in apiserver.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out apiserver.pem -days 365 -extensions v3_req -extfile openssl.cnf
這個例子里,ca-key.pem是Kubernetes管理員自己創建的CA的私鑰(其實是密 鑰對)。第二個命令(openssl req -x509 ...)不經過生成CSR的過程,直接 輸出CA的身份證。注意CA的域名是 kube-ca。
接下來三個命令分別創建 apiserver 的私鑰,生成 apiserver 的CSR,以及用 CA 的private key(ca-key.pem)來簽署 apiserver 的身份證。
注意,簽署 apiserver.csr 得到 apiserver 的身份證(apiserver.pem) 的過程中,不僅需要 ca-key.pem,還需要CA的身份證 ca.pem,因為 apiserver.pem 里附上了 CA 的身份證。從而構成一個 信任鏈。
HTTPS Server
現在我們有了 server.key 和 server.crt。我們可以寫一個HTTPS服務程序, 它私藏 server.key,同時在與任何客戶端程序首輪通信的時候通告自己的身 份證 server.crt。這里有幾點需要注意:
-
為了確保“私藏”一個文件,我們需要設置其文件系統訪問權限為只有owner可 讀sign:
chmod 400 server.key -
如果我們用Go語言來寫這個 HTTPS server,只需要在調用
http.ListenAndServeTLS()函數的時候,把server.key和server.crt的文件路徑傳遞給它即可。整個程序源碼如下:package main import ( "io" "log" "net/http" ) func main() { http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { io.WriteString(w, "hello, world!\n") }) if e := http.ListenAndServeTLS(":443", "server.crt", "server.key", nil); e != nil { log.Fatal("ListenAndServe: ", e) } } -
因為我們在前面這一步生成 server.csr 的時 候,指定的域名是 localhost,所以必須確保 HTTPS 程序監聽
localhost虛擬網卡上的端口 443。上面程序里指定的監聽地址是"443",只有端口沒 有標識網卡的IP地址或者域名,那么ListenAndServerTLS會讓程序監聽 本機所有網卡上的 443 端口。sudo go run server.go & -
同樣的原因,客戶端必須通過
localhost訪問我們的 HTTPS 服務。在這 個例子里,localhost域名意味著只有本機上執行的客戶端才能訪問。
訪問TLS服務
用瀏覽器
我們可以通過瀏覽器訪問我們的 HTTPS server。但是因為server的身份證是我 們自簽署的,瀏覽器里沒有CA的身份證其中的公鑰 可以驗證 server.crt,所以瀏覽器會提示說它不信任我們的HTTPS服務。但是 如果用戶表示信任,還是可以訪問的。
要想消除瀏覽器的提示,最簡單的辦法就是把我們為HTTPS服務自簽署的身份證 加入到瀏覽器里chrome。
實際上,很多公司的運維團隊都會生自命為本公司內部的CA,成一個自簽署的身 份證,加入到公司配發的電腦的操作系統或者瀏覽器里。而本公司內部的很多網 路服務(報銷系統、人事管理系統、考評系統、各種計算資源上的SSH服務)都 用這個內部CA來簽署。這樣用公司的電腦,即可訪問這些服務。
用curl
類似的,我們可以通過加 -k 參數讓 curl 信任我們的HTTPS 服務器:
$ /usr/local/Cellar/curl/7.49.1/bin/curl -k https://localhost
hello, world!
或者我們可以把我們自簽署的身份證告訴 curl,讓它用這個身份證驗證我們的 HTTPS 服務:
$ curl --cacert server.crt https://localhost
hello, world!
如果手邊沒有 server.crt,我們甚至可以用 openssl 工具找我們的 HTTPS server 要一份:
$ /usr/local/Cellar/openssl/1.0.2h/bin/openssl s_client -showcerts -connect localhost:443 > cacert.pem
$ curl --cacert cacert.pem https://localhost
hello, world!
請注意,Mac OS X 自帶的 openssl 版本太低,不支持 Go 語言 http package 里實現的高級加密算法,所以我們得用 Homebrew 安裝新版本:
brew update && brew install openssl
下一步
從上面操作可以看出來,TLS的具體操作和 OpenSSL 息息相關。關于OpenSSL的 更多用法,可以參見esse。
當我們用 OpenSSL 創建了CA身份證并且用CA身份證給相關程序簽署了各自的身 份證之后,我們就可以開工寫作和調試這些程序了。在下一篇 里,我們介紹如何用Go語言寫HTTPS的server和client。
參考文獻
-
genrsa https://www.openssl.org/docs/manmaster/man1/genrsa.html
-
pem https://www.namecheap.com/support/knowledgebase/article.aspx/9474/69/how-do-i-create-a-pem-file-from-the-certificates-i-received-from-you
-
sign https://coreos.com/kubernetes/docs/latest/openssl.html#kubernetes-api-server-keypair
-
perm http://stackoverflow.com/questions/9270734/ssh-permissions-are-too-open-error
-
chrome http://www.robpeck.com/2010/10/google-chrome-mac-os-x-and-self-signed-ssl-certificates/#.V4pvTJMrJhj
-
esse https://www.digitalocean.com/community/tutorials/openssl-essentials-working-with-ssl-certificates-private-keys-and-csrs

浙公網安備 33010602011771號