如何在Ubuntu14.04上使用iptables设置防火墙

来自菜鸟教程
跳转至:导航、​搜索

介绍

设置一个好的防火墙是保护任何现代操作系统的重要步骤。 大多数 Linux 发行版都附带了一些不同的防火墙工具,我们可以使用它们来配置我们的防火墙。 在本指南中,我们将介绍 iptables 防火墙。

iptables 是默认情况下包含在大多数 Linux 发行版中的标准防火墙(称为 nftables 的现代变体将开始取代它)。 它实际上是可以操纵 Linux 网络堆栈的内核级 netfilter 钩子的前端。 它通过将通过网络接口的每个数据包与一组规则进行匹配来决定要做什么来工作。

在之前的指南中,我们了解了 iptables 规则如何阻止不需要的流量 。 在本指南中,我们将转到一个实际示例来演示如何为 Ubuntu 14.04 服务器创建基本规则集。 生成的防火墙将允许 SSH 和 HTTP 流量。

注意: 本教程涵盖 IPv4 安全性。 在 Linux 中,IPv6 的安全性与 IPv4 分开维护。 例如,“iptables”仅维护 IPv4 地址的防火墙规则,但它有一个称为“ip6tables”的 IPv6 对应项,可用于维护 IPv6 网络地址的防火墙规则。

如果您的 VPS 配置为 IPv6,请记住使用适当的工具保护您的 IPv4 和 IPv6 网络接口。 有关 IPv6 工具的更多信息,请参阅本指南:如何配置工具以在 Linux VPS 上使用 IPv6


先决条件

在开始使用本教程之前,您应该在服务器上设置一个单独的非 root 超级用户帐户(具有 sudo 权限的用户)。 如果您需要进行设置,请遵循以下指南:Initial Server Setup with Ubuntu 14.04

基本 iptables 命令

现在您已经对 iptables 概念有了很好的理解,我们应该涵盖将用于形成复杂规则集和管理 iptables 接口的基本命令。

首先,您应该知道 iptables 命令必须以 root 权限运行。 这意味着您需要以 root 身份登录,使用 susudo -i 来获得 root shell,或者在所有命令前加上 sudo。 我们将在本指南中使用 sudo,因为这是 Ubuntu 系统上的首选方法。

一个好的起点是列出为 iptables 配置的当前规则。 您可以使用 -L 标志来做到这一点:

sudo iptables -L
Output:Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

如您所见,我们有三个默认链(INPUT、OUTPUT 和 FORWARD)。 我们还可以看到每个链的默认策略(每个链都有 ACCEPT 作为其默认策略)。 我们还看到了一些列标题,但没有看到任何实际规则。 这是因为 Ubuntu 没有附带默认规则集。

我们可以通过使用 -S 标志以反映启用每个规则和策略所需命令的格式查看输出:

sudo iptables -S
Output:-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT

要复制配置,我们只需要输入 sudo iptables,然后输入输出中的每一行。 (根据配置,如果我们远程连接,实际上可能会稍微复杂一些,这样我们就不会在规则到位之前制定默认丢弃策略来捕获并允许我们当前的连接。)

如果您 do 有规则并希望废弃它们并重新开始,您可以通过键入以下内容来刷新当前规则:

sudo iptables -F

再一次,默认策略在这里很重要,因为虽然所有规则都从您的链中删除,但默认策略将 not 使用此命令更改。 这意味着,如果您是远程连接的,则应确保在刷新规则之前将 INPUT 和 OUTPUT 链上的默认策略设置为 ACCEPT。 您可以通过键入以下内容来执行此操作:

sudo iptables -P INPUT ACCEPT
sudo iptables -P OUTPUT ACCEPT
sudo iptables -F

然后,您可以在建立明确允许连接的规则后将默认丢弃策略更改回 DROP。 稍后我们将讨论如何做到这一点。

制定你的第一条规则

我们将开始构建我们的防火墙策略。 正如我们上面所说,我们将使用 INPUT 链,因为这是传入流量将通过的渠道。 我们将从上面讨论过的规则开始:明确接受当前 SSH 连接的规则。

我们需要的完整规则是:

sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

这可能看起来非常复杂,但是当我们检查组件时,大部分都会有意义:

  • -A INPUT-A 标志 规则附加到链的末尾。 这是命令的一部分,它告诉 iptables 我们希望添加一个新规则,我们希望将该规则添加到链的末尾,并且我们想要操作的链是 INPUT 链。

  • -m conntrack:iptables 有一套核心功能,但也有一套扩展或提供额外能力的模块。

    在这部分命令中,我们声明我们希望能够访问 conntrack 模块提供的功能。 该模块允许访问可用于根据数据包与先前连接的关系做出决策的命令。

  • –ctstate:这是通过调用 conntrack 模块提供的命令之一。 该命令允许我们根据数据包与我们之前看到的数据包的关系来匹配数据包。

    我们将 ESTABLISHED 的值传递给它,以允许作为现有连接一部分的数据包。 我们将 RELATED 的值传递给它以允许与已建立的连接关联的数据包。 这是与我们当前的 SSH 会话匹配的规则部分。

  • -j ACCEPT:指定匹配数据包的目标。 在这里,我们告诉 iptables 符合上述条件的数据包应该被接受并允许通过。

我们把这条规则放在开头是因为我们想确保我们已经使用的连接在达到任何 DROP 规则之前被匹配、接受并从链中拉出。

如果我们列出规则,我们可以看到变化:

sudo iptables -L
Output:Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

现在您知道了一般语法,让我们继续添加一些我们想要接受连接的情况。

接受其他必要的连接

我们已经告诉 iptables 保持打开任何已经打开的连接并允许与这些连接相关的新连接。 但是,我们需要创建一些规则来确定何时要接受不符合这些条件的新连接。

我们希望专门保持两个端口打开。 我们希望保持我们的 SSH 端口打开(我们将在本指南中假设这是默认的 22。 如果您在 SSH 配置中更改了此项,请在此处修改您的值)。 我们还将假设这台计算机在默认端口 80 上运行 Web 服务器。 如果您不是这种情况,则不必添加该规则。

我们将用于添加这些规则的两行代码是:

sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT

如您所见,这些与我们的第一条规则非常相似,但可能更简单。 新选项是:

  • -p tcp:如果使用的协议是 TCP,则此选项匹配数据包。 这是一个基于连接的协议,将被大多数应用程序使用,因为它允许可靠的通信。
  • –dport:如果给出了 -p tcp 标志,则此选项可用。 它进一步要求匹配数据包的目标端口。 第一条规则匹配发往端口 22 的 TCP 数据包,而第二条规则匹配指向端口 80 的 TCP 流量。

我们还需要一条接受规则来确保我们的服务器能够正常运行。 通常,计算机上的服务通过相互发送网络数据包来相互通信。 他们通过使用称为 loopback device 的伪网络接口来做到这一点,该接口将流量引导回自身而不是其他计算机。

因此,如果一个服务想要与另一个正在侦听端口 4555 上的连接的服务进行通信,它可以向环回设备的端口 4555 发送一个数据包。 我们希望允许这种类型的行为,因为它对于许多程序的正确运行至关重要。

我们需要添加的规则是:

sudo iptables -I INPUT 1 -i lo -j ACCEPT

这看起来与我们的其他命令有点不同。 让我们回顾一下它在做什么:

  • -I INPUT 1-I 标志告诉 iptables insert 一条规则。 这与将规则附加到末尾的 -A 标志不同。 -I 标志采用链和要插入新规则的规则位置。

    在这种情况下,我们将此规则添加为 INPUT 链的第一条规则。 这将降低其余规则。 我们希望它位于顶部,因为它是基本的,不应受到后续规则的影响。

  • -i lo:如果数据包使用的接口是“lo”接口,则规则的这个组件匹配。 “lo”接口是回送设备的另一个名称。 这意味着任何使用该接口进行通信的数据包(在我们的服务器上为我们的服务器生成的数据包)都应该被接受。

要查看我们当前的规则,我们应该使用 -S 标志。 这是因为 -L 标志不包含一些信息,例如与规则绑定的接口,这是我们刚刚添加的规则的重要部分:

sudo iptables -S
Output:-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT

实施丢弃规则

我们现在有四个单独的规则,它们根据某些标准明确接受数据包。 但是,我们的防火墙目前没有阻止 任何

如果一个数据包进入 INPUT 链并且不匹配我们制定的四个规则之一,它将被传递到我们的默认策略,即无论如何都接受该数据包。 我们需要改变这一点。

我们有两种不同的方法可以做到这一点,但有一些非常重要的区别。

我们可以做到这一点的第一种方法是修改 INPUT 链的默认策略。 我们可以通过键入:

sudo iptables -P INPUT DROP

这将捕获通过我们的 INPUT 链的任何数据包,并丢弃它们。 这就是我们所说的默认丢弃策略。 这种设计的一个含义是,如果规则被刷新,它会退回到丢弃数据包。

这可能更安全,但如果您没有其他方式访问服务器,也会产生严重后果。 使用 DigitalOcean,如果发生这种情况,您可以通过我们的 Web 控制台登录以访问您的服务器。 Web 控制台充当虚拟本地连接,因此 iptables 规则不会影响它。

如果规则被转储,您可能希望您的服务器自动断开所有连接。 这将防止您的服务器被完全打开。 这也意味着您可以轻松地将规则附加到链的底部,同时仍然可以随意丢弃数据包。

另一种方法是将链的默认策略保持为接受,并添加一个规则,将所有剩余的数据包丢弃到链本身的底部。

如果您更改了上述 INPUT 链的默认策略,则可以通过键入以下内容将其设置回跟随:

sudo iptables -P INPUT ACCEPT

现在,您可以在链的底部添加一条规则,该规则将丢弃任何剩余的数据包:

sudo iptables -A INPUT -j DROP

正常操作条件下的结果与默认丢弃策略完全相同。 此规则通过匹配到达它的 每个 剩余数据包来工作。 这可以防止数据包从 ever 一路丢弃通过链到达默认策略。

基本上,这用于保持默认策略以接受流量。 这样,如果有任何问题并且规则被刷新,您仍然可以通过网络访问机器。 这是一种在不更改将应用于空链的策略的情况下实现默认操作的方法。

当然,这也意味着您希望添加到链末尾的任何附加规则都必须在删除规则之前添加。 您可以通过暂时删除删除规则来做到这一点:

sudo iptables -D INPUT -j DROP
sudo iptables -A INPUT new_rule_here
sudo iptables -A INPUT -j DROP

或者,您可以通过指定行号在链的末尾(但在删除之前)插入您需要的规则。 要在第 4 行插入规则,您可以键入:

sudo iptables -I INPUT 4 new_rule_here

如果您无法知道每条规则的行号,您可以通过键入以下命令告诉 iptables 对规则进行编号:

sudo iptables -L --line-numbers
Output:Chain INPUT (policy DROP)
num  target     prot opt source               destination         
1    ACCEPT     all  --  anywhere             anywhere            
2    ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
3    ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:ssh
4    ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:http

Chain FORWARD (policy ACCEPT)
num  target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination

这有助于确保您将规则添加到适当的位置。

列出和删除 iptables 规则

如果您想了解有关列出和删除 iptables 规则的详细信息,请查看本教程:如何列出和删除 iptables 防火墙规则

保存你的 iptables 配置

默认情况下,您添加到 iptables 的规则是临时的。 这意味着当您重新启动服务器时,您的 iptables 规则将消失。

这实际上是某些用户的一项功能,因为如果他们不小心将自己锁定在服务器之外,它可以为他们提供重新进入的途径。 但是,大多数用户会想要一种方法来自动保存您创建的规则并在服务器启动时加载它们。

有几种方法可以做到这一点,但最简单的方法是使用 iptables-persistent 包。 您可以从 Ubuntu 的默认存储库下载它:

sudo apt-get update
sudo apt-get install iptables-persistent

在安装过程中,系统会询问您是否要保存当前规则以自动加载。 如果您对当前配置感到满意(并且您已经测试了创建独立 SSH 连接的能力,则可以选择保存当前规则。

它还会询问您是否要保存已配置的 IPv6 规则。 这些是通过一个名为 ip6tables 的单独实用程序配置的,它以几乎相同的方式控制 IPv6 数据包的流。

安装完成后,您将拥有一个名为 iptables-persistent 的新服务,该服务配置为在启动时运行。 此服务将加载您的规则并在服务器启动时应用它们。

保存更新

如果您曾经更新防火墙并希望保留更改,则必须保存 iptables 规则以使它们保持不变。

使用以下命令保存防火墙规则:

sudo invoke-rc.d iptables-persistent save

结论

您现在应该有一个很好的起点来开发满足您需求的防火墙。 还有许多其他防火墙实用程序,有些可能更容易,但 iptables 是一个很好的学习工具,因为它公开了一些底层的 netfilter 结构,并且因为它存在于许多系统中。

要了解有关使用 iptables 保护网络的更多信息,请查看以下教程: