4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Cloudflare で gRPC を通す (1. プロキシ + Full TLS 化)

Last updated at Posted at 2023-01-29

はじめに

Cloudflare で gRPC を通すテストをしたので紹介します。
Screenshot 2023-01-29 at 11.37.21.png

2020年の Blog に記載がありましたが、試していませんでした。
サポートドキュメントもあります。

Cloudflare の特性を活かし、gRPC サービスに対して

  1. プロキシ + Full TLS 化 <<====
  2. ファイアウォール
  3. レートリミット
  4. ロードバランシング

を順に試していこうかと思います。

できることを見るため、有償版の機能も一部使っています。
特に明示してないのですが、ご容赦ください。

第1回として、まずプロキシで動くようにします。

プロキシ + Full TLS 化

gRPC クライアント ←--(TLS)--→ Cloudflare
Cloudflare ←-(TLS)-→ gRPC サーバ

どちらも TLS 化します。
(mTLS はやってないです)

Cloudflare を使うので、プロキシ部分はなるだけ近道するのを目指します。

gRPC サーバ

gRPC プロキシ時の前提事項

Cloudflare で gRPC を通す場合、要求事項が下記になっています。

Your gRPC endpoint must listen on port 443. 
Your gRPC endpoint must support TLS and HTTP/2.
HTTP/2 must be advertised over ALPN.
Use application/grpc or application/grpc+<message type (for example: application/grpc+proto) for the Content-Type header of gRPC requests.

gRPC サーバはポート 443 で TLS をリッスンする必要があります。
ALPN 対応で、content-type の指定も守る必要があります。

TLS サーバ証明書の準備 (gRPC サーバ用)

gRPC サーバを TLS 化するので証明書が必要になります。

OpenSSL とかで作るのもいいですけど、
Cloudflare の SSL/TLS Origin Certificates から作るとワンクリックで簡単なので、Cloudflare を通す場合はこちらを使うと楽です。
Screenshot 2023-01-29 at 11.46.19.png

API でも管理できるので、自動化にも使えます。

gRPC サーバ (greeter_server/main.go) TLS 化

gRPC サーバは Go/Quick start を拝借します。
ポート 443TLS をリッスンさせるため、サーバ greeter_server/main.goを変更します。

greeter_server/cert/ を作り、 Cloudflare の Origin Certificates で作成した公開鍵を cert.pem、秘密鍵を key.pem で配置します。

greeter_server/main.go を編集します。

--- greeter_server/main.go	2023-01-28 07:48:37.736281676 +0000
+++ greeter_server/main.tls.go	2023-01-29 03:07:17.779105810 +0000
@@ -27,11 +27,12 @@
 	"net"

 	"google.golang.org/grpc"
+	"google.golang.org/grpc/credentials"
 	pb "google.golang.org/grpc/examples/helloworld/helloworld"
 )

 var (
-	port = flag.Int("port", 50051, "The server port")
+	port = flag.Int("port", 443, "The server port")
 )

 // server is used to implement helloworld.GreeterServer.
@@ -51,7 +52,16 @@
 	if err != nil {
 		log.Fatalf("failed to listen: %v", err)
 	}
-	s := grpc.NewServer()
+	creds, err := credentials.NewServerTLSFromFile(
+		"/home/ubuntu/grpc-go/examples/helloworld/greeter_server/cert/cert.pem",
+		"/home/ubuntu/grpc-go/examples/helloworld/greeter_server/cert/key.pem",
+	)
+	if err != nil {
+		log.Fatal("Failed to generate credentials: %v", err)
+	}
+	s := grpc.NewServer(
+		grpc.Creds(creds),
+	)
 	pb.RegisterGreeterServer(s, &server{})
 	log.Printf("server listening at %v", lis.Addr())
 	if err := s.Serve(lis); err != nil {

参考リンク

サーバを起動します。

ubuntu@vm1:~/grpc-go/examples/helloworld$ sudo go run greeter_server/main.tls.go
2023/01/29 03:07:23 server listening at [::]:443

Cloudflare プロキシ

Cloudflare で gRPC プロキシの準備をします。

gRPC 有効化

gRPC を有効にします。
Screenshot 2023-01-29 at 12.16.06.png

HTTP/2 to Origin というスイッチがありますが、こちらは無効のままでも gRPC さえ有効にしておけばよかったです。

Screenshot 2023-01-29 at 12.17.20.png
gRPC 以外で HTTP/2 でオリジンと接続する場合に有効にします。

権威 DNS 設定

ホスト名でアクセスするので DNS の設定をします。
gRPC のパブリック IP (今回は GCP ) を A レコードで指定しています。
オレンジ雲に倒すとプロキシさせることになります。
Screenshot 2023-01-29 at 12.25.42.png

プロキシ中はオリジンの IP の代わりに、Cloudflare の IP が返ります。

$ dig rpc.example.com +short
104.18.xxx.xx
104.18.xxx.xx

TLS 設定

gRPC サーバの TLS 設定は終わってます。
プロキシサーバの TLS はどうしましょう、というところですが、こちらはすでに自動で適用されていると思います。
こういうところも楽ですね。

前提として、TLS のモードは Full あるいは Full Strict にしておきます。上記のように Cloudflare の Origin Certificate を発行した場合は Full Strict が使えて安心です。

全体の設定で合わせるか、
Screenshot 2023-01-29 at 12.39.25.png
Page Rules または Configuration Rules を使って条件を絞って個別に設定することもできます。

なお、モードの違いについてはこちらが詳しいです。

gRPC クライアント

クライアント (greeter_client/main.go) TLS 化

クライアントも Go/Quick start を拝借しますが、TLS でリクエストさせるため、クライアント greeter_client/main.go を編集します。

--- greeter_client/main.go	2023-01-29 04:08:18.455501186 +0000
+++ greeter_client/main.tls.go	2023-01-29 15:00:49.520768741 +0000
@@ -26,6 +26,7 @@
 	"time"

 	"google.golang.org/grpc"
+	"google.golang.org/grpc/credentials"
 	"google.golang.org/grpc/credentials/insecure"
 	pb "google.golang.org/grpc/examples/helloworld/helloworld"
 )
@@ -37,12 +38,19 @@
 var (
 	addr = flag.String("addr", "localhost:50051", "the address to connect to")
 	name = flag.String("name", defaultName, "Name to greet")
+	useTLS = flag.Bool("use_tls", false, "Connection uses TLS if true")
 )

 func main() {
 	flag.Parse()
+	var creds credentials.TransportCredentials
+	if *useTLS {
+        creds = credentials.NewClientTLSFromCert(nil, "")
+        } else {
+        creds = insecure.NewCredentials()
+        }
 	// Set up a connection to the server.
-	conn, err := grpc.Dial(*addr, grpc.WithTransportCredentials(insecure.NewCredentials()))
+	conn, err := grpc.Dial(*addr, grpc.WithTransportCredentials(creds))
 	if err != nil {
 		log.Fatalf("did not connect: %v", err)
 	}

参考リンク

接続

クライアント

ubuntu@vm2:~/grpc-go/examples/helloworld$ go run greeter_client/main.tls.go -addr=rpc.example.com:443 -use_tls=true
2023/01/29 04:20:08 Greeting: Hello world
ubuntu@vm2:~/grpc-go/examples/helloworld$ go run greeter_client/main.tls.go -addr=rpc.example.com:443 -use_tls=true -name=hoge
2023/01/29 04:21:54 Greeting: Hello hoge

サーバ

ubuntu@vm1:~/grpc-go/examples/helloworld$ sudo go run greeter_server/main.tls.go
2023/01/29 04:12:45 server listening at [::]:443
2023/01/29 04:20:08 Received: world
2023/01/29 04:21:54 Received: hoge

オブザバビリティ

ログ

HTTP リクエストの生ログをリアルタイムに確認するには Instant Logs です。
リクエストを投げながらログの確認ができるので、楽ちんです。

出力フィルタが用意されているので、欲しいログにマッチするフィルタを掛けてからログを開始しましょう。

Instant Logs の Host フィルタは host ヘッダそのものを取るようです。今回のようにクライアントが Hostname:443 とポートを追加してくるケースでは、equals する場合は :443 も付けるようにします。(下の例では starts with でやっているので、そこは無関係)

Screenshot 2023-01-29 at 13.26.16.png

行をクリックすると詳細を確認できます。
リクエストやレスポンスの詳細情報が見えてます。
(下記は一部抜粋で、その他にも色んな情報を見ることができます)
Screenshot 2023-01-29 at 13.28.02.png

統計情報

統計情報は Analytics Traffic で見ます。
裏では HTTP リクエストログをソースに Graphql が動いてますので、ソースログに対して多様な分析ができます。
いろいろなところをクリックすると面白いです。

Screenshot 2023-01-29 at 13.38.27.png

以上、 gRPC の単純なプロキシ (+ Full TLS) として動作させることができました。

第2回はファイアウォールを噛まして、必要なリクエストのみオリジンに届けようと思います。

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?