免費!讓 Https 證書不再成爲煩惱
前言
書承上回,上期寫了《實戰 goproxy 爲中國 steam 登錄加速》後,總是覺得服務端獲取到的客戶端信息太少了,爲了獲取更多的客戶端信息,就需要解包設置一箇中間代理人,我簡簡單單的用《Lego》申請了證書,兩種申請方式:
一種直接就是 cli,一種是代碼內申請直接使用。
#### 獻上 letsencrypt 的申請證書的工作原理,就知道爲什麼有申請和挑戰的環節了:
先介紹 Lego 的 cli 方式獲取證書與更新證書
# 通過源碼進行安裝
go install github.com/go-acme/lego/v4/cmd/lego@latest
# -----------------申請證書-----------------
lego --email="87066062@qq.com" --domains="www.laghaim.cn" --http run
# 申請的證書有效期爲90天
# 申請成功後就會獲得一下文件了。
# www.laghaim.cn.crt
# www.laghaim.cn.issuer.crt
# www.laghaim.cn.json
# www.laghaim.cn.key
# -----------------更新證書-----------------
lego --email="87066062@qq.com" --domains="www.laghaim.cn" --http renew
# 但是此時需要注意,這時續訂必須要小於30天
# 如果想提前更新證書,指定剩餘天數即可:
lego --email="87066062@qq.com" --domains="www.laghaim.cn" --http renew --days 45
如果想自動續租,寫個 crontab 就可以咯。
接下來就是利用 Lego 的庫代碼進行申請證書和續訂證書
關鍵地方我都進行了註釋,我喜歡一次性把整段代碼貼出來,大家也可以直接粘貼整段對部分常量參數進行修改後,直接調用 GetCertificateFromLego() 函數:
package get_certificate_from_lego
import (
"crypto"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"github.com/go-acme/lego/v4/certcrypto"
"github.com/go-acme/lego/v4/certificate"
"github.com/go-acme/lego/v4/challenge/http01"
"github.com/go-acme/lego/v4/challenge/tlsalpn01"
"github.com/go-acme/lego/v4/lego"
"github.com/go-acme/lego/v4/registration"
)
const (
EmailStr = "87066062@qq.com" // 修改爲自己的電子郵件
OneDomain = "www.laghaim.cn" // 修改爲自己的域名
)
type MyUser struct {
Email string
Registration *registration.Resource
key crypto.PrivateKey
}
func (u *MyUser) GetEmail() string {
return u.Email
}
func (u MyUser) GetRegistration() *registration.Resource {
return u.Registration
}
func (u *MyUser) GetPrivateKey() crypto.PrivateKey {
return u.key
}
func GetCertificateFromLego() (*certificate.Resource, error) {
// 創建myUser用戶對象。新對象需要email和私鑰才能啓動,私鑰我們自己生成
privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
return nil, err
}
myUser := MyUser{
Email: EmailStr,
key: privateKey,
}
config := lego.NewConfig(&myUser)
// 這裏配置密鑰的類型和密鑰申請的地址,記得上線後替換成 lego.LEDirectoryProduction ,測試環境下就用 lego.LEDirectoryStaging
config.CADirURL = lego.LEDirectoryStaging
config.Certificate.KeyType = certcrypto.RSA2048
// 創建一個client與CA服務器通信
client, err := lego.NewClient(config)
if err != nil {
return nil, err
}
// 這裏需要挑戰我們申請的證書,必須監聽80和443端口,這樣才能讓Let's Encrypt訪問到咱們的服務器
err = client.Challenge.SetHTTP01Provider(http01.NewProviderServer("", "80"))
if err != nil {
return nil, err
}
err = client.Challenge.SetTLSALPN01Provider(tlsalpn01.NewProviderServer("", "443"))
if err != nil {
return nil, err
}
// 把這個客戶端註冊,傳遞給myUser用戶裏
reg, err := client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})
if err != nil {
return nil, err
}
myUser.Registration = reg
request := certificate.ObtainRequest{
Domains: []string{OneDomain}, // 這裏如果有多個,就寫多個就好了,可以是多個域名
Bundle: true, // 這裏如果是true,將把頒發者證書一起返回,也就是返回裏面certificates.IssuerCertificate
}
// 開始申請證書
certificates, err := client.Certificate.Obtain(request)
if err != nil {
return nil, err
}
// 申請完了後,裏面會帶有證書的PrivateKey Certificate,都爲[]byte格式,需要存儲的自行轉爲string即可
return certificates, nil
}
// 如果要進行續訂,可將certificates, err := client.Certificate.Obtain(request)替換爲certificates, err := client.Certificate.Renew(request)
// renew裏面的參數就很簡單了,第一個參數就是第一次申請返回的指針的值certificates,第二個參數bundle上面已經講過傳true即可,後面兩個參數一個傳false,一個傳空字符串""即可。開啓PAC自動配置
然後剩下的內容,就是使用和解析打印一下咯:
package main
import (
"crypto/tls"
"crypto/x509"
"fmt"
"log"
"server/get_certificate_from_lego"
)
func main(){
cs, err := get_certificate_from_lego.GetCertificateFromLego()
if err != nil {
log.Fatalln("obtains certificate:", err)
}
ca, err := tls.X509KeyPair(cs.Certificate, cs.PrivateKey)
if err != nil {
log.Fatalln(err)
}
if ca.Leaf, err = x509.ParseCertificate(ca.Certificate[0]); err != nil {
log.Fatalln(err)
}
fmt.Println(ca.Leaf)
}
參考資料
lego**:**_https://github.com/go-acme/lego_
2022 GopherChina 大會報名火熱進行中!
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/QMiwx_2PhL3A1ogAAVeV2w