本节从组复制的IP白名单以及安全套接字(SSL)支持两个方面来介绍如何保护组合组成员之间连接的安全性。
5.1. 组复制的IP地址白名单
MGR插件有一个系统变量group_replication_ip_whitelist,用于确定可以接受从哪个主机传入的组通信系统连接。假设Server S1中设置了该系统变量,然后使用S1引导组启动,之后,将Server S2作为joiner节点,当S2尝试与S1建立组通讯连接时,S1在接受S2的组通讯连接请求之前,先检查系统变量group_replication_ip_whitelist的设置是否允许S2访问,如果允许,则接受S2的组通讯连接请求,否则拒绝S2的组通讯连接请求。
如果没有显式地指定白名单,则S1的组通信引擎(XCom)将自动扫描S1所在主机上的活跃网卡接口,并根据这些活跃网卡接口上配置的IP地址生成相应的子网地址(包括IPV4和IPV6地址)。根据这些生成的子网地址来自动创建一个组复制的白名单设置。自动生成的IP白名单地址可能包含如下范围:
代码语言:javascript复制IPv4 (在RFC 1918中定义的IPV4地址的划分)
# A类地址
10/8 (IP范围:10.0.0.0-10.255.255.255)
# B类地址
172.16/12 (IP范围:172.16.0.0-172.31.255.255)
# C类地址
192.168/16 (IP范围:192.168.0.0-192.168.255.255) -
IPv6 ( 在RFC 4193 和 RFC 5156中定义的IPV6地址的划分)
# 唯一的本地地址前缀(范围)
fc00:/7
# 本地链路的单播地址前缀(范围)
fe80::/10
# 本地(localhost)IPv4地址
127.0.0.1 - localhost for IPv4
# 本地(localhost)IPv6地址
::1 - localhost for IPv6
在MySQL的错误日志中会记录自动为主机添加的白名单地址信息。
从上面代码段中所述的IP范围我们可以看到,自动生成的白名单地址都是私有网络地址(即便主机上配置有公网IP地址,也不会生成公网地址网络的白名单),而私有地址只允许在私有网络内访问,不允许在公网上访问。因为,如果要使用公网地址作为白名单,则,你需要使用系统变量group_replication_ip_whitelist来显式指定你希望允许开放访问的公网地址范围,另外,一旦为系统变量group_replication_ip_whitelist指定值之后,自动生成白名单的功能就失效了,未在系统变量group_replication_ip_whitelist中指定的任何地址都不允许访问,因此,任何希望允许访问的IP地址范围,你都需要显式指定。
如果某个Server是组中的活跃成员,则不允许动态修改白名单地址,必须先执行STOP GROUP_REPLICATION语句停止组复制,让其主动脱离组,配置好白名单之后,再执行START GROUP_REPLICATION语句让其重新申请加入组。否则会报错:ERROR 3093 (HY000): The IP whitelist cannot be set while Group Replication is running。
如果要显式指定白名单地址,则,可以使用如下一些有效的字符串形式指定:
- 单个IPV4地址:例如,198.51.100.44
- 带有CIDR符号的IPv4地址:例如,192.0.2.21/24,可以理解为带有子网掩码的地址。
- IPv6地址(MySQL 8.0.14中引入IPV6地址支持):例如,2001:db8:85a3:8d3:1319:8a2e:370:7348
- 带有CIDR符号的IPv6地址(MySQL 8.0.14中引入IPV6地址支持):例如,2001:db8:85a3:8d3::/64
- 主机名:例如,example.org
- 带有CIDR符号的主机名:例如,www.example.com/24
在MySQL 8.0.14之前,主机名只能解析为IPv4地址。从MySQL 8.0.14开始,主机名可以解析为IPv4地址或IPv6地址或两者同时解析。如果主机名同时解析为IPv4和IPv6地址,则IPv4地址总是优先用于组复制连接。您可以将CIDR表示法与主机名或IP地址结合使用,将带有特定网络前缀的IP地址块列入白名单(即,带有子网掩码的IP地址范围的白名单),但是要确保指定的子网中包含了你希望允许访问的所有IP地址。
要修改白名单设置,需要重启组复制,如果有多个白名单地址,使用逗号分隔,如下:
代码语言:javascript复制# 先停止组复制
mysql> STOP GROUP_REPLICATION;
# 修改白名单地址
mysql> SET GLOBAL group_replication_ip_whitelist="192.0.2.21/24,198.51.100.44,203.0.113.0/24,2001:db8:85a3:8d3:1319:8a2e:370:7348,example.org,www.example.com/24";
# 重新启动组复制
mysql> START GROUP_REPLICATION;
白名单必须包含每个成员的系统变量group_replication_local_address中指定的IP地址或主机名。这个地址与MySQL Server的SQL协议主机和端口不一样(系统变量group_replication_local_address指定的地址和端口是用于组成员之间的组通讯的,而不是对外提供业务访问的)。
要成功加入复制组,则给定的待加入组的Server的IP地址需要在其请求加入组的种子成员的白名单中需要允许其发起组通讯请求。通常,是根据种子成员(即组的引导成员)的系统变量group_replication_group_seeds设置的IP进行适配,但是,也可以根据组中的任意成员的系统变量group_replication_group_seeds指定的值进行设定,例如:组中的成员混合使用了IPV4和IPV6地址,那么,建议将所有成员可能会用于组通讯的网络的IPV4和IPV6协议地址一并配置到白名单中,以避免出现有Server申请加入组时被拒绝连接的情况发生。有关管理混合IPv4和IPv6复制组的更多信息,请参见"4.5. 配置支持IPv6和混合IPv6与IPv4地址的组"。
当复制组被重新配置时(例如,当选举一个新的主要节点或者一个成员脱离组时),组成员会重新建立它们之间的连接。如果组中的所有成员的白名单地址配置不一致,在重新配置组之后,可能导致某个成员在重新配置组之前允许加入组的而在重新配置组之后无法重新加入组(例如:组中有3个成员S1、S2、S3,当S3脱离组并重新配置组时,因为白名单不一致的原因,S2不允许S1访问,S3允许S1访问,但是现在S3已经不在组中了,这就会导致S3脱离组之后,S1和S2也无法组成新的组)。要完全避免这种情况,建议在组中的所有成员中设置一致的白名单。
对于主机名的白名单设置,仅当有另外一个Server发起连接请求时才会进行名称解析。无法解析的主机名不会用于白名单验证,且会将警告信息写入MySQL错误日志中。
注意:主机名用作白名单,安全性不如IP地址,除非必须,否则不建议使用外部组件来实现名称解析(除非外部组件的安全性你能够把控),如果有临时需要,可以考虑使用本地主机中的/etc/hosts解析记录实现
5.2. 组复制安全套接字层(SSL)支持
我们可以使用SSL来保护组成员之间的通信连接和分布式恢复的连接。本节将介绍如何配置SSL的连接。
5.2.1. 为组通信配置SSL
安全套接字可用于组成员之间的组通信连接。MGR插件的系统变量group_replication_ssl_mode控制组通讯连接是否启用SSL,并为组通讯连接指定安全模式。默认设置为DISABLED,表示不使用SSL。该系统变量有如下有效值:
值 | 描述 |
---|---|
DISABLED | 建立一个未加密的连接(默认),即,不启用SSL |
REQUIRED | 如果组成员之间支持安全连接,则建立安全连接 |
VERIFY_CA | 类似于REQUIRED,但是要根据配置的证书颁发机构(CA)证书来验证服务器TLS证书 |
VERIFY_IDENTITY | 与VERIFY_CA类似,但是还要验证服务器证书是否与尝试连接的主机(组成员)匹配 |
复制的组通信连接的其余SSL相关的配置通过MySQL Server的SSL系统变量进行配置。这些SSL系统变量如下:
Server配置选项(系统变量) | 描述 |
---|---|
ssl_key | PEM格式的SSL私钥文件的路径名。在客户端,用于指定客户端私钥文件(例如:mysql命令行客户端的ssl_key选项);在服务端,用于指定服务端的私钥文件 |
ssl_cert | PEM格式的SSL公钥证书文件的路径名。在客户端,用于指定客户端的公钥证书文件;在服务端,用于指定服务端的公钥证书文件 |
ssl_ca | PEM格式的证书颁发机构(CA)证书文件的路径名 |
ssl_capath | 包含PEM格式的受信SSL证书颁发机构(CA)证书文件的目录的路径名 |
ssl_crl | 包含PEM格式的证书撤销列表的文件的路径名 |
ssl_crlpath | 包含PEM格式证书撤销列表文件的目录的路径名 |
ssl_cipher | 用于加密连接握手中允许使用的密码列表 |
tls_version | Server允许的用于加密连接的TLS协议的列表 |
tls_ciphersuites | Server允许的用于加密连接的TLSv1.3加密套件 |
重要事项:
- 从MySQL 8.0.16开始,MySQL Server支持TLSv1.3协议,前提是MySQL使用了OpenSSL 1.1.1或更高版本编译。但是,对于组复制来说,却是从MySQL 8.0.18开始支持TLSv1.3。在MySQL 8.0.16和MySQL 8.0.17中,只是MySQL Server支持TLSv1.3,但组通信引擎不支持TLSv1.3协议,所以在这两个版本中组复制不能使用TLSv1.3协议。
- 请确保在系统变量tls_version中指定的TLS协议列表的连续性(例如:TLSv1,TLSv1.1,TLSv1.2)。如果协议列表中有任何空白(例如,如果您指定了TLSv1,TLSv1.2、省略了TLS 1.1),则组复制可能无法建立组通信连接。
- 如果在组复制中使用TLSv1.3协议进行分布式恢复,则组复制组成员中至少需要一个默认启用TLSv1.3版本的加密算法套件(或称为"密码套件"),否则分布式恢复会失败。
在复制组中,使用OpenSSL来在所有成员之间协商大家都支持的最高TLS协议版本。如果某个新加入组的Server配置为仅支持TLSv1.3 (tls_version=TLSv1.3),则如果组中的现有成员不支持TLSv1.3时(例如:设置 tls_version=TLSv1,TLSv1.1,TLSv1.2 )的情况下,则新的Server无法加入组(因为此时组中的所有成员使用的TLS协议版本低于新Server的TLS版本)。要将新申请加入组的Server连接到组,必须修改新申请加入组的Server的系统变量tls_version以支持低版本(例如:tls_version=TLSv1,TLSv1.1,TLSv1.2,TLSv1.3),修改完成之后,再次尝试重新申请加入组。在这种情况下,OpenSSL使用较低的TLS协议版本来在申请加入组的Server与组中现有成员之间建立连接。而组中的现有成员之间仍然继续使用支持的最高可用TLS协议版本。
- 如果只是修改组中现有成员的TLS版本,但不重启组复制,则组中的现有成员之间已建立连接的TLS版本不会改变(不影响现有成员之间的连接)。
- 如果想要使用TLSv1.3版本,则可能需要先升级组中现有成员的MySQL Server版本到MySQL 8.0.18及其以上的版本,然后,将TLS版本都修改为支持TLSv1.3(例如:tls_version=TLSv1,TLSv1.1,TLSv1.2,TLSv1.3)。
从MySQL 8.0.16开始,tls_version系统变量可动态修改(即,可在线修改TLS协议版本列表)。注意,对于组复制,ALTER INSTANCE RELOAD TLS语句会根据系统变量tls_version的当前值来重新配置MySQL Server的SSL上下文,但在组复制运行时不会更改组通信连接的SSL上下文。要使新的系统变量tls_version配置对组复制生效,必须使用STOP GROUP_REPLICATION和START GROUP_REPLICATION语句重启组复制。
要对MySQL Server启用SSL支持,可按照如下示例进行配置:
代码语言:javascript复制[mysqld]
# 为MySQL Server配置好SSL相关的系统变量
ssl_ca = "cacert.pem"
ssl_capath = "/.../ca_directory"
ssl_cert = "server-cert.pem"
ssl_cipher = "DHE-RSA-AEs256-SHA"
ssl_crl = "crl-server-revoked.crl"
ssl_crlpath = "/.../crl_directory"
ssl_key = "server-key.pem"
# 为组复制激活SSL,设置为REQUIRED时,如果组成员之间支持安全连接,则建立安全连接
group_replication_ssl_mode= REQUIRED
5.2.2. 为分布式恢复配置SSL
当一个Server申请加入组时,会组合使用远程克隆操作(如果可用)和异步复制连接来执行分布式恢复。这两种状态传输的方法都需要为分布式恢复设置复制用户,如"2.1.3. 用户凭证"中所述。申请加入组时使用的复制用户需要在执行申请加入组之前提前在组的现有成员中创建好(如果需要使用SSL也需要提前配置好SSL),可以使用如下语句来创建复制用户并启用SSL。
代码语言:javascript复制donor> SET SQL_LOG_BIN=0;
donor> CREATE USER 'rec_ssl_user'@'%' REQUIRE SSL;
donor> GRANT replication slave ON *.* TO 'rec_ssl_user'@'%';
donor> GRANT BACKUP_ADMIN ON *.* TO 'rec_ssl_user'@'%';
donor> SET SQL_LOG_BIN=1;
假设在组中的所有成员中都已经配置好了一个启用SSL的复制用户,则,可以通过如下语句来为组复制的恢复通道配置使用该用户,当启动组复制时,复制恢复通道将使用这些凭据来连接其他组成员,如下所示:
代码语言:javascript复制new_member> CHANGE MASTER TO MASTER_USER="rec_ssl_user" FOR CHANNEL "group_replication_recovery";
要配置安全的分布式恢复连接,请使用组复制专用的分布式恢复SSL系统变量。这些变量对应用于组通信连接的Server SSL系统变量值,但它们仅适用于分布式恢复的连接。默认情况下,分布式恢复连接不使用SSL,即使为组通信连接激活了SSL,这些Server SSL系统变量也不会应用于分布式恢复连接。必须单独配置组复制专用的SSL系统变量才会生效。
如果将远程克隆操作用作分布式恢复的一部分,则组复制将自动配置克隆插件的SSL系统变量,以匹配对分布式恢复SSL系统变量的设置。
分布式恢复的专用SSL系统变量如下:
- group_replication_recovery_use_ssl:设置为ON时,组复制会对分布式恢复的连接使用SSL,包括基于远程克隆和基于二进制日志的状态传输都会启用SSL。
- group_replication_recovery_ssl_ca:用于分布式恢复连接的证书颁发机构(CA)文件的路径名。组复制会根据此系统变量的值自动配置为克隆插件的SSL系统变量clone_ssl_ca的值。
- group_replication_recovery_ssl_capath:包含受信任的SSL证书颁发机构(CA)证书文件的目录的路径名。
- group_replication_recovery_ssl_cert:用于分布式恢复连接的SSL公钥证书文件的路径名。组复制会根据此系统变量的值自动配置为克隆插件的SSL系统变量clone_ssl_cert的值。
- group_replication_recovery_ssl_key:用于分布式恢复连接的SSL私有密钥文件的路径名。组复制会根据此系统变量的值自动配置为克隆插件的SSL系统变量clone_ssl_key的值。
- group_replication_recovery_ssl_verify_server_cert:使分布式恢复连接检查donor节点发送的证书中Server的公共名称值。将此系统变量设置为ON与系统变量group_replication_ssl_mode设置为VERIFY_IDENTITY值等效。
- group_replication_recovery_ssl_crl:包含证书撤销列表的文件的路径名。
- group_replication_recovery_ssl_crlpath:包含证书撤销列表的目录的路径名。
- group_replication_recovery_ssl_cipher:用于分布式恢复连接的允许的加密算法列表。可以指定单个,也可以指定多个(多个算法之间用冒号分隔)。
为组复制的分布式恢复连接配置SSL的示例如下:
代码语言:javascript复制new_member> SET GLOBAL group_replication_recovery_use_ssl=1;
new_member> SET GLOBAL group_replication_recovery_ssl_ca= '.../cacert.pem';
new_member> SET GLOBAL group_replication_recovery_ssl_cert= '.../client-cert.pem';
new_member> SET GLOBAL group_replication_recovery_ssl_key= '.../client-key.pem';
| 作者简介
罗小波·数据库技术专家
《千金良方——MySQL性能优化金字塔法则》作者之一。熟悉MySQL体系结构,擅长数据库的整体调优,喜好专研开源技术,并热衷于开源技术的推广,在线上线下做过多次公开的数据库专题分享,发表过近100篇数据库相关的研究文章。
全文完。