Setup SSL cert for dev environment with mkcert
ปกติเวลาเราต้องการทดสอบ web server แบบ https เราก็จะ gen self sign cert เช่น ใช้ openssl
แต่ถ้าต้องการกำหนด DNS แบบ SAN ด้วยก็จะยุ่งยากขึ้นมาอีกหน่อย พอเปิด URL ด้วย web browser ก็จะโดนด่าตลอดว่าหน้าเว็บไม่ปลอดภัย ต้องมากด allow ทุกครั้งไป
สำหรับบล็อกนี้ผมจะมาแนะนำ mkcert เป็น tools เอาไว้ช่วย generate ssl cert เช่นกัน แต่มีความพิเศษกว่า tools อื่นๆ เพราะจะมีการ trust CA cert และ update trust store ของ OS ให้ด้วย
# TL;DR
ยาวไปไม่อ่าน ขอสั้นๆ เลย
$ mkcert -install
$ mkcert domain.com "*.domain.com" localhost 127.0.0.1 ::1
ก็จะได้ไฟล์ public/private cert ไปใช้งาน จบ !!!
# Installation
ทำการติดตั้ง mkcert
ถ้าต้องการ trust root CA ให้กับ Firefox ด้วยให้ติดตั้ง nss
เพิ่มดังนี้
$ brew install mkcert
$ brew install nss
# Setup SSL Cert for Local Dev
# 1. Install Local Root CA
ทำการติดตั้ง root CA กันก่อน โดยใช้คำสั่ง
$ mkcert -install
สร้าง local root CA ไว้ที่ /Users/username/Library/Application Support/mkcert
โดยจะมีไฟล์ private & public cert คือ rootCA-key.pem
และ rootCA.pem
เราสามารถดู path ของ root CA โดยใช้คำสั่ง
$ mkcert -CAROOT
ในขั้นตอนการ install mkcert นั้น จะทำ trust root CA เพิ่มไว้ที่ trust store ของ OS ให้ด้วย ทำให้ Web Browser ที่ใช้ trust store ของ OS อย่าง Chrome หรือ Safari จะ trust certificate ที่ออกโดย CA นี้ เมื่อเราเปิด url https ที่ address bar ก็จะไม่เป็นสีแดง
# 2. Generate SSL Cert
เราจะสร้าง SSL certificate แบบ wild card ชื่อ *.somebank.com
เพื่อให้ใช้กับ sub domain ได้ เช่น dev.somebank.com
โดยใช้คำสั่งดังนี้
$ mkcert somebank.com "*.somebank.com" localhost 127.0.0.1 ::1
Created a new certificate valid for the following names 📜
- "somebank.com"
- "*.somebank.com"
- "localhost"
- "127.0.0.1"
- "::1"
The certificate is at "./somebank.com+4.pem" and the key at "./somebank.com+4-key.pem" ✅
จากตัวอย่างจะได้ cert มา 2 ไฟล์ คือ public key ชื่อ somebank.com+4.pem
และ private key ชื่อ somebank.com+4-key.pem
สามารถตรวจสอบรายละเอียดของ cert ได้โดยใช้คำสั่งของ OpenSSL ดังนี้
$ openssl x509 -in somebank.com+4.pem -text -noout
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
ed:66:a7:8c:8e:e2:61:d4:f3:dc:aa:c8:99:a7:42:e9
Signature Algorithm: sha256WithRSAEncryption
Issuer: O=mkcert development CA, OU=junlapong@PHOENIX-MKIII.local, CN=mkcert junlapong@PHOENIX-MKIII.local
Validity
Not Before: Jul 30 04:27:49 2019 GMT
Not After : Jul 30 04:27:49 2029 GMT
Subject: O=mkcert development certificate, OU=junlapong@PHOENIX-MKIII.local
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
...
หรือถ้าต้องการดูเฉพาะชื่อ DNS ใช้ grep กรองเอา ดังนี้
$ openssl x509 -in somebank.com+4.pem -text -noout | grep "DNS:"
DNS:somebank.com, DNS:*.somebank.com, DNS:localhost, IP Address:127.0.0.1, IP Address:0:0:0:0:0:0:0:1
# 3. Add Local DNS Name
ใช้ editor ที่ถนัด เปิดไฟล์ /etc/hosts
เพื่อเพิ่ม DNS Name โดยผูกไว้กับ IP 127.0.0.1
$ sudo vi /etc/hosts
ในตัวอย่างนี้จะเพิ่ม DNS Name dev.somebank.com
127.0.0.1 localhost dev.somebank.com
# 4. Example
เราจะลองสร้าง HTTP/2 server ด้วยภาษา Go กัน โดยเขียนไฟล์ main.go
และกำหนด path ให้กับ public & private certs ตามตัวอย่างด้านล่าง
package main
import (
"net/http"
"golang.org/x/net/http2"
)
func main() {
var srv http.Server
srv.Addr = ":443"
//Enable http2
http2.ConfigureServer(&srv, nil)
http.HandleFunc("/", homePage)
srv.ListenAndServeTLS("/path/to/certs/somebank.com.pem", "/path/to/certs/somebank.com-key.pem")
}
func homePage(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("<h1><center> Hello from Go! </h1></center>"))
}
ทำการรันโปรแกรมด้วยคำสั่ง
$ go run main.go
ทดสอบเปิด URL https://dev.somebank.com ด้วย FireFox จะเห็นว่าลูกกุญแจที่ address bar เป็นสีเขียวแล้ว 😄 แต่ถ้าเปิดด้วย Chrome และ Safari จะเห็นกุญแจที่ address bar เป็นสีเทา
ทดสอบด้วย curl
$ export CAROOT="`mkcert -CAROOT`"
$ curl --cacert "$CAROOT/rootCA.pem" -I https://dev.somebank.com
HTTP/2 200
content-type: text/html; charset=utf-8
content-length: 42
date: Tue, 30 Jul 2019 04:37:38 GMT
ทดสอบด้วย HTTPie
$ http --verify=no https://dev.somebank.com
HTTP/1.1 200 OK
Content-Length: 42
Content-Type: text/html; charset=utf-8
Date: Tue, 30 Jul 2019 04:47:39 GMT
<h1><center> Hello from Go! </h1></center>
# อ้างอิง
- https://github.com/FiloSottile/mkcert
- https://github.com/Shyp/generate-tls-cert