Host 10.*.*. is blocked because of many connection errors

一、报错信息客户端程序错误:Host 10.*.*.  is blocked because of many connection errors; unblock with ‘mysqladmin flush-hosts’  

   mysql错误日志显示:[Warning] IP address 'xxxx' could not be resolved: Name or service not known

二、错误原因分析:

首先介绍三个参数:

1)max_connect_errors参数:                                                                                

在max_connect_errors之后,来自主机的连续连接请求在没有成功连接的情况下被中断(超过了connect_timeout时间也没有登录上mysql),服务器将阻止该主机进行进一步的连接。如果在前一个连接中断后,在少于max_connect_errors尝试的时间内成功建立了与主机的连接,则主机的错误计数将清除为零。要解除阻止被阻止的主机,请刷新主机缓存;请参阅刷新主机缓存。 2)connect_timeout参数:

mysqld服务器在使用Bad握手进行响应之前等待连接数据包的秒数。默认值为10秒。如果客户端经常遇到以下错误,增加connect_timeout值可能会有所帮助:Lost connection to MySQL server at  'XXX', system error: errno.  

3)skip-name-resolve参数     0 检查客户端连接时是否解析主机名。如果此变量为OFF,则mysqld在检查客户端连接时解析主机名。如果是ON,则mysqld只使用IP号码;在这种情况下,授予表中的所有主机列值都必须是IP地址;

原因分析:

当客户端连接服务端超时(超过connect_timeout), 服务端就会给这个客户端记录一次error,当出错的次数达到max_connect_errors的时候,这个客户端就会被锁定。所以根据业务来尽量把这个值设置大一点,mysql默认值为100,我们可以根据具体需要设置大一点,并非越大越好,越大被攻击时安全性越低。

使用命令:

set global max_connect_errors=300;    

mysql日志显示[Warning] IP address 'xxxx' could not be resolved: Name or service not known,那是因为mysql默认会反向解析DNS,对于访问者Mysql不会判断是hosts还是ip都会进行dns反向解析,频繁地查询数据库和权限检查,这大大增加了数据库的压力,导致数据库连接缓慢,严重的时候甚至死机,出现“连接数据库时出错”等字样。

因为MySQL实例设置skip-name-resolve=no,也就是说每次有客户端连接,MySQL都会去尝试进行dns反向解析,由于mysql服务器/etc/hosts没有配置客户端的ip解析,并且mysql服务器配置了dns,但是dns中也也没有配置客户端ip的解析,就会在dns中查找解析的时间越来越长,导致登录验证的时间超过connect_timeout,进而导致max_connect_errors的累计值增加1;最后超过max_connect_errors的阈值,最终导致客户端被锁定!

mysql是这样来处理客户端解析过程的:

1,当mysql的client连过来的时候,服务器会主动去查client的域名。

2,首先查找 /etc/hosts 文件,搜索域名和IP的对应关系。

3,如果hosts文件没有,则查找DNS设置,如果没有设置DNS服务器,会立刻返回失败,就相当于mysql设置了skip-name-resolve参数,如果设置了DNS服务器,就进行反向解析,直到timeout。

mysql接收到连接请求后,获得的是客户端的ip,为了更好的匹配mysql.user里的权限记录(某些是用hostname定义的)。

如果mysql服务器设置了dns服务器,并且客户端ip在dns上并没有相应的hostname,那么这个过程很慢,导致连接等待。

根本原因:

mysql 没有设置skip-name-resolve=1,此时对于访问者Mysql不会判断是hosts还是ip都会进行dns反向解析,如果/etc/hosts 文件没有匹配到客户端IP,进而去找dbs,因为dns里面也没有配置客户端ip的解析,频繁地查询数据库和权限检查,这大大增加了数据库的压力,导致数据库连接缓慢,所以就可能会超过connect_timeout,进而导致触发max_connect_errors阈值,导致客户端被锁定;

三、解决办法

1、禁用dns反查----根本解决办法进入/etc 找到mysql的配置文件my.cnf(linux环境下)或者my.ini(windows环境下)进行编辑加入如下一行即可:需要重启下MySQL实例[mysqld]skip-name-resolve如果不能重启MySQL数据库,可以把client的ip写在mysql服务器的/etc/hosts文件里,随便给个名字就可以了!找到了就不会去遍历dns;

2、清楚缓存----- 当问题已经发生了,只能这样处理了!也可以使用清楚缓存的方法。这样就会把计数清理掉。到安装bin目录下,使用mysqladmin -u root -p  flush-hosts命令,输入密码后,即完成清楚缓存。也可以进入mysql控制台,执行: flush hosts即mysql  -u -p -h 登录控制台,然后执行 flush hosts;

最终解决办法

1、可以尝试在/etc/hosts文件添加客户端ip解析--- 不重启的情况下解决;

2、可以设置skip-name-resolve跳过dns解析 ----需要重启MySQL;

3、如果也可以尝试把mysql服务器的dns配置去掉。这样也能快速返回错误,就不能使用主机名来做白名单控制了

4、还可以尝试调大connect_timeout,但是这个无法绝对解决问题,例如说你dns没有配置客户端解析,那最终还是得timeout,进而增加一个max_connect_errors值

5、将host_cache_size设为0.本质上就是禁掉host cache内存区域,但是可能导致每次都需要解析,导致连接请求变慢
注意,密码错误不会导致超过 max_connect_errors阈值而被block,只有当tcp验证无法通过的时候才会记录!
四、如果监控此类的错误:
1、事后监控:
可以通过查询select COUNT_HOST_BLOCKED_ERRORS   from performance_schema.host_cache 的值表示被blocked的客户端的连接个数,其中
COUNT_HOST_BLOCKED_ERRORS 表示由于超过max_connect_errors而被block的客户端的连接个数!COUNT_HOST_BLOCKED_ERRORS值为3,代表超过max_connect_errors之后已经阻止了3次客户端连接了,SUM_CONNECT_ERRORS=3表示客户端登录连接报错的累计的次数!
事后监控sql:
select count(*)   from performance_schema.host_cache  where  COUNT_HOST_BLOCKED_ERRORS>0;
2、事前监控:
通过查询
select SUM_CONNECT_ERRORS  from performance_schema.host_cache 这个结果和参数max_connect_errors对比
事前监控sql:
select  (select SUM_CONNECT_ERRORS  from performance_schema.host_cache) / (select VARIABLE_VALUE  from  performance_schema.global_variables  where  VARIABLE_NAME='max_connect_errors')  -----查出来是已经积累的错误占阈值的比例!
关于performance_schema.host_cache中字段COUNT_HOST_BLOCKED_ERRORS的解释如下:
The number of connections that were blocked because SUM_CONNECT_ERRORS exceeded the value of the max_connect_errors system variable
如果host_cache表为空。可能是因为performance_schema参数没开启!
查看官方文档介绍:
The host_cache table provides access to the contents of the host cache, which contains client host name and IP address information and is used to avoid DNS lookups. The host_cache table exposes the contents of the host cache so that it can be examined using SELECT statements. This may help you diagnose the causes of connection problems. The Performance Schema must be enabled or this table is
host_cache表提供对主机缓存内容的访问,其中包含客户机主机名和IP地址信息,用于避免DNS查找。host_cache表公开了主机缓存的内容,以便可以使用SELECT语句检查它。这可以帮助您诊断连接问题的原因。必须启用性能模式,否则此表为空。
可以看到,必须启用性能模式...官方mysql的各个版本performance_schema默认是开启的,但是MariaDB 10.0.12及之后的版本默认是关闭的
MariaDB [(none)]> show variables like 'performance_schema';
+--------------------+-------+
| Variable_name      | Value |
+--------------------+-------+
| performance_schema | OFF   |
+--------------------+-------+
1 row in set (0.00 sec)



请使用浏览器的分享功能分享到微信等