介绍
实施防火墙是保护服务器的重要一步。 其中很大一部分是决定将对网络实施流量限制的各个规则和策略。 如防火墙iptables
也让你有一个关于在应用您的规则的结构框架发言权。
在本指南中,我们将构建一个防火墙,作为更复杂规则集的基础。 此防火墙将主要侧重于提供合理的默认值,并建立一个鼓励轻松扩展的框架。 我们将在Ubuntu 14.04服务器上演示这个。
先决条件
在开始之前,您应该对希望实现的防火墙策略有基本的了解。 您可以按照本指南得到一些你应该思考的东西更好的主意。
为了跟进,您需要访问Ubuntu 14.04服务器。 我们将使用与配置的非root用户sudo
权限在本指南。 你可以学习如何在我们的配置此类型的用户的Ubuntu 14.04服务器初始设置指南 。
完成后,请继续下面。
安装持久防火墙服务
要开始,你需要安装iptables-persistent
包,如果你还没有这样做的话。 这将允许我们保存我们的规则集,并让它们在启动时自动应用:
sudo apt-get update
sudo apt-get install iptables-persistent
在安装过程中,系统会询问您是否要保存当前规则。 在这里说“是”。 我们将立即编辑生成的规则文件。
本指南中的有关IPv6的注意事项
在开始之前,我们应该简要介绍IPv4和IPv6。 在iptables
命令只处理IPv4流量。 对于IPv6流量,称为一个独立的配套工具ip6tables
使用。 规则存储在单独的表和链中。 对于iptables-persistent
,IPv4的规则写入和读取/etc/iptables/rules.v4
和IPv6的规则都保存在/etc/iptables/rules.v6
。
本指南假定你不积极使用IPv6的服务器上。 如果您的服务不利用IPv6,则完全阻止访问是更安全的,正如我们在本文中所做的。
实施基本防火墙策略(快速方式)
为了尽快开始和运行,我们将向您展示如何直接编辑规则文件以复制和粘贴已完成的防火墙策略。 随后,我们将解释的总体战略,并告诉你如何这些规则可以使用来实现iptables
命令,而不是修改文件。
为了实现我们的防火墙政策和框架,我们将编辑/etc/iptables/rules.v4
和/etc/iptables/rules.v6
文件。 打开rules.v4
用文本编辑器文件sudo
权限:
sudo nano /etc/iptables/rules.v4
在里面,你会看到一个看起来像这样的文件:
# Generated by iptables-save v1.4.21 on Tue Jul 28 13:29:56 2015
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT
# Completed on Tue Jul 28 13:29:56 2015
用以下内容替换内容:
*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
保存并关闭文件。
您可以通过键入此命令来测试文件的语法错误。 修复在继续之前显示的任何语法错误:
sudo iptables-restore -t /etc/iptables/rules.v4
接下来,打开/etc/iptables/rules.v6
文件来修改IPv6规则:
sudo nano /etc/iptables/rules.v6
我们可以通过使用以下配置替换文件的内容来阻止所有IPv6流量:
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
COMMIT
*raw
:PREROUTING DROP [0:0]
:OUTPUT DROP [0:0]
COMMIT
*nat
:PREROUTING DROP [0:0]
:INPUT DROP [0:0]
:OUTPUT DROP [0:0]
:POSTROUTING DROP [0:0]
COMMIT
*security
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
COMMIT
*mangle
:PREROUTING DROP [0:0]
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
:POSTROUTING DROP [0:0]
COMMIT
保存并关闭文件。
为了检验该文件的语法错误,我们可以使用ip6tables-restore
使用命令-t
选项:
sudo ip6tables-restore -t /etc/iptables/rules.v6
当两个规则文件都没有报告语法错误时,您可以通过键入以下内容来应用规则:
sudo service iptables-persistent reload
这将立即实施您的文件中概述的策略。 您可以通过列出验证这个iptables
当前使用的规则:
sudo iptables -S
sudo ip6tables -S
这些防火墙规则将在每次引导时重新应用。 测试以确保您仍然可以登录,并且所有其他访问被阻止。
我们的通用防火墙策略的解释
在我们使用上述规则构建的基本防火墙中,我们创建了一个可扩展的框架,可以轻松调整以添加或删除规则。 对于IPv4流量,我们主要关心的是INPUT
的内链filter
表。 这个链将处理发往我们服务器的所有数据包。 我们还允许所有传出的流量,并拒绝所有的数据包转发,这只是适当的,如果这个服务器作为一个路由器为其他主机。 我们接受所有其他表中的数据包,因为我们只想在本指南中过滤数据包。
一般来说,我们的规则设置了一个防火墙,默认情况下会拒绝入站流量。 然后,我们会为我们希望从此策略中排除的服务和流量类型创建例外。
在主INPUT
链中,我们已经增加了对交通一些通用的规则,我们有信心将永远是同样的方式处理。 例如,我们总是想拒绝被认为是“无效”的数据包,并且我们总是希望允许本地环回接口上的流量和与已建立的连接相关联的数据。
然后,我们根据它使用的协议匹配流量,并将其拖放到协议特定的链。 这些协议特定的链意味着保存匹配和允许特定服务的业务的规则。 在这个例子中,我们允许的唯一服务就是SSH在我们的TCP
链。 如果我们提供另一个服务,如HTTP(S)服务器,我们也可以添加这里的异常。 这些链将是您大部分定制的焦点。
不匹配协议特定的通用规则或服务规则的任何流量通过在过去的几年规则处理INPUT
链。 我们已经设置了默认的策略,以DROP
我们的防火墙,它会否认,通过我们的规则回落包。 然而,在年底的规则INPUT
链拒绝数据包并发送消息到模仿如何,如果有该端口上没有运行服务的服务器会回应客户端。
对于IPv6流量,我们只是删除所有流量。 我们的服务器没有使用此协议,因此最好不要与流量交互。
(可选)更新Nameservers
阻止所有IPv6流量可能会干扰您的服务器如何解决Internet上的问题。 例如,这可能会影响您如何使用APT。
如果当您尝试运行得到这样的错误apt-get update
:
Err http://security.ubuntu.com trusty-security InRelease
Err http://security.ubuntu.com trusty-security Release.gpg
Could not resolve 'security.ubuntu.com'
. . .
您应该按照此部分来使APT再次工作。
首先,将您的Nameservers设置为外部Nameservers。 此示例使用Google的Nameservers。 开放/etc/network/interfaces
编辑:
sudo nano /etc/network/interfaces
更新dns-nameservers
行,如下所示:
. . .
iface eth0 inet6 static
address 2604:A880:0800:0010:0000:0000:00B2:0001
netmask 64
gateway 2604:A880:0800:0010:0000:0000:0000:0001
autoconf 0
dns-nameservers 8.8.8.8 8.8.4.4
刷新您的网络设置:
sudo ifdown eth0 && sudo ifup eth0
预期输出为:
RTNETLINK answers: No such process
Waiting for DAD... Done
接下来,创建一个新的防火墙规则,以便在可用时强制IPv4。 创建此新文件:
sudo nano /etc/apt/apt.conf.d/99force-ipv4
将此单行添加到文件:
Acquire::ForceIPv4 "true";
保存并关闭文件。 现在你应该能够使用APT。
使用IPTables命令实现我们的防火墙
现在你明白我们建立了政策背后的总体思路,我们将走过你怎么可能去创造使用这些规则iptables
命令。 我们将最终得到与上面指定的相同的规则,但我们将通过迭代地添加规则来创建我们的策略。 由于iptables
立即应用每个规则,规则排序是非常重要的(我们离开否认数据包,直到年底的规则)。
重置防火墙
我们将从重置我们的防火墙规则开始,以便我们可以看到如何从命令行构建策略。 您可以通过键入以下命令来刷新所有规则:
sudo service iptables-persistent flush
您可以通过键入以下内容来验证您的规则是否已重置:
sudo iptables -S
应该看到,在规则filter
表中消失,且默认策略设置为ACCEPT
所有链:
output-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
创建特定于协议的链
我们将从创建我们所有的协议特定的链开始。 这些将用于保存规则,这些规则为我们要公开的服务的拒绝策略创建例外。 我们将创建一个UDP
流量,一个用于TCP
,一个用于ICMP
:
sudo iptables -N UDP
sudo iptables -N TCP
sudo iptables -N ICMP
我们可以立即行动,并添加SSH流量的例外。 SSH使用TCP,因此我们将添加一条规则来接受以TCP端口为端口22的TCP流量:
sudo iptables -A TCP -p tcp --dport 22 -j ACCEPT
如果我们想要添加额外的TCP服务,我们现在可以通过重复该命令替换端口号。
创建通用接受和拒绝规则
在INPUT
链中,所有的传入流量开始过滤,我们需要增加我们的通用规则。 这些是一些常识规则,通过接受低风险的流量(本地流量和与我们已经检查的连接相关联的流量)并丢弃明显无用(无效数据包)的流量,为防火墙设置基准。
首先,我们将创建一个异常来接受作为已建立连接的一部分或与已建立连接相关的所有流量:
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
此规则使用conntrack
延伸,其提供内部跟踪以便iptables
具有它需要评估分组作为较大的连接的一部分,而不是作为分立的,无关的分组流上下文。 TCP是基于连接的协议,因此已建立的连接是相当明确的。 对于UDP和其他无连接协议,已建立的连接是指已经看到响应的流量(原始数据包的源将是响应数据包的目标,反之亦然)。 相关连接是指与现有连接相关联地启动的新连接。 这里的典型示例是FTP数据传输连接,其将与已经建立的FTP控制连接相关。
我们还希望允许所有源自本地环回接口的流量。 这是由服务器生成并指定给服务器的流量。 它由主机上的服务使用以彼此通信:
sudo iptables -A INPUT -i lo -j ACCEPT
最后,我们要拒绝所有无效的数据包。 数据包可能由于多种原因而无效。 它们可以指不存在的连接,它们可以指定用于不存在的接口,地址或端口,或者它们可能简单地畸形。 在任何情况下,我们将删除所有无效的数据包,因为没有适当的方式来处理它们,并且它们可能代表恶意活动:
sudo iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
创建到特定于协议的链的跳转规则
到目前为止,我们已经创造了一些通用规则INPUT
链,为我们的特定协议链中的特定服务,接受一些规则。 然而,现在,交通进入了INPUT
链中,并没有达到我们的特定协议链的方式。
我们需要将流量在INPUT
链到适当的特定协议链。 我们可以匹配协议类型将其发送到正确的链。 我们还将确保该数据包表示一个新的连接(任何建立的或相关的连接应该已经被更早地处理)。 对于TCP数据包,我们将添加额外的要求,即数据包是一个SYN数据包,这是启动TCP连接的唯一有效类型:
sudo iptables -A INPUT -p udp -m conntrack --ctstate NEW -j UDP
sudo iptables -A INPUT -p tcp --syn -m conntrack --ctstate NEW -j TCP
sudo iptables -A INPUT -p icmp -m conntrack --ctstate NEW -j ICMP
拒绝所有剩余流量
如果传递给特定协议链的包也没有内匹配任何规则,控制将被传递回INPUT
链。 任何达到这一点的东西不应该被我们的防火墙所允许。
我们将使用拒绝流量REJECT
靶,其发送响应消息给客户端。 这允许我们指定出站消息,以便我们可以模拟在客户端尝试向常规关闭端口发送数据包时给出的响应。 响应取决于客户端使用的协议。
尝试到达关闭的UDP端口将导致ICMP“端口不可达”消息。 我们可以通过键入:
sudo iptables -A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
尝试在关闭的端口上建立TCP连接将导致TCP RST响应:
sudo iptables -A INPUT -p tcp -j REJECT --reject-with tcp-reset
对于所有其他数据包,我们可以发送ICMP“协议不可达”消息,指示服务器不响应该类型的数据包:
sudo iptables -A INPUT -j REJECT --reject-with icmp-proto-unreachable
调整默认策略
我们添加的最后三个规则应该处理的所有剩余流量INPUT
链。 但是,我们应该设置默认的策略, DROP
作为预防措施。 我们还应该设置此政策的FORWARD
链,如果这个服务器没有配置为路由器到其他机器:
sudo iptables -P INPUT DROP
sudo iptables -P FORWARD DROP
DROP
,如果你清楚你iptables
用sudo iptables -F
,当前的SSH连接将被丢弃!
带冲洗sudo iptables-persistent flush
是一个更好的办法来清除规则,因为它会重置默认策略为好。
为了配合我们删除所有的交通IPv6策略,我们可以使用下面的ip6tables
命令:
sudo ip6tables -P INPUT DROP
sudo ip6tables -P FORWARD DROP
sudo ip6tables -P OUTPUT DROP
这应该相当密切地复制我们的规则。
保存IPTables规则
在这一点上,您应该测试您的防火墙规则,并确保它们覆盖阻止您想要保持的流量,而不会阻碍您的正常访问。 一旦您确信规则运行正常,您可以保存它们,以便在引导时将其自动应用于您的系统。
键入以下内容保存当前规则(IPv4和IPv6):
sudo service iptables-persistent save
这将覆盖/etc/iptables/rules.v4
和/etc/iptables/rules.v6
文件,你在命令行上制作的策略。
结论
按照本指南,通过将防火墙规则直接粘贴到配置文件中,或通过在命令行上手动应用和保存防火墙规则,您已创建了良好的启动防火墙配置。 您将必须添加单个规则,以允许访问您想要提供的服务。
本指南中建立的框架应允许您轻松进行调整,并有助于澄清现有政策。 查看我们的一些其他指南,了解如何使用一些常用服务构建您的防火墙策略: