了解 iptables -L、iprule show(基于策略的路由)和具有多个表的 iproute 的输出

了解 iptables -L、iprule show(基于策略的路由)和具有多个表的 iproute 的输出

我正在寻找关于如何解释命令的输出iptables -L以及如何ip rule show与命令结合使用的很好的解释ip route show table <table_name>

当 WiFi 热点服务打开时,我很难理解 OnePlus 8 Pro 过于复杂的基于策略的路由。我拥有 CCNA 和 Cisco Certified Specialist - Enterprise Core 认证,因此对于路由和基于策略的路由我并不是一无所知,但我仍然需要帮助。

我对Linux的了解不多iptables。我了解一些输出ip rule show(例如优先级以及如果规则匹配则检查哪个路由表)。我对ip route使用单个表有很强的把握,但与基于策略的路由结合使用时则不太清楚。

不幸的是,我的 OnePlus 8 Pro 似乎将 iptables 与基于策略的路由和多个路由表结合起来,实际上没有什么充分的理由。我的系统已root,并且安装了busybox,它为我提供了大多数Linux 标准命令行工具。

所以这是我试图理解的混乱:

首先,这里列出了该设备的接口:

OnePlus8Pro# ifconfig
dummy0    Link encap:Ethernet  HWaddr ae:22:9c:ac:69:85
          inet6 addr: fe80::ac22:9cff:feac:6985/64 Scope: Link
          UP BROADCAST RUNNING NOARP  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:113 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 TX bytes:15971

wlan0     Link encap:Ethernet  HWaddr 4c:4f:ee:96:b3:ed  Driver cnss_pci
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:3000
          RX bytes:0 TX bytes:0

rmnet_data3 Link encap:UNSPEC
          inet6 addr: fe80::a00e:387b:f22e:c336/64 Scope: Link
          inet6 addr: 2607:fc20:1bc3:a194:a00e:387b:f22e:c336/64 Scope: Global
          UP RUNNING  MTU:1500  Metric:1
          RX packets:10 errors:0 dropped:0 overruns:0 frame:0
          TX packets:18 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:804 TX bytes:1284

rmnet_data0 Link encap:UNSPEC
          inet6 addr: fe80::11c2:944d:89dd:e766/64 Scope: Link
          UP RUNNING  MTU:1500  Metric:1
          RX packets:51 errors:0 dropped:0 overruns:0 frame:0
          TX packets:36 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:7720 TX bytes:2487

rmnet_mhi0 Link encap:UNSPEC    Driver mhi_netdev
          UP RUNNING  MTU:65535  Metric:1
          RX packets:48471 errors:0 dropped:0 overruns:0 frame:0
          TX packets:42815 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:23427476 TX bytes:11997668

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope: Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:59 errors:0 dropped:0 overruns:0 frame:0
          TX packets:59 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:5850 TX bytes:5850

wlan1     Link encap:Ethernet  HWaddr 62:59:38:18:bc:69  Driver cnss_pci
          inet addr:192.168.42.149  Bcast:192.168.42.255  Mask:255.255.255.0
          inet6 addr: fe80::6059:38ff:fe18:bc69/64 Scope: Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:4599 errors:0 dropped:0 overruns:0 frame:0
          TX packets:1756 errors:0 dropped:44 overruns:0 carrier:0
          collisions:0 txqueuelen:3000
          RX bytes:859009 TX bytes:143474

rmnet_data2 Link encap:UNSPEC
          inet addr:33.215.218.82  Mask:255.255.255.252
          UP RUNNING  MTU:1440  Metric:1
          RX packets:30742 errors:0 dropped:0 overruns:0 frame:0
          TX packets:35534 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:21959066 TX bytes:11141381

接下来,这是路由:

OnePlus8Pro# ip route
33.215.218.80/30 dev rmnet_data2 proto kernel scope link src 33.215.218.82
192.168.42.0/24 dev wlan1 proto kernel scope link src 192.168.42.149

现在,ip 规则(基于策略的路由):

OnePlus8Pro# ip rule show
0:      from all lookup local
10000:  from all fwmark 0xc0000/0xd0000 lookup legacy_system
10500:  from all iif lo oif dummy0 uidrange 0-0 lookup dummy0
10500:  from all iif lo oif rmnet_data0 uidrange 0-0 lookup rmnet_data0
10500:  from all iif lo oif rmnet_data2 uidrange 0-0 lookup rmnet_data2
10500:  from all iif lo oif wlan1 uidrange 0-0 lookup local_network
13000:  from all fwmark 0x10063/0x1ffff iif lo lookup local_network
13000:  from all fwmark 0xd0001/0xdffff iif lo lookup rmnet_data0
13000:  from all fwmark 0x10064/0x1ffff iif lo lookup rmnet_data2
14000:  from all iif lo oif dummy0 lookup dummy0
14000:  from all fwmark 0xc0000/0xc0000 iif lo oif rmnet_data0 lookup rmnet_data0
14000:  from all iif lo oif rmnet_data2 lookup rmnet_data2
14000:  from all iif lo oif wlan1 lookup local_network
15000:  from all fwmark 0x0/0x10000 lookup legacy_system
16000:  from all fwmark 0x0/0x10000 lookup legacy_network
17000:  from all fwmark 0x0/0x10000 lookup local_network
18000:  from all iif wlan1 lookup rmnet_data2
19000:  from all fwmark 0x64/0x1ffff iif lo lookup rmnet_data2
22000:  from all fwmark 0x0/0xffff iif lo lookup rmnet_data2
32000:  from all unreachable

所有命名路由表的列表:

OnePlus8Pro# show table all | grep "table" | sed 's/.*\(table.*\)/\1/g' | awk '{print $2}' | sort | uniq
1014
1025
dummy0
local
local_network
rmnet_data0
rmnet_data2

ip route show table <table_name>每个命名路由表的输出:

OnePlus8Pro# ip route show table 1014

OnePlus8Pro# ip route show table 1025

OnePlus8Pro# ip route show table dummy0
default dev dummy0 proto static scope link

OnePlus8Pro# ip route show table local
broadcast 33.215.218.80 dev rmnet_data2 proto kernel scope link src 33.215.218.82
local 33.215.218.82 dev rmnet_data2 proto kernel scope host src 33.215.218.82
broadcast 33.215.218.83 dev rmnet_data2 proto kernel scope link src 33.215.218.82
broadcast 127.0.0.0 dev lo proto kernel scope link src 127.0.0.1
local 127.0.0.0/8 dev lo proto kernel scope host src 127.0.0.1
local 127.0.0.1 dev lo proto kernel scope host src 127.0.0.1
broadcast 127.255.255.255 dev lo proto kernel scope link src 127.0.0.1
broadcast 192.168.42.0 dev wlan1 proto kernel scope link src 192.168.42.149
local 192.168.42.149 dev wlan1 proto kernel scope host src 192.168.42.149
broadcast 192.168.42.255 dev wlan1 proto kernel scope link src 192.168.42.149

OnePlus8Pro# ip route show table local_network
192.168.42.0/24 dev wlan1 proto static scope link

OnePlus8Pro# ip route show table rmnet_data0

OnePlus8Pro# ip route show table rmnet_data2
default via 33.215.218.81 dev rmnet_data2 proto static mtu 1500
33.215.218.80/30 dev rmnet_data2 proto static scope link

最后但并非最不重要的一点是,输出iptables -L

OnePlus8Pro# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
bw_INPUT   all  --  anywhere             anywhere
fw_INPUT   all  --  anywhere             anywhere

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination
oem_fwd    all  --  anywhere             anywhere
fw_FORWARD  all  --  anywhere             anywhere
bw_FORWARD  all  --  anywhere             anywhere
tetherctrl_FORWARD  all  --  anywhere             anywhere

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
nm_qti_filter_ssdp_dropper  all  --  anywhere             anywhere
oem_out    all  --  anywhere             anywhere
fw_OUTPUT  all  --  anywhere             anywhere
st_OUTPUT  all  --  anywhere             anywhere
bw_OUTPUT  all  --  anywhere             anywhere

Chain bw_FORWARD (1 references)
target     prot opt source               destination
bw_costly_rmnet_data2  all  --  anywhere             anywhere
bw_costly_rmnet_data2  all  --  anywhere             anywhere

Chain bw_INPUT (1 references)
target     prot opt source               destination
bw_global_alert  all  --  anywhere             anywhere
bw_costly_rmnet_data2  all  --  anywhere             anywhere
RETURN     esp  --  anywhere             anywhere
RETURN     all  --  anywhere             anywhere             mark match 0x100000/0x100000
MARK       all  --  anywhere             anywhere             MARK or 0x100000

Chain bw_OUTPUT (1 references)
target     prot opt source               destination
bw_global_alert  all  --  anywhere             anywhere
bw_costly_rmnet_data2  all  --  anywhere             anywhere

Chain bw_costly_rmnet_data2 (4 references)
target     prot opt source               destination
bw_penalty_box  all  --  anywhere             anywhere
REJECT     all  --  anywhere             anywhere             ! quota rmnet_data2: 9223372036854775807 bytes  reject-with icmp-port-unreachable

Chain bw_costly_shared (0 references)
target     prot opt source               destination
bw_penalty_box  all  --  anywhere             anywhere

Chain bw_data_saver (1 references)
target     prot opt source               destination
RETURN     all  --  anywhere             anywhere

Chain bw_global_alert (3 references)
target     prot opt source               destination
           all  --  anywhere             anywhere             ! quota globalAlert: 2097152 bytes

Chain bw_happy_box (1 references)
target     prot opt source               destination
RETURN     all  --  anywhere             anywhere            match bpf pinned /sys/fs/bpf/prog_netd_skfilter_whitelist_xtbpf
bw_data_saver  all  --  anywhere             anywhere

Chain bw_penalty_box (2 references)
target     prot opt source               destination
REJECT     all  --  anywhere             anywhere            match bpf pinned /sys/fs/bpf/prog_netd_skfilter_blacklist_xtbpf reject-with icmp-port-unreachable
bw_happy_box  all  --  anywhere             anywhere

Chain fw_FORWARD (1 references)
target     prot opt source               destination

Chain fw_INPUT (1 references)
target     prot opt source               destination

Chain fw_OUTPUT (1 references)
target     prot opt source               destination

Chain nm_mdmprxy_doze_mode_skip (0 references)
target     prot opt source               destination

Chain nm_mdmprxy_iface_pkt_fwder (0 references)
target     prot opt source               destination

Chain nm_qti_filter_ssdp_dropper (1 references)
target     prot opt source               destination
DROP       udp  --  anywhere             anywhere             udp dpt:1900
DROP       udp  --  anywhere             anywhere             udp dpt:1900

Chain oem_fwd (1 references)
target     prot opt source               destination

Chain oem_out (1 references)
target     prot opt source               destination

Chain st_OUTPUT (1 references)
target     prot opt source               destination

Chain st_clear_caught (2 references)
target     prot opt source               destination

Chain st_clear_detect (0 references)
target     prot opt source               destination
REJECT     all  --  anywhere             anywhere             connmark match  0x2000000/0x2000000 reject-with icmp-port-unreachable
RETURN     all  --  anywhere             anywhere             connmark match  0x1000000/0x1000000
CONNMARK   tcp  --  anywhere             anywhere             u32 "0x0>>0x16&0x3c@0xc>>0x1a&0x3c@0x0&0xffff0000=0x16030000&&0x0>>0x16&0x3c@0xc>>0x1a&0x3c@0x4&0xff0000=0x10000" CONNMARK or 0x1000000
CONNMARK   udp  --  anywhere             anywhere             u32 "0x0>>0x16&0x3c@0x8&0xffff0000=0x16fe0000&&0x0>>0x16&0x3c@0x14&0xff0000=0x10000" CONNMARK or 0x1000000
RETURN     all  --  anywhere             anywhere             connmark match  0x1000000/0x1000000
st_clear_caught  tcp  --  anywhere             anywhere             state ESTABLISHED u32 "0x0>>0x16&0x3c@0xc>>0x1a&0x3c@0x0&0x0=0x0"
st_clear_caught  udp  --  anywhere             anywhere

Chain st_penalty_log (0 references)
target     prot opt source               destination
CONNMARK   all  --  anywhere             anywhere             CONNMARK or 0x1000000
NFLOG      all  --  anywhere             anywhere

Chain st_penalty_reject (0 references)
target     prot opt source               destination
CONNMARK   all  --  anywhere             anywhere             CONNMARK or 0x2000000
NFLOG      all  --  anywhere             anywhere
REJECT     all  --  anywhere             anywhere             reject-with icmp-port-unreachable

Chain tetherctrl_FORWARD (1 references)
target     prot opt source               destination
bw_global_alert  all  --  anywhere             anywhere
tetherctrl_counters  all  --  anywhere             anywhere            [goto]  state RELATED,ESTABLISHED
DROP       all  --  anywhere             anywhere             state INVALID
tetherctrl_counters  all  --  anywhere             anywhere            [goto]
DROP       all  --  anywhere             anywhere

Chain tetherctrl_counters (2 references)
target     prot opt source               destination
RETURN     all  --  anywhere             anywhere
RETURN     all  --  anywhere             anywhere

我试图像手机一样处理/理解所有这些规则,但我迷失了。我找不到像10500: from all iif lo oif rmnet_data0 uidrange 0-0 lookup rmnet_data0中这样的行的良好解释ip rules show。我也不明白 iptables 中的标记以及如何知道它如何应用于13000: from all fwmark 0xd0001/0xdffff iif lo lookup rmnet_data0.

我的最终目标是编写一个 shell 脚本来修复这款手机上 WiFi 热点路由的混乱问题。我计划在每次启动 WiFi 热点后启动该脚本。然而,为了做到这一点,我需要首先了解这个混乱的路由正在做什么。

我在此处提供了我认为与理解路由相关的所有输出。任何帮助表示赞赏。

答案1

这里的聚会相当晚了,但是。如果不查看 AOSP 代码,就很难理解 Android 路由,这将帮助您了解很多内容。你可以弄清楚什么确实如此,但是为什么确实如此,这真的很难。 Android 的规则比普通的 UNIX 机器复杂得多,因为它通常同时连接到许多网络;有些进程可以访问某些网络,而其他进程则不能;每个 UID 可能有不同的默认网络;应用程序可以通过使用多个来请求默认网络之外的另一个网络应用程序编程接口。 Unix 服务器或桌面计算机不需要处理任何这种复杂性,并且可以通过更简单的路由来完成。

如果您对规则如何运作感兴趣,请开始这里获取最新代码(您可以查看旧分支,了解您感兴趣的特定 Android 版本)。除此之外,设备制造商可能会(并且经常)进行更改,因此任何特定设备的详细信息可能会有所不同。

通常的想法是,路由首先按优先级顺序(从低到低的顺序)查看每个规则。如果数据包符合规则,则内核将查找关联表;如果它在那里找到目的地,那就是它发送数据包的地方,否则它会返回并评估下一条规则。

像这样的规则

10500:  from all iif lo oif rmnet_data0 uidrange 0-0 lookup rmnet_data0

在 man ip-rule 中有描述。简而言之 :

  • 10500是首要任务。路由按升序评估规则。具有相同优先级的两个规则的顺序未定义。
  • from all iif lo oif rmnet_data0 uidrange 0-0是过滤器。每个都是两个词:
    • from all意味着任何来源都会匹配
    • iif lo(对于本地输入接口)仅匹配本地生成的流量(不匹配转发的流量)
    • oif rmnet_data0(对于输出接口)仅匹配发往该rmnet_data0接口的流量
    • uidrange 0-0仅匹配来自 0 到 0 之间的 UID 的流量(因此在本例中仅匹配 UID 0)。 Android 的每个应用程序都有不同的 UID。
  • lookup rmnet_data0简单地说,如果数据包与所有过滤器匹配,那么您应该查找表 rmnet_data0 来尝试查找路由。如果有,则遵循它,否则转到下一条规则。

至于标记,这里是您想要开始的地方。 Android 使用防火墙标记来管理网络权限和来自应用程序的显式请求。从代码中可以看到,防火墙标记中的底部16位是网络的ID(Android为每个网络分配一个16位的网络ID)。高位用于权限、记帐...

当您看到类似 的过滤器时fwmark 0xd0001/0xdffff,这意味着用右侧部分(此处为 0xdffff)掩盖套接字上的标记,并将其与左侧部分(此处为 0xd0001)进行比较。在这种情况下,再次查找该代码,0xdffff 将保留位 0~15(netId)、位 16(“显式选择”)以及位 18 和 19(权限)。屏蔽之后,套接字标记为 0xd0001 的流量将匹配此规则,因此它必须绑定到 netId 1 的网络,明确选择(这意味着应用程序已使用某些 API 来请求此网络,而不是默认的),它必须具有两个权限位(因此它必须是持有 android 权限的特权应用程序USE_RESTRICTED_NETWORKS)。

至于如何标记套接字,这是另一个故事,但为了简短起见,当您调用connect或某些允许您选择网络的 Android API时,Android 使用系统调用中的挂钩将套接字发送到(仅限 Android)netd 守护程序,netd 将为您标记该套接字。你可以看到逻辑在这段代码中如果您对细节感兴趣。还有一些 iptables 规则来标记接受的套接字以及大量技术细节,如果您想了解更多信息,可以在代码中查找。

希望这可以帮助,

相关内容