使用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 安全连接的更多相关文章

  1. Akka-CQRS(13)- SSL/TLS for gRPC and HTTPS:自签名证书产生和使用

    到现在,我们已经完成了POS平台和前端的网络集成.不过,还是那句话:平台系统的网络安全是至关重要的.前一篇博客里我们尝试实现了gRPC ssl/tls网络连接,但测试时用的证书如何产生始终没有搞清楚. ...

  2. MsSQL使用加密连接SSL/TLS

    说明 应用程序通过未加密的通道与数据库服务器通信, 这可能会造成重大的安全风险.在这种情况下, 攻击者可以修改用户输入的数据, 甚至对数据库服务器执行任意 SQL 命令. 例如,当您使用以下连接字符串 ...

  3. SQL Server使用加密连接SSL/TLS (转载)

    说明 应用程序通过未加密的通道与数据库服务器通信, 这可能会造成重大的安全风险.在这种情况下, 攻击者可以修改用户输入的数据, 甚至对数据库服务器执行任意 SQL 命令.例如,当您使用以下连接字符串时 ...

  4. 简而意赅 HTTP HTTPS SSL TLS 之间有什么不同

    HTTP HTTPS SSL TLS 之间有什么不同? SSL是Secure Sockets Layer的缩写.SSL的作用是为网络上的两台机器或设备提供了一个安全的通道. TLS是SSL的一个新的名 ...

  5. HTTPS详解二:SSL / TLS 工作原理和详细握手过程

    HTTPS 详解一:附带最精美详尽的 HTTPS 原理图 HTTPS详解二:SSL / TLS 工作原理和详细握手过程 在上篇文章HTTPS详解一中,我已经为大家介绍了 HTTPS 的详细原理和通信流 ...

  6. 跟我一起学Go系列:Go gRPC 安全认证机制-SSL/TLS认证

    Go gRPC 系列: 跟我一起学Go系列:gRPC 拦截器使用 跟我一起学Go系列:gRPC 入门必备 第一篇入门说过 gRPC 底层是基于 HTTP/2 协议的,HTTP 本身不带任何加密传输功能 ...

  7. .NET Core下使用gRpc公开服务(SSL/TLS)

    一.前言 前一阵子关于.NET的各大公众号都发表了关于gRpc的消息,而随之而来的就是一波关于.NET Core下如何使用的教程,但是在这众多的教程中基本都是泛泛而谈,难以实际在实际环境中使用,而该篇 ...

  8. 协议森林17 我和你的悄悄话 (SSL/TLS协议)

    作者:Vamei 出处:http://www.cnblogs.com/vamei 转载请先与我联系. TLS名为传输层安全协议(Transport Layer Protocol),这个协议是一套加密的 ...

  9. 好程序员带你了解一下HTTPS和SSL/TLS协议的背景与基础

    >> 相关背景知识 要说清楚 HTTPS 协议的实现原理,至少需要如下几个背景知识. 大致了解几个基本术语(HTTPS.SSL.TLS)的含义 大致了解 HTTP 和 TCP 的关系(尤其 ...

随机推荐

  1. linux命令之------rm命令

    rm命令 1)    作用:用于删除一个文件或者目录: 2)    -i:删除前逐一询问确认: 3)    -f:即使原档案属性设为只读,亦直接删除,无需逐一确认: 4)-r:将目录及以下之档案亦逐一 ...

  2. X86 下的SSDT HOOK

    目录 SSDTHOOK 1.SSDTHOOK 原理. 1.x32下的SSDT HOOK 2.SSDT HOOK代码 3.结果 4.总结 SSDTHOOK 1.SSDTHOOK 原理. x32下,直接获 ...

  3. Spring通知,顾问,增强

    1.AOP  (Aspect  Oriented Programming  面向切面编程) 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编 ...

  4. 一个bug程序员的入园

    大家好,我叫dg是一个只写bug的程序员.当然只写bug也是有好处的,那就是踩过的坑多了,摔的跟斗多了,并且没有被摔死,勇敢的活了下来,练就了一身钢筋铁骨.哈哈,开个玩笑.但是猜的坑多了就知道了哪里有 ...

  5. module 'torch' has no attribute 'gesv'

    新版torch不支持gesv,使用solve函数. Kt, _ = torch.gesv(P.mm(H.t()).t(), S) 改成 Kt, _ = torch.solve(P.mm(H.t()). ...

  6. Eclipse4.9集成Tomcat 9.0.21详细版

    1.下载Tomcat 从Tomcat官网下载:https://tomcat.apache.org 此处我下载的版本是Tomcat 7.0.94 下载完毕后解压即可,我解压后的路径是D:\soft\ap ...

  7. 市值TOP10,人类进化及中美坐标

    题记:观察人类进化,以及各国.各民族在这个进化中所起的作用.所处的位置,市值 TOP 10 的变迁,会是一个再好不过的指标! 2008年,经历了全球金融危机后,原油期货一路飙升,创出了147.27美元 ...

  8. 【技术博客】Pytorch代码生成

    开发组在开发过程中,都不可避免地遇到了一些困难或问题,但都最终想出办法克服了.我们认为这样的经验是有必要记录下来的,因此就有了[技术博客]. Pytorch代码生成经验文档 关于模型代码的生成,主要思 ...

  9. Object changed by Unknown

    https://documentation.red-gate.com/soc7/troubleshooting/object-changed-by-unknown https://documentat ...

  10. SVN提示is already locked 解决办法

    当svn提示is already locked ,反复clean up也无用, 可以在cmd下进入到目标文件夹的目录 执行svn cleanup 等待执行成功,就可以update了