连接管理 #
登录认证 #
Proxy 拥有严格的登录认证机制,只有经过身份认证的用户才可以成功建立连接。
概念 #
为保障用户数据和分布式配置信息的安全,DBPlusEngine-Proxy 提供了用户认证的功能,且该功能不可关闭,否则,未经认证的客户端连接将被拒绝。 当前,DBPlusEngine-Proxy 已经支持了多种用户认证协议,包括:
- MySQL 客户端:old password、native、clear-text、sha256
- PostgreSQL 客户端:scram-sha-256、MD5、password
- openGauss 客户端:scram-sha-256、md5
DBPlusEngine-Proxy 为各种数据库协议设置了默认的认证方式,且用户不能修改。其中:MySQL 使用 native,PG 使用 md5,OG 使用 scram-sha-256。为方便企业用户进行统一身份管理,DBPlusEngine 也提供了 LDAP(Lightweight Directory Access Protocol)认证方式,LDAP 认证已支持 MySQL 和 PostgreSQL 客户端。下面是配置用户使用不同的认证方式示例。
- !AUTHORITY
users:
- user: root@%
password: root
authenticationMethodName: md5
- user: sharding
password: sharding
authenticators:
md5:
type: MD5
scram_sha256:
type: SCRAM_SHA256
defaultAuthenticator: scram_sha256
特点 #
实际上,用户在使用 DBPlusEngine-Proxy 时不需要考虑选择何种协议,协议的协商过程是在 DBPlusEngine 与客户端之间自动完成的。
- 当使用 MySQL 客户端时,默认使用 mysql_native_password。仅当用户需要进行 LDAP 认证时,DBPlusEngine 会要求客户端切换为 mysql_clear_password 协议进行通信。
- 当使用 PostgreSQL 客户端时,默认使用 MD5。仅当用户需要进行 LDAP 认证时,DBPlusEngine 会要求客户端切换为 password 协议进行通信。
密码认证 #
默认情况下,Proxy 使用密码认证方式,登录用户需提供正确的用户名和密码。
特别的,由于 Proxy 支持多种数据库协议(如 MySQL、PostgreSQL 等),当用户应用不同的数据库客户端时,Proxy 能够自动适配密码通信协议,在复杂场景下为用户提供一致的安全体验。
主机限制 #
管理员可以为 Proxy 的用户限制登录主机地址,以提高安全等级。如:
- !AUTHORITY
users:
- user: root@127.0.0.1
password: root
以上配置指定了 root 用户只能从 127.0.0.1 这个地址访问 Proxy,从其他地址登录时,即使密码正确也将被拒绝。
LDAP 认证 #
为方便企业用户进行统一认证管理,Proxy 也提供了 LDAP(Lightweight Directory Access Protocol)认证方式,LDAP 认证现已支持 MySQL 和 PostgreSQL 客户端。 同时, Proxy 允许用户以非常灵活的方式来接入 LDAP,例如:
- 可以配置为默认使用 LDAP,这样所有用户都通过 LDAP 认证;
- 支持为用户配置 auth 属性,指定用户使用密码或 LDAP 认证,各个用户可以使用不同方式;
- 各个用户可以使用不同的 LDAP 认证器,即对接不同的 LDAP 服务;
- 支持为用户指定 DN 模板,满足复杂场景的需要;
- 支持 LDAPS 协议,可进一步提升安全等级。
连接配置 #
SphereEx-DBPlusEngine 支持 MySQL 或 PostgreSQL 方式连接,用户可通过标准数据库的方式进行连接,可使用包括 JDBC、ODBC 及本地 Socket 等多种方式进行连接。
Socket 连接 #
SphereEx-DBPlusEngine 支持通过 Socket 方式,可使用 MySQL 或 PostgreSQL 命令行进行连接。SphereEx-DBPlusEngine 的 Proxy 启动时,可指定生成 -s 选型指定 Socket 路径及文件。当 MySQL 命令行进行连接,可通过如下方式进行连接。
mysql -s /path/xxx.sock
mysql --socket /path/xxx.sock
SSL 连接 #
SphereEx-DBPlusEngine 支持 MySQL 或 PostgreSQL SSL加密方式连接。下文以 MySQL 为例进行说明。
TLS 版本 #
如果计算节点本地 openSSL 版本过低,可通过参数 proxy-frontend-ssl-version 进行设置。
props:
proxy-frontend-ssl-version: TLSv1.2
在客户端连接的时候,也使用此版本的 TLS 进行连接。
mysql -h xxx -P3306 -A --ssl-mode=REQUIRED --ssl-ca=/tmp/0608Test/proxy/certificate/Digicert-OV-DV-root.c
er --tls-version=TLSv1.2
CA 认证 #
用户可以选择使用 CA 认证登录。使用 openssl 生成服务器端数字证书和私钥,放于服务器指定路径。
props:
props:
proxy-frontend-ssl-enabled: true
proxy-frontend-ssl-cert-file: /path/xxx.pem
proxy-frontend-ssl-key-file: /path/xxx.key
启动服务器,可看到有如下日志输出。
[INFO ] 2023-05-06 11:54:32.190 [main] o.a.s.p.frontend.ssl.ProxySSLContext - Using X.509 certificate chain file [/home/wuweijie/projects/shardingsphere/.settings/ssl/9917537_proxy.wwj.icu.pem] and private key file [/home/wuweijie/projects/shardingsphere/.settings/ssl/9917537_proxy.wwj.icu.key]
可使用客户端验证服务端证书及域名,连接使用 CA 签发证书的计算节点。
mysql -h xxx -proot -P13306 -A --ssl-mode=VERIFY_IDENTITY --ssl-ca=/tmp/xxx.cer
也可以使用客户端仅验证服务端 CA,使用非 SSL 证书域名连接使用 CA 签发证书的计算节点
mysql -h xxx -proot -P13306 -A --ssl-mode=VERIFY_CA --ssl-ca=/tmp/xxx.cer
如客户端仅要求 SSL,可使用非 SSL 证书域名连接使用 CA 签发证书的计算节点
mysql -h xxx -proot -P13306 -A --ssl-mode=REQUIRED --ssl-ca=/tmp/xxx.cer
自签发认证 #
如客户端仅要求 SSL,可连接使用自签发证书的计算节点。
props:
props:
proxy-frontend-ssl-enabled: true
启动服务器,可看到有如下日志输出。
[WARN ] 2023-05-06 11:52:58.181 [main] o.a.s.p.frontend.ssl.ProxySSLContext - RSA key pair and CA certificate are generated by ShardingSphere-Proxy and self-signed.
使用客户端连接
mysql -h xxx -proot -P13306 -A --ssl-mode=REQUIRED
Proxy + LDAP & LDAPS 应用案例 #
背景 #
SphereEx-DBPlusEngine 增加了对 LDAP 登录认证的支持,以下应用案例展示了 LDAP 登录认证的使用流程。
在案例展示过程中,使用 Wireshark 工具进行抓包,以更形象的展示 LDAP 与 LDAPS 协议的区别。
LDAPS 是基于 SSL/TLS 的 LDAP 通信方式。
基础环境 #
名称 | 版本 |
---|---|
MySQL | 5.7+ |
SphereEx-DBPlusEngine | 1.0+ |
Wireshark | 3.6 |
ApacheDS | 2.0.0 |
- database-sharding-databases.yaml
schemaName: sharding_db
dataSources:
ds_0:
url: jdbc:mysql://127.0.0.1:3306/demo_ds_0?serverTimezone=UTC&useSSL=false
username: root
password:
connectionTimeoutMilliseconds: 30000
idleTimeoutMilliseconds: 60000
maxLifetimeMilliseconds: 1800000
maxPoolSize: 10
minPoolSize: 1
ds_1:
url: jdbc:mysql://127.0.0.1:3306/demo_ds_1?serverTimezone=UTC&useSSL=false
username: root
password:
connectionTimeoutMilliseconds: 30000
idleTimeoutMilliseconds: 60000
maxLifetimeMilliseconds: 1800000
maxPoolSize: 10
minPoolSize: 1
rules:
- !SHARDING
tables:
t_order:
actualDataNodes: ds_${0..1}.t_order
keyGenerateStrategy:
column: order_id
keyGeneratorName: snowflake
defaultDatabaseStrategy:
standard:
shardingColumn: user_id
shardingAlgorithmName: database_inline
defaultTableStrategy:
none:
shardingAlgorithms:
database_inline:
type: INLINE
props:
algorithm-expression: ds_${user_id % 2}
keyGenerators:
snowflake:
type: SNOWFLAKE
LDAP 服务器配置 #
采用 ApacheDS™ 的 Docker 镜像:tremolosecurity/apacheds。
a. 拉取镜像
docker pull tremolosecurity/apacheds:latest
b. 生成 SSL 证书
说明页:https://directory.apache.org/apacheds/basic-ug/3.3-enabling-ssl.html
按照页面中的方法,使用 keytool 生成证书。
这里以 Common name 为 localhost 为例,生成两个文件:
.
├── localhost.ks
└── localhost.cer
由于使用的容器对文件名有特殊要求,这里将 localhost.ks 重命名为 apacheds.jks。
.
├── apacheds.jks
└── localhost.cer
说明: 证书文件可以保存在任意路径,如:
- /Users/${yourname}/apacheds/apacheds.jks
- /Users/${yourname}/apacheds/localhost.cer
c. 启动容器
docker run --detach --rm --name apacheds \
-p 10389:10389 \
-p 10636:10636 \
-v /Users/${yourname}/apacheds:/etc/apacheds \
-e APACHEDS_ROOT_PASSWORD=secret \
-e APACHEDS_TLS_KS_PWD=secret \
tremolosecurity/apacheds:latest
说明:
- 该容器映射出两个端口,其中 10389 用作 ldap 非加密连接,10636 用作 ldaps 加密连接。
- ApacheDS 服务中包含一个默认用户 uid=admin,ou=system,通过 APACHEDS_ROOT_PASSWORD 参数指定了其密码为 secret。
启动操作后,查看日志是否正常:
docker logs -f apacheds
d. ldapsearch 测试
ldapsearch 命令可以便捷的对 LDAP 服务发起访问,验证 LDAP 服务是否正常:
docker exec -it apacheds ldapsearch -x -H ldap://localhost:10389 -b ou=system -D "uid=admin,ou=system" -w secret
至此,LDAP 服务器配置完成。
JDK 导入证书 #
由于 LDAP 服务端使用的是自签名证书,在客户端访问前需要先导入 JRE 的 keystore 中。 注意,导入过程需要输入该证书的密钥:secret。
keytool -import -alias localhost -keystore $JAVA_HOME/jre/lib/security/cacerts -file /Users/${yourname}/apacheds/localhost.cer
Proxy-LDAP 测试 #
a. global.yaml
authority:
users:
- user: root@%
- user: admin
- user: sharding
authenticators:
auth_ldap:
type: LDAP
props:
ldap_server_url: ldap://localhost:10389
ldap_dn_template: uid={0},ou=system
defaultAuthenticator: auth_ldap
b. 启动 Proxy。
c. 启动 Wireshark,开始抓取 10389 端口的数据包。
d. MySQL 客户端登录测试
注意指定 –enable-cleartext-plugin 参数
# 由于 LDAP 服务器中只有一个 admin 用户,这里使用 admin 进行登录。
# 如果尝试其他用户,得到结果是登录失败。
mysql -h 127.0.0.1 -P 3307 -A -u admin -p --enable-cleartext-plugin
输入密码 secret 后登录成功:
e. 查看抓包数据
从抓取的 TCP 数据包中,我们可以轻松的找到一条包含用户 DN 和密码的报文:
f. 小结
从 global.yaml 配置可以看出,在已有 LDAP 服务器的前提下,使用 LDAP 进行登录认证并不复杂,只需要简单配置即可。
另一方面,由于 LDAP 协议是未经加密的,在公开网络中使用 LDAP 认证有密码泄露的风险。
Proxy-LDAPS 测试 #
a. global.yaml
与 LDAP 案例的区别仅仅是更换了 LDAP 服务器的 URL。
authority:
users:
- user: root@%
- user: admin
- user: sharding
authenticators:
auth_ldap:
type: LDAP
props:
ldap_server_url: ldaps://localhost:10636
ldap_dn_template: uid={0},ou=system
defaultAuthenticator: auth_ldap
b. 启动 Proxy
c. 启动 Wireshark,开始抓取 10636 端口的数据包
d. MySQL 客户端登录测试
注意指定 –enable-cleartext-plugin 参数
# 由于 LDAP 服务器中只有一个 admin 用户,这里使用 admin 进行登录。
# 如果尝试其他用户,得到结果是登录失败。
mysql -h 127.0.0.1 -P 3307 -A -u admin -p --enable-cleartext-plugin
输入密码 secret 后登录成功:
e. 查看抓包数据 从数据包可以看到,Proxy 与 LDAP 服务器之间建立了 TLS 通信,已无法通过抓包获取通信的内容:
f. 小结
通过 SSL/TLS 加密,可以有效的保护用户登录信息。而 SphereEx-DBPlusEngine 对 LDAPS 的支持非常友好,仅需导入证书和替换 URL 就可以完成 LDAP 到 LDAPS 的切换。
其他问题 #
是否可使用 SSL 连接?
这分为两种情况,一是针对 SphereEx-DBPlusEngine 与底层数据库的连接;而是前端应用于 SphereEx-DBPlusEngine 的连接。针对前者,主要依赖于对应 SphereEx-DBPlusEngine 内置的 JDBC 驱动情况而定,针对 MySQL、PostgreSQL 都支持使用 SSL 方式进行连接。针对后者,SphereEx-DBPlusEngine 暂不支持 SSL 方式连接。
是否支持连接池配置?
SphereEx-DBPlusEngine 支持主流的数据库连接池,如:DBCP, C3P0, BoneCP, HikariCP 等。在具体配置时,需要关注连接池上限,以满足可能的高并发场景需求。
是否支持负载均衡配置?
SphereEx-DBPlusEngine 针对底层数据库提供读能力的负载均衡,具体参见读写分离部分。针对前端应用与 SphereEx-DBPlus Engine 连接,理论上支持任何四层负载均衡作为 SphereEx-DBPlusEngine 的负载均衡。
是否支持通过VIP方式接入 SphereEx-DBPlusEngine ?
SphereEx-DBPlusEngine 自身不提供 VIP 能力,可通过第三方服务完成。通过将 SphereEx-DBPlusEngine 作为标准服务来看待,通过 VIP 绑定来提升整体可用性。