所以,这是情况。 看来我们需要在世界上有一个开放的TCP端口5432,客户可以访问他的PostgreSQL数据库。
出于显而易见的原因,我们不能只说“不”,只能作为最后一招。
最大的麻烦是什么? 我如何捍卫我们的基础设施?
不pipe怎样:为什么不能向世界开放呢? 我想,也许这比20年前没有维护的FTP服务器更安全。
PS VPN不好。 一些encryption也许 (如果我可以给他一个JDBC连接的URL的作品 )。
需要SSL,保持SELinux打开,监视日志,并使用当前的PostgreSQL版本 。
在postgresql.conf
设置ssl=on
并确保你的密钥文件和certfile安装正确(请参阅文档和postgresql.conf
的注释)。
您可能需要从CA购买证书,如果您希望在客户端没有特殊设置的情况下让它信任客户端。
在pg_hba.conf
使用类似于:
hostssl theuser thedatabase 1.2.3.4/32 md5
…可能对于用户和/或数据库具有“全部”,并且可能具有更宽的源IP地址filter。
如果可能的话,不要让用户“全部” 如果可以避免超级用户login,则不需要远程login。
限制可以login的用户的权限。不要赋予他们CREATEDB
或CREATEUSER
权限。
在所有数据库上从PUBLIC
REVOKE
CONNECT
权限,然后仅将其返回给应该能够访问该数据库的用户/angular色。 (将用户分组到angular色的angular色和授予权限,而不是直接授予个人用户)。
确保具有远程访问权限的用户只能连接到他们需要的数据库,并且只有他们实际需要的模式,表和列的权限。 对于本地用户来说这也是一个很好的做法,这只是明智的安全性。
在PgJDBC中,传递参数ssl=true
:
要指示JDBC驱动程序尝试build立SSL连接,您必须添加连接URL参数ssl = true。
…并将服务器证书安装在客户端的信任库中,或者如果您不希望用户必须安装证书,则可以使用Java内置信任库中某个CA所信任的服务器证书。
现在确保你保持PostgreSQL是最新的 。 PostgreSQL只有一些预授权的安全漏洞,但是这比零多,所以保持最新。 无论如何,错误修正是很好的事情。
如果有大型networking区块/区域,您不需要从中访问,请在前面添加防火墙。
logging连接和断开连接(请参阅postgresql.conf
)。 logging查询是否可行。 如果可行的话,在前面运行入侵检测系统或fail2ban或类似的。 对于使用postgres的fail2ban,这里有一个方便的方法
监视日志文件。
额外的步骤来思考…
如果需要,还可以使用pg_hba.conf
来要求客户端提供服务器信任的X.509客户端证书。 它不需要使用与服务器证书相同的CA,您可以使用自制openssl CA来执行此操作。 JDBC用户需要使用keytool
将客户端证书导入到他们的Java Keystore中,并且可能configuration一些JSSE系统属性以将Java指向它们的密钥库,因此它不完全透明。
如果你想真正偏执狂,那么在一个单独的容器/虚拟机中,或者至less在不同的用户帐户下,只用他们需要的数据库来运行客户端的实例。
这样,如果他们妥协的PostgreSQL实例,他们不会得到任何进一步的。
我不应该这样说,但是…
运行带有SELinux支持(如RHEL 6或7)的机器, 不要closuresSELinux或将其设置为宽容模式 。 保持执行模式。
安全只是默默无闻。 安全性,一旦你做了合理的东西,使用一点默默无闻,可能不会受到伤害。
在非默认端口上运行Pg,使自动攻击者的生活变得困难一些。
您也可以在PostgreSQL之前运行PgBouncer或PgPool-II,充当连接池和代理。 这样你可以让代理处理SSL,而不是真正的数据库主机。 代理可以在单独的VM或机器上。
无论如何,使用连接池代理通常是PostgreSQL的一个好主意,除非客户端应用程序已经有一个内置的池。 大多数Java应用程序服务器,Rails等都有内置的池。 即使这样,一个服务器端共享代理是最坏的无害。
Craigs简单的扩展令人印象深刻的行动计划:
也许用户只使用相对较less的networking提供商(例如,移动时他的移动networking提供商,他的有线networking从家庭和工作场所传出工作ip)。
大多数networking提供商有许多IP,但不是很多的子网。 所以,你可以给iptablesfilter,这限制了postgresql访问你的客户使用的网段。 这大大降低了networking随机select的故障源的攻击可能性。
一个简单的支持scheme:
tcpdump -i eth0 -p tcp port 5432
命令,他从哪里来。 whois 1.2.3.4
你可以得到这个ip使用的ip地址。 例如,它可以是1.2.3.0/24
。 iptables -A INPUT -s 1.2.3.0/24 -p tcp --dport 5432 -j ACCEPT
(或者类似的)你可以使用他的新子网的tcp连接。 有一个非常好的名为uif
perl脚本,可以提供永久和直观的可声明的iptables规则集。 (Google for“uif iptables”)。
这里有一个相当简单的基于HOWTO的PostgreSQL的Fail2banconfiguration,但是经过微调,可以真正的使用Ubuntu软件包,捕获另一个错误条件并跳过各种debugging消息使其更快:
/etc/fail2ban/filter.d/local-postgresql.conf
:
[Definition] failregex = <HOST>\(\d+\) FATAL: password authentication failed for .+$ <HOST>\(\d+\) FATAL: no pg_hba.conf entry for host .+$ ignoreregex = duration:
/etc/fail2ban/jail.d/local-postgresql.conf
:
[local-postgresql] enabled = true filter = local-postgresql action = iptables[name=PostgreSQL, port=5432, protocol=tcp] sendmail-whois[name=PostgreSQL, dest=root@localhost] logpath = /var/log/postgresql/postgresql-9.3-main.log maxretry = 3
Fail2ban是一个function强大的工具,但不要相信filter可以正常工作。 使用failregex工具testing任何filter,并记住转义任何引号(即“pipe理员”将是“pipe理员”)。 作为一个例子,从我的/etc/log/postgresql/postgresql-9.3-main.logtesting下面的filterfailregex行不适用于我。
fail2ban-regex '2016-09-20 14:30:09 PDT FATAL: password authentication failed for user "admin"' '<HOST>\(\d+\) FATAL: password authentication failed for .+$'
以上给了我
Failregex:共计0个
我不得不更新failregex来匹配日志格式。
fail2ban-regex '2016-09-20 14:30:09 PDT FATAL: password authentication failed for user "admin"' 'FATAL: password authentication failed for user \"<HOST>\"'
这给了我一个积极的结果。
Failregex:总共1个
fail2ban-regextesting也可以在整个日志文件上实现。
fail2ban-regex /var/log/postgresql/postgresql-9.3-main.log /etc/fail2ban/filter.d/postgresql.local
以上给了我以下积极的结果与更新的failregex。
Failregex:总共169个