惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

WordPress大学
WordPress大学
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Hacker News: Ask HN
Hacker News: Ask HN
N
News and Events Feed by Topic
Forbes - Security
Forbes - Security
The Last Watchdog
The Last Watchdog
TaoSecurity Blog
TaoSecurity Blog
Schneier on Security
Schneier on Security
SecWiki News
SecWiki News
V
Vulnerabilities – Threatpost
Project Zero
Project Zero
O
OpenAI News
W
WeLiveSecurity
Security Archives - TechRepublic
Security Archives - TechRepublic
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
H
Hacker News: Front Page
Cisco Talos Blog
Cisco Talos Blog
Spread Privacy
Spread Privacy
Help Net Security
Help Net Security
P
Privacy & Cybersecurity Law Blog
K
Kaspersky official blog
S
Security @ Cisco Blogs
Latest news
Latest news
AWS News Blog
AWS News Blog
U
Unit 42
Martin Fowler
Martin Fowler
阮一峰的网络日志
阮一峰的网络日志
S
Secure Thoughts
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Know Your Adversary
Know Your Adversary
Scott Helme
Scott Helme
博客园 - 司徒正美
B
Blog RSS Feed
C
Check Point Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
D
Docker
Google Online Security Blog
Google Online Security Blog
Jina AI
Jina AI
aimingoo的专栏
aimingoo的专栏
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Last Week in AI
Last Week in AI
月光博客
月光博客
C
CXSECURITY Database RSS Feed - CXSecurity.com
S
SegmentFault 最新的问题
NISL@THU
NISL@THU
T
The Blog of Author Tim Ferriss
C
Cisco Blogs
Attack and Defense Labs
Attack and Defense Labs
小众软件
小众软件

Yesterday17's Blog

2026 新年解密红包 / Melody Flag | Yesterday17's Blog 谈谈 Iori 的设计思路(二):如何实现一个 Showroom 录制工具? | Yesterday17's Blog 谈谈 Iori 的设计思路(一):从 Nico Timeshift 说起 | Yesterday17's Blog Iori Minyami 0.1.0 发布 | Yesterday17's Blog 2025 新年解密红包 / Melody Flag | Yesterday17's Blog 使用 Cloudflare Warp 解决罗森票务的海外登录问题 | Yesterday17's Blog How To Blog 04: The Astro v5 Era | Yesterday17's Blog 谈谈 tokio::select! 的公平性 | Yesterday17's Blog Learning Pingora 05 - Connect with TLS | Yesterday17's Blog Leaving Bytedance | Yesterday17's Blog 大橋彩香 AsiaTour「Reflection」上海公演 个人向记录 & Repo | Yesterday17's Blog Recoving from burnout - What happened? | Yesterday17 Yubikey 重建手册 | Yesterday17's Blog How To Blog 03: Heimus | Yesterday17's Blog 🪧 Blog Migration Accouncement | Yesterday17's Blog Learn Your IDE - VSCode 是如何仅重启插件的? | Yesterday17's Blog How To Blog 02: Astro❤️Password | Yesterday17's Blog How To Blog 01: Why, How, and the Future | Yesterday17's Blog Learning Pingora 04 - Establish L4 Connection | Yesterday17's Blog Learning Pingora 03 - Upstreams and Peers | Yesterday17's Blog Learning Pingora 02 - A Simple HTTP Server | Yesterday17's Blog Learning Pingora 01 - Getting Started | Yesterday17's Blog 2024 新年解密红包 / Melody Flag | Yesterday17's Blog 向新的一年飞驰——记录 2023 | Yesterday17's Blog 「サクラノ刻」对话选摘(2) | Yesterday17's Blog PGP Key Revocation 注销声明 | Yesterday17's Blog 「サクラノ刻」对话选摘(1) | Yesterday17's Blog 2023 新年解密红包 / Melody Flag | Yesterday17's Blog 『蒼の彼方のフォーリズム』通关感想 | Yesterday17's Blog 单显卡直通教程 | Yesterday17's Blog 对博客与笔记的思考 | Yesterday17's Blog Project Anni 之旅(3)自动化 Flutter 应用 CI/CD 上架流程 | Yesterday17's Blog AsobiStage 直接播放链接 | Yesterday17 如何在后分P时代进行投稿——sswa使用详解 | Yesterday17's Blog JSON RPC 与 LSP 协议基础 | Yesterday17's Blog Grajapa Shueisha / BookEnd 加密方式调查 | Yesterday17's Blog 【2022篇+WriteUp】如何再收一个新年红包? | Yesterday17's Blog 如何将良心云的良心功能清理干净 | Yesterday17's Blog 【油猴脚本】bilibili 投稿页面返回旧版+旧版页面强制允许分P上传 | Yesterday17's Blog Cloudr1v1 授权方式分析 | Yesterday17 Typora 1.0.2 逆向实录 | Yesterday17's Blog Project Anni 之旅(2)ValueAfterTable——toml-rs的实现与限制 | Yesterday17's Blog IPv4透明代理+IPv6 Passthrough——树莓派单臂软路由折腾记 | Yesterday17's Blog Chaos; Child 汉化补丁 神秘编码探索 | Yesterday17's Blog 镣铐与舞蹈——个性与共性之迷思 | Yesterday17's Blog Go 学习笔记 02 - 找准 io 之道 | Yesterday17's Blog NAT Slipstreaming v1 原理浅析 | Yesterday17's Blog 绕过「9-nine-」的 CDKEY 验证——KrkrPlugin 正(?)向实录 | Yesterday17's Blog 静流的青春纪念册——「サクラノ刻 -櫻の森の下を歩む-」体验版感言 | Yesterday17's Blog Project Anni 之旅 01 - 从 clap-builder 到 derive | Yesterday17's Blog [Google CTF 2021] CPP WriteUp | Yesterday17's Blog 获取 アソビステージ 的实际播放链接 | Yesterday17's Blog 90 行 Rust 代码实现 AsyncTeeReader | Yesterday17's Blog 或许还算有价值一读的文章列表 | Yesterday17's Blog 从零开始的 Seedbox 之旅 | Yesterday17's Blog [随笔]技术型博客行文迷思(1) | Yesterday17's Blog 浅谈 git fetch 的工作方式 | Yesterday17's Blog 『ソーサレス*アライヴ! ~the World's End Fallen Star~』通关感想" | Yesterday17's Blog Rust std::fmt 格式语法简述 | Yesterday17's Blog 日亚修改居住国的解决方案 | Yesterday17's Blog [Windows/Linux] GC553 的 Switch 完美采集之路 | Yesterday17's Blog 【翻译】Subtyping and Variance / 子类型与变型 | Yesterday17's Blog Berd's Red Envelope 2021 WriteUp | Yesterday17's Blog 【中英对照】ALSA 音频 API 使用教程/A Tutorial on Using the ALSA Audio API | Yesterday17's Blog 从 cue_scanner.l 看 CUE Sheet 的词法单元 | Yesterday17's Blog Postman 历史记录导出的解决方案 | Yesterday17's Blog 《恋爱绮谭 不存在的夏天》通关感想 | Yesterday17's Blog [微机实验/TD-PITE] 微机接口综合实验 | Yesterday17's Blog [微机实验/TD-PITE] 键盘扫描及数码管显示实验 | Yesterday17's Blog [微机实验/TD-PITE] 数码管显示实验 | Yesterday17's Blog Airsonic Advanced+Google Drive+Caddy 部署纪实 | Yesterday17's Blog X-NUCA 2020 - hellowasm 题解 | Yesterday17's Blog [微机实验/TD-PITE] 8251 串行接口实验 | Yesterday17's Blog Node.js child_process.fork 与 env 污染 RCE | Yesterday17's Blog EP.01 「夜の向日葵」 | Yesterday17's Blog [微机实验/TD-PITE] 8254 定时/计数器实验+选做实验 | Yesterday17's Blog [JLU CTF/2020] babywasm WriteUp | Yesterday17's Blog PHP 反序列化与经典利用 | Yesterday17's Blog WebAssembly 逆向简述 | Yesterday17's Blog 『彼女、お借りします』一期完结点评 | Yesterday17's Blog [微机实验/TD-PITE] D/A 转换实验+选做实验 | Yesterday17's Blog [微机实验/TD-PITE] A/D 转换实验+选做实验 | Yesterday17's Blog 开源项目申请 JetBrains Open Source License 简单流程 | Yesterday17's Blog 微软拼音与 JetBrains 搜索快捷键冲突的解决方案 | Yesterday17's Blog [微机实验/TD-PITE] 8259 中断优先级实验+选做实验 | Yesterday17's Blog IFTTT 测试(续) | Yesterday17 IFTTT 测试 | Yesterday17's Blog [微机实验/TD-PITE] 存储器扩展实验+选做实验 | Yesterday17's Blog 新版 GCC 针对 -fdump-translation-unit 的替代方案 | Yesterday17's Blog 一次 HSTS 策略配置的排错之旅 | Yesterday17's Blog YukiNative 踩坑记——Windows 的消息队列 | Yesterday17's Blog 我是我自己——论获取 HTTPS 证书时的验证步骤 | Yesterday17's Blog 【设计文档】对 PUG 的大规模设计修订(1.1) | Yesterday17's Blog GS65 折腾记(2)加装固态,分区,Grub2 引导 Manjaro LiveCD | Yesterday17's Blog 「さくら、もゆ。」的空白字体列表——一次逆向问题定位过程实录 | Yesterday17's Blog GSuite 探索篇(1)使用 Service Account 向 Google Drive 传输文件 | Yesterday17's Blog 『サクラノ詩 -櫻の森の上を舞う-』通关感想 | Yesterday17's Blog 《ATRI -My Dear Moments-》通关感想 | Yesterday17's Blog [工具][VSCode 扩展] AegiKit——方便 Aegisub 使用的工具箱 | Yesterday17's Blog 贝塞尔曲线、字体矢量化与曲线运算 | Yesterday17's Blog
[v1.0] Tun+MITMProxy 初探 | Yesterday17's Blog
Yesterday17 · 2020-03-16 · via Yesterday17's Blog

昨天今天花了一天的时间,终于把网络环境配好了。当然了,中间还有一些杂七杂八的事情暂且不提(但是真的很舒服啊,比如下面这个,我好了)——

香不香啊,太香了这个
香不香啊,太香了这个

嘛,总之是配置完了,现在一切就都正常多了,整体的架构也很符合直觉。当然了,还有一些比较 dirty 的实现需要后期修正,那就是之后的事了(逃

当然,这些这是后话了。话说这一切,都要从……


目标?

其实原来目标很简单。本机能够实现流畅访问互联网。透明代理真的太快乐了

然后后来就开始慢慢加戏了。你说本机流畅了,那 create_ap 的热点呢?这个需求是解决了,但如果我要深度去广告怎么办?这又涉及到 MITM 和脚本的问题。还不是给刘大爷惯的

于是,最终的目标就成型了。我们的目标必须满足下列要求:

  • 能使本机流畅访问互联网
  • 能使连接了本机通过 create_ap 共享的网络的设备流畅访问互联网
  • 能够根据简单的域名规则屏蔽广告
  • 能够根据复杂的脚本规则屏蔽广告

方案 -2.0

最开始我使用的方案是旧白话文里的普通配置,这个配置最大的优点就是简单。我们这里不妨摸一份过来(有修改):

# TCP

iptables -t nat -N RUA # 新建一个名为 RUA 的链

iptables -t nat -A RUA -d 192.168.0.0/16 -j RETURN # 直连 192.168.0.0/16

iptables -t nat -A RUA -p tcp -m mark --mark 0xff -j RETURN # 直连 SO_MARK 为 0xff 的流量(0xff 是 16 进制数,数值上等同与上面配置的 255),此规则目的是避免代理本机(网关)流量出现回环问题

iptables -t nat -A RUA -p tcp -j REDIRECT --to-ports 12345 # 其余流量转发到 12345 端口(即 RUA)

iptables -t nat -A PREROUTING -p tcp -j RUA # 局域网其他设备

iptables -t nat -A OUTPUT -p tcp -j RUA # 本机

# UDP

ip rule add fwmark 1 table 100

ip route add local 0.0.0.0/0 dev lo table 100

iptables -t mangle -N RUA_MASK

iptables -t mangle -A RUA_MASK -d 192.168.0.0/16 -j RETURN

iptables -t mangle -A RUA_MASK -p udp -j TPROXY --on-port 12345 --tproxy-mark 1

iptables -t mangle -A PREROUTING -p udp -j RUA_MASK

这种方案的本质是 NAT。我们这里只讨论 TCP 部分:对于局域网内的流量,我们希望能够直接连接,因此我们让 192.168.0.0/16 的流量 RETURN;对于任意的 TCP 流量,我们希望它能够默认被送至 dokodemo,但又不希望从 dokodemo 出来的流量再被送回 dokodemo,于是我们给它打上 fwmark;对于剩下的流量,我们就把它送到 dokodemo 对应的端口,也就是文中对应的 12345

最后,我们需要让这条链(也可以说是我们定义的规则组)运作。我们需要把它加到两条链里:nat 表的 PREROUTING 链和 OUTPUT 链,前者是转发报文处理过程中的一环,而后者则是本机发出报文的必经之路。

经过这样的处理之后,无论是对于本机,又或是外部设备,访问互联网都是透明的了。那这种方案有什么问题呢?

其实问题是相对主观的。这个版本的配置我也用了一段时间,但最后还是换成了下一个版本的,其中最关键的因素就是速度。虽然没有经过 benchmark,但从个人的体感速度上来说是不如下一个版本的。另外,NAT 不支持 IPv6(原文)。

你去用 ip6tables 啊 kora!

方案 -1.0

这个版本的方案就是新白话文中的 TProxy 了,这也是上一个方案中处理 UDP 的做法,就一并放到这里讲好了。

TProxy 的详细原理在我后来写的这篇文章中有详细解释,感兴趣的不妨去看看(

TProxy 的方案非常优秀,整个过程中没有任何问题,这也是我使用时间最长的方案,将近一年了吧,但最后我还是放弃了这个方案主要的原因其实并不是它的过错,而是 JSON 的配置格式极大地限制了整个文档的修改与扩充。于是,在第114513次尝试扩充之后,我放弃了。

方案 0.0

这时候我遇到了 clashyaml 的格式很对我胃口,类 Surge 的配置方式也很顺眼(谁让我几个月前刚买了一年订阅呢)。正好,有新的 PR 支持了 Tun,虽然并不是太稳定,但也能用了不是,于是我就准备尝试一下。

这个过程持续了大约两个月的时间,使用的脚本是 AUR clash-tun 的个人修改版本,期间给 PR 解决了一个 [bug](https://github.com/Dreamacro/clash/pull/393#discussion_r379273286)。但是这个方案有一个最大的问题:热点共享失效了。

现在回过头来看其实原因很简单,是动了 PREROUTING 的奶酪,但这个问题着实困扰了我长大一个月的时间,期间各种补课,总算理解了整个过程。

#!/bin/bash

TUN_USER="root"

TUN_DEVICE="utun"

PROXY_FWMARK="0x162"

TUN_ROUTE_TABLE="0x162"

TUN_ADDRESS="198.18.0.1/16"

CREATE_AP_ADDR="192.168.114.0/24"

/srv/clash/scripts/clean.sh

# IPv4 环回地址

ipset create localnetwork hash:net

ipset add localnetwork 127.0.0.0/8

ipset add localnetwork "$CREATE_AP_ADDR"

# IPv6 环回地址

ipset create localnetwork6 hash:net -6

ipset add localnetwork6 fe80::/10

# 启动 Tun

ip tuntap add "$TUN_DEVICE" mode tun user $TUN_USER

ip link set "$TUN_DEVICE" up

# 将对应 IP 段分配给 TUN

ip address replace "$TUN_ADDRESS" dev "$TUN_DEVICE"

# 给 TUN 设备增加路由

ip route replace default dev "$TUN_DEVICE" table "$TUN_ROUTE_TABLE"

ip -6 route replace default dev "$TUN_DEVICE" table "$TUN_ROUTE_TABLE"

# 对带有 fwmark 的流量走 TUN_ROUTE_TABLE 路由表

ip rule add fwmark "$PROXY_FWMARK" lookup "$TUN_ROUTE_TABLE"

ip -6 rule add fwmark "$PROXY_FWMARK" lookup "$TUN_ROUTE_TABLE"

# IPv4 Clash 链

iptables -t mangle -N CLASH # 创建 CLASH 链

iptables -t mangle -A CLASH -m owner --uid-owner "$TUN_USER" -j RETURN # 绕过指定用户

iptables -t mangle -A CLASH -d "$TUN_ADDRESS" -j MARK --set-mark "$PROXY_FWMARK" # 将目标为对应 IP 段的流量打上标记

iptables -t mangle -A CLASH -d "$CREATE_AP_ADDR" -j RETURN # 绕过 create_ap 地址

iptables -t mangle -A CLASH -m addrtype --dst-type BROADCAST -j RETURN # 绕过广播地址

iptables -t mangle -A CLASH -m set --match-set localnetwork dst -j RETURN # 绕过本地地址

iptables -t mangle -A CLASH -p tcp -j MARK --set-mark "$PROXY_FWMARK" # 给 TCP 连接打上标记

#iptables -t mangle -A CLASH -p udp -j MARK --set-mark "$PROXY_FWMARK" # 给 UDP 连接打上标记

iptables -t mangle -A CLASH -p udp -j RETURN

# IPv6 Clash 链

ip6tables -t mangle -N CLASH6 # 创建 CLASH6 链

ip6tables -t mangle -A CLASH6 -m owner --uid-owner "$TUN_USER" -j RETURN # 绕过指定用户

ip6tables -t mangle -A CLASH6 -m set --match-set localnetwork6 dst -j RETURN # 绕过本地地址

ip6tables -t mangle -A CLASH6 -p tcp -j MARK --set-mark "$PROXY_FWMARK" # 给 TCP 连接打上标记

#ip6tables -t mangle -A CLASH6 -p udp -j MARK --set-mark "$PROXY_FWMARK" # 给 UDP 连接打上标记

ip6tables -t mangle -A CLASH6 -p udp -j RETURN

iptables -t mangle -I OUTPUT -j CLASH # IPv4 出口使用 CLASH 链

#iptables -t mangle -I PREROUTING -m set ! --match-set localnetwork dst -j MARK --set-mark "$PROXY_FWMARK" # 在 PREROUTING 给所有非本地流量打上标记

ip6tables -t mangle -I OUTPUT -j CLASH6 # IPv6 出口使用 CLASH 链

#ip6tables -t mangle -I PREROUTING -m set ! --match-set localnetwork6 dst -j MARK --set-mark "$PROXY_FWMARK" # 在 PREROUTING 给所有非本地流量打上标记

iptables -t nat -A PREROUTING -p tcp -j REDIRECT --to-ports 7892

# REJECT 对应 IP 的 Output

iptables -t filter -I OUTPUT -d "$TUN_ADDRESS" -j REJECT

// TODO: 有空补充一下为什么会炸

MITM?

MITM 的想法是在使用 Surge 脚本的时候浮现出来的,简单来说就是可以改请求改返回之类。由于脚本的功能非常强大,因此我一直想怎么才能在本机上实现这个功能。

在不需要自己手动实现的前提下,我很快就瞄准了 mitmproxy。正好,mitmproxy 也有 upstream 模式。于是在群友的帮助下,我确定了配置的基本架构:

字丑点丑点吧(悲)
字丑点丑点吧(悲)

为了简化设计,在 TUN -> MITMProxy 的中间件选择上,我使用了 clash 的 TUN 模式。于是——

方案 1.0

总之话不多说,先上配置好了。首先是第一层的配置:

# mitmproxy

port: 1081

socks-port: 1080

allow-lan: true

bind-address: "*"

redir-port: 7892

mode: Rule

log-level: info

external-controller: :9090

tun:

enable: true

dns:

enable: true

ipv6: true

listen: 0.0.0.0:53

enhanced-mode: redir-host

nameserver:

- 223.5.5.5

fallback:

- 8.8.8.8

Proxy:

- name: "mitmproxy"

type: http

server: localhost

port: 20020

- name: "clash"

type: socks5

server: localhost

port: 11080

udp: true

Rule:

# mitmproxy

- DOMAIN,mitm.it,mitmproxy

# no-mitm

- MATCH,clash

先来解释这一层吧。这一层是需要权限的一层,在启动这一层的时候需要执行 iptables 命令,正好和 53 端口分配重合了,于是就放在一起了。但事实证明,如果不放在同一个配置文件里,则会导致整个系统无法正常运行,原因未知。

(个人感觉是因为 TUN 要处理 IP<->Domain,因此 DNS 和 TUN 必须在同一层,有待验证。)

在这里,我们定义了两个规则:一个是需要 MITM 的,默认的 mitm.it 肯定是要的;接下来就是默认的规则,负责处理那些不需要经手的规则,通过前置代理直接送到下一层对应的 socks5 端口。

接下来是之前各个解决方案的本体,也是最终处理链接的层次:

# self

port: 11081

socks-port: 11080

mode: Rule

log-level: info

external-controller: :19090

Proxy:

- ...

Rule:

# optional param "no-resolve" for IP rules (GEOIP IP-CIDR)

- IP-CIDR,192.168.0.0/16,DIRECT

- IP-CIDR,127.0.0.0/8,DIRECT

- GEOIP,CN,DIRECT

- MATCH,custom-rule

这一层就没什么好说的了。

展望

回顾整个过程,从想法,到思维误区,到跳出习惯的舒服,我学到了 iptables 的基本规则和使用方法,Linux 下 TunTap 的一些常识,并且对网络的认识进一步加深了。

现在的方案存在一定的问题,首先就是 DNS 的问题,需要将所有发往 53 端口的DNS 请求都修改为发送至本机 DNS,换句话说就是 DNS 交给 clash 处理;其次是用户权限,root 还是太大了,在非 root 的情况下其实很多事情也能完成;最后就是这两层能不能相对融合?我什么时候造轮子?(逃

总之,路漫漫其修远兮,坑还有114514个。最近还在讨论 PUG 的设计,总之肯定是不会闲下来的(笑)

那暂时就这样,おやすみなせ〜