经过本系列前六篇文章的分布式特性介绍,相信大家已经了解了 OBProxy 在 OceanBase 数据库整体架构下的作用。本篇文章我们将换一个视角,介绍一些偏“中间件”的功能:安全、协议和监控功能。 进入【OBProxy 专题】 可查看系列内容。
从 OBProxy 整体来看,安全、协议和监控属于产品层,因此更加贴近用户和开发者,大家了解起来比较容易,我们用一篇文章来统一介绍。
1. 安全功能
OBProxy 的安全功能和 OBProxy 的使用场景相关。OBProxy 作为 OceanBase 数据库服务接入层和路由层,涉及到的安全包括:
- 登录安全。通过密码认证、IP白名单、连接数控制等保证登陆安全。
- 传输安全。通过SSL加密保证数据传输安全。
下面,我们将对这两方面展开详细介绍。
1.1 登录安全
1.1.1 密码认证
当用户登录发送用户名和密码给 OBProxy 后,OBProxy不做认证,直接转发给 OBServer 认证。这样 OBProxy 实现简单,也不存在泄漏密码风险。流程如下:
让用户管理密码增加了用户负担和密码泄漏风险。随着云服务的普及,用户可以不管理密码,只需要提供可信的身份认证信息就可以了,OBProxy 在蚂蚁内部做了类似功能,举个例子:
App 和 OBProxy 部署在同一个 k8s 的 安全 POD 内,OBProxy 信任App,App访问数据库,只需要传输用户名,不传输密码,OBProxy 向KMS(密钥管理服务)请求对应用户名的密码,和 OBServer 登录认证时传输用户名和从 KMS 获取到的密码。这样的好处有两点:
- App 的代码或者配置文件不需要保存密码,减轻用户负担。
- 数据库不需要改造,整个流程对数据库都是透明的。
此外,在使用 OBProxy 时,有两个账号大家需要特殊关注下:
- proxyro@sys账号:OBProxy 访问 OB 数据库元数据的账号,安全起见,用户无法通过该账号连接 OBProxy。
- root@proxysys账号:OBProxy 的管理员账号,可以查询 OBProxy 内部状态、修改配置等。
这两个密码大家在一些文档和部署配置中应该见过,经过这次讲解大家应该就熟悉了。
1.1.2 IP白名单
IP白名单指允许访问 OceanBase 集群的IP列表,默认为空,表示都允许访问。OBProxy 的白名单有以下特点:
- 支持指定IP和指定网络号两种方式设置IP。如 192.168.2.2和192.168.0.0/16
- 支持设置租户级别、集群级别和全局级别白名单,优先级为租户级别 > 集群级别 > 全局级别。
为了安全起见建议大家定期维护白名单。使用 root@proxysys 账号登录 OBProxy ,白名单操作方式如下:
MySQL [(none)]> select * from white_list;
Query OK, 0 rows affected (0.00 sec)
# 增加租户tenant1的白名单
MySQL [(none)]> replace into white_list(cluster_name, tenant_name, name, value) values('cluster1', 'tenant1', 'ip_list', '182.168.1.1');
Query OK, 0 rows affected (0.02 sec)
# 查询所有白名单内容
MySQL [(none)]> select cluster_name, tenant_name, name, value from white_list;
+--------------+-------------+---------+-------------+
| cluster_name | tenant_name | name | value |
+--------------+-------------+---------+-------------+
| cluster1 | tenant1 | ip_list | 182.168.1.1 |
+--------------+-------------+---------+-------------+
如果只设置集群级别,replace 语句不加入 tenant_name 即可,全局级别类似,replace 语句不加入 cluster_name 和 tenant_name 。这里大家需要注意使用网络号时要填写正确,如192.168.15.0/16就是错误的格式,第三位不应该为15,应该为0。
1.1.3 最大连接数
OBProxy 通过配置项client_max_connections控制客户端最大连接数。因为分布式系统连接较多,我们举例说明下。
从整个链路看,存在4个连接:App 和 OBProxy 有一个,OBProxy 和 OBServer 有三个。但从 App 角度去看,只有一个连接。因此配置项就是对 App 和 OBProxy 之间的连接数做限制,OBProxy 和 OBServer 之间的连接不计算在内。
当 OBProxy 的客户端连接数超过限制后,客户端再次建连会登陆失败,OBProxy 会给客户端返回 ERROR 报文,报错信息为 Maximum number of sessions exceeded。
1.2 传输加密
1.2.1 实现原理
OBProxy 通过 SSL 对数据传输进行加密。在实现上有两种方案:
方案一
方案二
大家可以看到,方案一 OBProxy 只做 SQL 转发,不感知报文内容,实现简单。方案二中,OBProxy 会重新加解密数据,并分析请求报文和响应报文的内容。方案二相比方案一更加复杂,但这样的优点是:
- 相比方案一,方案二中 OBProxy 感知 SQL 请求和回包内容,才能够实现 OBProxy 的连接管理、SQL 路由、高可用等核心功能。
- 方案二可以实现更灵活的加密控制,如 App <-> OBProxy 链路走 SSL 加密,OBProxy <-> OBServer 不走SSL 加密。
除了优点,方案二也有一些缺点,OBProxy 需要加解密数据,对性能有一定损耗。那么影响有多大呢?基于 OBProxy 优秀的异步和多线程模型,即使全链路都开 SSL,性能影响也在 3% 以内,大家可以放心使用。
1.2.2 使用案例
想要使用SSL功能还是比较复杂的一件事情。需要满足下面条件:
- 具备密钥和证书分发体系:如云厂商的KMS服务;个人用户可以通过 openssl 命令生成证书和密钥。
- 链路模块都支持SSL:如App、OBProxy 和 OBServer 都需要支持SSL能力。
我们以 OceanBase 某公有云客户使用 SSL 为例说明。
我们从控制流和数据流两个角度说下上面内容。
控制流:OBProxy 不直接对接密钥服务,对外提供 SQL 端口供设置证书和密钥。OCP对接不同的KMS服务,并给 OBProxy 发送 SQL 设置密钥相关信息。
数据流:业务 App 发送的数据跨越 VPC,进行加密传输。OBProxy 和 OBServer 在同一个 VPC 内,首先得到了 VPC 保护,OBProxy 接收到数据后,可以给 OBServer 发送加密数据或者非加密数据,给 App 回包时,OBProxy会对数据加密后再传输。
1.2.3 SSL配置
想要使用 SSL 能力,还需要对各个组件进行配置,本节介绍 OBProxy 如何配置SSL。方法如下图所示。
# 配置密钥和证书
replace into ssl_config (cluster_name, tenant_name, name, value) values('*', '*', 'key_info', '{"sourceType" : "FILE", "CA" : "certs/ca.pem", "publicKey" : "certs/server-cert.pem", "privateKey" : "certs/server-key.pem"}');
# 开启客户端和OBProxy之间的SSL
replace into proxy_config(name, value, config_level) values('enable_client_ssl', 1, 'LEVEL_GLOBAL');
# 开启OBProxy和OBServer之间的SSL
replace into proxy_config(name, value, config_level) values('enable_server_ssl', 1, 'LEVEL_GLOBAL');
这里介绍一下上面配置的含义,对于ssl_config表,字段含义如下:
- cluster_name和tenant_name:SSL配置也支持租户和集群级别,'*' 表示无,上面含义就是无租户和集群名,就是全局级别
- name:为 'key_info' 表示是 SSL 密钥配置
- value:json格式,包含密钥详细信息
sourceType:支持"FILE"和"KEY"两种信息。"FILE"表示用文件的方式设置,"KEY"表示用字符串的方式设置
CA:证书信息,文件名或者字符串,如果是文件名注意下权限信息
publicKey:公钥信息,也需要注意文件权限
privateKey:私钥信息,也需要注意文件权限
对于proxy_config表,字段含义如下:
- cluster_name和tenant_name:上面例子未出现,本身也支持租户和集群级别。这里需要注意下,不设置就表示无,而ssl_config中'*'表示无
- name:enable_client_ssl表示客户端和 OBProxy 之间是否使用 SSL 能力;enable_server_ssl表示OBProxy和 OBServer之间是否使用 SSL 能力,两者相互独立
- value:0表示不使用SSL能力;1表示使用SSL能力
这里需要注意一点:打开SSL配置并不代表一定使用SSL,比如客户端不支持的话,OBProxy 开启SSL能力也没作用。
是否走了加密,客户端可以通过\s命令确认(关注SSL一行,下图为Cipher in use is ECDHE-RSA-AES256-GCM-SHA384)。
MySQL [test]> \s
--------------
mysql Ver 15.1 Distrib 5.5.64-MariaDB, for Linux (x86_64) using readline 5.1
Connection id: 3221487953
Current database: test
Current user: root@127.0.0.1
SSL: Cipher in use is ECDHE-RSA-AES256-GCM-SHA384
Current pager: stdout
Using outfile: ''
Using delimiter: ;
Server: MySQL
Server version: 5.7.25 OceanBase 4.0.0.0 (r1-a06adb022eaa434bb5210294830a20003a5753a8) (Built Apr 7 2022 23:30:49)
Protocol version: 10
Connection: 127.1 via TCP/IP
Server characterset: utf8mb4
Db characterset: utf8mb4
Client characterset: utf8mb4
Conn. characterset: utf8mb4
TCP port: 33041
Active --------------
这里需要注意,上面内容只能确定客户端和 OBProxy 是否开启了 SSL,OBProxy 和 OBServer 是否开启需要查询 OBServer 的内部表确定。
2. 协议
大家都知道,使用开源 MySQL 驱动就可以连接 OBProxy 使用了,这是因为 OBProxy 支持了 MySQL 协议。其实,OBProxy 总共支持三种协议,见下图。
使用 MySQL 协议,使用 MySQL 生态的客户端即可。使用 2.0协议和 RPC 协议,需要使用专属客户端。对于 RPC 协议,在 OBKV 的产品形态下提供,本文不做详细介绍。MySQL 协议大家都很熟悉,所以重点介绍一下2.0协议。
2.0协议是 OceanBase 团队自研的协议。设计时考虑了兼容性、安全性和扩展性几个方面,整体格式如下:
ceanBase 2.0 Protocol Format:
0 1 2 3 4 Byte
+-----------------+----------------------+
| Magic Num | Version |
+-----------------+----------------------+
| Connection Id |
+-----------------------------+----------+
| Request Id | Seq |
+-----------------------------+----------+
| PayLoad Length |
+----------------------------------------+
| Flag |
+-----------------+----------------------+
| Reserved |Header Checksum(CRC16)|
+-----------------+----------------------+
| ... PayLoad Data ... |----------+
+----------------------------------------+ |
| Tailer PayLoad Checksum (CRC32) | |
+----------------------------------------+ |
|
|
+--------------------------+
|
|
v
+-------------------+-------------------+-------------------------------------+
| Extra Len(4Byte) | Extra Info(K/V) | Basic Info(Standard MySQL Packet) |
+-------------------+-------------------+-------------------------------------+
每个字段含义不在此作介绍,我们说明下设计考虑。
- 兼容性:2.0协议在 MySQL 协议上进行了扩展,可以方便的进行 2.0协议和MySQL协议转换。
- 安全性:尾部包含 CRC 32 信息,可以进行数据正确性校验。
- 扩展性:通过Extra Info等字段可以传输更多功能信息,实现丰富功能;如全链路诊断信息、事务状态信息都可以放到这里面。
OB 4.0版本已经发布,默认使用2.0协议,后续我们也会基于2.0协议开发更多功能,如全链路诊断、分布式事务路由等,大家也会慢慢发现2.0协议的好处。
3. 监控
对于监控信息,OBProxy 的设计理念是和开源产品最对接,让大家使用门槛更低。目前 OBProxy 支持了Prometheus监控。Prometheus监控系统的设计如下。
OBProxy 要做的就是实现图中左下角 exporters 的功能,对 Prometheus server 提供监控数据。OBProxy 使用2884端口供Prometheus server访问。如下图通过 curl -L 127.0.0.1/2884/metrics 获得了监控数据:
在 Prometheus 监控界面可以展现的更加清楚(下图是RT和QPS监控信息):
总结
除了分布式特性,OBProxy 也结合流行的云原生技术、安全技术等,提供面向用户的功能。
本文从安全和监控角度,介绍了登录安全、IP白名单、连接数、普罗米修斯监控等一些大家耳熟能详的功能。对于协议部分,大家可以看到 OBProxy 本身是一个协议转换器,支持了 MySQL协议、2.0协议和RPC协议,使 OBProxy 支持OBKV、融入MySQL 生态、扩展自身能力。
OBProxy 团队也在关注现有的云原生等技术,在蚂蚁公司内部做了云原生 Service Mesh 形态的功能并广泛使用,后续我们会更深入结合云产品和流行技术,为大家提供更好的服务。
课后互动
上期互动答案
问:当 OBProxy 和 某个 OBServer 节点发生网络故障后,但 OBServer 内部没有网络故障。此时如果要保证 RTO < 30s,那么 OBProxy 探测的周期、探测连续失败次数和探测超时时间该如何配置?
答:大家需要了解探测周期、探测超时时间和探测连续失败次数之间的关系,经验上看,连续失败次数不能为1,不然一次网络抖动就会导致探测失败,周期要在秒级别,不能太频繁也不能太长。对于RTO < 30 s,可以设置周期为5s,连续失败次数为4次,超时时间为5s,那么在25s~30s之间就可以发现故障。
本期互动
问:客户端发给 OBproxy 加密数据,那么 OBProxy 发给 OBServer 的一定是加密数据吗?
【查看系列专题】
首发!高性能数据访问中间件 OBProxy(一):功能模块及特性详解
高性能数据访问中间件 OBProxy(二):安装部署最佳实践
高性能数据访问中间件 OBProxy(三):问题排查和服务运维
高性能数据访问中间件 OBProxy(四):一文讲透连接管理
高性能数据访问中间件 OBProxy(五):一文讲透数据路由
高性能数据访问中间件 OBProxy(六):OBProxy高可用的那些事
高性能数据访问中间件 OBProxy(七):安全、协议和监控
欢迎持续关注 OceanBase 技术社区,我们将不断输出技术干货内容,与千万技术人共同成长!!!
搜索🔍钉钉群(33254054),或扫描下方二维码,还可进入 OceanBase 技术答疑群,有任何技术问题在里面都能找到答案哦~