[Linux] Curl 的 verify host 和 verify peer 的選項
今天專案提到了 Curl 的兩個選項,一個是 verify host,一個是 verify peer,
常常聽到 SSL 的這兩個東西,不過一直沒搞懂那是什麼意思,就來查一下吧~
首先在 Curl 的說明文件中可以查到這兩個選項:
=> 代表要確認 certificate 中的 domain name 和 URL 中的 domain name 一樣
=> 代表要確認 certificate 中的 CA chain 是 Curl 內建的 CA list 中有列出來的
用 Curl 直接連一個 HTTPS 網站來看看吧,加上 –verbose 選項看詳細資訊:
testuser@localhost ~ $ curl --verbose https://server.company.com * About to connect() to server.company.com port 443 (#0) * Trying 10.45.32.31... * Connected to server.company.com (10.45.32.31) port 443 (#0) * Initializing NSS with certpath: sql:/etc/pki/nssdb * CAfile: /etc/pki/tls/certs/ca-bundle.crt CApath: none * Server certificate: * subject: E=master@company.com,CN=*.company.com,OU=IT,O=Company Inc. * start date: Jan 03 00:58:48 2012 GMT * expire date: Jan 01 00:58:48 2017 GMT * common name: *.company.com * issuer: CN=CA01,DC=us,DC=companynet,DC=org * NSS error -8179 (SEC_ERROR_UNKNOWN_ISSUER) * Peer's Certificate issuer is not recognized. * Closing connection 0 curl: (60) Peer's Certificate issuer is not recognized. 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 拿到了網站傳過來的 server certificate,
發行者 issuer 是 CN=CA01,DC=us,DC=companynet,DC=org
但這個 CA 並不是 Curl 認得的 CA,因此吐出了錯誤訊息 Peer’s Certificate issuer is not recognized.
這應該算是 SSL_VERIFYPEER 的效果~
要關閉 SSL 的 certificate 檢查的話,可以加上 -k 選項,
但這選項同時會關掉 SSL_VERIFYHOST 和 SSL_VERIFYPEER,沒有辦法單獨開關…
testuser@localhost ~ $ curl --verbose -k https://server.company.com * About to connect() to server.company.com port 443 (#0) * Trying 10.45.32.31... * Connected to server.company.com (10.45.32.31) port 443 (#0) * Initializing NSS with certpath: sql:/etc/pki/nssdb * skipping SSL peer certificate verification * SSL connection using TLS_RSA_WITH_RC4_128_MD5 * Server certificate: * subject: E=master@company.com,CN=*.company.com,OU=IT,O=Company Inc. * start date: Jan 03 00:58:48 2012 GMT * expire date: Jan 01 00:58:48 2017 GMT * common name: *.company.com * issuer: CN=CA01,DC=us,DC=companynet,DC=org > GET / HTTP/1.1 > User-Agent: curl/7.29.0 > Host: server.company.com > Accept: */* > < HTTP/1.1 200 OK < Content-Type: text/html < Last-Modified: Wed, 13 Apr 2011 01:49:51 GMT < Accept-Ranges: bytes < ETag: "7caffe137df9cb1:0" < Server: Microsoft-IIS/7.5 < X-Powered-By: ASP.NET < Date: Tue, 29 Dec 2015 03:11:12 GMT < Content-Length: 689 < <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
可以看到加上 -k 選項後,Curl 一樣會拿到 server sertificate,
但不會做任何的驗證,而就直接做 HTTPS handshaking 後拿到網站內容囉~
最後順便看一下 Wireshark 抓到的封包比較吧 (最近學習 wireshark 魂上身)~
紅色的框框是沒加 -k 選項的連線,綠色的框框是有加 -k 選項的連線,
可以看到沒加 -k 選項時,server 回了 Server Hello, Certificate 之後,
本機 (curl) 這邊就回了一個 Alert (Unknown CA) 加上 FIN/ACK 回去,
導致 server 那邊就發 RST 中斷連線了~
有加 -k 選項時,server 回了 Server Hello, Ceriticate 之後,
本機 (curl) 這邊沒有出現錯誤,而是開始 SSL key 的交換囉~