当前位置: 首页 > 工具软件 > HostDB > 使用案例 >

MySQL 的 DNS 解析 和host cache

田化
2023-12-01

1. DNS 解析 和host cache

| 概述
MySQL 服务将会维护内存中的host cache ,host cache 包含的信息为:IP,地址,主机名,和错误信息.
host cache 的内容是公开的,可以用select 语句进行查询,以便诊断当前的连接问题.

1.1. 启用host cache 有以下好处.

  • 通过查找缓存找到IP 和主机名的对应结果,可以避免每个clinet 连接时都从DNS 查找.

  • host cahce 包含有关连接时发生的错误信息.如果错误发生的很频繁,max_connect_errors 将会阻塞这些发生错误的回话的新的链接.

  • hostcache 将用于 MySQL 使用非本地IP TCP 连接.但是对于环回接口地址是不会建立TCP 链接缓存,套接字也是一样不会使用缓存.

  • 服务将会检查每个新的客户机连接是否在主机缓存中.以便提高链接速度.

查看 hostcache 内容:

select ip,host,host_validated,sum_connect_errors,count_authentication_errors from performance_schema.host_cache;

服务器的缓存内容如下:

  1. 当一个tcp client 从指定的IP 地址链接到服务器时,将会创建新的缓存条目记录客户机的IP,主机名,客户机验证白标志.在未链接时,主机名设置为NULL,标志为false.这个初始化条目可以用于这个客户端的后续client 链接.

  2. 当有一个新的客户端连接进来时,MySQL Server会为这个IP在host cache中建立一个新的记录,包括IP,主机名和client lookup validation flag,分别对应host_cache表中的IP,HOST和HOST_VALIDATED这三列。第一次建立连接因为只有IP,没有主机名,所以HOST将设置为NULL,HOST_VALIDATED将设置为FALSE。

  3. MySQL Server检测HOST_VALIDATED的值,如果为FALSE,它会试图进行DNS解析,如果解析成功,它将更新HOST的值为主机名,并将HOST_VALIDATED值设为TRUE。如果没有解析成功,判断失败的原因是永久的还是临时的,如果是永久的,则HOST的值依旧为NULL,且将HOST_VALIDATED的值设置为TRUE,后续连接不再进行解析,如果该原因是临时的,则HOST_VALIDATED依旧为FALSE,后续连接会再次进行DNS解析。

  4. 如果链接时发生错误,服务器会记录错误次数和错误的描述.

1.2. 服务原理

服务器使用host cache 时,使用 gethostbyaddr_r()gethostbyname_r() 两个函数,这两个函数调用操作系统支持.如果不调用这两个线程,或者无法调用,线程将会互斥锁.在有互斥锁释放之前,是没有其他线程可以在主机缓存中找不存在于host cache 的主机名.

为了解决阻塞的服务,可以使用FLUSH HOSTS刷新host cache .

如果阻塞的主机没有使用手动flush hosts .被阻塞的主机也有可能解除阻塞.因为当新的client 链接进来后,如果缓存已经满了,服务器将会删除最近最少使用的缓存条目,以便为新的条目腾出空间,如果丢弃的时阻塞主机的,则主机将被解除阻塞.

host cache 默认开启,如果想禁用,使用host cache = 0

如果禁用 DNS 主机名查找功能,使用--skip-name-resove 选项启动服务器.但是注意如果没有指定IP 连接的客户端(例如通过DNS 解析的客户端)则会无法链接.

如果DNS 主机非常慢,可以禁用此项功能 --skip-name-resolve .或者增大host_cache_size

如果完全禁用TCP/IP 链接,请使用--skip-networing 选项启动服务器.

有些链接错误与 TCP 链接无关,这些错误信息请检查Connection_errors_*_xxx 状态变量

1.3. 总结

谈谈 host cache的优缺点:

缺点:当有一个新的客户端连接进来时,MySQL Server都要建立一个新的记录,如果DNS解析很慢,无疑会影响性能。如果被允许访问的主机很多,也会影响性能,这个与host_cache_size有关,这个参数是5.6.5引入的。5.6.8之前默认是128,5.6.8之后默认是-1,基于max_connections的值动态调整。所以如果被允许访问的主机很多,基于LRU算法,先前建立的连接可能会被挤掉,这些主机重新进来时,会再次进行DNS查询。

优点:通常情况下,主机名是不变的,而IP是多变的。如果一个客户端的IP经常变化,那基于IP的授权将是一个繁琐的过程。因为你很难确定IP什么时候变化。而基于主机名,只需一次授权。而且,基于host cache中的失败信息,可在一定程度上阻止外界的暴力破解攻击。

1.4. 阻止暴力破解

关于阻止外界的暴力破解攻击,涉及到max_connect_errors参数,默认为100,官方的解释如下:

If more than this many successive connection requests from a host are interrupted without a successful connection, the server blocks that host from further connections.

如果某个客户端的连接达到了max_connect_errors的限制,将被禁止访问,并提示以下错误:

Host 'host_name' is blocked because of many connection errors.
Unblock with 'mysqladmin flush-hosts'

查看当前的最大链接错误数.

mysql> show variables like 'max_connect_errors';
+--------------------+-------+
| Variable_name      | Value |
+--------------------+-------+
| max_connect_errors | 100   |
+--------------------+-------+
1 row in set (0.07 sec)

设置最大连接数错误

set global max_connect_errors=2;
  • 登录模拟错误
[root@mysql-slave1 ~]# telnet 192.168.244.145 3306
Trying 192.168.244.145...
Connected to 192.168.244.145.
Escape character is '^]'.
N
5.6.26-log
          K]qA1nYT!w|+ZhxF1c#|kmysql_native_password
^]
!#08S01Got packets out of orderConnection closed by foreign host.
[root@mysql-slave1 ~]# telnet 192.168.244.145 3306
Trying 192.168.244.145...
Connected to 192.168.244.145.
Escape character is '^]'.
N
Y#>PVB(>!Bl}NKnjIj]sMmysql_native_password
^]
!#08S01Got packets out of orderConnection closed by foreign host.
[root@mysql-slave1 ~]# mysql -h192.168.244.145 -uroot -p123456
Warning: Using a password on the command line interface can be insecure.
ERROR 1129 (HY000): Host '192.168.244.144' is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts'

即便后来使用了正确的账号和密码登录,依旧会被阻止。

  • 查看host_cache 内容

mysql> select ip,host,host_validated,sum_connect_errors,count_authentication_errors from performance_schema.host_cache;
+----------------+------+----------------+--------------------+-----------------------------+
| ip             | host | host_validated | sum_connect_errors | count_authentication_errors |
+----------------+------+----------------+--------------------+-----------------------------+
| 192.168.10.101 | NULL | YES            |                  2 |                           0 |
| 192.168.10.144 | NULL | YES            |                  0 |                           0 |
+----------------+------+----------------+--------------------+-----------------------------+
2 rows in set (0.00 sec)
  • 该阻止会一直生效,直到采取以下操作:
  1. mysql> flush hosts;

  2. mysqladmin flush-hosts

  3. truncate table performance_schema.host_cache;

  4. 或者等待该记录从host cache中被挤掉。

1.5. 需要DNS 解析的用户.


mysql> select User,Host from mysql.user
    -> ;
+------------------+-----------+
| User             | Host      |
+------------------+-----------+
| dsg              | %         |
| mysql.infoschema | localhost |
| mysql.session    | localhost |
| mysql.sys        | localhost |
| root             | localhost |
+------------------+-----------+
5 rows in set (0.00 sec)

1.6. 测试

  • 使用127.0.0.1 回环地址:
  • 使用\s 确定时TCP/IP 链接还是 套接字链接.
[root@dbserver ~]# mysql -h127.0.0.1 -u dsg -p  
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 17
Server version: 8.0.15 MySQL Community Server - GPL

Copyright (c) 2000, 2019, 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> \s
--------------
mysql  Ver 8.0.15 for Linux on x86_64 (MySQL Community Server - GPL)

Connection id:          17
Current database:
Current user:           dsg@127.0.0.1
SSL:                    Cipher in use is DHE-RSA-AES128-GCM-SHA256
Current pager:          stdout
Using outfile:          ''
Using delimiter:        ;
Server version:         8.0.15 MySQL Community Server - GPL
Protocol version:       10
Connection:             127.0.0.1 via TCP/IP
Server characterset:    utf8mb4
Db     characterset:    utf8mb4
Client characterset:    utf8mb4
Conn.  characterset:    utf8mb4
TCP port:               3306
Uptime:                 6 min 40 sec

Threads: 3  Questions: 29  Slow queries: 0  Opens: 148  Flush tables: 2  Open tables: 124  Queries per second avg: 0.072
--------------

mysql> 

以上结果说明 :通过127.0.0.1 是通过TCP/IP 链接.

使用localhost 登录:

[root@dbserver ~]# mysql -hlocalhost -u dsg -p         
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 18
Server version: 8.0.15 MySQL Community Server - GPL

Copyright (c) 2000, 2019, 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> \s
--------------
mysql  Ver 8.0.15 for Linux on x86_64 (MySQL Community Server - GPL)

Connection id:          18
Current database:
Current user:           dsg@localhost
SSL:                    Not in use
Current pager:          stdout
Using outfile:          ''
Using delimiter:        ;
Server version:         8.0.15 MySQL Community Server - GPL
Protocol version:       10
Connection:             Localhost via UNIX socket
Server characterset:    utf8mb4
Db     characterset:    utf8mb4
Client characterset:    utf8mb4
Conn.  characterset:    utf8mb4
UNIX socket:            /var/lib/mysql/mysql.sock
Uptime:                 8 min 25 sec

Threads: 3  Questions: 34  Slow queries: 0  Opens: 148  Flush tables: 2  Open tables: 124  Queries per second avg: 0.067
--------------

mysql> 

是通过套接字登录.

  • 如果禁用了DNS 则 localhost 则不会解析成回环地址.登录报错.
[root@dbserver ~]# mysql -h127.0.0.1 -u root -p         
Enter password: 
ERROR 1045 (28000): Access denied for user 'root'@'127.0.0.1' (using password: YES)
[root@dbserver ~]# 
  • 如果该参数设置为OFF,则上述方式就会报错,通过报错信息可以看出,它直接将127.0.0.1转化为localhost了。

[root@localhost ~]# mysql -uroot -h127.0.0.1 -p123456 -P3306
Warning: Using a password on the command line interface can be insecure.
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)

:::alert-warning
注意: ‘t1’@’%‘中包含’t1’@‘127.0.0.1’,如果开启skip_name_resolve参数,则’t1’@’%‘中定义的密码可用于’t1’@‘127.0.0.1’的登录,如果没有开启该参数,则’t1’@‘127.0.0.1’会转化为’t1’@‘localhost’登录,此时’t1’@’%'定义的密码并不适用。
:::

 类似资料: