透明代理
在购买了小主机J1900之后, 我在上面安装了OpenWrt, 一切都很正常, 我搭建了Clash, 配置了iptables使TCP/UDP走透明代理.
TCP透明代理
TCP透明代理比较简单, 因为TCP有状态, 所以透明代理成本较低, iptables提供重定向操作.
1 | iptables -t nat -A CLASH -p tcp -j REDIRECT --to-ports 7892 |
规则将tcp所有流量重定向到本地7892, iptables只需要在SYN包时记录下原始目标地址, 7892端口accept之后通过”SO_ORIGINAL_DST”即可拿到原始目标地址.
UDP透明代理
UDP没有状态, 所以想和TCP进行透明代理是不可能的, 每个连接都像TCP一样保存原始目标地址, 成本较大.
1 | iptables -t mangle -A CLASH -p udp -j TPROXY --on-port 7892 --tproxy-mark 0x111 |
UDP透明代理需要三条规则, 第一条使用iptables提供的tproxy模块, 将udp流量重定向到本地7892端口. 比较有意思的是tproxy不修改报文, 但是依旧可以完成重定向任务. 在报文匹配这条规则时, tproxy会查找本地是否开启7892端口, 并且该socket是否设置了”IP_TRANSPARENT”属性, 如果符合则将socket与报文做关联, 修改报文的结构体(skb->sock=sk).
但是在报文不做修改的情况下, 因为目的地址不是本机, 所以路由选择的时候, 该报文会被forward而不会进入本地协议栈进行处理, 那么关联socket的修改就没有意义了. 所以后面两条路由规则, 就是将报文送入本地协议栈进行处理.
tproxy会给每个匹配的报文打上标记”0x111”, 第二条路由规则表示带有”0x111”标记的报文使用”0x162”路由表. 第三条创建”0x162”路由表, 表里的规则将流量本地回环网卡lo, 这样流量顺利进入协议栈, 并且关联修改让它顺利被7892端口接收.
example
1 |
|
Docker
简单的翻墙使用, 让我觉得浪费了J1900的性能, 我突发奇想, 我想在上面装Docker! 当我在google反复搜索, 貌似出来的答案都是Docker里面装OpenWrt, 没有人在OpenWrt上装Docker, 唯一有价值的帖子是这篇Docker engine on OpenWrt.
Docker现在只存在于master分支, 如果想用需要自己编译, 于是我开始搭环境进行编译.
1 | git clone https://git.openwrt.org/openwrt/openwrt.git |
编译会遇到很多坑, 也和网络环境有关, 因为编译会下载大量的源码, 所以我全程使用了proxychains.
组件
make menuconfig时会让你选择组件, 此时我很自然的只勾选了docker-ce, 然而编译的结果是整个系统只有docker-ce! 自己编译是不会有软件源的, 因为内核版本不兼容, 你从OpenWrt的Snapshot源(官方dev源, 每天自动编译)下载的包是装不上, 所以连iptables-mod-tproxy都没有.
我勾选了tproxy模块重新编译后, 发现自带的web UI没有, 我开始暴躁了起来. 最后我发现官方发出的稳定版本会附上编译时的配置, 所以在make menuconfig之前先下载下来:
1 | curl https://downloads.openwrt.org/releases/19.07.3/targets/x86/64/config.buildinfo > .config |
再进行make menuconfig会在官方的配置上进行定制, 我勾选了所需要的模块, 编译进行的很顺利.
代理
我习惯使用proxychains进行代理, 它使用LD_PRELOAD进行socket相关的hook, 支持TCP/UDP. 不过在编译Python3时, 出现了错误:
1 | Fatal: You must get working getaddrinfo() function. |
搜索之后发现是proxychains的问题, 但是我没有详细探究原因, 我转而使用:
1 | export http_proxy="http://127.0.0.1:8080" |
因为编译的下载大多都会使用该环境变量, 所以也没有发生下载缓慢的问题.
问题
之前的文章已经写了详细安装过程, 这里不赘述了, 使用时发现了两个问题.
- 无法使用官方源, 要安装screen等软件需要自行编译
- Docker可正常使用, tproxy无法正常工作
第一个问题完全可以忍受, 因为编译后的目录结构与官方源完全相同, 所以可以上传到自己的VPS, 然后修改opkg配置文件, 使用自建源. 第二个问题相当诡异, 调试了几天依旧找不到原因, 我一度以为是OpenWrt的bug, 甚至发朋友圈怒斥之.
转变
最后我起了个念头, 我想把系统换成Debian, 通过DIV将它改造成软路由. 大概想了一下, 无非是搭建DNS/DHCP, 桥接网卡、开启ip中转, 设置iptables的DNAT规则. 我重新燃起了热情, 为即将可以使用舒适稳定的系统而躁动不安, 此时的我显然没有意识到有一个bug在前方等待着我.