TLS+gRPC怎麼玩?如何讓自己的RPC通訊更加安全?
前面松哥發了一篇文章和小夥伴們仔細聊了聊 TLS、CA 證照這些問題,還沒看過的小夥伴可以先戳下面瞭解下:
TLS、SSL、CA 證照、公鑰、私鑰。。。今天捋一捋!
今天我們要在前文的基礎之上,來和小夥伴們聊一聊如何確保 gRPC 的通訊安全。
確保 gRPC 的通訊安全我們有很多種不同的方式,其中一種,就是對通訊過程進行加密,使用上 TLS。對於 TLS 如何加密,如何協商金鑰,這些我這裡就不再囉嗦了,我在之前的文章中都已經介紹過了。我們們就直接來看具體的玩法。
這塊整體上可以分為兩大類:
啟用單向安全連線 啟用 mTLS 安全連線
我們分別來看。
1. 啟用單向安全連線
單向安全連線其實就是說只需要客戶端校驗服務端,確保客戶端收到的訊息來自預期的服務端,整個的校驗就涉及到我們前文所說的 TLS、CA 等內容了,具體流程是這樣:
首先我們先在自己電腦本地生成一個自簽名的 CA 證照。 利用這個 CA 證照,生成一個服務證照。
大致上就這兩個步驟就行了,然後在客戶端和服務端中分別載入相應的證照即可。
上面我們提到了需要先有一個自簽名的 CA 證照,這一步其實也可以省略,省略之後就直接生成一個自簽名的服務證照即可,然後在客戶端和服務端都使用這個服務證照。
來實際操作一下。
先自己安裝一下 openssl 工具,配置一下環境變數,軟體安裝比較簡單,我這裡就不囉嗦了。
1.1 生成 CA 證照
首先我們來看下如何生成 CA 證照。
一共是三個步驟:
生成 .key
私鑰檔案:
openssl genrsa -out ca.key 2048
out 表示輸出的檔名。 2048 表示私鑰的位數。
生成 .csr
證照籤名請求檔案:
CSR 即證照籤名申請(Certificate Signing Request),獲取 SSL 證照,需要先生成 CSR 檔案並提交給證照頒發機構(CA)。CSR 包含了用於簽發證照的公鑰、用於辨識的名稱資訊(Distinguished Name)(例如域名)、真實性和完整性保護(例如數字簽名),通常從 Web 伺服器生成 CSR,同時建立加解密的公鑰私鑰對。
openssl req -new -key ca.key -out ca.csr -subj "/C=CN/L=GuangZhou/O=javaboy/CN=local.javaboy.org"
subj 中描述的是一些國家、城市、組織以及通用名稱(域名)等資訊。
自簽名生成 .crt
證照檔案
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt -subj "/C=CN/L=GuangZhou/O=javaboy/CN=local.javaboy.org"
-x509 表示是要生成自簽名證照。 -days 3650 表示證照有效期是 3650 天。 -key 表示生成證照所需要的金鑰。
有人說公鑰呢?公鑰其實就在 .crt
證照檔案中。
1.2 生成服務證照
再來看生成服務證照,生成服務證照和生成 CA 證照其實整個過程差不多,唯一的區別在於,CA 證照是自簽名的,而服務證照是 CA 的私鑰給簽名的,就這個差別。
生成 .key
私鑰檔案:
openssl genrsa -out server.key 2048
生成 .csr
證照籤名請求檔案:
openssl req -new -key server.key -out server.csr -subj "/C=CN/L=GuangZhou/O=javaboy/CN=local.javaboy.org"
簽名生成 .crt
證照檔案
openssl x509 -req -days 3650 -in server.csr -out server.crt -CA ca.crt -CAkey ca.key
-req 和 -in 指定了 server.csr,這個是證照請求檔案,這裡實際上是表示簽署證照請求檔案。
證照現在就生成完畢。
這裡我們生成的私鑰都是 .key
檔案,這個用我們 Java 程式碼載入的時候會有問題,我們要將之轉為 .pem
格式然後再用 Java 程式碼進行載入,轉換的命令如下:
openssl pkcs8 -topk8 -inform pem -in server.key -outform pem -nocrypt -out server.pem
1.3 單向加密
現在證照都有了,在當前專案目錄下新建一個資料夾,專門用來放證照,專案目錄結構如下:
├── certs
│ ├── ca.crt
│ ├── ca.csr
│ ├── ca.key
│ ├── server.crt
│ ├── server.csr
│ ├── server.key
│ └── server.pem
├── grpc_api
│ ├── pom.xml
│ ├── src
│ └── target
├── grpc_client
│ ├── pom.xml
│ ├── src
│ └── target
├── grpc_server
│ ├── pom.xml
│ ├── src
│ └── target
└── pom.xml
我們看下程式碼該如何改造實現單向加密通訊。
先來看服務端程式碼:
public void start() throws IOException {
int port = 50051;
File certFile = Paths.get( "certs", "server.crt").toFile();
File keyFile = Paths.get("certs", "server.pem").toFile();
server = ServerBuilder.forPort(port)
.addService(new LoginServiceImpl())
.addService(ServerInterceptors.intercept(new HelloServiceImpl(), new AuthInterceptor()))
.useTransportSecurity(certFile,keyFile)
.build()
.start();
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
LoginServer.this.stop();
}));
}
大家注意,由於我生成簽名的時候,使用的域名是
local.javaboy.org
這是我在本地 hosts 檔案中配置的,指向本地地址,所以在後續的通訊中,我使用的域名都將是local.javaboy.org
。
Paths.get 方法表示從專案的根目錄下開始查詢檔案,引數是可變長度引數,引數共同組成檔案完整路徑。 服務端需要載入服務簽名和服務私鑰,簽名證照是客戶端驗證服務端身份用的,私鑰則是服務端解密客戶端訊息使用的。
服務端的改造就這些。
再來看客戶端的改造:
File certFile = Paths.get( "certs", "ca.crt").toFile();
SslContext sslContext = GrpcSslContexts.forClient().trustManager(certFile).build();
ManagedChannel channel = NettyChannelBuilder.forAddress("local.javaboy.org", 50051)
.useTransportSecurity()
.sslContext(sslContext)
.build();
客戶端主要是載入 CA 證照檔案,服務端的證照就是 CA 私鑰簽發的,但是需要 CA 公鑰也就是 ca.crt 進行驗籤,所以這裡客戶端載入了 ca.crt 即可。
好啦,整體上的流程差不多就是這個樣子。
2. 啟用 mTLS 安全連線
上面的例子只是客戶端校驗了服務端的身份,服務端並沒有校驗客戶端的身份,如果想要雙向校驗,那麼就把上面的流程對稱操作一遍就可以了。
首先我們需要為客戶端生成相應的證照,步驟跟前面也基本上一直,使用 CA 進行簽名,如下:
生成 .key
私鑰檔案:
openssl genrsa -out client.key 2048
生成 .csr
證照籤名請求檔案:
openssl req -new -key client.key -out client.csr -subj "/C=CN/L=GuangZhou/O=javaboy/CN=local.javaboy.org"
簽名生成 .crt
證照檔案
openssl x509 -req -days 3650 -in client.csr -out client.crt -CA ca.crt -CAkey ca.key
然後來看看程式碼。
先來看服務端:
public void start() throws IOException {
int port = 50051;
File certFile = Paths.get( "certs", "server.crt").toFile();
File keyFile = Paths.get("certs", "server.pem").toFile();
File caFile = Paths.get("certs", "ca.crt").toFile();
server = NettyServerBuilder.forPort(port)
.addService(new LoginServiceImpl())
.addService(ServerInterceptors.intercept(new HelloServiceImpl(), new AuthInterceptor()))
.sslContext(GrpcSslContexts.forServer(certFile,keyFile).trustManager(caFile).clientAuth(ClientAuth.REQUIRE).build())
.build()
.start();
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
LoginServer3.this.stop();
}));
}
服務端要載入的檔案多了 ca.crt
,這是給客戶端驗籤的時候需要用到。
再來看看客戶端程式碼:
File caFile = Paths.get( "certs", "ca.crt").toFile();
File certFile = Paths.get( "certs", "client.crt").toFile();
File keyFile = Paths.get( "certs", "client.pem").toFile();
SslContext sslContext = GrpcSslContexts.forClient().trustManager(caFile)
.keyManager(certFile, keyFile).build();
ManagedChannel channel = NettyChannelBuilder.forAddress("local.javaboy.org", 50051)
.useTransportSecurity()
.sslContext(sslContext)
.build();
客戶端多了 client.crt
和 client.pem
,兩者的作用根服務端中這兩者的作用基本一致,前文已有說明,這裡就不再贅述了。
好啦,如此之後,我們的 gRPC 通訊就加上了 TLS 的外殼,更加安全了。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70027824/viewspace-2941453/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 如何讓自己的程式碼更加安全?
- 雲端計算如何讓您的企業更加安全?
- 區塊鏈加密社交應用讓資訊更加安全區塊鏈加密
- Thrift RPC 通訊搭建RPC
- RocketMQ(二):RPC通訊MQRPC
- 樂訊通雲通訊:物聯卡與物聯網技術讓窗簾更加的智慧化
- lms微服務的rpc通訊框架微服務RPC框架
- 訊息中介軟體—RocketMQ的RPC通訊(一)MQRPC
- 如何讓AI教機器自己玩俄羅斯方塊?AI
- 微服務7:通訊之RPC微服務RPC
- 僅需五步,讓你的個人資料更加安全!
- async/await 是如何讓程式碼更加簡潔的?AI
- 《明日方舟》海貓:玩家的期許讓我對自己更加嚴格
- go語言實現自己的RPC:go rpc codecGoRPC
- 通訊安全重重考驗,阿里雲通訊如何打造企業級“安全感”?阿里
- php 透過 JSON RPC 與 golang 通訊PHPJSONRPCGolang
- 安全通訊
- 自媒體這行究竟是怎麼創造收益的?怎麼讓自己的收益提高?
- 結合RPC框架通訊談 netty如何解決TCP粘包問題RPC框架NettyTCP
- Seata 高效能 RPC 通訊的實現基石-Netty篇RPCNetty
- 深入理解Https如何保證通訊安全HTTP
- Android安全防護之旅---幾行程式碼讓Android應用變得更加安全Android行程
- 更安全的Web通訊HTTPSWebHTTP
- HTTPS的安全通訊機制HTTP
- 羊了個羊怎麼玩兒?微信小程式羊了個羊第二關怎麼玩通關微信小程式
- Hadoop3.2.1 【 YARN 】原始碼分析 :RPC通訊解析HadoopYarn原始碼RPC
- 如何讓自己安心養老呢?
- socket.io讓每個人都可以開發屬於自己的即時通訊
- 揭祕:中興通訊怎麼了?
- 你為什麼要讓自己的生活一團糟_做好自己
- 交友原始碼中即時通訊怎麼工作的?原始碼
- GO的日誌怎麼玩Go
- win10玩dnf傳送不了訊息怎麼解決_win10玩dnf傳送不了訊息如何處理Win10
- 如何設定讓Win10可以ping通_怎樣讓win10系統可以ping通Win10
- 怎麼自己裝Win10系統_如何自己重灌win10Win10
- 騰訊怎麼玩體育:堅持媒體定位
- 分散式下的遠端通訊技術(RPC)的一些理解分散式RPC
- 手機通訊錄怎麼備份?手機通訊錄的幾種備份方法