mTLS
mTLS
是 Mutual TLS(雙向TLS認證)
的縮寫
讓我們使用 curl
演示 mTLS 過程
首先, 我們需要一個 client
和 server
都信任的 certificate authority(CA)
CA
就是一個 public key
和 private key
其中 public key
包含在自簽名的 X.509證書
中.
使用下面的命令創(chuàng)建 CA
openssl req \
-new \
-x509 \
-nodes \
-days 365 \
-subj '/CN=my-ca' \
-keyout ca.key \
-out ca.crt
上述命令會產(chǎn)出2個文件: ca.key
和 ca.crt
, 使用 PEM格式. 其中
-
ca.key
是private key(私鑰)
-
ca.crt
是X.509證書
, 其中包含public key
使用 openssl x509 -in ca.crt -text -noout
查看證書內(nèi)容
通過查看證書內(nèi)容残邀,我們可以確認以下幾點:
-
Subject
和Issuer
都是CN = my-ca
, 這表明該證書是自簽名的 -
Validity
表明證書有效期是一年 -
X509v3 Basic Constraints
的值CA:TRUE
表明該證書可以用做CA
, 即可以用來簽署證書
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
[OBMITTED]
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN = my-ca
Validity
Not Before: Mar 7 00:00:19 2021 GMT
Not After : Mar 7 00:00:19 2022 GMT
Subject: CN = my-ca
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (2048 bit)
Modulus:
[OBMITTED]
Exponent: [OBMITTED]
X509v3 extensions:
X509v3 Subject Key Identifier:
[OBMITTED]
X509v3 Authority Key Identifier:
keyid:[OBMITTED]
X509v3 Basic Constraints:
CA:TRUE
Signature Algorithm: sha256WithRSAEncryption
[OBMITTED]
然后,創(chuàng)建Server端的private key和證書
首先創(chuàng)建 server端
的 private key
執(zhí)行下面的命令, 該命令會產(chǎn)生1個文件: server.key
, 即 server端
的 private key
openssl genrsa \
-out server.key 2048
然后創(chuàng)建 server端證書
(1) 先創(chuàng)建 Certificate Signing Request (CSR)
, 下面的命令會產(chǎn)生1個文件: server.csr
, 該文件用于第2步生成 server端證書
CN(Common Name)
填寫 server的hostname
, 本例中為 localhost
# 先創(chuàng)建 CSR
openssl req \
-new \
-key server.key \
-out server.csr
(2) 創(chuàng)建 server端證書
, 下面的命令會產(chǎn)生1個文件: server.crt
, 即 server端證書
, 使用 PEM格式
openssl x509 \
-req \
-in server.csr \
-CA ca.crt \
-CAkey ca.key \
-CAcreateserial \
-days 365 \
-out server.crt
使用 openssl x509 -in ca.crt -text -noout
查看證書內(nèi)容
通過查看證書內(nèi)容凿叠,我們可以確認以下幾點:
-
Issuer
是CN = my-ca
, 這表明證書是由my-ca證書頒發(fā)機構(gòu)
簽名的 -
Subject
是CN = localhost
, 這表明可以將該證書提供給客戶端,以驗證服務器是否可以信任DNS名稱localhost的內(nèi)容 -
Validity
表明證書有效期是一年
Certificate:
Data:
Version: 1 (0x0)
Serial Number:
[OBMITTED]
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN = my-ca
Validity
Not Before: Jun 13 00:50:18 2020 GMT
Not After : Jun 13 00:50:18 2021 GMT
Subject: CN = localhost
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (2048 bit)
Modulus:
[OBMITTED]
Exponent: [OBMITTED]
Signature Algorithm: sha256WithRSAEncryption
[OBMITTED]
然后,創(chuàng)建Client端的private key和證書
過程同上
然后,使用curl攜帶客戶端證書訪問服務器
curl \
--cacert ca.crt \
--key client.key \
--cert client.crt \
https://localhost:3000
除了 --cert參數(shù)
之外,其他參數(shù)還要簡單說明一下:
-
--cacert
是為了驗證server端證書
-
--key
是為了發(fā)送請求內(nèi)容時進行私鑰加密
TLS Termination
TLS Termination
主要作用是,作為一個 前置代理服務器 接收外部到達的加密TLS流量 瞧省, 然后將其 解密為HTTP明文 营密, 最后再將流量 轉(zhuǎn)發(fā)到內(nèi)部的某個服務
TLS Origination
TLS Origination
主要作用是 作為一個 代理服務器, 接收內(nèi)部服務的HTTP明文流量 扔嵌,然后將其 加密 掖桦,最后 轉(zhuǎn)發(fā)到一個HTTPS服務 上,該服務既可以是內(nèi)部供汛,也可以是外部的枪汪,但看起來就像是一個內(nèi)部的服務。
作為與邊界入口網(wǎng)關(guān)對立的存在怔昨,出口網(wǎng)關(guān)也通常放置在網(wǎng)絡的邊界雀久。
所有的出口流量都被它接管,在這個節(jié)點上我們可以 統(tǒng)一實施一些訪問控制策略 趁舀,或監(jiān)控赖捌,或日志等,這和 Ingress
的功能其實是一樣的矮烹,最大的不同在于 將明文流量加密再轉(zhuǎn)發(fā) 越庇。
我們對向外主動請求的流量常常是不設(shè)防的,這樣的嚴進寬出在安全要求較高的場合是不合適的奉狈。
了解了 Egress
這個概念后卤唉,不僅僅是在安全上對我們的業(yè)務有幫助,對于業(yè)務架構(gòu)的設(shè)計其實也是有所裨益的仁期。
考慮一個基于微信的服務桑驱,可能會有公眾號,小程序跛蛋,還可能會有多個小程序和公眾號熬的,更復雜一些,設(shè)計成微服務赊级,不同的服務可能會調(diào)用同一公眾號的微信接口押框。
那么問題來了, API access token
的存取就出現(xiàn)了競爭此衅,我們可以做一個獨立的服務强戴,將各種token的獲取亭螟,刷新和緩存封裝起來,所有的服務需要用到token時直接通過 token-server
獲取即可骑歹。
這種辦法是可以的预烙,雖然每次微信請求接口調(diào)用都產(chǎn)生了一次額外的內(nèi)部rpc調(diào)用,性能上其實可以忽略不計道媚,
麻煩的是代碼可能不會簡潔扁掸,更重要的是 對這些外發(fā)接口調(diào)用的監(jiān)控 ,日志沒有一個統(tǒng)一的地方處理最域。
我們還可以做得更好谴分,簡單的架構(gòu)如下:
在內(nèi)部服務中,所有調(diào)用微信API的協(xié)議均使用HTTP镀脂,然后這些請求都會經(jīng)過 wx-egress-server
牺蹄,它會給請求附加合適的 access token
,通過 HTTPS 協(xié)議發(fā)往外部的微信服務器薄翅。
除此以外沙兰,我們還可以 增加日志便于調(diào)試 ,監(jiān)控請求的成功率翘魄,甚至發(fā)起重試等等鼎天,這樣相對原來的方案要更靈活。