iptables
(和/或后续工具nftables
)是用户空间实用程序,允许系统管理员配置 Linux 内核防火墙的 IP 数据包过滤规则,该规则以不同的方式实现网络过滤器 模块。(摘要来自维基百科)
由于和iptables
是nftables
供人们、系统管理员使用的用户空间实用程序,而人们并不总是完全熟悉底层数字,因此它们接受 IP 协议(tcp、icmp、udp 等)、IP 地址(主机名)和端口号(服务名称)的人类可读描述。
从 UI 角度来看,使用人类可读的名称似乎是一件好事:
iptables --protocol udp
作为一名管理员,我可能不是唯一一个对“与……相比”和“类似”的含义有更直观的理解的人iptables --protocol 17
。- 主机名
gateway.example.net
通常比 IP 地址更有意义,例如192.0.2.1
- 在 Web 服务器上允许 HTTP 和 HTTPS 比允许 TCP/80 和 TCP/443 更加明显。
这样做安全吗?
或者你应该远离这个?
有哪些注意事项?
答案1
其效果可能并不总是如管理员所期望的。
一点背景知识:
这网络过滤器Linux 内核中的模块对 IP 数据包进行操作。它们主要评估、处理和/或修改这些 IP 数据包的标头,通常不涉及数据部分(这更像是深度数据包检测(DPI))。
IP 数据包的报头不包含人类可读的名称,它们包括诸如知识产权
protocol number
, A源和目标IP-address
, TCP 源和目标port
号码ETC。
为了达到最高效的目的,Linux 内核中的数据包过滤器规则也存储了 IP 协议、端口号和 IP 地址的值,其格式与它们正在评估的数据包中的格式相同。
当规则加载到内核时
iptables
并将nftables
人类可读的输入转换为数值netfilter 内核模块所需要并存储在其中。系统解析器用于转换协议、服务、网络名称和主机名。这使得实际解析取决于您的配置(nsswitch.conf)
iptables
并将nftables
人类可读的输入转换为数值当命令运行时。只要没有被明确刷新/删除/更新,生成的数字规则就会在内核中保持有效。
这也会产生一些不太明显的影响和/或后果。
使用协议名称和iptables
:
总的来说这是安全的并且不会引起任何不必要的混乱。
该文件/etc/protocols
默认用于将协议名称转换为协议编号在iptables --protocol [human readable protocol name]
IP 协议名称(例如 UPD 和 TCP)不太可能引起混淆。
使用主机名使用iptables
或nftables
:
默认文件/etc/networks
可用于翻译网络名称 在目的地和/或源中使用。至少根据手册,我从未见过任何人在现实世界中使用它。因为据我所知,getent networks network-name
也没有提供返回网络掩码的方法,所以在我看来,使用网络名称是不切实际的。
默认文件/etc/hosts
用于翻译主机名到目的地和/或源的 IP 地址,通常使用 DNS 作为后备。
不要使用主机名。
数据包过滤器作用于 IP 地址。在防火墙配置中也使用 IP 地址和 IP 地址范围。
当防火墙规则中使用主机名时,iptables
它将受到执行 iptables 命令时主机名解析到的(单个)IP 地址的影响。
当无法解析主机名时,根本不会添加规则。
这看起来很明显并且没有什么问题,但这导致了许多极端情况,在实践中这些情况变得非常常见。
防火墙配置通常在启动时应用前完全激活网络,然后 DNS 解析将无法工作。例如,
iptables -I INPUT --source bastion.example.com -j ALLOW
当系统 hosts 文件中没有条目 bastion.example.com 时,允许从堡垒主机进行远程管理的规则将不适用(在系统启动时)。(当他们拥有内部 DNS 时,谁愿意维护 hosts 文件?)当正向 DNS 记录更新时:Linux 防火墙将继续使用旧的 IP 地址,直到明确刷新/删除/更新规则(通过
iptables
再次运行命令)。当正向 DNS 记录是循环记录或使用地理位置时:通常只会使用单个 IP 地址。
换句话说:
iptables -I OUTPUT --destination www.google.com -j REJECT
例如,只会部分阻止对 Google 的访问,时间不超过 300 秒。然后 DNS TTL 到期,查询将www.google.com
返回不同的 IP 地址,通常是有效防火墙规则中未被阻止的新 IP 地址。通常,使用主机名来拒绝不受欢迎的访问已经是一个坏主意。
系统通常只能看到来自传入连接的 IP 地址,并且它们需要对 IP 地址进行反向查找以确定关联的主机名。通过主机名进行阻止是有问题的,原因有两个:反向 DNS 查询可能很慢
生成的主机名不可信任,因为 IP 地址的所有者可以在反向 DNS 记录上设置任何他们想要的主机名。他们可以随意更改主机名
untrusted.example.net
(trusted.example.com
某些系统通过从 PTR 记录中对主机名进行第二次正向查找来解决这个问题,并且只接受两者匹配的系统。)iptables -A INPUT --source untrusted.example.net -j REJECT
对于 iptables 来说,问题略有不同,因为只会进行正向 DNS 查找。但是,当您使用 untrusted.example.net 而不是 IP 地址时,您不再控制被阻止的内容。
如果该 DNS 记录的所有者将 untrusted.example.net 更改为您的网关的 IP 地址,您将被锁定。
如果所有者完全删除该记录,您也不再阻止他们的 IP。
另一个可能令人困惑的事情:显示防火墙规则时,如果通过反向 DNS 查找完成从 IP 地址到主机名的映射。通常,该 PTR 记录不存在,即使存在,生成的主机名通常也不会与创建规则时使用的主机名相对应。例如:
www.google.com. 300 IN A 172.217.168.228
228.168.217.172.in-addr.arpa. 18721 IN PTR ams15s40-in-f4.1e100.net.
可能还有一些我忘记的其他原因。
使用服务名称 和iptables
:
虽然安全,但这似乎也引起了一些混乱。
该文件/etc/services
用于翻译服务名称到端口号当端口号被替换为人类可读的“服务名称” 与……一起使用iptables --protocol tcp --source-port
(或别名--sport
及类似物--destination-port
/--dport
等)。
服务名称实际上是一个人类可读的端口号,并且(只要没有人修改/etc/services)当管理员使用例如 ssh
那 与使用相同港口22
。
iptables -I INPUT -p tcp --dport ssh -j ACCEPT
这混乱的根源似乎人们混淆了服务名称 (ssh) 和应用程序协议 (ssh)。
上述规则不允许所有传入的 ssh 流量。
例如,当您的 ssh 服务器配置为侦听端口 22222 时,该端口不会被此规则打开。
该规则仅允许所有到端口 22 的流量。
它还不阻止非 ssh 流量连接到端口 22两者都不是。典型的 ssh 守护程序将无法正确响应,但诸如此类的请求http://hostname:22/
也不会被数据包过滤器阻止。(这需要 DPI。)