介绍
它可能会诱人地认为,因为一个服务器最近被提出来,看到很少的流量,或提供任何似乎有价值的黑客,它会没有注意到。
允许远程连接是最常见和更容易纠正的情况之一,可能导致PostgreSQL数据库的剥削,这是因为某些配置使类似此类程序更容易发现服务器。
在本教程中,我们将展示如何减轻允许远程连接所造成的特定风险.虽然这是一个重要的第一步,因为服务器可能以其他方式受到威胁,我们还建议您采取额外的措施来保护您的数据,如在 额外的安全考虑中所述。
背景
要了解我们正在减轻的具体风险,想象服务器作为一个商店. 如果服务器在任何端口上倾听,这有点像打开一种开放
标志。
我们可以认为每个端口是进入商店的方式,比如门或窗口. 这些入口可能被打开,关闭,锁定或破坏,取决于正在收听的软件的状态,但在公共界面上收听意味着试图进入的脚本可以开始尝试。 例如,脚本可能会被配置为尝试使用默认密码登录,如果它没有更改,它可能会尝试听取戴蒙的已知利用,如果它没有被修补。
当我们限制像postgresql
这样的大门在本地聆听时,就好像那门到外面不存在一样。没有下一步可以尝试,至少在 Postgres 方面。防火墙和 VPN 以类似的方式保护。在本教程中,我们将专注于删除 PostgreSQL 作为公开访问的大门。为了保护大门本身或数据在传输或存储时,请参阅 额外的安全考虑。
前提条件
在本教程中,我们将使用 两个Ubuntu安装,一个用于数据库主机,一个作为将远程连接到主机的客户端。每一个都应该有一个sudo
用户和启用防火墙。
一个 Ubuntu 16.04 PostgreSQL 数据库主机:
如果您尚未安装 PostgreSQL,您可以使用以下命令:
1sudo apt-get update
2sudo apt-get install postgresql postgresql-contrib
One Ubuntu 16.04 客户端机:
为了证明和测试允许远程连接,我们将使用 PostgreSQL 客户端, psql
。
1[environment second]
2sudo apt-get update
3sudo apt-get install postgresql-client
当这些先决条件到位时,你准备跟随。
了解默认配置
当PostgreSQL从Ubuntu软件包安装时,默认情况下,它仅限于 localhost上收听,此默认设置可以通过在postgresql.conf文件中代替listen_addresses
,但默认情况会阻止服务器在公共接口上自动收听。
此外,pg_hba.conf 文件只允许从 Unix/Linux 域接口和服务器的本地回路地址进行连接,因此它不会接受来自外部主机的连接:
1[label replace]
2# Put your actual configuration here
3# ----------------------------------
4#
5# If you want to allow non-local connections, you need to add more
6# "host" records. In that case you will also need to make PostgreSQL
7# listen on a non-local interface via the listen_addresses
8# configuration parameter, or via the -i or -h command line switches.
9
10# DO NOT DISABLE!
11# If you change this first entry you will need to make sure that the
12# database superuser can access the database using some other method.
13# Noninteractive access to all databases is required during automatic
14# maintenance (custom daily cronjobs, replication, and similar tasks).
15#
16# Database administrative login by Unix domain socket
17local all postgres peer
18
19# TYPE DATABASE USER ADDRESS METHOD
20
21# "local" is for Unix domain socket connections only
22local all all peer
23# IPv4 local connections:
24host all all 127.0.0.1/32 md5
25# IPv6 local connections:
26host all all ::1/128 md5
这些默认功能满足了在公共界面上不听的目标,如果我们将它们保持不受影响并保持防火墙,我们已经完成了!我们可以直接进入 额外的安全考虑,以了解如何保护传输中的数据。
如果您需要从远程主机连接,我们将在下一节中介绍如何取消默认设置以及您可以采取的即时步骤来保护服务器。
设置远程连接
对于生产设置,在我们开始处理敏感数据之前,理想情况下,我们会使用 SSL 加密的 PostgreSQL 流量,通过外部防火墙保护或通过虚拟私人网络(VPN)保护。
步骤 1 – 添加用户和数据库
要做到这一点,我们将使用PostgreSQL客户端psql
作为管理用户postgres
连接。通过将-i
选项转移到sudo
我们将运行postgres用户的登录壳,确保我们从.profile
或其他登录特定的资源中加载选项。
1sudo -i -u postgres psql
接下来,我们将创建一个具有密码的用户,请确保使用安全密码,而不是下面的示例:
1CREATE USER sammy WITH PASSWORD 'password';
当用户成功创建时,我们应该收到以下输出:
1[secondary_label Output]
2CREATE ROLE
<$>[注] 注: 自 PostgreSQL 8.1 以来,ROLES 和 USERS 是同义词。根据惯例,具有密码的角色仍然被称为用户,而不被称为角色的角色,所以有时我们会在输出中看到ROLE,我们可能会期待看到用户。
接下来,我们将创建一个数据库,并为我们的新用户提供完整的访问权限。 最佳实践建议我们仅向用户提供他们需要的访问权限,并且仅向他们应该拥有的资源提供访问权限,因此根据使用情况,您可以进一步限制用户的访问权限,您可以在《如何在VPS上使用角色和管理PostgreSQL的授权权限》(How To Use Roles and Manage Grant Permissions in PostgreSQL)指南中了解更多有关权限的信息。
1CREATE DATABASE sammydb OWNER sammy;
当数据库成功创建时,我们应该收到确认:
1[secondary_label Output]
2CREATE DATABASE
现在,我们已经创建了一个用户和数据库,我们将离开监视器。
1\q
按下Enter后,我们将在命令提示器上,并准备继续。
步骤 2 – 配置 UFW
在 Ubuntu 16.04 初始服务器设置前提下,我们启用了 UFW 并只允许 SSH 连接。
1sudo ufw status
<$>[注]
注: 如果输出表示防火墙不活跃
,我们可以通过:
1sudo ufw enable
一旦启用,重启状态命令,sudo ufw status
将显示当前的规则。
1sudo ufw allow OpenSSH
美元
除非我们对前提条件进行了更改,否则输出应该显示只有 OpenSSH 是允许的:
1[secondary_label Output]
2Status: active
3
4To Action From
5-- ------ ----
6OpenSSH ALLOW Anywhere
7OpenSSH (v6) ALLOW Anywhere (v6)
现在我们已经检查了防火墙的状态,我们将允许访问PostgreSQL端口,并将其限制在我们想要允许的主机或主机上。
下面的命令将为 PostgreSQL 默认端口添加规则,即 5432. 如果您已更改该端口,请确保在下面的命令中更新它。
1sudo ufw allow from client_ip_address to any port 5432
若要对规则进行双重检查,我们可以再次运行ufw status
:
1sudo ufw status
1[secondary_label Output]
2To Action From
3-- ------ ----
4OpenSSH ALLOW Anywhere
55432 ALLOW client_ip_address
6OpenSSH (v6) ALLOW Anywhere (v6)
<$>[注] 注: 如果您是新的UFW,您可以在指南中了解更多信息 UFW Essentials: Common Firewall Rules and Commands。
有了这个防火墙规则,我们现在将配置 PostgreSQL 以倾听其公共 IP 地址,这需要两个设置的组合,一个在 pg_hba.conf 中的连接主机的输入和在
postgresql.conf 中的 listen_addresses 的配置。
步骤 3 – 配置允许的主机
我们将通过在「pg_hba.conf」中添加主机条目开始。如果您安装了不同的PostgreSQL版本,请确保在下面的路径中更换它:
1sudo nano /etc/postgresql/9.5/main/pg_hba.conf
我们将将主机
行放置在描述如何允许非本地连接的评论块下。我们还将包含数据库服务器的公共地址的行,以便我们可以快速测试我们的防火墙是否正确配置。
1[label Excerpt from pg_hba.conf]
2# If you want to allow non-local connections, you need to add more
3# "host" records. In that case you will also need to make PostgreSQL
4# listen on a non-local interface via the listen_addresses
5# configuration parameter, or via the -i or -h command line switches.
6host sammydb sammy client_ip_address/32 md5
在保存更改之前,在您想要更改某些选项的情况下,让我们专注于本行中的每个值:
- host
第一个参数,
host
,确定将使用 TCP/IP 连接。 - database
sammydb
第二列表示主机可以连接到哪个数据库/s。 可以通过将名称与符号分开来添加多个数据库。 - user**
sammy
表示允许进行连接的用户。 与数据库列一样,可以指定多个用户,以符号分开。 - address 地址指定客户端机地址或地址,并可能包含主机名称、IP地址范围或其他特殊的关键字(https://www.postgresql.org/docs/9.5/static/auth-pg-hba-conf.html)。 在上面的例子中,我们允许我们的
有关这些和其他设置的详细讨论,请参阅 PostgreSQL 文档。
一旦完成,保存并退出文件。
步骤 4 – 配置倾听地址
接下来,我们将设置postgresql.conf
文件中的收听地址:
1sudo nano /etc/postgresql/9.5/main/postgresql.conf
查找listen_addresses
行,在其下方,定义您的收听地址,确保取代您的数据库主机的主机名称或IP地址。
1[label postgresql.conf]
2#listen_addresses = 'localhost' # what IP address(es) to listen on;
3listen_addresses = 'localhost,server_ip_address'
完成后,保存并退出文件。
第5步:重新启动PostgreSQL
直到我们重新启动 PostgreSQL 示例之前,我们的配置更改不会生效,所以在我们测试之前,我们会这样做:
1sudo systemctl restart postgresql
由于systemctl
没有提供反馈,我们将检查状态,以确保戴蒙成功重新启动:
1sudo systemctl status postgresql
如果输出包含活跃:活跃
,并以如下方式结束,则 PostgreSQL 示例正在运行。
1[secondary_label Output]
2...
3Jan 10 23:02:20 PostgreSQL systemd[1]: Started PostgreSQL RDBMS.
现在我们重新启动了戴蒙,我们已经准备好进行测试。
步骤6:测试
最後,讓我們測試我們是否可以從我們的客戶機器上連接。要做到這一點,我們將使用「psql」與「-U」來指定使用者,「-h」來指定客戶端的 IP 位址,以及「-d」來指定資料庫,因為我們已經加強了我們的安全性,使「sammy」只能連接到一個單一的資料庫。
1[environment second]
2psql -U sammy -h postgres_host_ip -d sammydb
如果一切都配置正确,您应该收到以下提示:
1[secondary_label Output]
2[environment second]
3Password for user sammy:
输入您之前在 PostgreSQL 监视器中添加用户sammy
时设置的密码。
如果您到达以下提示,您已成功连接:
1[secondary_label]
2[environment second]
3sammydb=>
这证实我们可以通过防火墙连接到数据库,我们现在将退出:
1[environment second]
2\q
由于我们已经确认了我们的配置,我们将通过清理完成。
步骤 7 – 删除测试数据库和用户
回到主机,一旦我们完成了测试连接,我们可以使用以下命令删除数据库和用户。
1sudo -i -u postgres psql
删除数据库:
1DROP DATABASE sammydb;
该行动由以下输出证实:
1[secondary_label Output]
2DROP DATABASE
删除用户:
1DROP USER sammy;
成功得到了证实:
1[secondary_label Output]
2DROP ROLE
我们将通过从pg_hba.conf
文件中删除sammydb
数据库的主机条目来完成清理,因为我们不再需要它:
1sudo nano /etc/postgresql/9.5/main/pg_hba.conf
1[label Line to remove from `pg_hba.conf`]
2host sammydb sammy client_ip_address/32 md5
为了更改生效,我们将保存和退出,然后重新启动数据库服务器:
1sudo systemctl restart postgresl
为了确保它成功重新启动,我们将检查状态:
1sudo systemctl status postgres
如果我们看到活跃:活跃
,我们会知道重新启动成功。
在此时,我们可以继续配置需要远程连接的客户端上的应用程序或服务。
额外的安全考虑
本教程旨在减轻允许不受保护的远程连接到 PostgreSQL 的风险,这是一个常见的情况,无意间将 PostgreSQL 暴露在剥削中。
在使用真实数据之前,我们建议您查看以下资源,并为您的使用案例采取适当步骤。
- PostgreSQL 内部安全性:GRANT 声明决定哪些用户被允许访问任何特定数据库,而角色建立了这些用户的特权。结合起来,它们在一个安装中提供多个数据库之间的分离。
- 设置 SSL 与 PostgreSQL:配置 SSL 将加密过境中的数据。这保护数据的发送。
- 使用 SSH 隧道确保 PostgreSQL TCP/IP 连接: SSH 隧道在连接客户端时非常有用。在几乎任何其他情况下,最好使用 Postgres 设置 SSL。
结论
在本教程中,我们采取了必不可少的步骤,以防止广告我们的PostgreSQL安装,通过配置服务器的防火墙只允许访问需要的主机的连接,并通过配置PostgreSQL只接受这些主机的连接。