介绍
将应用程序设置中的离散组件部署到不同的节点是减少负载并开始水平扩展的常用方法。 典型的示例是在与应用程序不同的服务器上配置数据库。 尽管此设置具有许多优点,但通过网络连接涉及一组新的安全问题。
在本指南中,我们将演示如何在分布式设置中的每个服务器上设置简单的防火墙。 我们将配置我们的策略以允许组件之间的合法流量,同时拒绝其他流量。
对于本指南中的演示,我们将使用两个Ubuntu 14.04服务器。 一个将具有与Nginx一起提供的WordPress实例,另一个将托管应用程序的MySQL数据库。 虽然我们将使用此设置作为示例,您应该能够推断所涉及的技术,以适应您自己的服务器要求。
先决条件
要开始,你必须有两个新的Ubuntu 14.04服务器。 添加普通用户帐户使用sudo
每个权限。 要了解如何正确地做到这一点,按照我们的Ubuntu 14.04服务器初始设置指南 。
我们将保护应用程序的设置是基于本指南 。 如果你想跟随,按照教程指示设置你的应用程序和数据库服务器。
设置基本防火墙
我们将首先为每个服务器实施基准防火墙配置。 我们将实施的政策采取基于安全的方法。 我们将锁定几乎除SSH流量以外的一切,然后在防火墙中戳我们的特定应用程序。
在防火墙本指南提供了我们所需要的基本设置。 安装iptables-persistent
包并粘贴基本规则到/etc/iptables/rules.v4
文件:
sudo apt-get update
sudo apt-get install iptables-persistent
sudo nano /etc/iptables/rules.v4
*filter
# Allow all outgoing, but drop incoming and forwarding packets by default
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
# Custom per-protocol chains
:UDP - [0:0]
:TCP - [0:0]
:ICMP - [0:0]
# Acceptable UDP traffic
# Acceptable TCP traffic
-A TCP -p tcp --dport 22 -j ACCEPT
# Acceptable ICMP traffic
# Boilerplate acceptance policy
-A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
-A INPUT -i lo -j ACCEPT
# Drop invalid packets
-A INPUT -m conntrack --ctstate INVALID -j DROP
# Pass traffic to protocol-specific chains
## Only allow new connections (established and related should already be handled)
## For TCP, additionally only allow new SYN packets since that is the only valid
## method for establishing a new TCP connection
-A INPUT -p udp -m conntrack --ctstate NEW -j UDP
-A INPUT -p tcp --syn -m conntrack --ctstate NEW -j TCP
-A INPUT -p icmp -m conntrack --ctstate NEW -j ICMP
# Reject anything that's fallen through to this point
## Try to be protocol-specific w/ rejection message
-A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
-A INPUT -p tcp -j REJECT --reject-with tcp-reset
-A INPUT -j REJECT --reject-with icmp-proto-unreachable
# Commit the changes
COMMIT
*raw
:PREROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
COMMIT
*security
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT
*mangle
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
COMMIT
如果你在一个真实环境中实施这一不重装你的防火墙规则呢 。 加载此处概述的基本规则集将立即删除应用程序和数据库服务器之间的连接。 在重新加载之前,我们需要调整规则以反映我们的操作需求。
发现您的服务正在使用的港口
为了添加异常以允许我们的组件之间的通信,我们需要知道正在使用的网络端口。 我们可以通过检查我们的配置文件找到正确的网络端口,但是找到正确端口的应用程序不可知的方法是检查哪些服务正在监听我们每台机器上的连接。
我们可以使用netstat
工具来发现这一点。 由于我们的应用程序仅通信通过IPv4,我们将添加-4
说法,但你可以删除,如果你使用的是IPv6为好。 其他参数,我们需要以找到我们正在运行的服务是-plunt
。
在您的网络服务器上,我们会看到这样的:
sudo netstat -4plunt
OutputActive Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1058/sshd
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 4187/nginx
第一个突出显示的列显示了服务突出显示的行末端正在侦听的IP地址和端口。 特别0.0.0.0
地址是指有问题的服务上所有可用的地址听。
在我们的数据库服务器上,我们会看到这样的:
sudo netstat -4plunt
OutputActive Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1097/sshd
tcp 0 0 192.0.2.30:3306 0.0.0.0:* LISTEN 3112/mysqld
您可以读取这些列完全相同。 在上述的例子中, 192.0.2.30
地址表示数据库服务器的私有IP地址。 在应用程序设置中,出于安全原因,我们将MySQL锁定到私有接口。
记下您在此步骤中找到的值。 这些是我们需要的网络详细信息,以调整我们的防火墙配置。
在我们的示例场景中,我们可以注意到,在我们的Web服务器上,我们需要确保以下端口可访问:
- 端口80在所有地址
- 端口22在所有地址(已在防火墙规则中考虑)
我们的数据库服务器必须确保以下端口可访问:
- 上的地址端口3306
192.0.2.30
(或与之相关联的接口) - 端口22在所有地址(已在防火墙规则中考虑)
调整Web服务器防火墙规则
现在我们有了我们需要的端口信息,我们将调整我们的Web服务器的防火墙规则集。 在您的编辑器中打开规则文件sudo
权限:
sudo nano /etc/iptables/rules.v4
在Web服务器上,我们需要将端口80添加到可接受的流量列表中。 由于服务器正在侦听所有可用的地址,因此我们不会根据接口或目标地址限制规则。
我们的网站访问者将使用TCP协议进行连接。 我们的基本框架已调用自定义链TCP
的TCP应用程序异常。 我们可以添加端口80到该链,在我们的SSH端口的例外下面:
*filter
. . .
# Acceptable TCP traffic
-A TCP -p tcp --dport 22 -j ACCEPT
-A TCP -p tcp --dport 80 -j ACCEPT
. . .
我们的Web服务器将启动与我们的数据库服务器的连接。 我们的出站流量不受我们的防火墙限制,并且允许与已建立的连接相关联的入站流量,因此我们不必在此服务器上打开任何其他端口允许此连接。
保存并在完成后关闭文件。 我们的网络服务器现在有一个防火墙策略,将允许所有合法流量,同时阻止一切。
测试规则文件是否存在语法错误:
sudo iptables-restore -t < /etc/iptables/rules.v4
如果未显示语法错误,请重新加载防火墙以实现新规则集:
sudo service iptables-persistent reload
调整数据库服务器防火墙规则
在我们的数据库服务器,我们需要允许访问端口3306
上我们的服务器的私有IP地址。 在我们的例子中,该地址是192.0.2.30
。 我们可以限制专门针对此地址的访问,或者我们可以通过与分配该地址的接口匹配来限制访问。
要查找与该地址关联的网络接口,请键入:
ip -4 addr show scope global
Output2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
inet 203.0.113.5/24 brd 104.236.113.255 scope global eth0
valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
inet 192.0.2.30/24 brd 192.0.2.255 scope global eth1
valid_lft forever preferred_lft forever
突显区域显示, eth1
接口与地址相关联。
接下来,我们将调整数据库服务器上的防火墙规则。 打开的规则文件sudo
数据库服务器上权限:
sudo nano /etc/iptables/rules.v4
同样,我们将增加一条规则,我们的TCP
链,形成我们的Web服务器和数据库服务器之间的连接异常。
如果您希望根据相关实际地址限制访问,则可以按如下所示添加规则:
*filter
. . .
# Acceptable TCP traffic
-A TCP -p tcp --dport 22 -j ACCEPT
-A TCP -p tcp --dport 3306 -d 192.0.2.30 -j ACCEPT
. . .
如果您希望根据包含该地址的接口允许异常,则可以添加与此类似的规则:
*filter
. . .
# Acceptable TCP traffic
-A TCP -p tcp --dport 22 -j ACCEPT
-A TCP -p tcp --dport 3306 -i eth1 -j ACCEPT
. . .
保存并在完成后关闭文件。
使用此命令检查语法错误:
sudo iptables-restore -t < /etc/iptables/rules.v4
准备好后,重新加载防火墙规则:
sudo service iptables-persistent reload
您的两个服务器现在应该受到保护,而不限制它们之间的必要数据流。
结论
在设置应用程序时,实施正确的防火墙应始终是部署计划的一部分。 虽然我们演示了使用运行Nginx和MySQL的两个服务器来提供WordPress实例的此配置,但无论您的具体技术选择如何,以上演示的技术都适用。
要了解更多关于防火墙和iptables
具体,看看以下指南: