Linux iptables:传入和传出规则示例(SSH 和 HTTP)

在我们之前的 iptables 防火墙系列文章中,我们回顾了如何使用 iptables -A 添加防火墙规则。

我们还解释了如何允许传入的 SSH 连接。在高层次上,它涉及以下 3 个步骤。

  • 删除所有现有规则:“iptables -F”
  • 只允许传入的 SSH:“iptables -A INPUT -i eth0 -p tcp –dport 22 -j ACCEPT”
  • 丢弃所有其他传入的数据包:“iptables -A INPUT -j DROP”

以上工作。但它并不完整。上述步骤的一个问题是它不限制传出数据包。

默认链策略

链的默认策略是 ACCEPT。如果我们不了解链的含义,最好阅读我们的 iptables 介绍文章。因此,INPUT 和 OUTPUT 链的默认策略都是 ACCEPT。在上面的 3 个步骤中,我们在最后丢弃了所有传入的数据包(传入的 ssh 除外)。但是,我们没有限制传出流量。

正如我们在下面注意到的那样,它在所有三个链名称(INPUTOUTPUT 和 FORWARD)旁边都显示“(policy ACCEPT)”。这表明默认的链策略是 ACCEPT。

$ iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     tcp  --  anywhere             anywhere            tcp dpt:ssh
DROP       all  --  anywhere             anywhere            

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

所以,你有两个选择。

选项 1:添加丢弃规则

最后,添加以下三个丢弃规则,它们将丢弃所有传入、传出和转发的数据包(除了在这三个规则之上定义的那些)。 如果你这样做,默认的链策略仍然是 ACCEPT,这无关紧要,因为无论如何你都会丢弃所有的数据包。

iptables -A INPUT -j DROP
iptables -A OUTPUT -j DROP
iptables -A FORWARD -j DROP

选项 2:将默认链策略更改为 DROP

一开始,执行以下三个命令,将链的默认策略更改为 DROP。

iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP

现在,如果我们添加允许 ssh 规则:iptables -A INPUT -i eth0 -p tcp –dport 22 -j ACCEPT,然后执行 iptables -L,我们会注意到它旁边显示“(policy DROP)” 所有三个链。

$ iptables -L
Chain INPUT (policy DROP)
target     prot opt source               destination
ACCEPT     tcp  --  anywhere             anywhere            tcp dpt:ssh
DROP       all  --  anywhere             anywhere            

Chain FORWARD (policy DROP)
target     prot opt source               destination         

Chain OUTPUT (policy DROP)
target     prot opt source               destination

但是这里有一个问题。 允许 ssh 传入连接规则将不再起作用,因为所有传出数据包都被丢弃。


允许传入连接

当 INPUT 和 OUTPUT 链的默认策略为 DROP 时,对于每个传入的防火墙规则,我们需要指定以下两个规则。

  • 请求规则 :这是来自客户端对传入连接的服务器的请求。
  • 响应规则 :这是针对从服务器发出到客户端的响应(针对相应的传入请求)。

示例 1:允许传入 SSH 连接

这是为了允许从外部到我们的服务器的 SSH 连接。 即我们可以从外部 ssh 到我们的服务器。

这涉及两个步骤。 首先,我们需要允许传入的新 SSH 连接。 一旦允许传入的 ssh 连接,我们还需要允许返回对该传入 ssh 连接的响应。

首先,允许传入的 SSH 连接请求,如下所示。

iptables -A INPUT -i eth0 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT

在上面的例子中:

  • iptables -A INPUT :将新规则附加到 INPUT 链。对于传入的连接请求,这始终必须是 INPUT。
  • -i eth0 :这是指输入接口。对于传入连接,这始终必须是“-i”。
  • -p tcp :表示这是针对 TCP 协议的。
  • –dport 22 :这是指传入连接的目标端口。端口 22 用于 ssh。
  • -m state :这表示使用“状态”匹配模块。我们将在以后的文章中讨论更多关于“-m”选项(以及 iptables 的所有可用匹配模块)的信息。
  • –state NEW, ESTABLISHED :“状态”匹配模块的选项。在此示例中,仅允许 NEW 和 ESTABLISHED 状态。第一次从客户端向服务器发起 SSH 连接请求时,使用 NEW 状态。 ESTABLISHED 状态用于从客户端到服务器的所有进一步请求。

接下来,允许传出(仅限 ESTABLISHED 状态)SSH 连接响应(针对相应的传入 SSH 连接请求)。

iptables -A OUTPUT -o eth0 -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT

在上面的例子中:

  • iptables -A OUTPUT:将新规则附加到 OUTPUT 链。 由于这是针对从服务器发出的响应规则(针对相应的传入请求),因此应该是 OUTPUT。
  • -o eth0:这是指输出接口。 对于传出连接,这始终必须是“-o”。
  • -p tcp:表示这是针对 TCP 协议的。
  • –sport 22:这是指传出连接的源端口。 端口 22 用于 ssh。 由于传入请求(来自上一条规则)到达“目标”端口,因此传出响应将通过“源”端口。
  • -m state:这表示使用“状态”匹配模块。
  • –state ESTABLISHED:因为这是一个响应规则,我们只允许 ESTABLISHED 连接(而不是任何 NEW 连接)。

示例 2:允许传入的 HTTP 连接

这是为了允许从外部到我们的服务器的 HTTP 连接。 即我们可以从外部查看您在服务器上运行的网站。

就像上面的 SSH 传入规则一样,这也涉及到两个步骤。 首先,我们需要允许传入的新 HTTP 连接。 一旦允许传入 HTTP 连接,我们需要允许返回该传入 HTTP 连接的响应。

首先,允许传入的 HTTP 连接请求,如下所示。

iptables -A INPUT -i eth0 -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT

接下来,允许传出(仅限 ESTABLISHED)HTTP 连接响应(针对相应的传入 SSH 连接请求)。

iptables -A OUTPUT -o eth0 -p tcp --sport 80 -m state --state ESTABLISHED -j ACCEPT

注意 :在上面的 HTTP 请求和响应规则中,除了端口号之外,一切都与 SSH 示例相同。


允许传出连接

当 INPUT 和 OUTPUT 链的默认策略为 DROP 时,对于每个传出防火墙规则,我们需要指定以下两个规则。

  • 请求规则 :这是从服务器向外发出连接的请求。
  • 响应规则 :这是针对从外部返回到服务器的响应(针对相应的传出请求)。

示例 3:允许传出 SSH 连接

这是为了允许从我们的服务器到外部的 SSH 连接。 即我们可以从服务器 ssh 到外部服务器。

这涉及两个步骤。 首先,我们需要允许传出新的 SSH 连接。 一旦允许传出 ssh 连接,我们还需要允许返回该传出 ssh 连接的响应。

首先,允许传出 SSH 连接请求,如下所示。

iptables -A OUTPUT -o eth0 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT

在上面的例子中:

  • iptables -A OUTPUT :将新规则附加到 OUTPUT 链。 对于传出连接请求,这始终必须是 OUTPUT。
  • -o eth0 :这是指输出接口。 对于传出连接,这始终必须是“-o”。
  • -p tcp :表示这是针对 TCP 协议的。
  • –dport 22 :这是指传出连接的目标端口。
  • -m state :这表示使用“状态”匹配模块。
  • –state NEW, ESTABLISHED :“状态”匹配模块的选项。 在此示例中,仅允许 NEW 和 ESTABLISHED 状态。 第一次从服务器向外部发起 SSH 连接请求时,使用 NEW 状态。 ESTABLISHED 状态用于从服务器到外部的所有进一步请求。

接下来,允许传出(仅限 ESTABLISHED)SSH 连接响应(针对相应的传入 SSH 连接请求)。

iptables -A INPUT -i eth0 -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT

在上面的例子中:

  • iptables -A INPUT:将新规则附加到 INPUT 链。 由于这是针对从外部到服务器的响应规则(针对相应的传出请求),因此应该是 INPUT。
  • -i eth0:这是指输入接口。 对于传入连接,这始终必须是“-i”。
  • -p tcp:表示这是针对 TCP 协议的。
  • –sport 22:这是指传入连接的源端口。 由于传出请求(来自上一条规则)到达“目标”端口,传入响应将来自“源”端口。
  • -m state:这表示使用“状态”匹配模块。
  • –state ESTABLISHED:因为这是一个响应规则,我们只允许 ESTABLISHED 连接(而不是任何 NEW 连接)。

把它们放在一起

创建执行以下操作的 rules.sh shell 脚本:

  • 删除所有现有规则
  • 设置默认链策略
  • 允许入站 SSH
  • 允许入站 HTTP
  • 允许出站 SSH

首先,创建 rules.sh

# 1. Delete all existing rules
iptables -F

# 2. Set default chain policies
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT DROP

# 3. Allow incoming SSH
iptables -A INPUT -i eth0 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -o eth0 -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT

# 4. Allow incoming HTTP
iptables -A INPUT -i eth0 -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -o eth0 -p tcp --sport 80 -m state --state ESTABLISHED -j ACCEPT

# 5. Allow outgoing SSH
iptables -A OUTPUT -o eth0 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A INPUT -i eth0 -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT

接下来,执行 rules.sh 并查看规则。

$ chmod u+x rules.sh

$ ./rules.sh

$ iptables -L
Chain INPUT (policy DROP)
target     prot opt source      destination
ACCEPT     tcp  --  anywhere    anywhere      tcp dpt:ssh state NEW,ESTABLISHED
ACCEPT     tcp  --  anywhere    anywhere      tcp dpt:http state NEW,ESTABLISHED
ACCEPT     tcp  --  anywhere    anywhere      tcp spt:ssh state ESTABLISHED 

Chain FORWARD (policy DROP)
target     prot opt source      destination         

Chain OUTPUT (policy DROP)
target     prot opt source      destination
ACCEPT     tcp  --  anywhere    anywhere      tcp spt:ssh state ESTABLISHED
ACCEPT     tcp  --  anywhere    anywhere      tcp spt:http state ESTABLISHED
ACCEPT     tcp  --  anywhere    anywhere      tcp dpt:ssh state NEW,ESTABLISHED

以此为基础,我们应该能够编写自己的传入和传出 iptables 防火墙规则。 iptables 中还有很多内容需要介绍。 敬请关注!