配置防火墙iptables

介绍

实施防火墙是保护服务器安全的重要一步。其中很大一部分是决定将对您的网络实施流量限制的单个规则和策略。像iptables这样的防火墙还允许您对应用规则的结构框架有发言权。

在本指南中,您将学习如何构建防火墙,作为更复杂规则集的基础。该防火墙将主要关注提供合理的默认值和建立鼓励扩展性的框架。

安装持久防火墙服务

首先更新本地包缓存:

1
apt update

现在安装iptables-persistent软件包。这允许您保存规则集,并在引导时自动应用它们:

1
apt install iptables-persistent

在安装过程中,系统会询问您是否要保存当前规则,请选择****。请注意,您将运行netfilter-persistent命令来执行iptables永久防火墙服务。接下来,您将编辑生成的规则文件。

本指南中关于IPv6的说明

在开始之前,我们将简要讨论IPv4与IPv6。iptables命令仅处理IPv4流量。对于IPv6流量,使用了一个名为ip6tables的单独配套工具。规则存储在单独的表和链中。对于netfilter-persistent命令,IPv4规则写入/etc/iptables/rules.v4并从中读取,IPv6规则存储在/etc/iptables/rules.v6中。

本指南假设您没有在服务器上积极使用IPv6。如本指南所示,如果您的服务不利用IPv6,则完全阻止访问更安全。

重置防火墙

首先重置防火墙规则,以便查看如何从命令行构建策略。运行以下命令刷新所有规则:

1
netfilter-persistent flush

现在验证规则是否已重置:

1
iptables -S

您应该有输出,显示filter表中的规则已消失,并且所有链上的默认策略设置为ACCEPT:

1
2
3
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT

清空配置

1
2
3
iptables -F  
iptables -X
iptables -Z

ipv6

1
2
3
ip6tables -F  
ip6tables -X
ip6tables -Z

创建协议特定链

接下来,您将创建所有特定于协议的链。这些将用于保存为要公开的服务创建拒绝策略例外的规则。您将为UDP流量创建一个:

1
iptables -N UDP
1
ip6tables -N UDP

然后是TCP的另一个:

1
iptables -N TCP
1
ip6tables -N TCP

ICMP还有一个:

1
iptables -N ICMP
1
ip6tables -N ICMP

配置,允许回环网卡

您还需要允许来自本地环回接口的所有流量。这是由服务器生成并发送到服务器的流量。主机上的服务使用它来相互通信:

1
iptables -A INPUT -i lo -j ACCEPT
1
ip6tables -A INPUT -i lo -j ACCEPT

允许ping

1
iptables -A INPUT -p icmp -j ACCEPT
1
ip6tables -A INPUT -p icmpv6 -j ACCEPT

允许DHCPv6

1
ip6tables -I INPUT -p udp --dport 546 -j ACCEPT

允许ssh

1
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
1
ip6tables -A INPUT -p tcp --dport 22 -j ACCEPT

允许ftp

1
2
iptables -A INPUT -p tcp --dport 21 -j ACCEPT
iptables -A INPUT -p tcp --dport 20 -j ACCEPT
1
2
ip6tables -A INPUT -p tcp --dport 21 -j ACCEPT
ip6tables -A INPUT -p tcp --dport 20 -j ACCEPT

允许ftp被动接口范围,在ftp配置文件里可以设置

1
iptables -A INPUT -p tcp --dport 20000:30000 -j ACCEPT
1
ip6tables -A INPUT -p tcp --dport 20000:30000 -j ACCEPT

学习felix,把smtp设成本地

1
2
iptables -I INPUT -p tcp -m tcp --dport 25 -j ACCEPT -s 127.0.0.1
iptables -I INPUT -p tcp -m tcp --dport 25 -j REJECT
1
2
ip6tables -I INPUT -p tcp -m tcp --dport 25 -j ACCEPT -s 127.0.0.1
ip6tables -I INPUT -p tcp -m tcp --dport 25 -j REJECT

允许DNS

1
2
iptables -I INPUT -p tcp -m tcp --dport 53 -j ACCEPT
iptables -I INPUT -p udp -m udp --dport 53 -j ACCEPT
1
2
ip6tables -I INPUT -p tcp -m tcp --dport 53 -j ACCEPT
ip6tables -I INPUT -p udp -m udp --dport 53 -j ACCEPT

允许http和https

1
2
iptables -I INPUT -p tcp --dport 80 -j ACCEPT
iptables -I INPUT -p tcp --dport 443 -j ACCEPT
1
2
ip6tables -I INPUT -p tcp --dport 80 -j ACCEPT
ip6tables -I INPUT -p tcp --dport 443 -j ACCEPT

允许已建立的或相关连的通行

INPUT链中,所有传入流量开始过滤,我们需要添加通用规则。这些是一些常识规则,通过接受低风险的流量(本地流量和与我们已经检查的连接相关的流量)和丢弃明显无用的流量(无效数据包),为防火墙设置基线。

首先,创建一个例外,以接受作为已建立连接的一部分或与已建立连接相关的所有流量:

1
2
3
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
1
2
3
ip6tables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

ip6tables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

该规则使用conntrack扩展,该扩展提供了内部跟踪,因此iptables具有所需的上下文,以将数据包作为更大连接的一部分进行评估,而不是作为离散的、不相关的数据包流。TCP是一种基于连接的协议,因此已建立的连接定义得相当好。对于UDP和其他无连接协议,已建立的连接指的是已看到响应的流量(原始数据包的源将是响应数据包的目的地,反之亦然)。相关连接是指与现有连接关联启动的新连接。这里的经典示例是FTP数据传输连接,它与已经建立的FTP控制连接有关。

禁止其他未允许的规则访问

1
2
iptables -A INPUT -j REJECT       #(注意:如果22端口未加入允许规则,SSH链接会直接断开。)  
iptables -A FORWARD -j REJECT
1
2
ip6tables -A INPUT -j REJECT       #(注意:如果22端口未加入允许规则,SSH链接会直接断开。)  
ip6tables -A FORWARD -j REJECT

最后,拒绝所有无效数据包。由于多种原因,数据包可能无效。它们可能指的是不存在的连接,可能指向不存在的接口、地址或端口,也可能格式不正确。在任何情况下,您都会丢弃所有无效数据包,因为没有适当的方法来处理它们,而且它们可能代表恶意活动:

1
iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
1
ip6tables -A INPUT -m conntrack --ctstate INVALID -j DROP

创建到协议特定链的跳转规则

到目前为止,我们已经在INPUT链中创建了一些一般规则,并在我们的协议特定链中为特定的可接受服务创建了一些规则。然而,目前,流量进入INPUT链,无法到达我们的协议特定链。

现在,您需要将INPUT链中的流量引导到适当的协议特定链中。您可以匹配协议类型以将其发送到正确的链。此外,确保数据包代表一个新的连接(任何已建立的或相关的连接都应该提前处理)。从UDP流量开始:

1
iptables -A INPUT -p udp -m conntrack --ctstate NEW -j UDP
1
ip6tables -A INPUT -p udp -m conntrack --ctstate NEW -j UDP

接下来,对TCP流量运行以下命令。请注意,对于TCP数据包,您将添加额外的要求,即数据包是_SYN_数据包,这是启动TCP连接的唯一有效类型:

1
iptables -A INPUT -p tcp --syn -m conntrack --ctstate NEW -j TCP
1
ip6tables -A INPUT -p tcp --syn -m conntrack --ctstate NEW -j TCP

然后对ICMP流量运行以下操作:

1
iptables -A INPUT -p icmp -m conntrack --ctstate NEW -j ICMP
1
ip6tables -A INPUT -p icmp -m conntrack --ctstate NEW -j ICMP

拒绝所有剩余流量

如果传递给协议特定链的数据包不符合其中的任何规则,则控制将传递回INPUT链。防火墙不允许任何达到这一点的行为。

您将使用REJECT目标拒绝流量,该目标向客户端发送响应消息。这允许您指定出站消息传递,以便您可以模拟客户端尝试将数据包发送到常规封闭端口时将给出的响应。响应取决于客户端使用的协议。

试图到达关闭的UDP端口将导致ICMP消息,说明“无法访问端口”。您可以通过运行以下命令来模拟此操作:

1
iptables -A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
1
ip6tables -A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable

尝试在封闭端口上建立TCP连接会导致TCP RST响应:

1
iptables -A INPUT -p tcp -j REJECT --reject-with tcp-reset
1
ip6tables -A INPUT -p tcp -j REJECT --reject-with tcp-reset

对于所有其他数据包,您可以发送ICMP“protocol unreachable”消息,以指示服务器不响应该类型的数据包:

1
iptables -A INPUT -j REJECT --reject-with icmp-proto-unreachable
1
ip6tables -A INPUT -j REJECT --reject-with icmp-proto-unreachable

调整默认策略

您添加的最后三条规则应处理INPUT链中的所有剩余流量。但是,作为预防措施,您应该将默认策略设置为DROP,如下所示:

1
iptables -P INPUT DROP

如果此服务器未配置为其他机器的路由器,则还应在FORWARD链中设置此策略:

1
iptables -P FORWARD DROP

**警告:**当策略设置为DROP时,如果用sudo iptables -F清除iptables,则当前SSH连接将被删除!使用sudo netfilter-persistent flush刷新是清除规则的更好方法,因为它还将重置默认策略。

为了匹配删除所有流量的IPv6策略,可以使用以下ip6tables命令,从INPUT开始:

1
ip6tables -P INPUT DROP

然后对FORWARD运行以下操作:

1
ip6tables -P FORWARD DROP

最后,设置OUTPUT的策略:

1
ip6tables -P OUTPUT DROP

这应该相当紧密地复制您的规则集。

保存iptables条规则

在这一点上,你应该测试你的防火墙规则,确保它们阻止了你想要阻止的流量,同时不妨碍你的正常访问。一旦您确信您的规则运行正常,您可以保存它们,以便它们在引导时自动应用于您的系统。

通过运行以下命令保存当前规则(IPv4和IPv6):

1
netfilter-persistent save

这将使用您在命令行上制定的策略覆盖/etc/iptables/rules.v4/etc/iptables/rules.v6文件。

Docker与iptables 只允许特定ip访问Docker的服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
Docker与iptables (在DOCKER-USER链中处理)
Docker至少会在iptables规则中自动安装两个新链,一个是DOCKER,一个是DOCKER-USER,可以通过如下方式查看
iptables -S -t nat 查看DOCKER链规则
iptables -S 查看DOCKER-USER链规则
随着docker版本不同,可能还会有其他链,但一般来说,我们应该只修改DOCKER-USER链即可。
如果想要对docker端口做访问限制,可以参考如下规则:
#ext_if(网卡名称) 192.168.1.1(内网网段)

#只允许本地127.0.0.1访问docker的服务-IPV4
iptables -I DOCKER-USER -i lo ! -s 127.0.0.1 -j DROP

#只允许本地127.0.0.1访问docker的服务-IPV6
ip6tables -I DOCKER-USER -i lo ! -s ::1 -j DROP


#只允许192.168.1.1访问docker的服务,其中ext_if是你机器上的实际网卡名
iptables -I DOCKER-USER -i ext_if ! -s 192.168.1.1 -j DROP

#只允许网段192.168.1.0/24
iptables -I DOCKER-USER -i ext_if ! -s 192.168.1.0/24 -j DROP

#只允许ip范围
iptables -I DOCKER-USER -m iprange -i ext_if ! --src-range 192.168.1.1-192.168.1.3 -j DROP

#由于外网网卡提供业务,而业务回包也是从外网网卡走的,因此需要增加连接状态,如果是回包的话也允许通过-IPV4
iptables -I DOCKER-USER -i eth1 -p tcp -m state --state RELATED,ESTABLISHED -j ACCEPT

#由于外网网卡提供业务,而业务回包也是从外网网卡走的,因此需要增加连接状态,如果是回包的话也允许通过-IPV6
ip6tables -I DOCKER-USER -i eth1 -p tcp -m state --state RELATED,ESTABLISHED -j ACCEPT


原文链接:
Docker and iptables
https://docs.docker.com/network/iptables/

结论

通过遵循本指南,或者直接将防火墙规则粘贴到配置文件中,或者在命令行上手动应用并保存它们,您已经创建了一个良好的初始防火墙配置。您必须添加单独的规则,以允许访问您想要提供的服务。

本指南中建立的框架应允许您进行调整,并有助于澄清您现有的政策。查看我们的其他一些指南,了解如何使用一些流行的服务构建防火墙策略:

  • Iptables要点:通用防火墙规则和命令
  • 如何设置Iptables防火墙以保护服务器之间的通信
  • 如何通过带有Iptables的Linux网关转发端口
  • 如何使用Nmap和Tcpdump测试防火墙配置