[grpc]双向tls加密认证

这篇具有很好参考价值的文章主要介绍了[grpc]双向tls加密认证。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

假设gRPC服务端的主机名为qw.er.com,需要为gRPC服务端和客户端之间的通信配置tls双向认证加密。

生成证书

  1. 生成ca根证书。生成过程会要求填写密码、CN、ON、OU等信息,记住密码。
openssl req -x509 -newkey rsa:4096 -keyout ca.key -out ca.crt -subj "/CN=qw.er.com" -days 365
  1. 新建并编辑文件openssl.cnf文件。req_distinguished_name中内容按需填写,DNS.1要替换成实际域名。
[req]
req_extensions = v3_req
distinguished_name = req_distinguished_name
prompt = no

[req_distinguished_name]
countryName = CN
stateOrProvinceName = Anhui
localityName = Hefei
organizationName = zhangsan
commonName = qw.er.com

[v3_req]
subjectAltName = @alt_names

[alt_names]
DNS.1 = qw.er.com
  1. 生成服务端证书
openssl req -newkey rsa:2048 -nodes -keyout server.key -out server.csr -subj "/CN=qw.er.com" -config openssl.cnf

# 提示输入ca私钥的密码
openssl x509 -req -in server.csr -out server.crt -CA ca.crt -CAkey ca.key -CAcreateserial -days 365 -extensions v3_req -extfile openssl.cnf
  1. 生成客户端证书
openssl req -newkey rsa:2048 -nodes -keyout client.key -out client.csr -subj "/CN=qw.er.com" -config openssl.cnf

# 提示输入ca私钥的密码
openssl x509 -req -in client.csr -out client.crt -CA ca.crt -CAkey ca.key -CAcreateserial -days 365 -extensions v3_req -extfile openssl.cnf

proto示例

用的还是入门级的helloworld

syntax = "proto3";   // protocol buffers版本
option go_package = "./;proto";   // 生成的Go代码将被放在当前目录,并使用proto作为包名称

// 定义grpc服务的接口。服务就是一组可被远程调用的方法
service Greeter {
	// 定义远程调用方法
    rpc SayHello (HelloRequest) returns (HelloReply);
}

// 定义消息格式和消息类型
message HelloRequest {
    string name = 1; // 1 是二进制格式中的字段编号, 应该唯一
}

message HelloReply {
    string message = 1;
}

生成go代码:

protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative hello.proto

服务端代码示例

如果需要客户端和服务端直接通信,可以参考以下示例代码。

package main

import (
	pb "grpcs/proto"
	"context"
	"crypto/tls"
	"crypto/x509"
	"flag"
	"fmt"
	"log"
	"net"
	"os"

	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
)

var (
	port    = flag.Int("port", 8010, "the server port")
	crtFile = flag.String("crt", "server.crt", "the server crt file")
	keyFile = flag.String("key", "server.key", "the server key file")
	caFile  = flag.String("ca", "ca.crt", "the server ca file")
)

type server struct{
	pb.UnimplementedGreeterServer
}

func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
	log.Printf("Received: %v", in.GetName())
	return &pb.HelloReply{Message: "Hello " + in.GetName()}, nil
}

func main() {
	flag.Parse()

	// 通过服务端的证书和密钥直接创建X.509密钥对
	certificate, err := tls.LoadX509KeyPair(*crtFile, *keyFile)
	if err != nil {
		log.Fatalf("Failed to load key pair: %v", err)
	}

	// 通过CA创建证书池
	certPool := x509.NewCertPool()
	ca, err := os.ReadFile(*caFile)
	if err != nil {
		log.Fatalf("Failed to read ca: %v", err)
	}

	// 将来自CA的客户端证书附加到证书池
	if ok := certPool.AppendCertsFromPEM(ca); !ok {
		log.Fatalf("Failed to append ca certificate")
	}

	opts := []grpc.ServerOption{
		grpc.Creds( // 为所有传入的连接启用TLS
			credentials.NewTLS(&tls.Config{
				ClientAuth: tls.RequireAndVerifyClientCert,
				Certificates: []tls.Certificate{certificate},
				ClientCAs: certPool,
			},
		)),
	}

	listen, err := net.Listen("tcp", fmt.Sprintf("0.0.0.0:%d", *port))
	if err != nil {
		log.Fatalf("failed to listen %d port", *port)
	}
	// 通过传入的TLS服务器凭证创建新的gRPC服务实例
	s := grpc.NewServer(opts...)
	pb.RegisterGreeterServer(s, &server{})
	log.Printf("server listening at %v", listen.Addr())
	if err := s.Serve(listen); err != nil {
		log.Fatalf("Failed to serve: %v", err)
	}
}

运行:

go build -o server.bin
./server.bin -ca ca.crt -crt server.crt -key server.key -port 8010

客户端代码示例

package main

import (
	pb "grpcc/proto"
	"context"
	"crypto/tls"
	"crypto/x509"
	"flag"
	"log"
	"os"
	"time"

	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
)

var (
	addr     = flag.String("addr", "qw.er.com:8010", "server address")
	hostname = flag.String("host", "qw.er.com", "server hostname")
	crtFile  = flag.String("crt", "client.crt", "client crt file")
	keyFile  = flag.String("key", "client.key", "client key file")
	caFile   = flag.String("ca", "ca.crt", "ca file")
	name = flag.String("n", "zhangsan", "name")
)

func main() {
	flag.Parse()

	certificate, err := tls.LoadX509KeyPair(*crtFile, *keyFile)
	if err != nil {
		log.Fatalf("Failed to load client key pair, %v", err)
	}

	certPool := x509.NewCertPool()
	ca, err := os.ReadFile(*caFile)
	if err != nil {
		log.Fatalf("Failed to read %s, error: %v", *caFile, err)
	}

	if ok := certPool.AppendCertsFromPEM(ca); !ok {
		log.Fatalf("Failed to append ca certs")
	}

	opts := []grpc.DialOption{
		grpc.WithTransportCredentials(credentials.NewTLS(
			&tls.Config{
				ServerName:   *hostname,
				Certificates: []tls.Certificate{certificate},
				RootCAs:      certPool,
			})),
	}

	// conn, err := grpc.Dial(*addr, grpc.WithTransportCredentials(insecure.NewCredentials()))
	conn, err := grpc.Dial(*addr, opts...)
	if err != nil {
		log.Fatalf("Connect to %s failed", *addr)
	}
	defer conn.Close()

	client := pb.NewGreeterClient(conn)
	// 创建带有超时时间的上下文, cancel可以取消上下文
	ctx, cancel := context.WithTimeout(context.Background(), time.Second*3)
	defer cancel()

	// 业务代码处理部分 ...
	r, err := client.SayHello(ctx, &pb.HelloRequest{Name: *name})
	if err != nil {
		log.Printf("Failed to greet, error: %v", err)
	} else {
		log.Printf("Greeting: %v",r.GetMessage())
	}
}

运行:

go build -o client.bin
./client.bin -addr qw.er.com:8010 -host qw.er.com -ca ca.crt -crt client.crt -key client.key -name 'lisi'

nginx代理

某些场景下服务端和客户端无法直接通信,需要在中间加个nginx反向代理服务端。目前个人方案是客户端与nginx之间为https双向加密通信,nginx与服务端之间为http普通通信。

客户端代码无需改动,服务端就是去掉tls相关配置,示例:

package main

import (
	"context"
	"flag"
	"fmt"
	"log"
	"net"

	pb "grpcs/proto"

	"google.golang.org/grpc"
)

var (
	port = flag.Int("port", 8010, "The server port")
)

// server is used to implement hello.GreeterServer.
type server struct {
	pb.UnimplementedGreeterServer
}

// SayHello 实现 proto 中的 service Greeter
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
	log.Printf("Received: %v", in.GetName())
	return &pb.HelloReply{Message: "Hello " + in.GetName()}, nil
}

func main() {
	flag.Parse()
	lis, err := net.Listen("tcp", fmt.Sprintf(":%d", *port))
	if err != nil {
		log.Fatalf("failed to listen: %v", err)
	}
	s := grpc.NewServer()
	pb.RegisterGreeterServer(s, &server{})
	log.Printf("server listening at %v", lis.Addr())
	if err := s.Serve(lis); err != nil {
		log.Fatalf("failed to serve: %v", err)
	}
}

tls证书配到nginx:文章来源地址https://www.toymoban.com/news/detail-622562.html

server {
    listen       80 ssl http2;
    server_name  qw.er.com;

	# 证书文件路径
    ssl_certificate /home/admin/apps/openresty/nginx/certs/qwer/server.crt;
    ssl_certificate_key /home/admin/apps/openresty/nginx/certs/qwer/server.key;
    # 验证客户端证书
    ssl_verify_client on;
    ssl_client_certificate /home/admin/apps/openresty/nginx/certs/qwer/ca.crt;

	# 反向代理服务端
    location / {
        grpc_pass grpc://192.168.1.111:8010;
    }
}

到了这里,关于[grpc]双向tls加密认证的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • [golang]使用mTLS双向加密认证http通信

    假设一个场景,服务端部署在内网,客户端需要通过暴露在公网的nginx与服务端进行通信。为了避免在公网进行 http 明文通信造成的信息泄露,nginx与客户端之间的通信应当使用 https 协议,并且nginx也要验证客户端的身份,也就是mTLS双向加密认证通信。 这条通信链路有三个角

    2024年02月14日
    浏览(42)
  • PostgreSQL安装和开启SSL加密连接【配置单/双向认证】

    SSL单向认证和双向认证: SSL单向认证 :只有一端校验对端的证书合法性,通常都是客户端来校验服务器的合法性。即在一般的单向认证中,只要求服务器端部署了ssl证书就行,客户端可以无证书,任何用户都可以去访问服务端,服务端只是提供了身份认证。 client: 无证书

    2024年02月06日
    浏览(46)
  • QtWebApp开发https服务器,完成客户端与服务器基于ssl的双向认证,纯代码操作

    引言:所谓http协议,本质上也是基于TCP/IP上服务器与客户端请求和应答的标准,web开发中常用的http server有apache和nginx。Qt程序作为http client可以使用QNetworkAccessManager很方便的进行http相关的操作。 Qt本身并没有http server相关的库 ,也许是因为很少有这种需求吧。但是实际开发中

    2024年02月14日
    浏览(55)
  • 搭建Radius认证服务器 安当加密

    搭建Radius认证服务器需要完成以下步骤: 安装Radius服务器软件。可以选择使用FreeRadius、Radiusd或WinRadius等开源软件,也可以选择使用商业软件如Cisco或 安当ASP 等。 配置认证数据库。在Radius服务器上配置认证数据库,用于存储用户信息和认证信息。可以选择使用常见的数据库

    2024年02月05日
    浏览(52)
  • springboot整合https使用自签名证书实现浏览器和服务器之间的双向认证

    效果描述: 本地环境  两台以上电脑  可以实现安装客户端证书的电脑可以访问springboot启动项目,没有安装客户端证书的电脑无法访问springboot启动项目 1.操作:需要安装openssl工具 工具包:Win64OpenSSL_Light-3_3_0.exe 或者Win64OpenSSL_Light-3_3_0.msi  官网:[ Downloads ] - /source/index.html

    2024年04月28日
    浏览(50)
  • .netcore grpc双向流方法详解

    简单来讲客户端可以向服务端发送消息流,服务端也可以向客户端传输响应流,即客户端和服务端可以互相通讯 客户端无需发送消息即可开始双向流式处理调用 。 客户端可选择使用  RequestStream.WriteAsync  发送消息。 使用  ResponseStream.MoveNext()  或  ResponseStream.ReadAllAsync()  可

    2024年02月13日
    浏览(38)
  • grpc介绍(二)——认证方式

    HTTP是明文传输的,即客户端与服务端之间通信的信息是可见的,这就存在被窃听、冒充或篡改的风险。HTTPS在HTTP和TCP之间加入了TLS协议,如图所示: TLS协议主要解决了以下三个网络安全问题: 信息加密 : HTTP 交互信息是被加密的,第三方就无法被窃取; 校验机制 :校验信

    2023年04月23日
    浏览(39)
  • EMQX启用双向SSL/TLS安全连接以及java连接

    作为基于现代密码学公钥算法的安全协议,TLS/SSL 能在计算机通讯网络上保证传输安全,EMQX 内置对 TLS/SSL 的支持,包括支持单/双向认证、X.509 证书、负载均衡 SSL 等多种安全认证。你可以为 EMQX 支持的所有协议启用 SSL/TLS,也可以将 EMQX 提供的 HTTP API 配置为使用 TLS。 强认证

    2024年02月11日
    浏览(34)
  • MQTT使用TLS加密

            使用TLS加密在MQTT的使用中是比较常见的,TLS加密过程在网上有很多说明,但是没几个应用教程的,MQTT软件中的EMQX软件是支持TLS加密的,只不过要进行一些设置。 首先先安装EMQX软件 软件安装说明 免费下载、试用 EMQ 产品 (emqx.com) https://www.emqx.com/zh/try?product=broke

    2024年02月04日
    浏览(33)
  • HTTPS、TLS加密传输

    1、HTTPS(HyperText Transfer Protocol Secure) HTTPS(HyperText Transfer Protocol Secure)是一种加密通信协议,用于在计算机网络上进行安全的数据传输。它使用TLS(Transport Layer Security)协议建立一个加密的连接,确保在客户端和服务器之间传输的数据是加密和完整的。 2、TLS TLS是一个加密

    2024年02月14日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包