iBug Thought �
最近写 Linux 201 的时候把 netfilter 这块搞清楚了,然后发现 Wikipedia 这张著名的流程图居然把这两个节点画反了
现在怀疑这里也画反了,如果 reroute check 指的是
ip_route_me_harder / ip6_route_me_harder 的话,它应该发生在 mangle/OUTPUT 和 nat/OUTPUT 后面各一次
iBug Thought �
现在怀疑这里也画反了,如果 reroute check 指的是 ip_route_me_harder / ip6_route_me_harder 的话,它应该发生在 mangle/OUTPUT 和 nat/OUTPUT 后面各一次
结论:reroute check 在 mangle 和 nat 后面各发生一次是正确的,但 reroute 的结果并不会用于后续的 iptables 匹配(-o 参数仍然匹配最开始的 routing decision 确定的 oif)
❤1
iBug Thought �
结论:reroute check 在 mangle 和 nat 后面各发生一次是正确的,但 reroute 的结果并不会用于后续的 iptables 匹配(-o 参数仍然匹配最开始的 routing decision 确定的 oif)
草,原来如此:
但匹配时用的是 (struct nf_hook_state*)
所以能同时观测到:
- 数据包的路由结果在 mangle/nat 后面各变了一次(经过
- 数据包在 filter 表中仍然匹配上了原始的 oif
ip_route_me_harder 改的是 skb->_skb_refdst(用于最终执行路由)但匹配时用的是 (struct nf_hook_state*)
state->out所以能同时观测到:
- 数据包的路由结果在 mangle/nat 后面各变了一次(经过
ip_route_me_harder 之后)- 数据包在 filter 表中仍然匹配上了原始的 oif
❤1
iBug Thought �
草,我机器 DNS 挂了一个小时了,刚才实验时加的 ip rule 和 iptables 忘记删了
cd ~/iptables
git checkout -f HEAD
./apply.sh
完工
👏2
iBug Thought �
草,原来如此: ip_route_me_harder 改的是 skb->_skb_refdst(用于最终执行路由) 但匹配时用的是 (struct nf_hook_state*) state->out 所以能同时观测到: - 数据包的路由结果在 mangle/nat 后面各变了一次(经过 ip_route_me_harder 之后) - 数据包在 filter 表中仍然匹配上了原始的 oif
虽然只是一个不到 800 字的 admonition,却有 6 个 code reference,写着也十分费劲(因为要时不时回去看代码避免写错)
https://201.ustclug.org/ops/network/firewall/#netfilter-chains
https://201.ustclug.org/ops/network/firewall/#netfilter-chains
🥰2❤1
iBug Thought �
虽然只是一个不到 800 字的 admonition,却有 6 个 code reference,写着也十分费劲(因为要时不时回去看代码避免写错) https://201.ustclug.org/ops/network/firewall/#netfilter-chains
经过实验,mangle/FORWARD 不会触发 reroute,毕竟代码都叫 ipt_mangle_out 了嘛,所以 Wikipedia 的图至少还有一处额外的问题
iBug Thought �
亲自指挥、亲自画图(
重大勘误:没有 OUTPUT 直接到 INPUT 的路径,而是先 POSTROUTING 到 lo 出,再从 lo 进到 PREROUTING
晚上更新图片(((
感谢评论区指出
晚上更新图片(((
感谢评论区指出
❤3
Forwarded from Welcome to the Black Parade
我发现很多工程师可能不知道 linux 并没有 local -> local 这条网络链路,当我们 curl localhost:8000 的时候本质是走了一次 outbound 链路,然后被 lo 导回来,变成一次 inbound 链路。
所以熟悉 nf 立刻就知道一个 curl localhost 会走哪些 chains 了:
1. outbound: OUTPUT + POSTROUTING
2. inbound: PREROUTING + INPUT
这就是为什么 “网上最容易找到的 iptables 各 table 各 chain 关系的图,怎么都像是画图的人根本不知道还可以同一台机器内 process -> process 一样,只画了 interface -> process, interface -> interface, process -> interface,导致看不出 process -> process 会经过哪些 chain”。
如果自己用过 AF_PACKET + SOCK_RAW 模拟 tcpdump 抓包,会发现 lo 上会抓到双重流量,这就是因为一次 egress 一次 ingress (tcpdump 本身处理得很好所以你看不到 lo 的双重流量)
如果用 pwru 也能看到 lo 上的 rx 路径的软中断,是一次完整的收包链路。
所以,local -> local 的流量,本质是一次 tx + 一次 rx。
所以熟悉 nf 立刻就知道一个 curl localhost 会走哪些 chains 了:
1. outbound: OUTPUT + POSTROUTING
2. inbound: PREROUTING + INPUT
这就是为什么 “网上最容易找到的 iptables 各 table 各 chain 关系的图,怎么都像是画图的人根本不知道还可以同一台机器内 process -> process 一样,只画了 interface -> process, interface -> interface, process -> interface,导致看不出 process -> process 会经过哪些 chain”。
如果自己用过 AF_PACKET + SOCK_RAW 模拟 tcpdump 抓包,会发现 lo 上会抓到双重流量,这就是因为一次 egress 一次 ingress (tcpdump 本身处理得很好所以你看不到 lo 的双重流量)
如果用 pwru 也能看到 lo 上的 rx 路径的软中断,是一次完整的收包链路。
所以,local -> local 的流量,本质是一次 tx + 一次 rx。
🥰9
Forwarded from codedump的电报频道 (老C)
#系统编程
《The Life of a Packet in the Linux kernel》,Linux中数据包的一生。
这篇文章以curl 访问一个网站为例,介绍了数据包在Linux系统中从应用程序发送到接收的完整路径。包括Linux网络数据包从send()到recv()的九大核心步骤,涵盖套接字、TCP/IP协议栈、路由、ARP、队列管理、DMA、NAPI、防火墙、NAT等关键机制,结合命令实践,帮助开发者理解底层网络通信原理,可以看作是Linux网络栈入门指南。
《The Life of a Packet in the Linux kernel》,Linux中数据包的一生。
这篇文章以curl 访问一个网站为例,介绍了数据包在Linux系统中从应用程序发送到接收的完整路径。包括Linux网络数据包从send()到recv()的九大核心步骤,涵盖套接字、TCP/IP协议栈、路由、ARP、队列管理、DMA、NAPI、防火墙、NAT等关键机制,结合命令实践,帮助开发者理解底层网络通信原理,可以看作是Linux网络栈入门指南。
0xkato
The Life of a Packet in the Linux kernel
A practical, plain-English tour of how Linux moves packets from write() to the wire and back
❤5👍4
顺便补充一个小知识(后面找时间写进 201):
1. net.ipv{4,6}.non_local_bind
2. setsockopt(IP_FREEBIND) or setsockopt(IP_TRANSPARENT)
3. table local 中存在一条到该地址的 local route
IPv4 能 bind 任意地址的条件是以上三点任选一个,但 IPv6 能 bind 任意地址的条件只有 1 或 2,仅有第 3 点的情况下你会吃一个 EADDRNOTAVAIL
1. net.ipv{4,6}.non_local_bind
2. setsockopt(IP_FREEBIND) or setsockopt(IP_TRANSPARENT)
3. table local 中存在一条到该地址的 local route
IPv4 能 bind 任意地址的条件是以上三点任选一个,但 IPv6 能 bind 任意地址的条件只有 1 或 2,仅有第 3 点的情况下你会吃一个 EADDRNOTAVAIL
iBug Thought �
顺便补充一个小知识(后面找时间写进 201): 1. net.ipv{4,6}.non_local_bind 2. setsockopt(IP_FREEBIND) or setsockopt(IP_TRANSPARENT) 3. table local 中存在一条到该地址的 local route IPv4 能 bind 任意地址的条件是以上三点任选一个,但 IPv6 能 bind 任意地址的条件只有 1 或 2,仅有第 3 点的情况下你会吃一个 EADDRNOTAVAIL
Matt Oswalt
Non-Local Address Binds in Linux
I came across some interesting sockets-related behavior this week that caused me to go down a bit of a rabbit hole. This ended up taking me on a tour of Linux’s socket and IPv4/IPv6 implementation. I thought the journey was instructive, and I hope that my…
iBug Thought �
原来有人写过了,那我是不是翻译一下就行了 https://oswalt.dev/2022/02/non-local-address-binds-in-linux/
TL;DR:
__sys_bind 在 IPv6 的路径上没有 FIB lookup,所以只需要检查三个 flag(一个 sysctl 两个 setsockopt)即可下结论。