九维我操你爹
Lance Yang 老师昨晚在评论区为我指明方向,我觉得这个很重要所以整理了一下单独发出来,因为这个问题在互联网上似乎搜不到正确的信息,AI 也全军覆没。
envoy sidecar 在云原神里被用做透明代理,pod -> remote 的流量(几乎)被全量劫持到同一 netns 里的 envoy,实际路径是 pod -> envoy -> reomte (正向代理,两个 tcp 会话)。不过 envoy sidecar 劫持流量默认不使用炫酷的 tproxy,而是古典的 REDIRECT
把 packets DNAT 成 127.0.0.1:15001。
envoy 劫持到这个流量之后,通过 getsockopt(SO_ORIGINAL_DST) 拿到原始的 dip:dport。
回程的 rev-DNAT 由 nf conntrack 隐式处理。
这看起来没有问题,但是注意力稍微集中一点就能意识到 DNAT 之后可以导致连接冲突。我们可以显式地尝试构造这种冲突:
先运行 python main.py 1.1.1.1:80 建立一个 nodeip:19233 -> 1.1.1.1:80,然后再运行 python main.py 1.0.0.1:80 建立一个 nodeip:19233 -> 1.0.0.1:80。两个 tcp 连接有不同的 dip,零冲突,很合规。
但是 iptables DNAT 之后,两个连接都变成了 nodeip:19233 -> 127.0.0.1:15001,这样后发起握手的连接似乎必被 reset,就算安慰自己“这应该是小概率事件”,严肃的工程师都应该意识到这绝对会让生产爆炸。
但是真的如此吗?
立刻着手测试,发现第二个 tcp 其实也能成功握手,ss 看到第二个连接的 sport 居然被 SNAT 了,这就是昨晚 Lance Yang 的发现:
用 pwru 追一下 skb,会发现还要稍微复杂一点点,以下是
额外的 SNAT 并非发生在 -j REDIRECT 的 OUTPUT nat 里,而推迟到了 POSTROUTING nat,通过 ct 来传递 SNAT 信息。nf_nat_redirect_ipv4 只会计算出需要 SNAT 的新端口,记录到 ct 里,待到 POSTROUTING 再 SNAT。
如果此时再加入一些 SNAT --to-source 会怎样,其实也不会怎样,ct 只有一条干净的 entry 记录 10.0.0.16:19233 -> 1.0.0.1:80 被 NAT 成 127.0.0.1:13902 -> 127.0.0.1:15001,所有 ip port 都被换过。
这对 envoy 用户态调用 getsockopt(SO_ORIGINAL_DST) 没有影响,rev-NAT 也无需用户态操心,延迟 SNAT 的行为目测半完全正确(否则在 OUTPUT 发生隐式 SNAT 、影响 POSTROUTING 的规则命中就绝了😊 ),就算 POSTROUTING 再次命中显式 SNAT 也没关系,几乎不会踩坑(除了要消耗 ct),唯一需要注意的就是在旁路观测的时候不能通过 socket tuple 来配对 client socket 和被劫持的 conn socket😭 因为我真的就在这么干,周一改。
envoy sidecar 在云原神里被用做透明代理,pod -> remote 的流量(几乎)被全量劫持到同一 netns 里的 envoy,实际路径是 pod -> envoy -> reomte (正向代理,两个 tcp 会话)。不过 envoy sidecar 劫持流量默认不使用炫酷的 tproxy,而是古典的 REDIRECT
iptables -t nat -A OUTPUT -j REDIRECT --to-ports 15001把 packets DNAT 成 127.0.0.1:15001。
envoy 劫持到这个流量之后,通过 getsockopt(SO_ORIGINAL_DST) 拿到原始的 dip:dport。
回程的 rev-DNAT 由 nf conntrack 隐式处理。
这看起来没有问题,但是注意力稍微集中一点就能意识到 DNAT 之后可以导致连接冲突。我们可以显式地尝试构造这种冲突:
import socket, sys, time
sk = socket.socket()
sk.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sk.bind(('', 19233))
sk.connect((sys.argv[1], int(sys.argv[2])))
time.sleep(1000)先运行 python main.py 1.1.1.1:80 建立一个 nodeip:19233 -> 1.1.1.1:80,然后再运行 python main.py 1.0.0.1:80 建立一个 nodeip:19233 -> 1.0.0.1:80。两个 tcp 连接有不同的 dip,零冲突,很合规。
但是 iptables DNAT 之后,两个连接都变成了 nodeip:19233 -> 127.0.0.1:15001,这样后发起握手的连接似乎必被 reset,就算安慰自己“这应该是小概率事件”,严肃的工程师都应该意识到这绝对会让生产爆炸。
但是真的如此吗?
立刻着手测试,发现第二个 tcp 其实也能成功握手,ss 看到第二个连接的 sport 居然被 SNAT 了,这就是昨晚 Lance Yang 的发现:
nf_nat_redirect_ipv4
-> nf_nat_redirect
-> nf_nat_setup_info
-> get_unique_tuple
-> nf_nat_l4proto_unique_tuple
-> nf_nat_used_tuple_harder
有趣。最新代码,NAT REDIRECT 如果源端口检测到冲突后会自动进行源端口重分配 。。。
用 pwru 追一下 skb,会发现还要稍微复杂一点点,以下是
pwru --all-kmods --filter-track-skb 'tcp[tcpflags]=tcp-syn and src port 19233' 的导演剪辑版:10.0.0.16:19233->1.0.0.1:80 ip_local_out
10.0.0.16:19233->1.0.0.1:80 __ip_local_out
10.0.0.16:19233->1.0.0.1:80 nf_hook_slow
// iptables -A OUTPUT -t nat -j REDIRECT
10.0.0.16:19233->1.0.0.1:80 nft_nat_do_chain[nft_chain_nat]
10.0.0.16:19233->1.0.0.1:80 redirect_tg4[xt_REDIRECT]
// DNAT, be aware of changes of dport and dip, and re-route
10.0.0.16:19233->1.0.0.1:80 l4proto_manip_pkt[nf_nat]
10.0.0.16:19233->1.0.0.1:15001 nf_csum_update[nf_nat]
10.0.0.16:19233->1.0.0.1:15001 inet_proto_csum_replace4
10.0.0.16:19233->1.0.0.1:15001 inet_proto_csum_replace4
10.0.0.16:19233->127.0.0.1:15001 ip_route_me_harder
// iptables POSTROUTING
10.0.0.16:19233->127.0.0.1:15001 apparmor_ip_postroute
// extra SNAT due to conflicts, be aware of the change of sport
10.0.0.16:19233->127.0.0.1:15001 l4proto_manip_pkt[nf_nat]
10.0.0.16:46801->127.0.0.1:15001 nf_csum_update[nf_nat]额外的 SNAT 并非发生在 -j REDIRECT 的 OUTPUT nat 里,而推迟到了 POSTROUTING nat,通过 ct 来传递 SNAT 信息。nf_nat_redirect_ipv4 只会计算出需要 SNAT 的新端口,记录到 ct 里,待到 POSTROUTING 再 SNAT。
如果此时再加入一些 SNAT --to-source 会怎样,其实也不会怎样,ct 只有一条干净的 entry 记录 10.0.0.16:19233 -> 1.0.0.1:80 被 NAT 成 127.0.0.1:13902 -> 127.0.0.1:15001,所有 ip port 都被换过。
这对 envoy 用户态调用 getsockopt(SO_ORIGINAL_DST) 没有影响,rev-NAT 也无需用户态操心,延迟 SNAT 的行为目测半完全正确(否则在 OUTPUT 发生隐式 SNAT 、影响 POSTROUTING 的规则命中就绝了
在Ingress夏至活动过去三年后,NIAS宣布在即将到来的2025年冬至前将举办限时挑战并在商城限时上架冬至纪念奖章,详情如下:
免费限时挑战
时间:东八区时间 2025年12月6日凌晨2:00 - 2025年12月23日凌晨2:00
形式:完成四个阶段的战令任务,完成第二阶段获得「Winter Solstice 2025 Dispatch Challenge」奖章铜牌(上图左一),完成第四阶段获得银牌(上图中)
战令任务内容
阶段1
- 充能75,000 XM
- 遥控机入侵15次
- 入侵能量塔25次
- 部署共振器100枚
- 占领能量塔20次
阶段2(铜牌)
- 充能150,000 XM
- 获得画图入侵点数50点
- 入侵能量塔50次
- 部署强化模组40个
- 进行链接35次
阶段3
- 充能200,000 XM
- 遥控机入侵25次
- 入侵能量塔75次
- 部署共振器225枚
- 占领能量塔45次
阶段4(银牌)
- 充能250,000 XM
- 获得画图入侵点数100点
- 入侵能量塔100次
- 进行链接60次
- 创建控制场40个
限时机制变化
活动期间将有以下游戏内增益
- 占领能量塔收益从800 AP增加到2000 AP
- 入侵获得两倍能量核
- 无能量塔的钥匙时入侵必定获得其钥匙
- 画图入侵时限增加50%
- 遥控机冷却时间降低至15分钟
- 动能合成胶囊合成Hypercube的配方走路需求从8km降低至1km
收费奖章
与限时挑战奖章同一设计语言的收费奖章「Winter Solstice 2025」(上图右)将在活动期间限时上架游戏内商城,盛惠10,000 CMU
编注:利好仓鼠式囤XM行为,鉴定为NIAS希望大家花完钱后冬眠
来源:Ingress
#冬至活动 #限时活动 #可持续发展 #新闻
https://x.com/jijicom/status/1994013608876114042
> 法改正により、手数料の上限を永住許可は30万円に、資格変更・更新は10万円に引き上げる案を検討する。
いじめ真是贵国悠久的传统文化呢
> 法改正により、手数料の上限を永住許可は30万円に、資格変更・更新は10万円に引き上げる案を検討する。
いじめ真是贵国悠久的传统文化呢
https://ziglang.org/news/migrating-from-github-to-codeberg/
这应该是第一个知名 programming language 从 GitHub 迁出。
骂得真狠,不过确实该骂!
codeberg 现在居然连 actions 都有了,不知道钱从哪儿来。
https://codeberg.org/Codeberg-Infrastructure/meta/src/branch/main/hardware
Emm,这一点都不云原生啊😯 让子弹飞一会儿吧
这应该是第一个知名 programming language 从 GitHub 迁出。
骂得真狠,不过确实该骂!
codeberg 现在居然连 actions 都有了,
https://codeberg.org/Codeberg-Infrastructure/meta/src/branch/main/hardware
Emm,这一点都不云原生啊😯 让子弹飞一会儿吧
AGENTS.md 越简单越好,自己手写好过复制热门提示词,一个简单的方式是先什么都不写,遇到 agent 有不满意的表现,就添加一句简短、明确的指令来纠正它
https://fixupx.com/leerob/status/1993162978410004777?s=46
https://fixupx.com/leerob/status/1993162978410004777?s=46
我最欣赏 Daniel 教授的地方不在于他的博客提供了只有密码学专家才拥有的宝贵视野,而是即便英语像我这么差的人,不用翻译也能轻松读完整篇文章
只要不涉及数学公式,我就有自信说这篇文章我全读懂了。而这篇文章正是如此
https://fixupx.com/hashbreaker/status/1993330843939750194
只要不涉及数学公式,我就有自信说这篇文章我全读懂了。而这篇文章正是如此
https://fixupx.com/hashbreaker/status/1993330843939750194
哈哈哈哈 咱就说啥叫草台班子 🤣
GitHub 把 GitHub Action 中 GITHUB_TOKEN 的默认权限改了, 导致一大批项目的 CI 都出现了问题
https://github.com/orgs/community/discussions/180355
GitHub 把 GitHub Action 中 GITHUB_TOKEN 的默认权限改了, 导致一大批项目的 CI 都出现了问题
https://github.com/orgs/community/discussions/180355
如果 GitHub 批量删除恶意软件的仓库,或者 npm 批量撤销被盗用的令牌,成千上万个受感染的系统可能会同时销毁用户数据。这种攻击的分布式特性意味着每台受感染的机器都会独立监控访问情况,并在检测到访问中断时触发用户数据的删除。
https://about.gitlab.com/blog/gitlab-discovers-widespread-npm-supply-chain-attack/
妙啊