概念 作用
iptables允许用户使用这些链和规则
工作原理
小写是表,大写是链。
所有(无论内部外部)进入网卡的IP数据包都必须经历这个流程!
如果 IP 数据包到达一个内置链的末端,包括一个空链,那么该链的策略target 便决定 IP 数据包的最终目的地。
本质
iptables本质上不是通常定义的防火墙 ,实践上是做了一个代理。
将用户设置的安全规则在安全框架(netfilter)中执行。
netfilter位于内核空间 ,是真正的防火墙框架。
iptables在用户空间,可以控制安全框架。
流程
在任何接口上接收的网络数据包都将按照流程图 中所示的顺序遍历表的流量控制链。
第一个路由决策 涉及决定信息包的最终目的地是本地机器 (在这种情况下,信息包通过INPUT链 )还是其他机器 (在这种情况下,信息包通过FORWARD链 )。
随后的路由决策 包括决定将哪个接口分配给一个出包 。
在路径中的每个链上,该链中的每个规则都按顺序计算 ,每当规则匹配时,就执行相应的目标/跳转操作。3个最常用的目标是ACCEPT、DROP和跳转到用户定义链 。
虽然内置链可以有默认策略 ,但用户定义链不能 。
如果跳过的链中的每个规则都不能提供完全匹配 ,则包将被丢回调用链中 ,如下图所示。
如果在任何时候对具有DROP目标的规则实现了完全匹配 ,则丢弃数据包 ,不再进行进一步的处理。
如果一个包在一个链中被ACCEPT ,它也将在所有超集链 中被ACCEPT ,并且它将不再进一步遍历任何超集链 。但是,包将继续以正常方式遍历 其他表中的所有其他链 。
组成 表
iptables 包含五个表:
raw仅用于配置数据包,使它们免于连接跟踪。
filter是默认表,通常与防火墙相关联的所有操作都发生在该表中。
nat用于网络地址转换(例如端口转发)。
mangle用于专门的数据包更改。
security用于强制访问控制网络规则。
常用的表为filter和nat 。
链
规则
包过滤是基于规则的,规则由多个匹配项 (报文必须满足的条件才能应用该规则)和一个目标 (报文匹配所有条件时的动作)指定 。
规则可能匹配的典型内容是数据包来自哪个网卡(例如eth0或eth1),它是什么类型的数据包(ICMP、TCP或UDP),或者数据包的目的端口。
使用-j或—jump选项指定目标。
目标 可以是用户定义链 (如果这些条件匹配,则跳转到以下用户定义链并在那里继续处理)、特殊的内置目标之一或目标扩展 。
内置目标 是ACCEPT, DROP, QUEUE和RETURN,如果目标是内置目标,则立即决定数据包的命运 ,并停止对当前表中的数据包的处理。
目标扩展 包括例如REJECT和LOG。
用户定义链 ,若数据包的命运不是由该链决定的,它将根据原始链的剩余规则进行过滤 。目标扩展可以是终止的(作为内置目标)或非终止的(作为用户定义的链)。
模块
有许多模块可用于扩展 iptables,例如 connlimit、conntrack、limit 和 recent。
配置
iptables是一个systemd服务 ,叫做iptables.service。
iptables包在/etc/iptables/iptables.rules
中安装了一组空的规则,当你第一次启动iptables.service单元时将加载这些规则。
与其他服务一样,如果希望iptables在引导时自动加载,则必须启用它。
IPv6的iptables规则默认保存在/etc/iptables/ip6tables.rules
中,由ip6tables.service读取。
如下所示,通过命令行添加规则后,配置文件不会自动更改,必须手动保存:
1 iptables-save -f /etc/iptables/iptables.rules
如果手动编辑配置文件,则必须重新加载iptables。或者你可以直接通过iptables加载它:
1 iptables-restore /etc/iptables/iptables.rules
使用 显示当前规则
列出当前规则的基本命令是list-rules (-S),其输出格式类似于iptables-save实用程序。
这两个命令的主要区别是,后者默认输出所有表 的规则,而所有iptables命令默认只输出filter表 。
1 2 3 4 student@6858-v20:~$ sudo iptables -S -P INPUT ACCEPT -P FORWARD ACCEPT -P OUTPUT ACCEPT
—list (-L)命令接受更多修饰符并显示更多信息。
例如,可以使用以下命令查看当前的规则集和每条规则的命中次数:
1 2 3 4 5 6 7 8 9 student@6858-v20:~$ sudo iptables -nvL Chain INPUT (policy ACCEPT 1059 packets, 89762 bytes) pkts bytes target prot opt in out source destination Chain FORWARD (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 1051 packets, 88652 bytes) pkts bytes target prot opt in out source destination
如果输出像上面那样,那么在默认的过滤表中没有规则(即没有阻塞)。
可以使用-t选项指定其他表。
要在列出规则时显示行号,请将—line-numbers追加到该输入。当在命令行上编辑规则时,行号是一种有用的速记。
重置规则
可以使用以下命令将iptables刷新和重置为默认值:
1 2 3 4 5 6 7 8 9 10 11 12 13 iptables -F iptables -X iptables -t nat -F iptables -t nat -X iptables -t mangle -F iptables -t mangle -X iptables -t raw -F iptables -t raw -X iptables -t security -F iptables -t security -X iptables -P INPUT ACCEPT iptables -P FORWARD ACCEPT iptables -P OUTPUT ACCEPT
不带参数的-F命令将刷新其当前表中的所有链 。
类似地,-X删除表中所有空的非默认链 。
可以通过在-F和-X后面加上[chain]参数 来清除或删除单个链 。
编辑规则
可以通过以下方式编辑规则 :在链上添加-A规则,在链上的特定位置插入-I,替换现有规则-R,或删除-D规则。
首先,我们的计算机不是路由器。我们希望将FORWARD链上的默认策略从ACCEPT更改为DROP。
1 iptables -P FORWARD DROP
Dropbox的局域网同步功能每30秒向它能看到的所有计算机广播数据包。如果我们碰巧与Dropbox客户端在局域网中,并且没有使用该功能,那么我们可能会希望拒绝这些数据包。
1 iptables -A INPUT -p tcp --dport 17500 -j REJECT --reject-with icmp-port-unreachable
1 2 3 4 5 6 7 8 9 10 student@6858-v20:~$ sudo iptables -nvL --line-numbers Chain INPUT (policy ACCEPT 67 packets, 5771 bytes) num pkts bytes target prot opt in out source destination 1 0 0 REJECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:17500 reject-with icmp-port-unreachable Chain FORWARD (policy DROP 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 55 packets, 5174 bytes) num pkts bytes target prot opt in out source destination
注意:这里我们使用REJECT而不是DROP ,因为RFC 1122要求主机尽可能地返回ICMP错误,而不是丢弃数据包 。这一页 解释了为什么拒绝包几乎总是比DROP包更好。
现在,假设我们改变了对Dropbox的看法,决定在自己的电脑上安装它。我们还想进行局域网同步,但只能与网络上的一个特定IP进行同步。
所以我们应该用-R来代替原来的规则 。其中10.0.0.85是我们的其他IP:
1 iptables -R INPUT 1 -p tcp --dport 17500 ! -s 10.0.0.85 -j REJECT --reject-with icmp-port-unreachable
1 2 3 4 student@6858-v20:~$ sudo iptables -nvL --line-numbers Chain INPUT (policy ACCEPT 21 packets, 1849 bytes) num pkts bytes target prot opt in out source destination 1 0 0 REJECT tcp -- * * !10.0.0.85 0.0.0.0/0 tcp dpt:17500 reject-with icmp-port-unreachable
我们现在已经用一个允许10.0.0.85访问17500端口的规则替换了原来的规则。
我们意识到这是不可扩展的 。如果我们友好的Dropbox用户 试图访问设备上的17500端口,我们应该立即允许 他,而不是测试他是否违反任何防火墙规则。
因此,我们编写了一个新的规则,允许我们的信任用户。使用-I将新规则插入到旧规则之前 :
1 iptables -I INPUT -p tcp --dport 17500 -s 10.0.0.85 -j ACCEPT -m comment --comment "Friendly Dropbox"
1 2 3 4 5 6 7 8 9 10 11 student@6858-v20:~$ sudo iptables -nvL --line-numbers Chain INPUT (policy ACCEPT 19 packets, 1857 bytes) num pkts bytes target prot opt in out source destination 1 0 0 ACCEPT tcp -- * * 10.0.0.85 0.0.0.0/0 tcp dpt:17500 /* Friendly Dropbox */ 2 0 0 REJECT tcp -- * * !10.0.0.85 0.0.0.0/0 tcp dpt:17500 reject-with icmp-port-unreachable Chain FORWARD (policy DROP 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 16 packets, 1892 bytes) num pkts bytes target prot opt in out source destination
把我们的第二条规则替换成拒绝所有17500端口的规则:
1 iptables -R INPUT 2 -p tcp --dport 17500 -j REJECT --reject-with icmp-port-unreachable
1 2 3 4 5 6 7 8 9 10 11 student@6858-v20:~$ sudo iptables -nvL --line-numbers Chain INPUT (policy ACCEPT 19 packets, 1656 bytes) num pkts bytes target prot opt in out source destination 1 0 0 ACCEPT tcp -- * * 10.0.0.85 0.0.0.0/0 tcp dpt:17500 /* Friendly Dropbox */ 2 0 0 REJECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:17500 reject-with icmp-port-unreachable Chain FORWARD (policy DROP 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 15 packets, 2224 bytes) num pkts bytes target prot opt in out source destination
允许组播流量
使用多播标识的协议(例如,SANE搜索网络扫描器)将向网络的广播IP发送流量,并从特定的客户端的IP返回响应。
由于这些IP地址是不同的,所以iptables不会将响应识别为RELATED或ESTABLISHED,它将阻塞响应 。
首先,创建一个ipset散列容器。
1 ipset create upnp hash :ip,port timeout 3
timeout是接受客户端响应的时间窗口。
其次,创建一个规则,将传出多播流量添加到ipset散列中。
1 iptables -A OUTPUT -d 239.255.255.250/32 -p udp -m udp -j SET --add-set upnp src,src --exist
第三,创建一个规则,允许与ipset散列匹配的传入流量。
1 iptables -A INPUT -p udp -m set --match-set upnp dst,dst -j ACCEPT
最后,记住保存新规则,并确保启用iptables.service和ipset.service,以便在系统启动时加载规则。
日志
1 2 iptables -A logdrop -m limit --limit 5/m --limit-burst 10 -j LOG iptables -A logdrop -j DROP
limit和limit-burst选项解释如下 。
现在,当我们想要丢弃一个包并记录这个事件时,我们只需跳转到日志丢弃链,例如:
1 iptables -A INPUT -m conntrack --ctstate INVALID -j logdrop
限制日志速率
上面的logdrop链使用limit模块 来防止iptables日志变得太大或导致不必要的硬盘写操作 。
在不限制错误配置的服务尝试连接的情况下,攻击者可以通过引起对iptables日志的写入来填充驱动器 (或至少是/var
分区)。
limit模块使用-m limit调用 。
使用—limit来设置平均速率 ;
使用—limit-burst来设置初始突发速率 。
1 iptables -A logdrop -m limit --limit 5/m --limit-burst 10 -j LOG
上述命令附加 一个规则,该规则将记录通过它的所有数据包。
记录前10个连续数据包 ,从那时起每分钟仅记录5个数据包 。
每当“限制速率”未被打破时,“限制突发”计数将被重置,即日志记录活动自动恢复正常。
查看记录包
记录的数据包在systemd journal中作为内核消息可见 。
要查看自计算机最后一次启动以来记录的所有包:
1 journalctl -k --grep="IN=.*OUT=.*"
syslog-ng
可以在syslog-ng.conf中控制iptables的日志输出到哪里 。
1 2 3 4 filter f_everything { level(debug..emerg) and not facility(auth, authpriv); }; filter f_everything { level(debug..emerg) and not facility(auth, authpriv) and not filter(f_iptables); };
这将停止将iptables输出记录到/var/log/everything.log
。
如果你也想让iptables记录到不同于/var/log/iptables.log
的文件中,可以简单地改变目标d_iptables的文件值(仍然在syslog-ng.conf中):
1 destination d_iptables { file("/var/log/iptables.log" ); };
ulogd
ulogd是用于netfilter的专用用户空间包日志记录守护进程,它可以替换默认的LOG目标。
ulogd包可以在[community]存储库中找到。