-
Notifications
You must be signed in to change notification settings - Fork 30
权限管理
Arkproxy的权限管理,与其它中间层是不一样的,所有的变化,都是出于对安全性的考虑,同时也考虑到了用户的友好性。
中间层,作用是将客户端连接请求,转发到合适的后端数据库节点中,并且将对应的返回结果,再原路返回给客户端,这样的架构,就存在三层,分别是客户端、中间层以及后端服务器,他们之间建立的连接,有两层,分别是客户端与中间层的连接,以及中间层与后端数据库的连接。
从运维角度来看,在后端数据库中,比如执行一个简单 show processlist; 命令,从结果中可以尽可能的看到最原始的连接信息,比如用户名、连接IP等信息,就像我们直连一个MySQL服务器时能看到的那样。
但现在是三层,连接有两层,不管客户端是从多少个IP连接过来,不管用到了什么用户名,在后端服务器,看到的连接IP只有一个,那就是中间层的IP地址。而能看到的用户名,有可能也是固定的一个,也有可能是与客户端连接时所使用的用户名相同,这取决于如何实现这个中间层了,也就是其友好性。
IP是固定的,只能是中间层程序所在机器的IP,这个是没法改变的。而用户名的显示,一般有两种方式来实现。
- 直接在中间层配置文件中,配置一个在后端所有数据库中具有所有权限的帐号,这样不管任何用户具有任何权限,只要有权限连接中间层,那就有权限做任何操作了,因为真正在后端做操作的,就是在配置文件中配置好的具有所有权限的一个用户,这种情况下,毫无疑问,在后端数据库中看到的所有连接,都是同一个用户名及同一个IP地址,这样的话,
show processlist;
在处理问题时,变得毫无意义,因为没办法区分什么语句是从什么IP发过来的,是什么用户名执行的。这种实现方式是最不友好的,因为它将权限无限制的放大了,造成了非常大的安全隐患,极不可取。 - 另一种实现方式,就是保持原始连接中间层的用户名,但不同用户名的情况下,就需要不同用户名在后端数据库,具有中间层IP的权限了。也就是在后端有很多类似 [email protected],[email protected],等等这样的帐号,但还是有一个问题,如果同一个用户名,具有不同权限的业务,比如针对一个帐号 [email protected],某一个业务申请了 SELECT,另一个业务申请了 DELETE,那此时在后端数据库中,[email protected] 帐号就拥有了 SELECT 和 DELETE 的权限,那当初申请权限的两个业务当然也同时具有了这两个权限,相当于是把权限合并了。这种情况当然是可以在后端数据库中看到真实用户名的,但还是将权限放大了,还是不安全。当然有一种方法可以缓解这个问题,就是人为约定用户名的唯一,但很明显,这要求业务在起名的时候,考虑再三不要重复,很不友好,也不可取。
Arkproxy 能做到的是,权限没有任何放大的可能性,同时连接时都会使用原始用户名,这种解决办法,需要在中间层来创建用户,中间层会在后端创建与之一一对应的用户,但用户名是加密的,加密之后,在后端数据库中的用户名信息都是不会被破解,增强了数据库的安全性,同时也保证了用户名的唯一性,这样客户端使用原始信息连接时,中间层会将其加密后再连接到后端数据库,只要加密之后是同一个用户名,那说明来源用户必然是同一个帐号,权限没有任何放大,权限验证也只发生在后端数据库中,这样的中间层,才是真正的中间层。
另外,后端数据库如果是 Percona,Arkproxy 还支持无任何权限修改,无侵入地接入业务、提供服务。在后端数据库上面 my.cnf 配置参数 proxy_protocol_networks
,设置为中间层的 Arkproxy 的IP地址/网段,比如 proxy_protocol_networks = 10.0.0.0/24
,参数说明
在配置中间层时,首先需要设置参数 proxy_non_encrypted_ips
,这个参数设置之后,只要与这个名单里的用户,都不会对其加密,这样就可以直接使用后端 MySQL 中已经有的用户登录了。这样是为了更方便的运维,让DBA做到所见即所得,不需要再去转换。其他还需要设置的参数有 proxy_username_encypted = ON
这里我们假设 proxy_non_encrypted_ips 参数的值为 127.0.0.1。
在需要程序帐号的时候,这个程序就需要部署在 proxy_non_encrypted_ips 之外的机器上面了,此时给这个程序授权,只能在中间层的服务端口来授权。比如:
# /usr/bin/mysql -h 127.0.0.1 -P 3336 -uarkproxy -pArkproxy-721
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.7.31-34 Percona Server (GPL), Release 34, Revision 2e68637
Copyright (c) 2009-2020 Percona LLC and/or its affiliates
Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
mysql> GRANT ALL PRIVILEGES ON *.* TO proxytest@'10.0.0.136' IDENTIFIED BY 'Proxytest-123';
Query OK, 0 rows affected, 1 warning (0.01 sec)
从上面结果看出,这个授权已经成功了,我们可以通过 show grants
命令,来查看其权限:
mysql> show grants for proxytest@'10.0.0.136';
+----------------------------------------------------------------+
| Grants for [email protected] |
+----------------------------------------------------------------+
| GRANT ALL PRIVILEGES ON *.* TO 'be72169b5f925579'@'10.0.0.135' |
+----------------------------------------------------------------+
1 row in set (0.00 sec)
从上面结果看出,显示的用户名,其实并不是 proxytest@'10.0.0.136',而是 [email protected],这是因为在后端数据库中,真正的用户就是[email protected],是为中间层开通的权限。而不是为客户端 10.0.0.136 开通的权限。 此时我们可以在 10.0.0.136 机器上登录中间层,并且查看其权限,如下所示:
[root@slave2 ~]# mysql -A -h10.0.0.135 -P 3336 -uproxytest -pProxytest-123
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.31-34 Percona Server (GPL), Release 34, Revision 2e68637
Copyright (c) 2009-2017 Percona LLC and/or its affiliates
Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show grants;
+----------------------------------------------------------------+
| Grants for [email protected] |
+----------------------------------------------------------------+
| GRANT ALL PRIVILEGES ON *.* TO 'be72169b5f925579'@'10.0.0.135' |
+----------------------------------------------------------------+
1 row in set (0.00 sec)
可以看出,输出的权限结果,与上面授权之后马上查看时,显示的结果完全相同。
当然如果此时想要创建一个用户,其IP地址在参数 proxy_non_encrypted_ips
中,此时中间层不会对其加密,会直接在后端数据库中创建这个用户。如下图所示:
那可能有人会问,在有业务连接中间层之后,此时如何知道业务用户与加密用户之间的对应关系呢?这点 Arkproxy 也考虑到了,我们可以在 show backend connections
命令的结果中看到,我们登录中间层管理端口:
# mysql -h127.0.0.1 -uproxyshell -ppassword -P3335
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 4
Server version: 5.7.31-34
Copyright (c) 2009-2017 Percona LLC and/or its affiliates
Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show backend connections\G
*************************** 1. row ***************************
Parent_Id: 2
User: proxytest
Host: 10.0.0.136
MD5_HASH: be72169b5f925579
Backend_Host: 10.0.0.135
Port: 3306
Db:
Route_Type: Write
Wait_Timeout: 28800
Last_Heartbeat: 2020-09-02 12:17:16.272588
Last_Execution: 2020-09-02 12:05:31.951383
Alived: 1
Env_Version: 1
Route_Count: 2
Slave_Lag: 0
Running_SQL: NULL
*************************** 2. row ***************************
Parent_Id: 2
User: proxytest
Host: 10.0.0.136
MD5_HASH: be72169b5f925579
Backend_Host: 10.0.0.135
Port: 3306
Db:
Route_Type: Read
Wait_Timeout: 28800
Last_Heartbeat: 2020-09-02 12:17:16.272638
Last_Execution: 2020-09-02 12:05:31.949826
Alived: 1
Env_Version: 0
Route_Count: 0
Slave_Lag: 0
Running_SQL: NULL
2 rows in set (0.00 sec)
mysql>
从这个结果来看,其中第二列 User,对应的就是用户登录时使用的用户名,而第四列,MD5_HASH 对应的才是后端数据库中存储的真实用户名,所以可以在业务运行过程中,通过这个命令来找他们的对应关系。具体关于这个命令详细的说明,请参考相关章节。