The error reporting of one of my services reported problems to connect to my MySQL server. This problems were not consistent, it just happened a few times to different servers.
I started debugging using strace
and noticed that MySQL is reading both /etc/hosts.allow
and /etc/hosts.deny
every time it tries to open a new connection:
read(127, "# /etc/hosts.allow: list of hosts that are allowed to access the system.\n# See the manual pages hosts_access(5) and hosts_options(5).\n#\n# Example: ALL: LOCAL @some_netgroup\n# ALL: .foobar.edu EXCEPT terminalserver.foobar.edu\n#\n# If you're going to protect the portmapper use the name \"portmap\" for the\n# daemon name. Remember that you can only use the keyword \"ALL\" and IP\n# addresses (NOT host or domain names) for the portmapper, as well as for\n# rpc.mountd (the NFS mount daemon). See portmap(8) and rpc.mountd(8)\n# for further information.\n#\n\n", 4096) = 580
read(127, "", 4096) = 0
close(127) = 0
munmap(0x7f94533f9000, 4096) = 0
open("/etc/hosts.deny", O_RDONLY) = 127
fstat(127, {st_mode=S_IFREG|0644, st_size=880, ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f94533f9000
read(127, "# /etc/hosts.deny: list of hosts that are _not_ allowed to access the system.\n# See the manual pages hosts_access(5) and hosts_options(5).\n#\n# Example: ALL: some.host.name, .some.domain\n# ALL EXCEPT in.fingerd: other.host.name, .other.domain\n#\n# If you're going to protect the portmapper use the name \"portmap\" for the\n# daemon name. Remember that you can only use the keyword \"ALL\" and IP\n# addresses (NOT host or domain names) for the portmapper, as well as for\n# rpc.mountd (the NFS mount daemon). See portmap(8) and rpc.mountd(8)\n# for further information.\n#\n# The PARANOID wildcard matches any host whose name does not match its\n# address.\n#\n# You may wish to enable this to ensure any programs that don't\n# validate looked up hostnames still leave understandable logs. In past\n# versions of Debian this has been the default.\n# ALL: PARANOID\n\n", 4096) = 880
read(127, "", 4096) = 0
close(127) = 0
[...]
getpeername(127, {sa_family=AF_INET, sin_port=htons(33362), sin_addr=inet_addr("10.2.3.19")}, [16]) = 0
getsockname(127, {sa_family=AF_INET, sin_port=htons(3306), sin_addr=inet_addr("10.2.2.9")}, [16]) = 0
I guess this is the expected behaviour, but I want to know if is there any way I can bypass the read of those files? I think just adding the ip address to the /etc/hosts.allow
will do it (as the IP will be matched from that file and the deny wont be read)...
MySQL Server doesn't read these files by itself, it's TCP Wrappers library that's responsible. You can compile MySQL without support for the library, but I see no point to cripple it, because you're right in that an IP addresses from allow file is not checked against deny file, so just do it if you want to whitelist it.
But if your connection problems are random, I'd likely look for another reason.
I would guess that the server has something like fail2ban or denyhosts running on it, they have features which keep track of failed login attempts and have configurable
bantime
and reset on successful. Even if they are not necessarily configured to keep track of MySQL login failures, they can keep track of other login failures such like SSH, and if configured to use/etc/hosts.deny
, and then MySQL would pick that up.I would recommend you to go to the bottom of why these clients end up in that file in the first place, and then make an educated decision based on what you find out.
If it is any of the two tools which is populating the
/etc/hosts.deny
file for you, they can be configured to ignore certain IP ranges, maybe you want to allow rfc1918? I would take no such action, however, without understanding what makes those clients appear in that file in the first place.