cephx: ceph的认证和加密协议

Ceph作为一个分布式存储系统,支持对象存储、块设备和文件系统。为了在网络传输中防止数据被篡改,做到较高程度的安全性,加入了Cephx加密认证协议。其目的是识别身份,加密、验证传输中的数据。

在ceph系统中,元数据保存在一个叫做ceph-mon的进程中,也可以称为monitor节点,系统可以有多个monitor副本节点,用paxos保持数据一致性。 这里不谈paxos,也不谈多个monitor节点,我们只以单个monitor为例,重点说明cephx的实现。

monitor保存了系统中重要的元数据,例如每个用户的key以及权限,这也是我们要重点谈及的,至于其他osdmap, crush数据在这里不涉及。

一个ceph系统主要由monitor, osd, client 这几种类型的节点组成。monitor存放元数据,osd存放对象,client就是使用ceph系统的客户端。

一个monitor里存放着和认证相关的数据,简单可以用表结构来描述:


名称


key


Caps(权限)


client.admin


xxxxxxyyyyy


osd allow rw, mon allow rw


osd.1


aaaaaaaaaaaaa


osd allow rw


osd.2


bbbbbbbbbbbbb


osd allow rw

client和osd 必须先连接到monitor进行认证。client和osd都有一个叫做monclient的模块负责认证和密钥交换。而monitor上有一个AuthMonitor的paxos服务模块负责与monclient对话,cephx协议的实现则位于ceph源代码目录src/auth/cephx,有好几个模块负责。

 

Cephx是一种对称密钥加密协议,加密算法使用AES,并包含临时密钥生成和替换。每个client和osd都在本地有一个密钥,该密钥的副本同样存在于monitor上。

Ceph里面每一个节点都会使用一个名称,类型是EntityName, 例如:client.admin, osd.1等。而每一个节点连接到monitor以后,monitor都会为其生成一个global id,代表这个节点在整个ceph 系统中的全局id。

monclient连接monitor的会话是为了获得session key、ticket以及临时密钥(rotating key)。

ceph 系统里面有auth认证服务,osdmap服务,还有文件系统的mds服务等。当节点之间彼此通讯时,刚连接开始时,使用ticket表明身份,使用rotating key加密加密解密ticket和session key, 验明身份后,后续通讯使用session key加、解密数据包。

在monclient里,对每一种服务monclient都保存有从monitor获得的数据:与某类型节点网络连接时的session key,与某类型节点网络连接对应的ticket, 与该种服务对应的rotating key.


cephx认证大致步骤如下:

monclient向monitor 发起连接,获得与monitor 通讯时的AUTH service的session key以及ticket。

认证信息是以后通讯中识别身份的凭据,其结构如下:

struct AuthTicket {

EntityName name;

uint64_t global_id; /* global instance id */

uint64_t auid;

utime_t created, renew_after, expires;

AuthCapsInfo caps;

__u32 flags;

};

内容依次是发起连接的实体名称,全局id、 用户id、一些和ticket生存周期有关的时间,以及权限。

struct CephXServiceTicketInfo {

AuthTicket ticket;

CryptoKey session_key;

};

 

我们在这里称CephxServiceTicketInfo为ticket,它包含认证信息以及session key。

通过了与monitor的认证以后,client就可以从monitor获取与每一种service类型的相关的session key 和ticket,例如与osd服务和mds服务相关的session key和ticket, ticket的name和global_id,auid是相同的,其他存活期时间信息和权限则是不同的,client在每一种service上可以有不同的权限。其中ticket数据对client是透明的,是被相关service的临时密钥加密的,其内容只有monitor和相关的service会去解密。

对于每一种service,它们的monclient除了上面的内容,还会定时从monitor获取它们自身这种service相关的临时密钥,主要数据结构如下:

一个会过期的密钥:

struct ExpiringCryptoKey {

CryptoKey key;

utime_t expiration

};

 

一个对过期密钥的管理器:

struct RotatingSecrets {

map<uint64_t, ExpiringCryptoKey> secrets;

version_t max_ver;

};

管理器包含3个密钥,依次是过去的、现在的和将来的,map的key是一个临时密钥id (称为secret id), 每次往里面添加一个密钥,max_ver增加1,并且把最前面个一密钥删除,始终保持3个密钥,所以每次增加一个密钥,他们的secret id都比以前的大,这样就不存在secret id重复。

当client准备发起对osd的访问时,就用对应的osd service的ticket去访问osd, osd服务则用从monitor得到的临时密钥解密ticket,验证其身份,然后从ticket取出session key, 因为客户端已经有session key, 这样双方就有了相同的session key,以后通讯时client和osd就用这个密钥加密和解密数据包,来验证数据的正确性。只要连接没有断开,session key就保持不变。

 

cephx认证具体步骤如下:

monclient和monitor的会话:

 

Step 1:

monclient: 发送 { protocol: 0, entity name, global id: 0 }

monintor: 保存entity name, 生成并保存64bit server challenge,

并把 server challenge 发送给对方。

 

Step 2:

monclient: 生成一个64bit client challenge, 用本地盘上的密钥把server challenge和client challenge加密后,再用64比特为单位混淆生成一个64bit key, 并发送请求:

{ CEPHX_GET_AUTH_SESSION_KEY, client challenge, key, old ticket }

注意(第一次连接开始old ticket为无效数据)

 

monitor 接收到CEPHX_GET_AUTH_SESSION_KEY请求, 把得到的client challenge和存在自己内存里的server challenge用client对应的key加密后混淆生成一个64bit key, 并与传过来的key比较,如果不相等,则认证不通过。 (注意,monitor在自身数据库存有对方的key) ,解密传过来的old ticket, 得到 CephXServiceTicketInfo结构。从密钥库取出client对应的身份信息(密钥,权限)。 生成新的ticket: (创建的时间,存活时间,global id, auid) ,生成与本monserver对话的session key, 从keystore获取对应于AUTH service 的临时密钥rotating key(secret 密钥, secret id密钥id).

 生成CephXServiceTicket结构(session key, ticket的存活时间), 用client在密钥库中的密钥加密。生成 CephXTicketBlob, 其中包含临时密钥secret id 和 CephXServiceTicketInfo, 而CephxServiceTicketInfo包含 : (session key, ticket, 权限),其中CephxServiceTicketInfo用对应的临时密钥secret加密。注意Client不在乎ticket是什么内容,因为这个作为一张票子是给通讯对方的,自己并不需要解释什么。如果上次成功解密 old ticket info,则使用old tick info中的session key加密整个CephXTicketBlob结构。

 

把经过上述处理后的CephxServiceTicket和CephxTicketBlob一起发送给monclient。

 

Step 3:

monclient 用自身本地盘上的密钥解密 CephxServciceTicket,在获得CephxTicketBlob时,如果CephxTicketBlob是经过加密的,则用客户端当前的session key解密CephxTicketBlob。

保存CephxServiceTicket中的session key为最新的session key,保存CephXServiceTicket中session key的存活时间。

lient 如果需要其他服务的密钥,则发起CEPHX_GET_PRINCIPAL_SESSION_KEY请求。

 首先生成内容HEADER, 包括(global id, service id, CephxServiceTicketBlob),其中service id就是AUTH认证服务的id,然后生成CephXServiceTicketRequest结构, 内容包括bitmask,每一位代表一种服务类型,例如位掩码中可以包含OSD, MDS。

生成CephXAuthorize结构, 内容包含随机数nonc,并用session key 加密CephxAuthorize.

 

monclient发送:Header 、 CephxAuthorize 、 CephxServiceTicketRequest。

 

Monitor读取Header, CephxServiceTickBlob,用CephxServiceTicketBlob中指定的secret id,从内存中获得临时密钥secret,用secret解密CephxServiceTicketBlob, 获得CephXServiceTicketInfo, 检验Header中的global id是否和CephxServiceTickeInfo中的global id相同,不相同就失败。

用CephxServiceTicketInfo中的session key解密CephxAuthorize.

生成CephXAuthorizeReply , 内容包含CephxAuthoriz的nonce +1.

解码 CephxServiceTicketRequest, 对其中的bitmask对应的每一种service,过程如下:

 

生成与该服务对话的session key

从keystore获取对应于该service的临时密钥(secret, secret id).

生成 CephXServiceTicket(session key, ticket的存活时间),

用刚才解密的CephxServiceTicketInfo中的session key加密之。

 

生成 CephXTicketBlob, 其中包含 (secret id 和 CephXServiceTicketInfo)

而CephXServiceTicketInfo代表代表一张票子(ticket), 其中包含 : (刚才生成的与该service对话的session key, ticket, 权限),其中CephxServiceTicketInfo用服务对应的临时密钥secret加密. ticket继承了step 2中的大部分内容,但是权限项目是对应的service中该client的权限。使用解密的CephxServiceTickt中的session key加密整个CephXTicketBlob.

把经过上述处理后的CephxServiceTicket和CephxTicketBlob一起发送给client.

 

monclient:对每一种service服务,过程如下:

用与monitor对话的session key解密CephxServciceTicket,如果CephxTicketBlob时经过密钥

加密的,则用这个session key解密CephxTicketBlob。保存CephxServiceTicket中的session key为最新的session key,保存CephXServiceTicket中session key的存活时间。

client 与 osd会话的建立:

ceph 使用消息通讯机制,其中messenger模块负责通讯,以simple messenger为例:

起实现通讯的代码位于src/msg/simple/Pipe.cc中,例如当发起一个连接时,Pipe::connect被调用,执行开始就区获得一个认证信息:

get_authorizer最终会执行到Client的代码中:

而build_authorizer最后会执行到CephxTicketManager中,该代码取出对应于某service的认证处理代码:

 

而该处理程序则提供认证信息:

我们看到它主要是打包global_id, service id 以及ticket和一个随机数,然后用session key加密。

以上时连接方发起的,下面看接收连接方时如何工作的:
接收连接方的入口在src/msg/simple/Pipe.cc的accept()函数:

而vierfy_authorizer函数最终会执行到:

我们看到这个函数最终获得对方的caps_info也即权限信息,对方的名称,对方的全局id, 对方的session_key,以及uid.

而cephx_verify_authorizer做了什么? 它用get_service_secret(service_id, ticket.secret_id, service_secret)得到临时密钥,然后decode_decrypt_enc_bl(cct, ticket_info, service_secret, ticket.blob, error)把票子解密。检验票子中的global id是否和明文发送过来的global id相同,不相同就会返回失败。

最后它做一些nonce的解密,这不太重要,没有什么信息量。

双方握手成功后,都会创建一个消息处理器,主要起到数据报的加密和检验。

以后双方发送数据都用sign_message签名:

而当前cephx 的sign_message依赖crc数据,只使用头尾几个crc字段来计算签名:

而接收数据方调用check_message_signature来验证签名:

时间: 2024-09-28 13:29:56

cephx: ceph的认证和加密协议的相关文章

Ceph实验室:第二课:集成ceph与openstack

本课程介绍如何配置ceph作为Nova的后端存储,用来存放vm的临时磁盘. 集成ceph与Openstack Nova 安装ceph客户端集成ceph与Openstack的第一步就是要在openstack的节点上安装ceph客户端(一些ceph命令行工具和连接ceph集群需要的libraries). $ ceph-deploy install --cli --no-adjust-repos openstack $ ceph-deploy config push openstack 创建pool

Ceph cluster configure introduce - 1

ceph存储集群运行需要osd和mon模块, 如果要使用对象存储, 需要添加radosgw模块, 如果需要使用ceph 文件系统需要添加mds模块. 这些模块在启动时, 需要读取配置文件, ceph所有类型的daemon配置文件统一放在一个配置文件中, 配置文件的顺序如下 : The default Ceph configuration file locations in sequential order include: $CEPH_CONF (i.e., the path following

ceph install in CentOS 7 x64 within docker - 3

部署ceph cluster的第一步是部署monitor节点, 本例我们使用3台monitor. 并且monitor之间使用cephx认证. INSTALL CEPH STORAGE CLUSTER 1. 安装yum-plugin-priorities  (所有节点) [root@deploy yum.repos.d]# su - ceph [ceph@deploy ~]$ ssh 172.17.0.1 sudo yum install -y yum-plugin-priorities [cep

Ceph cluster configure introduce - 2

一般配置 : 初始化时的监控节点配置, 包含(非FQDN)hostname -s, IP. [global] mon_initial_members = ceph1 mon_host = 10.0.0.1 如果是手工部署, 可以写3个mon节点的信息, 如 : mon initial members = mon1, mon2, mon3 mon host = 172.17.0.2, 172.17.0.3, 172.17.0.4 如果是使用chef, ceph-deploy来配置, 建议配置时只使

openstack 与 ceph (osd 部署)

当 monitor 运行后, 你需要添加 OSD, 你的集群只有在获得足够的 OSD 数量用于复制对象时候才可能获得 active + clean 状态 例如 osd pool size = 2, 那么至少需要 2 个 OSD, 在启动 MONITOR 后,你的集群具有默认的 CURSH MAP, 当前 CURSH MAP 并没有 CEPH OSD 进程映射到 CEPH 节点 CEPH 提供 CEPH-DISK 工具, 可以准备一次磁盘, 分区或者目录用于 CEPH, ceph-disk 工具通

ceph GLOSSARY

ceph文档里术语较多, 为了方便理解, 最好先了解一下ceph的术语. 以下摘自ceph doc, 少了PG. PG placement group      PG, 存储 object 的逻辑组. PG存储在OSD中. OSD包含journal和data. 写完journal后返回ack确认数据安全性.      一般journal使用SSD来存储, 需要高的响应速度(类型postgresql xlog)      Ceph stores a client's data as objects

PHP 5 连接 mysql 5 的认证协议问题

mysql|问题 MYSQL 4.1以后, 采用了一种新的用户认证协议, 对于老的客户端会出现不支持认证协议的错误, 以下是官方网站的解决方法﹔ 1Upgrade all client programs to use a 4.1.1 or newer client library. 更新客户端库,这需要更新PHP的扩展库,对于老的api PHP已经不提供了这样的扩展库了 2When connecting to the server with a pre-4.1 client program, u

PHP5连接Mysql5的认证协议问题

mysql|php5|问题 MYSQL 4.1以后, 采用了一种新的用户认证协议, 对于老的客户端会出现不支持认证协议的错误, 以下是官方网站的解决方法﹔ 1Upgrade all client programs to use a 4.1.1 or newer client library. 更新客户端库,这需要更新PHP的扩展库,对于老的api PHP已经不提供了这样的扩展库了 2When connecting to the server with a pre-4.1 client progr

nginx配置ssl加密(单/双向认证、部分https)

nginx下配置ssl本来是很简单的,无论是去认证中心买SSL安全证书还是自签署证书,但最近公司OA的一个需求,得以有个机会实际折腾一番.一开始采用的是全站加密,所有访问http:80的请求强制转换(rewrite)到https,后来自动化测试结果说响应速度太慢,https比http慢慢30倍,心想怎么可能,鬼知道他们怎么测的.所以就试了一下部分页面https(不能只针对某类动态请求才加密)和双向认证.下面分节介绍. 默认nginx是没有安装ssl模块的,需要编译安装nginx时加入--with