Bug #24761 | dropped TCP connections not logged as errors but result in blocked host | ||
---|---|---|---|
Submitted: | 1 Dec 2006 20:50 | Modified: | 29 Sep 2008 13:24 |
Reporter: | Joshua Franklin | Email Updates: | |
Status: | Verified | Impact on me: | |
Category: | MySQL Server: General | Severity: | S3 (Non-critical) |
Version: | 5.0.36-BK, 5.0.27, 5.1, 6.0.7 | OS: | Linux (Linux (Fedora)) |
Assigned to: | Assigned Account | CPU Architecture: | Any |
Tags: | affects_connectors |
[1 Dec 2006 20:50]
Joshua Franklin
[3 Dec 2006 10:04]
Valeriy Kravchuk
Thank you for a problem report. Please, read the manual (http://dev.mysql.com/doc/refman/5.0/en/communication-errors.html, http://dev.mysql.com/doc/refman/5.0/en/error-log.html) and try with log_warnings=2.
[4 Dec 2006 19:46]
Joshua Franklin
I already mentioned that we tried that and there was nothing in the log. You can easily verify this yourself with nmap.
[4 Dec 2006 22:23]
Joshua Franklin
Here is a more clear example. On testhost (Fedora Core 6, mysqld 5.0.27) I have added the following to /etc/my.cnf: log-long-format log_warnings=2 log-error=/var/log/mysql/error.log log=/var/log/qmysql.log log-error=/var/log/mysqld.log max_connect_errors=1 The following is a sample session from remotehost: [joshuadf]$ mysql -p -h testhost TESTDB Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 22 to server version: 5.0.27-log Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql> quit; Bye [joshuadf]$ telnet testhost 3306 Trying 192.168.0.30... Connected to testhost (192.168.0.30). Escape character is '^]'. 8 5.0.27-logP=}~&<;T,uqYF5rcyX-u' Bad handshakeConnection closed by foreign host. [joshuadf]$ [joshuadf]$ telnet testhost 3306 Trying 192.168.0.30... Connected to testhost (192.168.0.30). Escape character is '^]'. 8 5.0.27-log=0w+l`|q,A1nXOax[>d]' Bad handshakeConnection closed by foreign host. [joshuadf]$ telnet testhost 3306 Trying 192.168.0.30... Connected to testhost (192.168.0.30). Escape character is '^]'. {Host 'remotehost' is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts'Connection closed by foreign host. [joshuadf]$ mysql -p -h testhost TESTDB Enter password: ERROR 1129 (00000): Host 'remotehost' is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts' Please note that if the client "mysql" program is used, the error is logged, but when just "telnet" is used there is no logging. The complete log for this test is: 061204 14:14:55 21 Connect root@localhost on 21 Query flush hosts 21 Quit 061204 14:15:16 22 Connect joshuadf@remotehost on TESTDB 22 Query show databases 22 Query show tables 061204 14:15:19 22 Quit
[16 Jan 2007 23:16]
Patrick Feliciano
I have encountered the same problem with 5.0.26
[12 Feb 2007 17:34]
Valeriy Kravchuk
Please, clarify where is the bug here? According to http://dev.mysql.com/doc/refman/5.0/en/blocked-host.html, you are explicitely required your host to be blocked after one interrupted connection request. And you had not aborted conection (that should be logged with log_warnings=2), but rather not yet established connection. So, this looks like a new feature request to me. Do you agree?
[13 Feb 2007 18:24]
Joshua Franklin
No, it is not a feature request. The bug is that even with log_warnings=2 nothing is logged. http://dev.mysql.com/doc/refman/5.0/en/error-log.html says "Aborted connections are not logged to the error log unless the value is greater than 1." This means that with log_warnings=2 aborted connections should be logged to the error log. Again, the logging only fails if you are NOT using a mysql client program (or jdbc, etc.) but instead just open the TCP port with telnet or netcat or nagios. If you do not know how to test just use "telnet testhost 3306" several times. Nothing appears in the log even with log_warnings=2.
[13 Feb 2007 18:36]
Joshua Franklin
Sorry, another way of looking at the bug is that a TCP connect should not be counted as a failed attempt if the connection is not established. So in the case of a TCP connect ("telnet testhost 3306") either: --do not count as a failed connection attempt <- bugfix opportunity --no logging required (current behavior) OR --count a TCP connect as a failed connection attempt (current behavior) --log it when log_warnings=2 <- bugfix opportunity
[14 Feb 2007 13:17]
Valeriy Kravchuk
Verified based on your last comment with 5.0.36-BK on Linux: openxs@suse:~/dbs/5.0> bin/mysql -uroot test Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 1 Server version: 5.0.36 Source distribution Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql> show global status like '%abort%'; +------------------+-------+ | Variable_name | Value | +------------------+-------+ | Aborted_clients | 0 | | Aborted_connects | 0 | +------------------+-------+ 2 rows in set (0.00 sec) Now, from other shell: openxs@suse:~> telnet localhost 3306 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. 4 5.0.36 ☻ 9:W'Xi&} ,☻ hq|?aL7oI^!% Connection closed by foreign ho st. openxs@suse:~> Let's check: mysql> show global status like '%abort%'; +------------------+-------+ | Variable_name | Value | +------------------+-------+ | Aborted_clients | 0 | | Aborted_connects | 1 | +------------------+-------+ 2 rows in set (0.00 sec) mysql> exit Bye openxs@suse:~/dbs/5.0> tail var/suse.err InnoDB: Have you moved InnoDB .ibd files around without using the InnoDB: commands DISCARD TABLESPACE and IMPORT TABLESPACE? InnoDB: It is also possible that this is a temporary table #sql..., InnoDB: and MySQL removed the .ibd file for this. InnoDB: Please refer to InnoDB: http://dev.mysql.com/doc/refman/5.0/en/innodb-troubleshooting.html InnoDB: for how to resolve the issue. 070214 13:53:21 InnoDB: Started; log sequence number 1 1106293645 070214 13:53:21 [Note] /home/openxs/dbs/5.0/libexec/mysqld: ready for connection s. Version: '5.0.36' socket: '/tmp/mysql.sock' port: 3306 Source distribution So, this attempt was treated as aborted connection, but not logged. It is a bug.
[21 Feb 2007 19:25]
Konstantin Osipov
Thank you for writing to us. The described behaviour corresponds to the manual: If Aborted connections messages appear in the error log, the cause can be any of the following: * The client program did not call mysql_close() before exiting. * The client had been sleeping more than wait_timeout or interactive_timeout seconds without issuing any requests to the server. See Section 5.2.3, “System Variables”. * The client program ended abruptly in the middle of a data transfer. When any of these things happen, the server increments the Aborted_clients status variable. The server increments the Aborted_connects status variable when the following things happen: * A client doesn't have privileges to connect to a database. * A client uses an incorrect password. * A connection packet doesn't contain the right information. * It takes more than connect_timeout seconds to get a connect packet. See Section 5.2.3, “System Variables”. As you can see from this explanation, the error message is printed only when one of the three reasons occur: no mysql_close(), connect timeout, data transfer error. All of these errors can occur on an already established connection. Generally, the idea is to print a warning when something spooky is going on with the client application. The warning is not printed on an authentication error - this can potentially cause a Denial Of Service: if a mailicious user tries to open and close loads of connections, MySQL Server will have to fight for the error log mutex trying to log all the failing attempts. So, the server does not print anything to the log when a connection that is not yet authenticated is aborted. I am providing the maintenance team with instructions how to fix this below, but I believe this is not a bug in behaviour - the code works as designed. At best we should clarify this in the manual. Please feel free to reopen this bug report if you have additional information. Tim: the function that needs a fix is check_connection(). Search for the call to inc_host_errors() - you will see that no warning is printed to the log there. If check_connection returns an error, handle_one_connection function terminates silently, without writing anything to the log: if ((error=check_connection(thd))) { // Wrong permissions if (error > 0) net_printf_error(thd, error, sctx->host_or_ip); #ifdef __NT__ if (vio_type(net->vio) == VIO_TYPE_NAMEDPIPE) my_sleep(1000); /* must wait after eof() */ #endif statistic_increment(aborted_connects,&LOCK_status); goto end_thread; } (Nothing is printed in end_thread label either). Here's the place that logs the warning - it is alrady after do_command loop, that is, it is executed only if do_command returned an error: if (net->error && net->vio != 0 && net->report_error) { if (!thd->killed && thd->variables.log_warnings > 1) sql_print_warning(ER(ER_NEW_ABORTING_CONNECTION), thd->thread_id,(thd->db ? thd->db : "unconnected"), sctx->user ? sctx->user : "unauthenticated", sctx->host_or_ip, (net->last_errno ? ER(net->last_errno) : ER(ER_UNKNOWN_ERROR))); net_send_error(thd, net->last_errno, NullS); statistic_increment(aborted_threads,&LOCK_status); }
[21 Feb 2007 22:23]
Joshua Franklin
I cannot agree that this is "not a bug in behaviour". There is no technical reason for a failed attempt to be counted but not logged if the connection is not established. It is already a possible denial of service vector; if "a mailicious user tries to open and close loads of connections" the MySQL server blocks the host! It might even be possible to block an arbitrary host by setting the source header for the tcp connect() calls. If you're worried about the system performance in writing to the error log, the correct behavior would be not to increment Aborted_connects.
[23 Feb 2007 13:11]
Jeff Potter
I'd like to add support for Joshua's position -- we are running into the same problem; and would like to see MySQL fix this. It is most certainly a bug that it locks out users and does not log it. Our preference would be that tcp connections with no login attempt do not count toward any lock-out.
[6 Aug 2007 13:50]
Brendan Byrd
I also concur that this is a security bug. If nothing is logged, yet the action will eventually block the connection, there is no way to track what is causing the connection to go down. There is also a possible DoS scenario without any tracking in the log.
[27 Sep 2008 10:59]
Konstantin Osipov
I believe this was fixed in 6.0, needs to be re-verified.
[28 Sep 2008 7:13]
Valeriy Kravchuk
I do not know what was fixed, but my test case gives exactly the same results with 6.0.7 from bzr: openxs@suse:/home2/openxs/dbs/6.0> bin/mysql -uroot test Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 1 Server version: 6.0.7-alpha-debug Source distribution Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql> show variables like '%warn%'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | log_warnings | 2 | | sql_warnings | OFF | | warning_count | 0 | +---------------+-------+ 3 rows in set (0.00 sec) mysql> show global status like '%abort%'; +------------------+-------+ | Variable_name | Value | +------------------+-------+ | Aborted_clients | 0 | | Aborted_connects | 0 | +------------------+-------+ 2 rows in set (0.02 sec) Now, from other shell: openxs@suse:/home2/openxs/dbs/5.1> telnet localhost 3306 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. ? 6.0.7-alpha-debugg>?aK3^?^>X#A_;F.R4Connection closed by foreign host. openxs@suse:/home2/openxs/dbs/5.1> This attempt was counted as aborted connect: mysql> show global status like '%abort%'; +------------------+-------+ | Variable_name | Value | +------------------+-------+ | Aborted_clients | 0 | | Aborted_connects | 1 | +------------------+-------+ 2 rows in set (0.00 sec) But nothing is logged in the error log: mysql> exit Bye openxs@suse:/home2/openxs/dbs/6.0> tail var/suse.err 080813 12:58:27 InnoDB: Starting shutdown... 080813 12:58:28 InnoDB: Shutdown completed; log sequence number 0 48117 080813 12:58:28 [Note] /home2/openxs/dbs/6.0/libexec/mysqld: Shutdown complete 080813 12:58:28 mysqld_safe mysqld from pid file /home2/openxs/dbs/6.0/var/suse.pid ended 080901 21:59:30 mysqld_safe Starting mysqld daemon with databases from /home2/openxs/dbs/6.0/var 080901 21:59:35 InnoDB: Started; log sequence number 0 48117 080901 21:59:37 [Note] Event Scheduler: Loaded 0 events 080901 21:59:37 [Note] /home2/openxs/dbs/6.0/libexec/mysqld: ready for connections. Version: '6.0.7-alpha-debug' socket: '/tmp/mysql.sock' port: 3306 Source distribution
[29 Sep 2008 8:03]
Konstantin Osipov
OK, it was fixed differently: /* Log the command before authentication checks, so that the user can check the log for the tried login tried and also to detect break-in attempts. */ general_log_print(thd, command, (thd->main_security_ctx.priv_user == thd->main_security_ctx.user ? (char*) "%s@%s on %s" : (char*) "%s@%s as anonymous on %s"), thd->main_security_ctx.user, thd->main_security_ctx.host_or_ip, db ? db : (char*) ""); So, this is logged in the general log at least. I was reviewing a patch that added more logging, but I can't remember the worklog task number.
[29 Sep 2008 8:04]
Konstantin Osipov
The reason the behavior described in the report is default is that printing messages to the error log can significantly bog down performance. If we decide to fix the bug, we should perhaps have an option for this behavior.
[29 Sep 2008 13:24]
Joshua Franklin
I'd just like to point out that blocking connections also has some pretty serious performance issues. If you can't connect, performance drops to zero while the poor admin is trying to figure out what's going on with no logging to work with.
[1 Dec 2008 20:22]
Collen Blijenberg
hmmm, but is this fixed in the 5.x series aswell... since we will not use an alpha version on a production server.. find it odd aswell, blocking users but not telling it in the log.. toke me a week to figure out the prob.
[1 Dec 2008 20:55]
Valeriy Kravchuk
This is NOT fixed yet in any version. But currently we are going to fix it only in 6.0 and up.
[3 Dec 2008 10:18]
Collen Blijenberg
Would be nice to know what hosts are blocked. (list blocked hosts) i mean, i would like to know who or what is attacking the system. only a counter with abort counts will not cut it for most system admins... We'll wait and see.... Thx..
[5 Jun 2009 0:48]
James Day
Collen, adding a SHOW HOSTS CACHE feature is covered by bug #22821. It seems more likely to arrive as an information schema table, but no idea when or if it will happen.
[9 Nov 2009 17:45]
James Day
One way to address this without introducing a denial of service vulnerability would be logging only the change of a host from not blocked to blocked. Not a lot of load except in a DDoS case. A log entry when the count reaches 75% of the limit would also be nice.
[20 Jul 2015 13:14]
Simon Bazley
I'm using 5.5 and have the same issue. How can I identify when a host has had a problem (and I need to run flush hosts), when I can't check a log, or a status, to identify that a particular host is blocked?.