前言
在本地開發(fā)中,有時候我們經(jīng)常需要模擬https環(huán)境嵌牺,比如PWA應(yīng)用要求必須使用https訪問议慰。在傳統(tǒng)的解決方案中蒙保,我們需要使用自簽證書辕棚,然后在http server中使用自簽證書。由于自簽證書瀏覽器不信任,為了解決瀏覽器信任問題我們需要將自簽證書使用的CA證書添加到系統(tǒng)或瀏覽器的可信CA證書中逝嚎,來規(guī)避這個問題扁瓢。
以前這些步驟需要一系列繁瑣的openssl
命令生成,盡管有腳本化的方案幫助我們簡化輸入這些命令(可以參考以前的blog: Nginx SSL快速雙向認(rèn)證配置)补君。但是仍然覺得對本地開發(fā)不那么友好引几,有些繁重了。本文將介紹一種更加簡單友好的方式生成本地https證書挽铁,并且信任自簽CA的方案——mkcert伟桅。
mkcert簡介
mkcert是一個使用go語言編寫的生成本地自簽證書的小程序,具有跨平臺叽掘,使用簡單楣铁,支持多域名,自動信任CA等一系列方便的特性可供本地開發(fā)時快速創(chuàng)建https環(huán)境使用更扁。
安裝方式也非常簡單盖腕,由于go語言的靜態(tài)編譯和跨平臺的特性,官方提供各平臺預(yù)編譯的版本浓镜,直接下載到本地溃列,給可執(zhí)行權(quán)限(Linux/Unix需要)就可以了。下載地址: https://github.com/FiloSottile/mkcert/releases/latest
此外膛薛,mkcert已經(jīng)推送至Homebrew, MacPorts, Linuxbrew, Chocolatey, Scoop等包管理平臺中听隐,也可以直接借助對應(yīng)的包管理平臺安裝。如:
brew install mkcert # Homebrew/Linuxbrew
choco install mkcert # Chocolatey
安裝成功后哄啄,應(yīng)該可以使用mkcert
命令了:
PS C:\Users\abcfy\projects> mkcert
Using the local CA at "C:\Users\abcfy\AppData\Local\mkcert" ?
Usage of mkcert:
$ mkcert -install
Install the local CA in the system trust store.
$ mkcert example.org
Generate "example.org.pem" and "example.org-key.pem".
$ mkcert example.com myapp.dev localhost 127.0.0.1 ::1
Generate "example.com+4.pem" and "example.com+4-key.pem".
$ mkcert "*.example.it"
Generate "_wildcard.example.it.pem" and "_wildcard.example.it-key.pem".
$ mkcert -uninstall
Uninstall the local CA (but do not delete it).
For more options, run "mkcert -help".
mkcert基本使用
從上面自帶的幫助輸出來看遵绰,mkcert
已經(jīng)給出了一個基本的工作流,規(guī)避了繁雜的openssl
命令增淹,幾個簡單的參數(shù)就可以生成一個本地可信的https證書了。更詳細(xì)的用法直接看官方文檔就好乌企。
將CA證書加入本地可信CA
$ mkcert -install
Using the local CA at "C:\Users\abcfy\AppData\Local\mkcert" ?
僅僅這么一條簡單的命令虑润,就幫助我們將mkcert使用的根證書加入了本地可信CA中,以后由該CA簽發(fā)的證書在本地都是可信的加酵。
在Windows的可信CA列表可以找到該證書:
在MacOS的證書列表同樣也可以找到:
同理拳喻,在Linux系統(tǒng)中也是類似的效果,這里就不演示了猪腕。
生成自簽證書
生成自簽證書的命令十分簡單:
mkcert domain1 [domain2 [...]]
直接跟多個要簽發(fā)的域名或ip就行了冗澈,比如簽發(fā)一個僅本機訪問的證書(可以通過127.0.0.1
和localhost
,以及ipv6地址::1
訪問)
mkcert localhost 127.0.0.1 ::1
Using the local CA at "C:\Users\abcfy\AppData\Local\mkcert" ?
Created a new certificate valid for the following names ??
- "localhost"
- "127.0.0.1"
- "::1"
The certificate is at "./localhost+2.pem" and the key at "./localhost+2-key.pem" ?
通過輸出陋葡,我們可以看到成功生成了localhost+2.pem
證書文件和localhost+2-key.pem
私鑰文件亚亲,只要在web server上使用這兩個文件就可以了。
使用生成的證書文件
默認(rèn)生成的證書格式為PEM
(Privacy Enhanced Mail)格式,任何支持PEM
格式證書的程序都可以使用捌归。比如常見的Apache
或Nginx
等肛响,這里我們用python自帶的SimpleHttpServer
演示一下這個證書的效果(代碼參考來自: https://gist.github.com/RichardBronosky/644cdfea681518403f5409fa16823c1f):
python2版本(MacOS自帶的版本):
#!/usr/bin/env python2
import BaseHTTPServer, SimpleHTTPServer
import ssl
httpd = BaseHTTPServer.HTTPServer(('0.0.0.0', 443), SimpleHTTPServer.SimpleHTTPRequestHandler)
httpd.socket = ssl.wrap_socket(httpd.socket, certfile='./localhost+2.pem', keyfile='./localhost+2-key.pem', server_side=True, ssl_version=ssl.PROTOCOL_TLSv1_2)
httpd.serve_forever()
python3版本:
#!/usr/bin/env python3
import http.server
import ssl
httpd = http.server.HTTPServer(('0.0.0.0', 443), http.server.SimpleHTTPRequestHandler)
httpd.socket = ssl.wrap_socket(httpd.socket, certfile='./localhost+2.pem', keyfile='./localhost+2-key.pem', server_side=True, ssl_version=ssl.PROTOCOL_TLSv1_2)
httpd.serve_forever()
使用python simple-https-server.py
運行即可(注意Linux/Unix下綁定443端口需要root權(quán)限,你可能需要使用sudo
提權(quán))
局域網(wǎng)內(nèi)使用
有時候我們需要在局域網(wǎng)內(nèi)測試https應(yīng)用惜索,這種環(huán)境可能不對外特笋,因此也無法使用像Let's encrypt
這種免費證書的方案給局域網(wǎng)簽發(fā)一個可信的證書,而且Let's encrypt
本身也不支持認(rèn)證Ip巾兆。
先來回憶一下證書可信的三個要素:
- 由可信的CA機構(gòu)簽發(fā)
- 訪問的地址跟證書認(rèn)證地址相符
- 證書在有效期內(nèi)
如果期望我們自簽證書在局域網(wǎng)內(nèi)使用猎物,以上三個條件都需要滿足。很明顯自簽證書一定可以滿足證書在有效期內(nèi)角塑,那么需要保證后兩條顿痪。我們簽發(fā)的證書必須匹配瀏覽器的地址欄,比如局域網(wǎng)的ip或者域名剪廉,此外還需要信任CA烈疚。
我們先重新簽發(fā)一下證書,加上本機的局域網(wǎng)ip認(rèn)證:
mkcert localhost 127.0.0.1 ::1 192.168.31.170
Using the local CA at "C:\Users\abcfy\AppData\Local\mkcert" ?
Created a new certificate valid for the following names ??
- "localhost"
- "127.0.0.1"
- "::1"
- "192.168.31.170"
The certificate is at "./localhost+3.pem" and the key at "./localhost+3-key.pem" ?
再次驗證發(fā)現(xiàn)使用https://192.168.31.170
本機訪問也是可信的留攒。然后我們需要將CA證書發(fā)放給局域網(wǎng)內(nèi)其他的用戶煤惩。
mkcert -CAROOT
C:\Users\abcfy\AppData\Local\mkcert
使用mkcert -CAROOT
命令可以列出CA證書的存放路徑
ls $(mkcert -CAROOT)
目錄: C:\Users\abcfy\AppData\Local\mkcert
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2019-04-09-星期二 上午 1 2484 rootCA-key.pem
2:16
-a---- 2019-04-09-星期二 上午 1 1651 rootCA.pem
2:16
可以看到CA路徑下有兩個文件rootCA-key.pem
和rootCA.pem
兩個文件,用戶需要信任rootCA.pem
這個文件炼邀。將rootCA.pem
拷貝一個副本魄揉,并命名為rootCA.crt
(因為windows并不識別pem
擴展名,并且Ubuntu也不會將pem
擴展名作為CA證書文件對待)拭宁,將rootCA.crt
文件分發(fā)給其他用戶洛退,手工導(dǎo)入。
windows導(dǎo)入證書的方法是雙擊這個文件杰标,在證書導(dǎo)入向?qū)е袑⒆C書導(dǎo)入受信任的根證書頒發(fā)機構(gòu)
:
MacOS的做法也一樣兵怯,同樣選擇將CA證書導(dǎo)入到受信任的根證書辦法機構(gòu)。
Ubuntu的做法可以將證書文件(必須是crt
后綴)放入/usr/local/share/ca-certificates/
腔剂,然后執(zhí)行sudo update-ca-certificates
Android和IOS信任CA證書的做法參考官方文檔媒区。
在局域網(wǎng)其他計算機就可以訪問https而不報警了。我在另一臺虛擬機Ubuntu上使用curl測試結(jié)果:
$ curl -I https://192.168.31.170
HTTP/1.0 200 OK
Server: SimpleHTTP/0.6 Python/3.6.8
Date: Tue, 09 Apr 2019 05:22:12 GMT
Content-type: text/html; charset=utf-8
Content-Length: 1794
無警告掸犬,加上-v
參數(shù)輸出還會告訴證書是可信的袜漩。
其他一些高級用法
以上我們演示了一些mkcert
最基本的用法,非常簡單湾碎。如果我們打開mkcert --help
看幫助的話宙攻,還會發(fā)現(xiàn)很多高級用法。
比如-cert-file FILE, -key-file FILE, -p12-file FILE
可以定義輸出的證書文件名介褥。
-client
可以產(chǎn)生客戶端認(rèn)證證書座掘,用于SSL雙向認(rèn)證递惋。之前的文章介紹過使用openssl腳本的(Nginx SSL快速雙向認(rèn)證配置),可以對比下雹顺。
-pkcs12
命令可以產(chǎn)生PKCS12
格式的證書丹墨。java程序通常不支持PEM
格式的證書,但是支持PKCS12
格式的證書嬉愧。通過這個程序我們可以很方便的產(chǎn)生PKCS12
格式的證書直接給Java程序使用贩挣,這里就不演示了。
其他高級用法不做介紹了没酣,各位有興趣可以根據(jù)自己的實際需求和場景進(jìn)行發(fā)掘吧王财。
小結(jié)
本篇文章我們介紹了一個好用的小工具mkcert,簡化我們在本地搭建https環(huán)境的復(fù)雜性裕便,無需操作繁雜的openssl實現(xiàn)自簽證書了绒净,這個小程序就可以幫助我們自簽證書,在本機使用還會自動信任CA偿衰,非常方便挂疆。