在输出和输入中匹配特定用户的流量以对其使用配额

在输出和输入中匹配特定用户的流量以对其使用配额

我如何转换:

iptables -t mangle -A OUTPUT -m owner --uid-owner root -j MARK --set-mark 1

iptables -A OUTPUT -m owner --uid-owner root -m quota2 --name 10mb_quota --quota 10240000 -j MARK --set-mark 1

用于 INPUT?

我尝试过这样的:

iptables -t mangle -A INPUT -m owner --uid-owner root -j MARK --set-mark 1

iptables -A INPUT -m owner --uid-owner root -m quota2 --name 10mb_quota --quota 10240000 -j MARK --set-mark 1

但我没有成功。

答案1

问题

手册页告诉我们:

owner

对于本地生成的数据包,该模块尝试匹配数据包创建器的各种特性。此匹配仅在 OUTPUT 和 POSTROUTING 链中有效。转发的数据包没有与之关联的套接字。来自内核线程的数据包确实有套接字,但通常没有所有者。

因此,没有与 INPUT 直接对应的函数。原因很简单:传入的数据包不是来自进程,因此无法检查将(很快但尚未)接收此数据包的进程的套接字所有者(尽管存在socket匹配它可以进行这种提前查找但没有任何与所有者相关的功能)。

connmark

我们可以做的是关联连接跟踪标记到此流的传出数据包与用户关联的(第一次),并从 conntrack 标记中标记后续数据包(包括传入数据包)。然后可以使用其他功能,例如配额。

  1. 盲目地将 conntrack 流中的标记恢复到数据包:如果有标记(0 表示没有),则现在在传入包。

    这可以在 mangle/INPUT 中完成,因为整体功能仅对本地流量有意义(因此对通过 FORWARD 链的流量没有意义),但这更容易以后不关心规则排序并在 mangle/PREROUTING 中执行(可以选择优化并将其移动到 mangle/INPUT)。

    iptables -t mangle -A PREROUTING -j CONNMARK --restore-mark
    

    (根据需要在这里或者在 mangle/INPUT 或 filter/INPUT 中添加更多相关规则,这些规则应以 开头-m mark --mark 1)。

  2. 还将 conntrack 流中的标记恢复到传出数据包。然后,如果没有标记,则执行所有者测试以将防火墙标记添加到数据包中

    按时间顺序,这是最初设置标记的位置,因为只能在输出路径中测试数据包的所有者。

    设置标记之前进行的标记测试可能允许后续规则再次更改此标记(最终是 conntrack 标记),而不会在下一个输出数据包上再次覆盖它。

    iptables -t mangle -A OUTPUT -j CONNMARK --restore-mark
    iptables -t mangle -A OUTPUT -m mark --mark 0 -m owner --uid-owner root -j MARK --set-mark 1
    

    (根据需要在这里或在 filter/OUTPUT 中添加更多相关规则,这些规则应以 开头-m mark --mark 1)。

  3. 将数据包上的防火墙标记保存回conntrack流标记(它还会保存一个被改变的标记)

    这是在 POSTROUTING 中完成的,因此无需关心规则排序(也可以在 mangle/OUTPUT 中完成)。

    iptables -t mangle -A POSTROUTING -j CONNMARK --save-mark
    

根据问题的不同,可能需要进行一些优化,但这给出了想法。

通过这种设置,一旦流中的数据包第一次获得标记(来自根进程的最初传出流的第一个数据包,或最初传入根进程的流的第一个回复数据包),该流将继承该标记,并且此流的任何其他数据包也将继承此标记,双向。

警告:此方法不允许计算第一个数据包传入流量。对于配额核算,这意味着不会核算第一个有效负载大小(例如:收到的 UDP 查询,或第一个 TCP 传入(SYN)数据包(不是那么重要,除非它是具有初始有效负载的 TCP 快速打开))。


解决 OP 的具体问题

一旦上述框架到位,现在就可以检查 INPUT 或 OUTPUT 中的标记以了解它是发往或来自 root 用户的数据包。

  1. 输入

    quota2匹配在(默认)倒计时模式下,只要有剩余配额,就会返回 true:测试必须用 反转!,如下所述:

    从最初的配额开始倒计时,计数器将停止在 0 处并且匹配将返回 false[...]

    [ !]--quota智商

    指定此计数器的初始配额。如果计数器已存在,则不会重置。可以使用“!”来反转匹配结果。当使用 --grow 时,否定无效。

    返回 false 并且不执行目标 DROP,直到没有剩余配额(达到 0)。另一种方法(这里没有这样做)是反转操作的逻辑(-j ACCEPT后跟单个-j DROP规则)。

    对于 OPquota2匹配然后在 INPUT 中应用:

    iptables -A INPUT -m mark --mark 1 -m quota2 --name 10mb_quota ! --quota 10000000 -j DROP
    

    请注意,重新应用与 OP 示例中相同的标记是没有意义的:这已在 mangle/PREROUTING 中的前一个命令中完成(就像已经用 OP 的初始命令完成一样iptables -t mangle -A OUTPUT -m owner --uid-owner root -j MARK --set-mark 1,因此没有额外的效果)。而不是-j DROP可以跳转到新的用户链,该链将使用以下方式处理基本流量监管速率限制。我认为应用配额这不是个好主意,但对其他用户来说可能有意义。无论如何,这就是 OP 所要求的。

  2. 修正输出

    修订后的 OP配额2像在 INPUT 中一样应用于 OUTPUT。

    iptables -A OUTPUT -m mark --mark 1 -m quota2 --name 10mb_quota ! --quota 10000000 -j DROP
    

    与以前一样,一旦全局配额用完,就可以选择速率限制。

相关内容