本地https快速解決方案——mkcert

原文鏈接

前言

在本地開發(fā)中,有時候我們經(jīng)常需要模擬https環(huán)境,比如PWA應用要求必須使用https訪問。在傳統(tǒng)的解決方案中,我們需要使用自簽證書,然后在http server中使用自簽證書。由于自簽證書瀏覽器不信任,為了解決瀏覽器信任問題我們需要將自簽證書使用的CA證書添加到系統(tǒng)或瀏覽器的可信CA證書中,來規(guī)避這個問題。

以前這些步驟需要一系列繁瑣的openssl命令生成,盡管有腳本化的方案幫助我們簡化輸入這些命令(可以參考以前的blog: Nginx SSL快速雙向認證配置)。但是仍然覺得對本地開發(fā)不那么友好,有些繁重了。本文將介紹一種更加簡單友好的方式生成本地https證書,并且信任自簽CA的方案——mkcert。

mkcert簡介

mkcert是一個使用go語言編寫的生成本地自簽證書的小程序,具有跨平臺,使用簡單,支持多域名,自動信任CA等一系列方便的特性可供本地開發(fā)時快速創(chuàng)建https環(huán)境使用。

安裝方式也非常簡單,由于go語言的靜態(tài)編譯和跨平臺的特性,官方提供各平臺預編譯的版本,直接下載到本地,給可執(zhí)行權限(Linux/Unix需要)就可以了。下載地址: https://github.com/FiloSottile/mkcert/releases/latest

此外,mkcert已經(jīng)推送至Homebrew, MacPorts, Linuxbrew, Chocolatey, Scoop等包管理平臺中,也可以直接借助對應的包管理平臺安裝。如:

brew install mkcert  # Homebrew/Linuxbrew
choco install mkcert  # Chocolatey

安裝成功后,應該可以使用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證書了。更詳細的用法直接看官方文檔就好。

將CA證書加入本地可信CA

$ mkcert -install
Using the local CA at "C:\Users\abcfy\AppData\Local\mkcert" ?

僅僅這么一條簡單的命令,就幫助我們將mkcert使用的根證書加入了本地可信CA中,以后由該CA簽發(fā)的證書在本地都是可信的。

在Windows的可信CA列表可以找到該證書:

image.png

在MacOS的證書列表同樣也可以找到:


image.png

image.png

同理,在Linux系統(tǒng)中也是類似的效果,這里就不演示了。

生成自簽證書

生成自簽證書的命令十分簡單:

mkcert domain1 [domain2 [...]]

直接跟多個要簽發(fā)的域名或ip就行了,比如簽發(fā)一個僅本機訪問的證書(可以通過127.0.0.1localhost,以及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上使用這兩個文件就可以了。

使用生成的證書文件

默認生成的證書格式為PEM(Privacy Enhanced Mail)格式,任何支持PEM格式證書的程序都可以使用。比如常見的ApacheNginx等,這里我們用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權限,你可能需要使用sudo提權)

image.png

證書效果

局域網(wǎng)內(nèi)使用

有時候我們需要在局域網(wǎng)內(nèi)測試https應用,這種環(huán)境可能不對外,因此也無法使用像Let's encrypt這種免費證書的方案給局域網(wǎng)簽發(fā)一個可信的證書,而且Let's encrypt本身也不支持認證Ip。

先來回憶一下證書可信的三個要素:

  • 由可信的CA機構簽發(fā)
  • 訪問的地址跟證書認證地址相符
  • 證書在有效期內(nèi)

如果期望我們自簽證書在局域網(wǎng)內(nèi)使用,以上三個條件都需要滿足。很明顯自簽證書一定可以滿足證書在有效期內(nèi),那么需要保證后兩條。我們簽發(fā)的證書必須匹配瀏覽器的地址欄,比如局域網(wǎng)的ip或者域名,此外還需要信任CA。

我們先重新簽發(fā)一下證書,加上本機的局域網(wǎng)ip認證:

 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.pemrootCA.pem兩個文件,用戶需要信任rootCA.pem這個文件。將rootCA.pem拷貝一個副本,并命名為rootCA.crt(因為windows并不識別pem擴展名,并且Ubuntu也不會將pem擴展名作為CA證書文件對待),將rootCA.crt文件分發(fā)給其他用戶,手工導入。

windows導入證書的方法是雙擊這個文件,在證書導入向?qū)е袑⒆C書導入受信任的根證書頒發(fā)機構:

image.png

MacOS的做法也一樣,同樣選擇將CA證書導入到受信任的根證書辦法機構。

Ubuntu的做法可以將證書文件(必須是crt后綴)放入/usr/local/share/ca-certificates/,然后執(zhí)行sudo update-ca-certificates

Android和IOS信任CA證書的做法參考官方文檔。

在局域網(wǎng)其他計算機就可以訪問https而不報警了。我在另一臺虛擬機Ubuntu上使用curl測試結果:

$ 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)生客戶端認證證書,用于SSL雙向認證。之前的文章介紹過使用openssl腳本的(Nginx SSL快速雙向認證配置),可以對比下。

-pkcs12命令可以產(chǎn)生PKCS12格式的證書。java程序通常不支持PEM格式的證書,但是支持PKCS12格式的證書。通過這個程序我們可以很方便的產(chǎn)生PKCS12格式的證書直接給Java程序使用,這里就不演示了。

其他高級用法不做介紹了,各位有興趣可以根據(jù)自己的實際需求和場景進行發(fā)掘吧。

小結

本篇文章我們介紹了一個好用的小工具mkcert,簡化我們在本地搭建https環(huán)境的復雜性,無需操作繁雜的openssl實現(xiàn)自簽證書了,這個小程序就可以幫助我們自簽證書,在本機使用還會自動信任CA,非常方便。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容