Akka-CQRS(10)- gRPC on SSL/TLS 安全连接
使用gRPC作为云平台和移动前端的连接方式,网络安全应该是必须考虑的一个重点。gRPC是支持ssl/tls安全通讯机制的。用了一个周末来研究具体使用方法,实际上是一个周末的挖坑填坑过程。把这次经历记录下来与各位分享。
gRPC的ssl/tls的原理是在服务端安装安全证书公用certificate和私钥key, 在客户端安装公共证书就可以了,gRPC代码是这样写的:
// Server
SslContext sslContext = SslContextBuilder.forServer(
new File("/Users/u/Desktop/api.grpc/src/main/resources/my-public-key-cert.pem"),
new File("/Users/u/Desktop/api.grpc/src/main/resources/my-private-key.pem"))
.build(); server = NettyServerBuilder.forPort(port).sslContext(sslContext)
.addService(GreeterGrpc.bindService(new GreeterImpl())).build()
.start(); / Client
SslContext sslContext = SslContextBuilder.forClient().trustManager(new File(
"/Users/u/Desktop/api.grpc/src/main/resources/my-public-key-cert.pem")).build();
channel = NettyChannelBuilder.forAddress(host, port)
.sslContext(sslContext)
.build();
blockingStub = GreeterGrpc.newBlockingStub(channel);
先构建SslContextBuilder,然后在构建NettyServerBuilder和NettyChannelBuilder时加入sslContext。上面的my-public-key-cert.pem,my-private_key.pem是用openssl产生的:
openssl req -x509 -newkey rsa:4096 -keyout my-private-key.pem -out my-public-key-cert.pem -days 365 -nodes -subj '/CN=localhost'
不过使用这个证书和私钥测试时出现了错误:
Jan 27, 2019 4:08:22 PM io.grpc.netty.GrpcSslContexts defaultSslProvider
INFO: netty-tcnative unavailable (this may be normal)
java.lang.ClassNotFoundException: io.netty.internal.tcnative.SSL
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
...
INFO: Jetty ALPN unavailable (this may be normal)
java.lang.ClassNotFoundException: org/eclipse/jetty/alpn/ALPN
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:348)
...
仔细研究了一下github上的gRPC-java说明文件SECURITY.MD,感觉应该是grpc和netty版本问题,特别是下面这几个依赖:
Find the dependency tree (e.g., mvn dependency:tree), and look for versions of: io.grpc:grpc-netty
io.netty:netty-handler (really, make sure all of io.netty except for netty-tcnative has the same version)
io.netty:netty-tcnative-boringssl-static:jar ... grpc-netty version netty-handler version netty-tcnative-boringssl-static version
1.0.0-1.0.1 4.1.3.Final 1.1.33.Fork19
1.0.2-1.0.3 4.1.6.Final 1.1.33.Fork23
1.1.x-1.3.x 4.1.8.Final 1.1.33.Fork26
1.4.x 4.1.11.Final 2.0.1.Final
1.5.x 4.1.12.Final 2.0.5.Final
1.6.x 4.1.14.Final 2.0.5.Final
1.7.x-1.8.x 4.1.16.Final 2.0.6.Final
1.9.x-1.10.x 4.1.17.Final 2.0.7.Final
1.11.x-1.12.x 4.1.22.Final 2.0.7.Final
1.13.x 4.1.25.Final 2.0.8.Final
1.14.x-1.15.x 4.1.27.Final 2.0.12.Final
1.16.x-1.17.x 4.1.30.Final 2.0.17.Final
1.18.x-1.19.x 4.1.32.Final 2.0.20.Final
1.20.x-1.21x 4.1.34.Final 2.0.22.Final
1.22.x- 4.1.35.Final 2.0.25.Final
解决问题必须先搞清楚这些库的版本。这个可以用sbt插件sbt-dependency-graph。加入project/plugins.sbt:
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.9")
addSbtPlugin("net.virtual-void" % "sbt-dependency-graph" % "0.9.2")
addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.3.15")
addSbtPlugin("com.thesamet" % "sbt-protoc" % "0.99.21")
addSbtPlugin("net.virtual-void" % "sbt-dependency-graph" % "0.9.2")
libraryDependencies += "com.thesamet.scalapb" %% "compilerplugin" % "0.9.0-M6"
在sbt中执行dependencyTree:
~/scala/intellij/learn-grpc> sbt
[info] Loading settings for project global-plugins from idea.sbt ...
sbt:learn-grpc> dependencyTree
[info] | | +-com.google.protobuf:protobuf-java:3.7.1
[info] | | +-io.grpc:grpc-api:1.21.0
[info] | | +-io.netty:netty-handler:4.1.34.Final
[info] | | | +-io.netty:netty-buffer:4.1.34.Final
[info] | | | | +-io.netty:netty-common:4.1.34.Final
...
好像缺失了io.netty:netty-tcnative-boringssl-static:jar,按照对应的gRPC版本在build.sbt里加上:
name := "learn-grpc" version := "0.1" scalaVersion := "2.12.8" scalacOptions += "-Ypartial-unification" val akkaversion = "2.5.23" libraryDependencies := Seq(
"com.typesafe.akka" %% "akka-cluster-metrics" % akkaversion,
"com.typesafe.akka" %% "akka-cluster-sharding" % akkaversion,
"com.typesafe.akka" %% "akka-persistence" % akkaversion,
"com.lightbend.akka" %% "akka-stream-alpakka-cassandra" % "1.0.1",
"org.mongodb.scala" %% "mongo-scala-driver" % "2.6.0",
"com.lightbend.akka" %% "akka-stream-alpakka-mongodb" % "1.0.1",
"com.typesafe.akka" %% "akka-persistence-query" % akkaversion,
"com.typesafe.akka" %% "akka-persistence-cassandra" % "0.97",
"com.datastax.cassandra" % "cassandra-driver-core" % "3.6.0",
"com.datastax.cassandra" % "cassandra-driver-extras" % "3.6.0",
"ch.qos.logback" % "logback-classic" % "1.2.3",
"io.monix" %% "monix" % "3.0.0-RC2",
"org.typelevel" %% "cats-core" % "2.0.0-M1",
"io.grpc" % "grpc-netty" % scalapb.compiler.Version.grpcJavaVersion,
"io.netty" % "netty-tcnative-boringssl-static" % "2.0.22.Final",
"com.thesamet.scalapb" %% "scalapb-runtime" % scalapb.compiler.Version.scalapbVersion % "protobuf",
"com.thesamet.scalapb" %% "scalapb-runtime-grpc" % scalapb.compiler.Version.scalapbVersion ) // (optional) If you need scalapb/scalapb.proto or anything from
// google/protobuf/*.proto
//libraryDependencies += "com.thesamet.scalapb" %% "scalapb-runtime" % scalapb.compiler.Version.scalapbVersion % "protobuf" PB.targets in Compile := Seq(
scalapb.gen() -> (sourceManaged in Compile).value
) enablePlugins(JavaAppPackaging)
试了一下启动服务,现在不出错误了(构建sslContext成功了)。不过客户端在使用了证书后仍然无法连接到服务端。没办法,又要再去查资料了。看来现在应该是证书的问题了。先看看是不是因为使用的证书是自签的self-signed-certificate。grpc-java里提供了一些测试用的证书和私钥和说明文档。在测试程序里使用了它们提供的server1.pem,server1.key,ca.pem:
package learn.grpc.server
import io.grpc.{ServerBuilder,ServerServiceDefinition}
import io.grpc.netty.NettyServerBuilder import java.io._ trait gRPCServer { val serverCrtFile = new File("/Users/tiger/certs/server1.pem")
val serverKeyFile = new File("/Users/tiger/certs/server1.key") def runServer(service: ServerServiceDefinition): Unit = {
val server = NettyServerBuilder
.forPort(50051)
.addService(service)
.useTransportSecurity(serverCrtFile,serverKeyFile)
.build
.start
// make sure our server is stopped when jvm is shut down
Runtime.getRuntime.addShutdownHook(new Thread() {
override def run(): Unit = server.shutdown()
}) server.awaitTermination()
} } ... package learn.grpc.sum.one2many.client
import java.io.File import io.grpc.stub.StreamObserver
import demo.services.sum._
import io.grpc.netty.{GrpcSslContexts, NegotiationType, NettyChannelBuilder} object One2ManyClient { def main(args: Array[String]): Unit = { val clientCrtFile = new File("/Users/tiger/certs/ca.pem") // new File(getClass.getClassLoader.getResource("badserver.pem").getPath) val sslContextBuilder = GrpcSslContexts.forClient().trustManager(clientCrtFile) //build connection channel
val channel = NettyChannelBuilder
.forAddress("192.168.0.189",50051)
.negotiationType(NegotiationType.TLS)
.sslContext(sslContextBuilder.build())
.overrideAuthority("foo.test.google.fr")
.build() // get asyn stub
val client: SumOneToManyGrpc.SumOneToManyStub = SumOneToManyGrpc.stub(channel)
// prepare stream observer
val streamObserver = new StreamObserver[SumResponse] {
override def onError(t: Throwable): Unit = println(s"error: ${t.getMessage}")
override def onCompleted(): Unit = println("Done incrementing !!!")
override def onNext(value: SumResponse): Unit = println(s"current value: ${value.currentResult}")
}
// call service with stream observer
client.addOneToMany(SumRequest().withToAdd(6),streamObserver) // wait for async execution
scala.io.StdIn.readLine()
} }
连接成功了。判断正确,是证书的问题。再研究一下证书是怎么产生的,尝试按文档指引重新产生这些自签证书:可惜的是好像还有些文件是缺失的,如serial。那么上面的.overrideAuthority("foo.test.google.fr")又是什么意思呢?算了,以后有时间再研究吧。这次起码证明grpc ssl/tls是可以发挥作用的。
Akka-CQRS(10)- gRPC on SSL/TLS 安全连接的更多相关文章
- Akka-CQRS(13)- SSL/TLS for gRPC and HTTPS:自签名证书产生和使用
到现在,我们已经完成了POS平台和前端的网络集成.不过,还是那句话:平台系统的网络安全是至关重要的.前一篇博客里我们尝试实现了gRPC ssl/tls网络连接,但测试时用的证书如何产生始终没有搞清楚. ...
- MsSQL使用加密连接SSL/TLS
说明 应用程序通过未加密的通道与数据库服务器通信, 这可能会造成重大的安全风险.在这种情况下, 攻击者可以修改用户输入的数据, 甚至对数据库服务器执行任意 SQL 命令. 例如,当您使用以下连接字符串 ...
- SQL Server使用加密连接SSL/TLS (转载)
说明 应用程序通过未加密的通道与数据库服务器通信, 这可能会造成重大的安全风险.在这种情况下, 攻击者可以修改用户输入的数据, 甚至对数据库服务器执行任意 SQL 命令.例如,当您使用以下连接字符串时 ...
- 简而意赅 HTTP HTTPS SSL TLS 之间有什么不同
HTTP HTTPS SSL TLS 之间有什么不同? SSL是Secure Sockets Layer的缩写.SSL的作用是为网络上的两台机器或设备提供了一个安全的通道. TLS是SSL的一个新的名 ...
- HTTPS详解二:SSL / TLS 工作原理和详细握手过程
HTTPS 详解一:附带最精美详尽的 HTTPS 原理图 HTTPS详解二:SSL / TLS 工作原理和详细握手过程 在上篇文章HTTPS详解一中,我已经为大家介绍了 HTTPS 的详细原理和通信流 ...
- 跟我一起学Go系列:Go gRPC 安全认证机制-SSL/TLS认证
Go gRPC 系列: 跟我一起学Go系列:gRPC 拦截器使用 跟我一起学Go系列:gRPC 入门必备 第一篇入门说过 gRPC 底层是基于 HTTP/2 协议的,HTTP 本身不带任何加密传输功能 ...
- .NET Core下使用gRpc公开服务(SSL/TLS)
一.前言 前一阵子关于.NET的各大公众号都发表了关于gRpc的消息,而随之而来的就是一波关于.NET Core下如何使用的教程,但是在这众多的教程中基本都是泛泛而谈,难以实际在实际环境中使用,而该篇 ...
- 协议森林17 我和你的悄悄话 (SSL/TLS协议)
作者:Vamei 出处:http://www.cnblogs.com/vamei 转载请先与我联系. TLS名为传输层安全协议(Transport Layer Protocol),这个协议是一套加密的 ...
- 好程序员带你了解一下HTTPS和SSL/TLS协议的背景与基础
>> 相关背景知识 要说清楚 HTTPS 协议的实现原理,至少需要如下几个背景知识. 大致了解几个基本术语(HTTPS.SSL.TLS)的含义 大致了解 HTTP 和 TCP 的关系(尤其 ...
随机推荐
- 修改Docker容器启动配置参数
有时候,我们创建容器时忘了添加参数 --restart=always ,当 Docker 重启时,容器未能自动启动, 现在要添加该参数怎么办呢,方法有二: 1.Docker 命令修改 docker c ...
- leetcode:7. 整数反转
题目描述: 给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转. 示例: 输入: 123 输出: 321 输入: -123 输出: -321 输入: 120 输出: 21 注意:假 ...
- Salt-Formulas的使用
Saltstack自0.17.x版本开始引进Formulas的概念,旨在通过简化State和集成数据来实现State的友好管理.根据SALT FORMULAS的官方文档,在完成手动添加formula目 ...
- Android相关视频
Android架构师 层次分析 –从顶层到底层 洞察其原理https://www.bilibili.com/video/av59066641?t=132安卓/Android 逆向破解系统班 第2期 全 ...
- android双进程守护,让程序崩溃后一定可以重启
由于我们做的是机器人上的软件,而机器人是24小时不间断服务的,这就要求我们的软件不能退出到系统桌面.当然最好是能够做到程序能够不卡顿,不崩溃,自己不退出.由于我们引用了很多第三方的开发包,也不能保证他 ...
- H3C交换机恢复出厂设置
reset saved-configuration reboot 恢复出厂设置后查看当前配置: ..............................
- linux命令(55):环境变量:LIBRARY_PATH 和 LD_LIBRARY_PATH的区别
添加环境变量:https://www.cnblogs.com/lovychen/p/5583703.html PATH是可执行文件的环境变量. LIBRARY_PATH 和 LD_LIBRARY_PA ...
- Scrapy的 Shell终端
crapy Shell Scrapy终端是一个交互终端,我们可以在未启动spider的情况下尝试及调试代码,也可以用来测试XPath或CSS表达式,查看他们的工作方式,方便我们爬取的网页中提取的数据. ...
- QT5.12 qtcreate 在Ubuntu14.04
Ubuntu14.04 下出现了 symbol dbus_message_get_allow_interactive_authorization, version LIBDBUS_1_3 not de ...
- ospf的路由更新和撤销总结
首先ospf 的报文有:hello报文,主要作用ospf 邻居建立及维护.dd报文,主要作用主从选举,序列号主从的确认,mtu的协商(可选).lsr 报文,主要作用向邻居请求lsa.lsu报文,主要作 ...