RPC框架设计的安全性考量

简介: RPC里面该如何提升单机资源的利用率,你要记住的关键点就一个,那就是“异步化”。调用方利用异步化机制实现并行调用多个服务,以缩短整个调用时间;而服务提供方则可以利用异步化把业务逻辑放到自定义线程池里面去执行,以提升单机的OPS。

RPC里面该如何提升单机资源的利用率,你要记住的关键点就一个,那就是“异步化”。调用方利用异步化机制实现并行调用多个服务,以缩短整个调用时间;而服务提供方则可以利用异步化把业务逻辑放到自定义线程池里面去执行,以提升单机的OPS。


1 为何要考虑安全问题?

RPC是解决应用间互相通信的框架,而应用之间的远程调用过程一般不会暴露在公网,RPC一般用于内部应用通信。


“内部”指应用都部署在同一大局域网。相对公网环境,局域网隔离性更好,相对安全,所以在RPC里很少考虑数据包篡改、请求伪造等。


那RPC里应关心什么安全问题?


2 完整的RPC应用流程

先由Provider定义好一个接口,并把这个接口的Jar包发布到私服,然后在项目中实现这接口,最后通过RPC API把这接口和其对应实现类完成对外暴露,若是Spring应用,直接定义成一个Bean即可。至此,服务提供方就完成了一个接口的对外发布。


对服务调用方就更简单,只要拿到刚才上传到私服的Jar坐标,就可把发布到私服的Jar引入项目,借助RPC动态代理功能,服务调用方直接就可在项目完成RPC调用。


安全隐患

因为私服上所有Jar坐标所有人都可看到,只要拿到Jar坐标,就可将发布到私服的Jar引入项目,完成RPC调用了吗?公司内部这种不向服务提供方咨询就直接调用的行为很少发生,一般真实业务的接口出入参数都不太简单,这样不经过咨询只靠调用方自己猜测完成调用的工作效率实在太低。


虽然这种靠猜测调用的概率很小,但当调用方在其它新业务场景要用之前项目中使用过的接口,很可能真的不跟服务提供方打招呼就直接调用。这行为对Provider很危险,因为接入新调用方就意味着承担的调用量变大,有时可能新增的调用量会成为Provider的“最后一根稻草”,导致Provider无法正常提供服务,还不知道是被谁给压垮的。


可通过公司严格流程让研发达成“君子约定”,即在应用里每次要用一个接口时,须先向服务提供方报备,这确实能在很大程度避免。但就RPC本身,可提供某种功能来解决这种问题呢?毕竟对人数多的团队,口头约定不能彻底杜绝这类问题。


3 调用方之间的安全保证

根本原因就是服务提供方收到请求后,不知道这次请求是哪个调用方发起的,没法判断这次请求是属于之前打过招呼的调用方还是没有打过招呼的调用方,所以也就没法选择拒绝这次请求还是继续执行。


只需给每个调用方设定一个唯一身份,每个调用方在调用前都先来服务提供方这登记身份,只有登记过的调用方才能继续放行,没有登记过的调用方一律拒绝。


好比坐火车凭身份证购买火车票,买票成功就类似服务调用方去服务提供方进行登记。当你进站准备上火车,须同时出示你的身份证和火车票,这两个就是代表你能上这趟火车的“唯一身份”,只有验证身份,负责检票的工作人员才会让你上车,否则拒乘。


4 RPC里的实现

先要有个可供caller进行调用接口登记的地方,“授权平台”,caller可在授权平台上申请自己应用里要调用的接口,而provider在授权平台进行审批,只有服务提供方审批后调用方才能调用。但这解决调用数据收集的问题,并没有完成真正授权认证功能,缺少一个检票环节。


搭建了授权平台,而且接口的授权数据也在这平台,可将检票环节放到授权平台。caller每次发起业务请求时,先去发一条认证请求到授权平台:“hello,我能调用这个接口吗?”


只有授权平台返回:“sure”,才继续把业务请求发到provider。


4.1 集中式认证流程


1111.png

@startuml

title:集中式认证流程


participant 调用方 as 调用方

participant 授权平台 as 授权平台

participant 提供方 as 提供方


调用方 -> 授权平台++ : 我们调用 x 接口吗?

授权平台 --> 调用方-- : sure!


调用方 -> 提供方++ : 真实业务请求

提供方 --> 调用方-- : 返回结果


@enduml


这种设计没问题,整个认证过程对RPC使用者透明。问题是这授权平台承担公司内所有RPC请求的次数总和,当公司内部RPC使用程度高了,这授权平台就会成为性能瓶颈,须保证高可用。


如何优化呢?是否不需要把这认证逻辑放到业务请求过程,而是挪到初始化过程?确实可很大程度减少授权平台压力,但本质无变化,还是集中式授权平台。


5 更优方案

caller能否调相关接口,由provider说了算,就可将检票过程放到provider。在caller启动初始化接口时,带上授权平台上颁发的身份去provider认证下,当认证通过后,就认为这接口可调。


provider验票时,对照的数据来自哪儿,不能又去请求授权平台吧?


不可逆加密算法

如HMAC。provider应用里放个用于HMAC签名的私钥,在授权平台上用这私钥为申请调用的调用方应用进行签名,这签名生成的串就变成caller唯一身份。


provider收到caller的授权请求后,只需验证这个签名跟调用方应用信息是否对应得上,这样集中式授权瓶颈就不存在了。


HMAC来做认证,服务提供方是使用 “公钥” 验证服务调用方的签名串。事先要生成公私钥。


6 服务发现也有安全问题?

解决了调用方之间的安全认证问题。还有其它安全问题吗?


服务提供方会把接口Jar发布到私服,以方便调用方能引入项目快速完成RPC调用,可能有人拿到Jar后,发布出来一个服务提供方呢?导致调用方通过服务发现拿到的服务提供方IP地址集合里有那个伪造的提供方。


解决这个问题的根本:要把接口跟应用绑定,一个接口只允许有一个应用发布提供者,避免其它应用也能发布该接口。


实现

服务提供方启动时,把接口实例在注册中心登记。


可利用这流程,注册中心在收到服务提供方注册请求时,验证请求过来的应用是否跟接口绑定的应用一样,只有相同才允许注册,否则返回错误信息给启动的应用,避免假冒的服务提供者对外提供错误服务。


7 总结

RPC常用于解决内网应用之间的调用,内网环境相对公网也没有那么恶劣,也要去建立一套可控的安全体系,去防止一些错误行为。


对RPC,我们所关心的安全问题不会有公网应用那么复杂,我们只要保证让服务调用方能拿到真实的服务提供方IP地址集合,且服务提供方可以管控调用自己的应用就够了。


8 FAQ

前面讲的调用方之间的安全问题,我们更多只是解决认证问题,并没有解决权限问题。一个RPC接口定义里面包含多个方法,目前只是解决你能不能调用接口,并没有解决你能调用我接口里面的哪些方法,如何解决?


订单中间件,提供服务防止未知系统任意调用,服务调用管理功能,到方法级:


提供服务调用的申请模板,描述那个系统,那个应用,调用我们那个服务的那个方法,调用量多少,调用应用负责人是谁,对接研发谁,还有别的配置信息

把调用配置信息落库,然后放入缓存,使用调用者信息及我们提供服务的信息组成key,放入redis

调用方调用我们时,去做拦截和鉴权

统一部署平台中有系统和应用的唯一标识信息,这些信息在调用接口时作为入参的一部分,就能实现细粒度到方法基本的控制

另外,就是使用token,也是申请时分发,本质一样的,就看对应的配置信息存储在哪里。


服务端提供的安全校验方式

md5摘要校验

安全级别较低,服务端直接提供或者网关代劳。


非对称加密算法

签名(RSA和HMAC等算法,服务端直接提供或者网关代劳。


Oauth2授权

有单独的授权服务,四种模式。


觉得rpc好像跟k8s有点像,k8s是类似把一个大服务拆分成很多模块,完了之后来把这些微服务管理起来,而rpc是提供了一系列接口,通过网络的方式,让各个调用方去调用。


k8s可以看做rpc升级版本。


可以从鉴权和授权2个方面来看(参考k8s):


鉴权可以用 token 的方式,token鉴权应该是目前用的最多的一种认证方式

授权可以用 RBAC 方式,类似k8s里面的 serviceAccount 和 role 和 roleBinding 等

认证和授权一般都是同时使用。


我们之前是用的配置中心来存储对应的关系,B服务可以被那些服务调用或者不可以被那些服务调用,同时,也有B服务的接口权限,然后内部网关同步相关信息,保存到内存缓存中,当调用方请求经过网管时,获取调用方,服务方,服务方具体的接口,然后去校验相关的信息,判断是否可以放行,我们的鉴权没有放在服务方本身去实现,是在网关实现的。


前提就是怎么识别调用方的身份,比如应用id。


请问服务提供方对服务调用方的授权认证后,已认证的状态应该存在服务提供端本地吧,那服务端集群中各个节点之间怎么共享同一个服务调用方应用的认证状态呢?还是说每次调用到不同的的服务提供方节点都需要从新进行鉴权?或者说是服务调用方在获取到服务提供方的IP列表后统一进行一次遍历的授权认证?


每个节点都得鉴权一次。


RPC可以用于公网通信吗?鉴权放在服务端对服务端的压力是不是也挺大的?


公网一般比较少,鉴权只要一次开销,压力还是可控的。


这种授权方式,对于调用方而言,加密后的签名怎么维护呢,感觉有代码侵入呀?


统一授权平台上获取。


首先肯定是在服务端做,其次是应该在每一个服务提供端对其接口做权限审核,假如一个服务端提供10个接口出来,5个可以被A调用,另外5个不能被A服务调用,那么就应该有个配置文件配置这调用端和服务端各个接口的权限配置信息,这个权限配置应该放在配置中心,然后每个服务端会动态获取配置信息根据配置信息来决定是否拒绝服务。对于新增的调用服务,它需要先申请权限,然后服务端提供方修改配置文件对其提供服务。


这也是一种思路。


权限控制应放在服务提供方,权限控制规则可以放到单独管理节点,服务启动的时候从管理节点获取规则,权限规则变更后下发到服务节点。


这有一个前提就是统一调用方身份的问题,规则里面是按照什么对象来识别身份。


进行接口授权的同时也进行接口方法的授权。


授权和认证都需要考虑。


相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
目录
相关文章
|
8月前
|
负载均衡 Dubbo Java
Dubbo 3.x:探索阿里巴巴的开源RPC框架新技术
随着微服务架构的兴起,远程过程调用(RPC)框架成为了关键组件。Dubbo,作为阿里巴巴的开源RPC框架,已经演进到了3.x版本,带来了许多新特性和技术改进。本文将探讨Dubbo 3.x中的一些最新技术,包括服务注册与发现、负载均衡、服务治理等,并通过代码示例展示其使用方式。
420 9
|
8月前
|
JSON 负载均衡 网络协议
Rpc编程系列文章第二篇:RPC框架设计目标
Rpc编程系列文章第二篇:RPC框架设计目标
|
8月前
|
设计模式 负载均衡 网络协议
【分布式技术专题】「分布式技术架构」实践见真知,手把手教你如何实现一个属于自己的RPC框架(架构技术引导篇)
【分布式技术专题】「分布式技术架构」实践见真知,手把手教你如何实现一个属于自己的RPC框架(架构技术引导篇)
308 0
|
8月前
|
Dubbo Java 应用服务中间件
Rpc编程系列文章第三篇:Hessian RPC一个老的RPC框架
Rpc编程系列文章第三篇:Hessian RPC一个老的RPC框架
|
2月前
|
自然语言处理 负载均衡 API
gRPC 一种现代、开源、高性能的远程过程调用 (RPC) 可以在任何地方运行的框架
gRPC 是一种现代开源高性能远程过程调用(RPC)框架,支持多种编程语言,可在任何环境中运行。它通过高效的连接方式,支持负载平衡、跟踪、健康检查和身份验证,适用于微服务架构、移动设备和浏览器客户端连接后端服务等场景。gRPC 使用 Protocol Buffers 作为接口定义语言,支持四种服务方法:一元 RPC、服务器流式处理、客户端流式处理和双向流式处理。
|
5月前
|
Dubbo 网络协议 Java
RPC框架:一文带你搞懂RPC
这篇文章全面介绍了RPC(远程过程调用)的概念、原理和应用场景,解释了RPC如何工作以及为什么在分布式系统中广泛使用,并探讨了几种常用的RPC框架如Thrift、gRPC、Dubbo和Spring Cloud,同时详细阐述了RPC调用流程和实现透明化远程服务调用的关键技术,包括动态代理和消息的编码解码过程。
RPC框架:一文带你搞懂RPC
|
4月前
|
XML 负载均衡 监控
分布式-dubbo-简易版的RPC框架
分布式-dubbo-简易版的RPC框架
|
7月前
|
存储 缓存 Linux
【实战指南】嵌入式RPC框架设计实践:六大核心类构建高效RPC框架
在先前的文章基础上,本文讨论如何通过分层封装提升一个针对嵌入式Linux的RPC框架的易用性。设计包括自动服务注册、高性能通信、泛型序列化和简洁API。框架分为6个关键类:BindingHub、SharedRingBuffer、Parcel、Binder、IBinder和BindInterface。BindingHub负责服务注册,SharedRingBuffer实现高效数据传输,Parcel处理序列化,而Binder和IBinder分别用于服务端和客户端交互。BindInterface提供简单的初始化接口,简化应用集成。测试案例展示了客户端和服务端的交互,验证了RPC功能的有效性。
451 8
|
5月前
|
XML 存储 JSON
(十二)探索高性能通信与RPC框架基石:Json、ProtoBuf、Hessian序列化详解
如今这个分布式风靡的时代,网络通信技术,是每位技术人员必须掌握的技能,因为无论是哪种分布式技术,都离不开心跳、选举、节点感知、数据同步……等机制,而究其根本,这些技术的本质都是网络间的数据交互。正因如此,想要构建一个高性能的分布式组件/系统,不得不思考一个问题:怎么才能让数据传输的速度更快?
125 1
|
6月前
|
分布式计算 负载均衡 数据安全/隐私保护
什么是RPC?有哪些RPC框架?
RPC(Remote Procedure Call,远程过程调用)是一种允许运行在一台计算机上的程序调用另一台计算机上子程序的技术。这种技术屏蔽了底层的网络通信细节,使得程序间的远程通信如同本地调用一样简单。RPC机制使得开发者能够构建分布式计算系统,其中不同的组件可以分布在不同的计算机上,但它们之间可以像在同一台机器上一样相互调用。
171 8