没有 uid 的 iptables 数据包

没有 uid 的 iptables 数据包

我正在尝试通过 VPN 路由来自计算机上某一特定用户的所有流量。我通过使用“-mowner --uid-owner”创建 iptables 规则来标记来自用户的数据包,然后使用该数据包中的路由表来实现此目的。为了确保所有内容都被重定向,我还有一个“-m Owner ! --uid-owner 0-99999 -j DROP”来删除所有“匿名”网络包,以防万一。

在大多数情况下,它运行良好,但是我收到一些没有 uid 的数据包,尽管明显来自用户;观察到某些 SSL 连接很少发生这种情况。意思是我正在做“wgethttps://google.com我在日志中看到发送到 google IP 的数据包被丢弃,因为它是在没有 uid 的情况下发出的。

我的理解是,内核有时可能会出于某种原因“排队”请求,然后异步处理它,而不设置数据包的 uid。在这种情况下是否可以追踪该数据包的真正来源?我无法通过 VPN 转发所有“匿名”数据包,因为我认为其他用户也会发生这种情况。

谢谢。

答案1

有些数据包实际上不属于任何用户,只属于内核:

  • 路由数据包
  • 内核响应外部事件而生成的数据包。例如:当收到 icmp echo-r​​equest 时,内核将用 icmp echo-r​​eply 进行应答。
  • 可能是所有 iptables 的 -j REJECT 数据包。
  • ...

现在关于您正在谈论的数据包:从标记有和没有所有者的数据包进行的测试来看,它们似乎属于通信结束协商ACK结束时FIN以及RST连接突然切断时的最终数据包。我的猜测是,在这两种情况下,内核已经停止考虑属于用户的连接,因为它正在将其撕裂,尽管这并不总是发生ACK(也许与 PSH 和最终数据混合时?)。

更新:答案“Iptables:将传出流量与 conntrack 和所有者相匹配。适用于奇怪的丢弃”提供有关该问题的更详细信息。

如果您不想丢失这些数据包并且仍然想使用 MARK 进行决策,您仍然可以依赖Netfilter的CONNMARK因为最后一个数据包,即使没有所有者,仍然是同一连接的一部分。例如,使用根据链接中的示例改编的规则进行测试:

#!/bin/sh

iptables -t mangle -N connmark_test
iptables -t mangle -N connmark_log
iptables -t mangle -A connmark_test -j CONNMARK --restore-mark
iptables -t mangle -A connmark_test -m mark ! --mark 0 -j RETURN
iptables -t mangle -A connmark_test -m mark --mark 0 -m owner --uid-owner 0-99999 -p tcp -j MARK --set-mark 1
iptables -t mangle -A connmark_test -m mark --mark 0 -m owner --uid-owner 0-99999        -j MARK --set-mark 2
iptables -t mangle -A connmark_test -m mark --mark 0                              -p tcp -j MARK --set-mark 3
iptables -t mangle -A connmark_test -m mark --mark 0                                     -j MARK --set-mark 4
iptables -t mangle -A connmark_test -j CONNMARK --save-mark
iptables -t mangle -A connmark_log -m owner --uid-owner 0-99999 -j LOG --log-prefix "with_owner "
iptables -t mangle -A connmark_log -m owner ! --uid-owner 0-99999 -j LOG --log-prefix "  NO_owner "
iptables -t mangle -A POSTROUTING -j connmark_test
iptables -t mangle -A POSTROUTING -m mark ! --mark 0 -j connmark_log

我可以看到 with curl -s -L https://google.com/ >/dev/null(建立两个连接)最终连接的 ACK 或 RST 通常在所有者匹配时失败,但仍然有一个 connmark,因为有MARK=0x1

[14668.179780] with_owner IN= OUT=eth0 SRC=10.0.3.66 DST=216.58.209.238 LEN=83 TOS=0x00 PREC=0x00 TTL=64 ID=53193 DF PROTO=TCP SPT=33472 DPT=443 WINDOW=339 RES=0x00 ACK PSH URGP=0 MARK=0x1 
[14668.181740] with_owner IN= OUT=eth0 SRC=10.0.3.66 DST=216.58.209.238 LEN=52 TOS=0x00 PREC=0x00 TTL=64 ID=53194 DF PROTO=TCP SPT=33472 DPT=443 WINDOW=339 RES=0x00 ACK FIN URGP=0 MARK=0x1 
[14668.181914]   NO_owner IN= OUT=eth0 SRC=10.0.3.66 DST=216.58.209.238 LEN=52 TOS=0x00 PREC=0x00 TTL=64 ID=53195 DF PROTO=TCP SPT=33472 DPT=443 WINDOW=339 RES=0x00 ACK URGP=0 MARK=0x1 
[14668.182667] with_owner IN= OUT=eth0 SRC=10.0.3.66 DST=216.58.198.67 LEN=83 TOS=0x00 PREC=0x00 TTL=64 ID=58460 DF PROTO=TCP SPT=33210 DPT=443 WINDOW=520 RES=0x00 ACK PSH URGP=0 MARK=0x1 
[14668.184588] with_owner IN= OUT=eth0 SRC=10.0.3.66 DST=216.58.198.67 LEN=52 TOS=0x00 PREC=0x00 TTL=64 ID=58461 DF PROTO=TCP SPT=33210 DPT=443 WINDOW=520 RES=0x00 ACK RST URGP=0 MARK=0x1 
[14668.201316]   NO_owner IN= OUT=eth0 SRC=10.0.3.66 DST=216.58.198.67 LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=20784 DF PROTO=TCP SPT=33210 DPT=443 WINDOW=0 RES=0x00 RST URGP=0 MARK=0x1 

最后注意:不要忘记,用户的活动可以触发来自其他用户的数据包:例如,向本地 DNS 服务器发出 DNS 请求,然后本地 DNS 服务器将使用运行 DNS 服务器的用户拥有的数据包发出 DNS 请求。

相关内容