PostgreSQL 连接攻击(类似DDoS)
背景
客户端请求连接数据库后,会提示客户端输入用户密码,如果客户端不输入密码,那么数据库服务端会在一个超时时间后,断开连接。
也就是说,在服务端主动断开连接前,这个连接实际上需要占用一个SLOT,也就是max_connection中的一个。
https://www.postgresql.org/docs/9.6/static/runtime-config-connection.html#RUNTIME-CONFIG-CONNECTION-SECURITY
authentication_timeout (integer)
Maximum time to complete client authentication, in seconds.
If a would-be client has not completed the authentication protocol in this much time, the server closes the connection.
This prevents hung clients from occupying a connection indefinitely.
The default is one minute (1m). This parameter can only be set in the postgresql.conf file or on the server command line.
另一个参数是客户端连接超时参数,与攻击没什么关系,我这里只是拿出来给大家了解一下。
https://www.postgresql.org/docs/9.6/static/libpq-connect.html#LIBPQ-CONNECT-CONNECT-TIMEOUT
connect_timeout
Maximum wait for connection, in seconds (write as a decimal integer string).
Zero or not specified means wait indefinitely.
It is not recommended to use a timeout of less than 2 seconds.
攻击者可以利用这个规则,并发的发起大量连接请求,但是不提供密码,等待服务端的超时,这样可以把max_connection的连接都占用掉。
现象
用户如果连接被占满,其他正常的请求发起的连接会遇到连接不足的报错。
53300 too_many_connections
同时在pg_stat_activity中查询到的count(*)小于实际的max_connection配置,
因为没有认证成功的连接还不会出现在pg_stat_activity会话中。
防范措施
1、不要暴露监听端口。
2、如果监听端口一定要暴露,建议使用源IP鉴权,过滤非法IP,规避大部分攻击。
3、配置pg_hba.conf,鉴权IP,DB,USER,规避大部分的攻击。
4、配置用户、DB级连接限制,即使被攻击了,也可以保证一部分连接是可以被使用。除非攻击者知道所有的数据库名、用户名,对其进行攻击。否则就占用不掉所有连接。
相关问题
即使不是DDoS攻击,用户也可能遇到类似的问题。
例如在数据库非常繁忙时,用户请求响应变慢,用户的应用程序堆积了很多请求,这些请求需要新建与数据库的连接,由于本身数据库非常繁忙响应变慢,加上爆炸性的高并发连接请求使得PG服务端的fork操作变慢,返回auth消息包在此之后(所以造成了类似现象)。
因此用户如果遇到这样的诡异问题,pg_stat_activity中显示的连接数比max_connection小,确无法连接数据库(报too_many_connections的错误),那么可以看看是不出现了DDoS攻击或者是数据库繁忙导致。