春节回老家,偶尔翻看一些资料的时候因网络原因众多网站打不开,此事颇为恼人。不由怀念起在家小机柜那点小设备,无奈现在手上空空,闲置的软路由也没带回来,巧妇难为无米之炊。当前这套网络是TPLink AC+AP方案,便对这个AC有了点想法。也就它有点算力,有个系统了吧?:)
网络背景
这是几年前给家里多层楼选择的一套TPLink方案(其实是我先在深圳用淘汰的方案给回了老家使用,吼吼)。有一个AC叫TL-R479GP,为了方便部署,同时支持8口POE供电,连接两个主AP(TL-AP1758GC)和各楼层的一些补充AP(86面板AP)。这不由的回想起,当时在京东下单这一套,也着实不便宜,然后发现1688上居然有几百块线差价,果断退掉去1688买,太香了。当然,很久没去了解了,不清楚如何状况,但从此内心觉得国内有些产品各渠道加价真高啊!
打入R479GP的内部
获得R479GP的ssh权限
不需要复杂的破解,网上已经有几种获得ssh的教程了。主要分两类:
- 通过修改配置(ssh的用户名/密码)并且重新打包导入配置,获得ssh的登录。
- 通过默认密码的方式进入。难点在计算默认密码,好在有前人经验,只有一行命令。
我的R479GP最近找客服要了最新固件(1.1.5 Build 20201110 Rel.72597)。感谢京东,客服甚至没问订单没管我是否在他们那购买的就果断发了固件过来,品牌还是不错的嘛:)刷完后我看人家教程一下心惊,听说后续版本有修复一些ssh漏洞,可别搬起石头砸了自己脚啊!所幸后续一切顺利。只要这样:
- 在设置中[系统工具]->[诊断工具]->[故障诊断]->[开启诊断模式] 即可打开ssh通道,默认端口为
33400 - root密码为LAN口mac地址md5后的前8位(有些版本是前16位)。LAN的MAC地址在
基本设置->LAN设置里可以看到。这里假设我的是CC-08-07-06-05-04,然后可以如下一行命令获得密码:
1
2
| ❯ echo "CC-08-07-06-05-04" | tr -d '-' | tr -d '\n' | md5 | cut -c 1-8
42df9037
|
你以为这就结束了吗,太理想了,有用户名和密码后,你登录会神奇的报错,这个我之前没见过啊:
1
| Unable to negotiate with 192.168.0.1 port 33400: no matching key exchange method found. Their offer: diffie-hellman-group1-sha1,diffie-hellman-group14-sha1,kexguess2@matt.ucc.asn.au
|
原因或许是因为R479GP系统的ssh服务端(dropbear)用的比较旧的版本了。要想能正常登录,需要添加一系列参数才可以。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| ❯ ssh -o HostKeyAlgorithms=+ssh-rsa -o PubkeyAcceptedAlgorithms=+ssh-rsa \
-o KexAlgorithms=diffie-hellman-group1-sha1 root@192.168.0.1 -p 33400
root@192.168.0.1's password:
BusyBox v1.22.1 (2020-11-10 20:05:06 CST) built-in shell (ash)
Enter 'help' for a list of built-in commands.
_______ ________ __
| |.-----.-----.-----.| | | |.----.| |_
| - || _ | -__| || | | || _|| _|
|_______|| __|_____|__|__||________||__| |____|
|__| W I R E L E S S F R E E D O M
-----------------------------------------------------
BARRIER BREAKER (Barrier Breaker, r96964)
-----------------------------------------------------
* 1/2 oz Galliano Pour all ingredients into
* 4 oz cold Coffee an irish coffee mug filled
* 1 1/2 oz Dark Rum with crushed ice. Stir.
* 2 tsp. Creme de Cacao
-----------------------------------------------------
root@TP-LINK:~#
|
随便看看
既然进来了,我们当然要看看这台设备的信息。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| root@TP-LINK:~# uname -a
Linux TP-LINK 3.3.8 #1 Tue Nov 10 20:09:13 CST 2020 mips GNU/Linux
root@TP-LINK:~# cat /etc/openwrt_release
DISTRIB_ID="OpenWrt"
DISTRIB_RELEASE="Barrier Breaker"
DISTRIB_REVISION="r96964"
DISTRIB_CODENAME="barrier_breaker"
DISTRIB_TARGET="ar71xx/generic"
DISTRIB_DESCRIPTION="OpenWrt Barrier Breaker 14.07"
DISTRIB_TAINTS="no-all no-ipv6 busybox"
root@TP-LINK:~# cat /etc/openwrt_version
14.07
|
原来是openwrt的系统啊,MIPS架构。再瞧瞧CPU:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| root@TP-LINK:~# cat /proc/cpuinfo
system type : Qualcomm Atheros QCA956X rev 0
machine : TP-LINK TL-R4299G 2.0
processor : 0
cpu model : MIPS 74Kc V5.0
BogoMIPS : 373.55
wait instruction : yes
microsecond timers : yes
tlb_entries : 32
extra interrupt vector : yes
hardware watchpoint : yes, count: 4, address/irw mask: [0x0000, 0x0ff8, 0x0ff8, 0x0ff8]
ASEs implemented : mips16 dsp
shadow register sets : 1
kscratch registers : 0
core : 0
VCED exceptions : not available
VCEI exceptions : not available
|
我去啊,高通芯片,怎么解读它的强弱,我们看看GPT(其实这次让Gemini客串了)怎么说:
这台网络设备的 CPU 性能一般。它使用的是 Qualcomm Atheros QCA956X 芯片,该芯片于 2013 年发布。它是一款单核 MIPS 74Kc V5.0 处理器,主频为 373.55 MHz。
MIPS 74Kc 是 MIPS 公司于 2002 年发布的一款 32 位 RISC 处理器架构。它是一款低功耗、低成本的处理器,适用于嵌入式系统。
QCA956X 芯片主要用于网络设备,例如路由器和交换机。它还可用于其他嵌入式系统,例如家用电器和工业控制设备。
这台网络设备的 CPU 性能足以满足大多数网络应用的需求。但是,对于要求更高的应用,例如视频流或游戏,它可能不够强大。
以下是 QCA956X 芯片的一些性能指标:
- 主频:373.55 MHz
- 指令集:MIPS 32
- 缓存:32 KB L1 指令缓存、32 KB L1 数据缓存
- 内存:支持 DDR2 和 DDR3 内存
- 外围设备:支持多种外围设备,例如 USB、Ethernet 和 PCIe
我不由的担心起来它这小身板还能不能被折腾一下。 再看看内存:1
2
3
4
5
6
7
8
9
| root@TP-LINK:~# cat /proc/meminfo
MemTotal: 126464 kB
MemFree: 58968 kB
Buffers: 7960 kB
Cached: 32548 kB
SwapCached: 0 kB
Active: 28672 kB
Inactive: 19708 kB
Active(anon): 10584 kB
|
128MB的家庭,让我又想起被嫌弃只有几G内存的软路由静静在躺在家里角落许久,是我的不该啊:) 就这点内存,跑个大点的程序,是不是系统就各种OOM了,想想都怕! 最后看一眼存储空间:
1
2
3
4
5
6
7
8
9
| root@TP-LINK:~# df -h
Filesystem Size Used Available Use% Mounted on
rootfs 61.8M 732.0K 61.0M 1% /
/dev/root 9.3M 9.3M 0 100% /rom
tmpfs 61.8M 4.0M 57.7M 7% /tmp
root 61.8M 732.0K 61.0M 1% /tmp/root
overlayfs:/tmp/root 61.8M 732.0K 61.0M 1% /
/dev/mtdblock7 2.0M 712.0K 1.3M 35% /tmp/userconfig
tmpfs 512.0K 0 512.0K 0% /dev
|
什么!只有61M,并且还不是都可持久化。网上查了一下,可持久化保存的只有/tmp/userconfig这里,其它重启后会被重置。不要怀疑你的眼睛,真的是只有1.3MB呢? 怎么办,我程序放哪啊,还怎么折腾啊?
让v2ray住进小房子
编译自己的v2ray
想要更好的网络条件,我们要借助v2ray等,幸好它是golang开发的,交叉编译出MIPS版本也非难事。可能你也像我一样对交叉编译经验不多,特别是上面GOOS是啥,是linux吗?不会是openwrt吧?哈哈,你可以这样:
go tool dist list看到go所支持的系统和架构。
最后我们的编译命令是:
1
| GOMIPS=softfloat CGO_ENABLED=0 GOOS=linux GOARCH=mips go build -o $HOME/v2ray -trimpath -ldflags "-s -w -buildid=" ./main
|
编译后赶紧看一下生成的二进制有多大。31M,完蛋了,放在/tmp/userconfig下是不可能了。所幸你也发现了/tmp目录下还有57M剩余空间,希望点燃了。 这时你想把这编译的二进制SCP过去就好了吧,对不起,dropbear不支持scp。我发现这个系统里有wget命令(curl没有),这是一个积极信号。
我们顺手先在编译机起一个http服务器(在对应二进制目录下),编译机当然有python啦:
然后在R479GP下:
1
2
3
4
5
6
7
8
9
| # 只有/tmp下有点空间放东西了
cd /tmp
# 下载我们编译好的v2ray,注意换成你自己的ip/port
wget http://192.168.0.153:8000/v2ray
# 顺便看一下是否能执行
root@TP-LINK:/tmp# ./v2ray version
V2Ray 5.13.0 (V2Fly, a community-driven edition of V2Ray.) Custom (go1.20 linux/mips)
A unified platform for anti-censorship.
|
搞定了编译和二进制问题啦。
构建自己的v2ray配置
我基本没怎么使用过v2ray,它的配置和其它一些类似软件不太一样,服务器也不通用。我随便找了一个简单的模版,对其进行了某些修改:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
| {
"log": {
"loglevel": "debug"
},
"routing": {
"domainStrategy": "AsIs",
"rules": [
{
"type": "field",
"ip": [
"223.5.5.5/32",
"119.29.29.29/32",
"180.76.76.76/32",
"114.114.114.114/32"
],
"outboundTag": "direct"
}
]
},
"inbounds": [
{
"listen": "0.0.0.0",
"port": "1080",
"protocol": "socks",
"settings": {
"auth": "noauth",
"udp": true,
"ip": "0.0.0.0"
}
},
{
"listen": "0.0.0.0",
"port": "1081",
"protocol": "http"
}
],
"outbounds": [
{
"tag": "proxy",
"settings": {
"vnext": [
{
"address": "<vws-url....>",
"users": [
{
"alterId": 0,
"id": "<id>",
"level": 0,
"security": "auto"
}
],
"port": "<port>"
}
]
},
"streamSettings": {
"security": "none",
"wsSettings": {
"headers": {
"host": ""
},
"path": "<...>"
},
"network": "ws"
},
"mux": {
"enabled": false,
"concurrency": 8
},
"protocol": "vmess"
},
{
"protocol": "freedom",
"settings": {
"userLevel": 0,
"domainStrategy": "UseIP"
},
"tag": "direct"
},
{
"settings": {
"response": {
"type": "none"
}
},
"protocol": "blackhole",
"tag": "block"
}
]
}
|
其中有几处主要修改:
- inbounds里修改了listen的地址为0.0.0.0,方便内网其它使用。
- outbounds里的配置我不太清楚怎么写。我开始也不知道,做了两种尝试,它们都是有效的。
从订阅中获取
我们手上可能有支持v2ray的订阅,但具体到v2y配置应该怎么写,我是不懂也懒得研究。但我发现有个工具v2sub可以拉取v2ray的订阅并且生成配置,它居然也是golang的,这可太喜欢了(意味着使用方便)。
在两轮交互式输入下,它会产生/etc/v2ray.json和/etc/v2sub.json文件。其中/etc/v2ray.json里的那一段outbounds就是我们要抄过来的。题外话一下,个人感觉工具非必要不需要交互式,还是带参数更加好用一些。又没有复杂度又没有太多上下文,你交互式有啥意义呢? 当然,作为经历过喝水不忘挖井教育的我们,还是感谢一下作者。
从V2rayU中获取
我们都知道很多工具支持订阅,我试着在MacOS下安装了V2rayU,在正常操作能使用后(这步确认了代理服务器没问题),我们可以在菜单中点开查看到它的config.json。同样我们可以复制出我们想要的outbounds那一段。
验证
到此处,程序和配置都有了,你可以把生成的配置放在前面http-server的目录下,然后同样的在R479GP中用wget收入囊中。这里我默认你会了,并且这个配置叫config.json,然后我们只需要这样:
1
| ./v2ray run -c config.json &
|
便启动了一个v2ray客户端,它监听在1080(socks)和1081(http)。之后,就可以在本地浏览器上通过设置你的SwitchyOmega插件,添加一个sock5或http协议的proxy,让某些网站走它即可。这期间从日志上看v2ray有一些报错,但不影响使用。发现看网站如google等,CPU/Mem也没多大负载。或许v2ray确实更轻量和高效一点吧:)
如果到这里就结束,那和我们在电脑上直接开一个软件也没多大区别,必须得有后手。
断电就无怎么可以接受?
上面已经描述过,在这台小身板的R479GP中,只有1.3M的空间是永久存储东西的。我们可以进去看看,发现有个文件/tmp/userconfig/etc/rc.local文件。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| root@TP-LINK:/tmp/userconfig/etc# cat rc.local
# Put your custom commands here that should be executed once
# the system init finished. By default this file does nothing.
irq_balance()
{
local irqnum=`cat /proc/interrupts | awk -F: '/eth/ {print $1}' | sed 's/[^0-9]//g'`
[ "1" == `cat /proc/irq/${irqnum}/smp_affinity` ] && {
local core_num=`cat /proc/cpuinfo | grep -w processor | awk 'END{print NR}'`
local mask=`awk "BEGIN{f=lshift(1,$core_num)-1; print f}"`
echo `printf %x $mask` > /proc/irq/${irqnum}/smp_affinity
}
}
irq_balance
exit 0
|
写得挺友好,Put your custom commands here that should be executed once。那么我们可以放点什么进来呢?有些文章说在这里sleep一下,然后放上之前我们的一系列下载配置和启动程序的命令,虽然可行,但不优雅。我想要守护进程,你不给我这机制,那么我就定时执行,于是乎借助crontab来搞:
1
2
| # add crontab for start v2ray
echo "*/1 * * * * echo \"check v2ray process at \`date\`\" >> /tmp/result.crontab 2>&1 && sh /tmp/userconfig/start-v2ray.sh" | crontab -
|
为了防止日程月累打爆日志,我们得小心不去不断追加日志和打印不必要的输出,当然因为/tmp/目录也是易失的,定时重启也会缓存这种情况。之后将以上内容写到上述rc.local文件的exit 0之前。接下来编写我们的脚本:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
| #!/bin/sh
# 定义工作目录和服务器URL
WORK_DIR="/tmp"
HTTP_SERVER_URL="http://192.168.0.153:8000"
V2RAY_BIN="v2ray"
CONFIG_FILE="config.json"
# 预期的v2ray文件的MD5值
EXPECTED_MD5="2c2adf543c9008f3d8976c71c14b483e"
# 下载v2ray和配置文件
download_files() {
echo "Downloading v2ray and config file..."
wget -O "${V2RAY_BIN}" "${HTTP_SERVER_URL}/${V2RAY_BIN}"
wget -O "${CONFIG_FILE}" "${HTTP_SERVER_URL}/${CONFIG_FILE}"
# 检查MD5校验值
if echo "${EXPECTED_MD5} ${V2RAY_BIN}" | md5sum -c -s; then
echo "MD5 check succeeded."
else
echo "MD5 check failed, exiting script."
exit 1
fi
# 赋予v2ray执行权限
chmod +x "${V2RAY_BIN}"
}
# 检查v2ray进程是否在运行
check_v2ray() {
return `ps | grep "[v]2ray" | grep -v grep`
}
# 启动v2ray进程
start_v2ray() {
echo "Starting v2ray process..."
./"${V2RAY_BIN}" run -c "${CONFIG_FILE}" &
}
# 主流程开始
cd "${WORK_DIR}"
# 检查v2ray文件是否存在且MD5值是否匹配
if [ ! -f ${V2RAY_BIN} ] || ! echo "${EXPECTED_MD5} ${V2RAY_BIN}" | md5sum -c -s; then
download_files
else
echo "v2ray file exists and MD5 check passed."
fi
# 检查v2ray进程是否已经在运行
if check_v2ray; then
echo "No v2ray process detected. start v2ray"
start_v2ray
else
echo "The v2ray process is either already running."
fi
echo "----------- end -----------"
echo
|
在写脚本时要注意需要在目标机器上能运行,所以有些命令要稍作调整,比如md5sum的参数略有不同等。目标上也无bash,不要想当然:)
至此,无论啥时,包括重启我们的机器也会自动下载v2ray及配置并且启动,它的代码和程序都是在云上的,那么有点云控的味道了。
折腾没止境了?
事情到这里其实还没有结束,但折腾的时间有限。眼看春节放假(包括休了几天)就要过完了,我木有时间再玩这个了,但也有几点想法待后续有空再折腾。
其一:上面会发现我们的程序二进制过大了,在这小小的存储空间中,你都放不下2个这种程序,为了瘦身,我们可以借助upx等工具将其压缩到较小体积。如以下,32M变8M了,这也太棒了吧!
1
2
3
4
5
6
7
8
9
10
| ➜ ~ upx --best v2ray
Ultimate Packer for eXecutables
Copyright (C) 1996 - 2024
UPX 4.2.2 Markus Oberhumer, Laszlo Molnar & John Reiser Jan 3rd 2024
File size Ratio Format Name
-------------------- ------ ----------- -----------
33095680 -> 8659500 26.17% linux/mips v2ray
Packed 1 file.
|
其二:我们在保障主网络稳定下,又想给某些人(如我)有点新特权。我想可以通过iptables DNAT规则在主路由器上做一些配置,让某些设备可以天然默认进入代理模式而不必配置任何东西,即透明代理。初步想了一下,我们可分几步:
- 在DHCP中预留一些IP资源段,不自动分配出去。
- 将预留的IP段借助iptables规则,使其在访问时转发给v2ray。这块因时间关系没空玩了,网上似乎也有一点资料,大概也能找到灵感。资料见附录。
其三:上面云控的味道来了!既然我们可以自动下载软件和配置,何不自动下载脚本呢,这样我只有一个壳脚本,通过它来从云端下载资源,未来的想象空间也会更大!你能想到有多少玩法吗?而我,等有时间再来折腾了。
参考资料
-EOF