说到RPC,不得不说下IPC,也就是进程间调用,如何在两个进程之间传输数据的问题。
两个进程可以是独立进程各自互不影响各自有自己的内存空间。
也可是是父子之类的进程。
IPC有如下方式
1.共享内存
2.信号量
3.消息队列
4.pipe-(又分匿名,有名)
pipe在windows中被看作文件对象,访问方式和文件一样。其安全性在于创建的时候指定安全的ACL
远程访问pipe的时候由于pipe被当作对象,可以经由SMB协议访问该文件。
SMB访问的时候可以提供用户认证,pipe本身没有用户鉴别功能,借助于SMB达到认证之后靠ACL来授权
那么RPC又是个什么东西。
RPC服务器需要注册接口,定义底层是什么传输协议,客户端是如何区分不同RPC服务器和某个节点上有哪些RPC服务呢,是如何调用的呢。
答案是类似域名工作一样。
RPC server注册一个UUID跑到endpoint maper上,client查询endpoint maper查到特定UUID和其服务,安装规定格式传输参数,等待答复并解包。服务器端获取参数,并回复结果。
底层协议可以是如下:
- ncacn_ip_tcp needs a TCP port number, e.g. 9999
- ncacn_np needs a Named Pipe name, e .g. “\pipe\FRPC-NP”
- ncalrpc needs an ALPC port name, e.g. “\RPC Control\FRPC-LRPC”
RPC也和pipe一样达到进程间通信的目的。但是又不同,RPC会指定数据的格式和返回方式。
而pipe可以理解为文件,可以读写任意格式的数据。
所以RPC可以建立在name pipe之上。将name pipe作为一个数据媒介来使用。
如下图:RPC当然也可以之间基于HTTP,将数据依靠HTTP传输。或者直接基于更底层的TCP/IP也是可以的。
基于named pipe的RPC调用如下:
那么这个binding是什么东西呢
当客户端连接到服务器的时候,如果啥也不指定,那么就是匿名访问或者未授权的访问。
服务器端无法知道是谁在访问。
可以有以下方式实现授权访问:
1.服务器端注册RPC interface的时候设置一个标记说明访问限制,例如可以设置标记
RPC_IF_ALLOW_LOCAL_ONLY
只允许本地访问。
2.服务器端注册RPC interface的时候设置一个回调函数,例如可以写一个回调函数用于基于IP来授权访问。
3.同1一样,不过标记设置为RPC_IF_ALLOW_SECURE_ONL.
同时服务器端和客户端都需要设置认证信息
服务器端:
RPC_STATUS rpcStatus = RpcServerRegisterAuthInfo( pszSpn, // Server principal name RPC_C_AUTHN_WINNT, // using NTLM as authentication service provider NULL, // Use default key function, which is ignored for NTLM SSP NULL // No arg for key function );
客户端:
RPC_STATUS status = RpcBindingSetAuthInfoEx( hExplicitBinding, // the client's binding handle pszHostSPN, // the server's service principale name (SPN) RPC_C_AUTHN_LEVEL_PKT, // authentication level PKT RPC_C_AUTHN_WINNT, // using NTLM as authentication service provider NULL, // use current thread credentials RPC_C_AUTHZ_NAME, // authorization based on the provided SPN &secQos // Quality of Service structure );
client端的secQos可以指定用户扮演的程度
对于安全问题。RPC是什么机制呢?