我经常看到这条规则-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
的应用。虽然我不是专家,但这条特定的路线让我感到担忧。很明显,规则允许全部流量,唯一的例外是连接必须已建立或与已建立的连接相关。
设想
22
我将允许从子网中的服务器 LAN192.168.0.0/16
或其他端口连接到默认 SSH 端口。SuperInsecureApp®
在 port 上公开一些东西1337
,我将其添加到我的INPUT
链中。- 我添加了
conntrack
接受规则ESTABLISHED
并RELATED
来自的规则全部来源 - 连锁政策是
DROP
因此基本上该配置应仅允许来自 LAN 的 SSH 连接,同时允许来自世界的端口 1337 上的入站流量。
这就是我困惑的地方。是否会conntrack
以任何方式暴露一个安全漏洞,使人们能够获得已建立的连接1337(因为它是世界开放的),然后利用该连接来访问 SSH 端口(或任何其他端口)?
答案1
我不认为 ESTABLISHED 和 RELATED 流量过于开放。您可以省略 RELATED,但绝对应该允许 ESTABLISHED。这两个流量类别都使用 conntrack 状态。
ESTABLISHED 连接已由另一条规则验证。这使得实现单向规则变得更加简单。这只允许您在同一端口上继续交易。
RELATED 连接也通过另一条规则进行验证。它们不适用于很多协议。它们再次使配置规则变得更加简单。它们还确保应用时的连接顺序正确。这实际上使您的规则更加安全。虽然这可能使连接到不同的端口成为可能,但该端口只能是相关进程的一部分,例如 FTP 数据连接。允许哪些端口由协议特定的 conntrack 模块控制。
通过允许 ESTABLISHED 和 RELATED 连接,您可以专注于希望防火墙接受哪些新连接。它还避免了允许返回流量但允许新连接的破坏规则。
鉴于您已将端口 1337 上的程序归类为不安全,因此应使用专用的非 root 用户 ID 来启动它。如果有人设法破解应用程序并获得增强的访问权限,这将限制他们可能造成的损害。
端口 1337 上的连接不太可能用于远程访问端口 22,但到端口 1337 的连接可能用于代理到端口 22 的连接。
您可能希望确保 SSH 受到深度保护:
- 除了防火墙限制之外,还可以使用hosts.allow 来限制访问。
- 防止 root 访问,或者至少要求使用密钥并在authorized_keys 文件中限制其访问。
- 审核登录失败。日志扫描器可以定期向您发送异常活动报告。
- 考虑使用像 fail2ban 这样的工具来在重复访问失败时自动阻止访问。
答案2
ESTABLISHED 和 RELATED 是“有状态”数据包过滤的功能,其中过滤不仅取决于静态规则集,还取决于考虑数据包的上下文。您需要 ESTABLISHED 才能允许连接正常工作,并且需要 RELATED 才能获得相关 ICMP 消息。与静态“无状态”规则相比,有状态过滤允许更精确地进行过滤。
我们先看看ESTABLISHED。例如,考虑端口 22 上的 TCP。发起者(客户端)发送一个SYN
to serverIPaddr:22
。服务器返回SYN+ACK
给客户端。现在轮到客户发送ACK
.服务器上的过滤规则应该是什么样子,以便只ACK
接受“匹配”?一般的无状态规则看起来像
-A INPUT --proto tcp --port 22 -j ACCEPT
这比相应的国家规则更加自由。无状态规则允许任意 TCP 段,例如,ACK
或者FIN
在没有首先建立连接的情况下。端口扫描器可以利用这种行为进行操作系统指纹识别。
现在让我们看一下“相关”。这用于 ICMP 消息,主要是错误消息。例如,如果从服务器到客户端的数据包被丢弃,则会向服务器发送一条错误消息。此错误消息与先前建立的连接“相关”。如果没有 RELATED 规则,人们要么需要一般性地允许传入错误消息(没有上下文),要么按照许多站点的惯例,完全丢弃 ICMP 并等待传输层上的超时。 (请注意,这对于 IPv6 来说是一个坏主意;对于 IPv6,ICMPv6 比对于传统 IP 的 ICMP 发挥着更重要的作用。)
答案3
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
对于不想花太多时间配置防火墙的用户来说,这是一个很好的默认设置,并且它可能始终相当安全。然而,它将实际的策略留给了 Linux 内核。
考虑:
- 所有协议都将被接受,只要它们是由本地系统发起的。
- 所有协议和消息都将被接受,只要它们与本地系统发起的连接和协议相关。
特别是,它接受内核可能认为与现有连接“相关”的所有 ICMP 消息类型。我还没有检查内核源代码到底意味着什么,但是没有立即提供文档,并且大多数 ICMP 消息类型都是不必要的(并且可能有害)。因此,更合理的选择可能如下:
-A INPUT -p tcp -m state --state ESTABLISHED -j ACCEPT
-A INPUT -p icmp --icmp-type 3 -m state --state RELATED -j ACCEPT
-A INPUT -p icmp --icmp-type 11 -m state --state RELATED -j ACCEPT
-A INPUT -p icmp --icmp-type 12 -m state --state RELATED -j ACCEPT
这只允许建立与 TCP 协议的连接,以及与 ICMP 协议的相关连接,用于“目标不可达”(类型 3)、“超时”(类型 11)和“参数问题”(类型 12)控制消息。例如,这会阻止内核仅仅因为认为新的 TCP 连接与前一个连接“相关”而允许新的 TCP 连接(但它可能永远不会这样做)。
据我所知,这些是唯一的ICMP 消息类型接受相关连接将是有益的。类型 11 控制消息允许使用 TCP 跟踪路由功能traceroute -T
。
IPv6 的情况更为复杂,因为它使用 ICMPv6。对于在本地计算机上使用,我暂时只需丢弃出站接口上的所有 IPv6 流量,因为这需要花费更多精力来保护它,而且目前我的 ISP 没有必要这样做。如果我正在配置服务器,我会尝试以类似的方式配置它。
为了后代的缘故,我会提到,允许输入链中的 ICMP 类型 0 和 9 控制消息以及输出链中的 ICMP 类型 8 和 10 控制消息也可能很有用,以便 ping (0/8) 和 IPv4 路由器征集(9/10)工作。这应该不会引入额外的安全问题,因为接受回显回复或路由器通告消息不需要响应,因此不能用于查询系统状态。
iptables -A INPUT -p icmp --icmp-type 0/0 -j ACCEPT
iptables -A INPUT -p icmp --icmp-type 9/0 -j ACCEPT
iptables -A OUTPUT -p icmp --icmp-type 8/0 -j ACCEPT
iptables -A OUTPUT -p icmp --icmp-type 10/0 -j ACCEPT