01月 06

支持双线的Dnspod动态域名解析工具(golang)

之前用bash写了一个Dnspod动态域名解析工具,可不是并发请求的,子域名多了,添加新域名的时候,真的要很长时间。
发现有个golang轮毂dnspod-go,拿过来配上轮胎,又是一个好轮子!
还是一样的套路,只不过请求都变成用协程去执行了,这下子更新起来就块多了,近40个子域名,双线更新的情况下,所需时间也只有不到8秒。

real    0m 7.04s
user    0m 0.54s
sys    0m 0.18s

配置文件还是跟bash版的一样

{
    "token":"yourApiToken",
    "domains":{
        "xxxx.xx":[
            "@",
            "www",
            "aaa"
        ]
    },
    "ips":{
        "ip-chinanet":"ifconfig |grep inet|grep netmask|grep 192|awk '{print $2}'",
        "ip-chinamobile":"ifconfig |grep inet|grep netmask|grep 10|awk '{print $2}'",
        "ip-chinaunicom":"ifconfig |grep inet|grep netmask|grep 12|awk '{print $2}'"
    }
}

运行命令则为

dns -c dns.json

项目地址

08月 05

利用tcpdump抓取IPTV播放列表

之前抓取IPTV播放列表都是用Openwrt的端口镜像,配合台式机去抓包的,但是每次这样弄都好麻烦了,路由器,机顶盒,电脑都要用网线连接在一起,主力机变成XPS 15后,没有网口就显得更麻烦了。
此时就想起tcpdump了,这货不是能把所有数据包全抓下来吗,在路由器搞一搞就好了!
家里用的是软路由,弄个tcpdump还是很简单的,但是老人家里用的是K2P,还没硬改过的,装这个包和对应依赖空间有压力啊。。。
Google一番,没找到能用的tcpdump静态链接版本,又是DIY时刻了。
K2P刷的是高恪的固件,基于openwrt 14.07的,找到对应SDK和Toolchain,
参照之前的高恪插件编译教程弄起来了,却发现没有tcpdump这个包,搜索一番得知在base这个repo,SDK默认是没有添加这个repo的.

Openwrt 14.07也算是年代久远了,费劲一番才找到这个repo的源

git://git.archive.openwrt.org/14.07/openwrt.git

添加后就是常规操作

./script/feeds update
./script/feeds install

先按照官方动态链接的方式编译一遍看会不会出错。

make -j16 package/network/utils/tcpdump compile

成功编译后,看到依赖库libpcap把静态链接库也编译出来了。
接下来就是尝试编译静态链接的tcpdump了
只需要对Makefile稍作改动

  49 CONFIGURE_ARGS += \
  50         --without-crypto
  51 
  52 ifeq ($(CONFIG_IPV6),y)
  53 CONFIGURE_ARGS += \
  54         --enable-ipv6
  55 endif
  56 
  57 TARGET_CFLAGS += -ffunction-sections -fdata-sections
  58 TARGET_LDFLAGS += -Wl,--gc-sections
  59 
  60 CONFIGURE_VARS += \
  61         BUILD_CC="$(TARGET_CC)" \
  62         HOSTCC="$(HOSTCC)" \
  63         td_cv_buggygetaddrinfo="no" \
  64         ac_cv_linux_vers=$(LINUX_VERSION) \
  65         ac_cv_header_rpc_rpcent_h=no \
  66         ac_cv_lib_rpc_main=no \
  67         ac_cv_path_PCAP_CONFIG=""
  68 
  69 MAKE_FLAGS :=

改成

  49 CONFIGURE_ARGS += \
  50         --without-crypto
  51 
  52 ifeq ($(CONFIG_IPV6),y)
  53 CONFIGURE_ARGS += \
  54         --enable-ipv6
  55 endif
  56 
  57 TARGET_CFLAGS += -ffunction-sections -fdata-sections
  58 TARGET_LDFLAGS += -static -Wl,--gc-sections
  59 
  60 CONFIGURE_VARS += \
  61         BUILD_CC="$(TARGET_CC)" \
  62         HOSTCC="$(HOSTCC)" \
  63         td_cv_buggygetaddrinfo="no" \
  64         ac_cv_linux_vers=$(LINUX_VERSION) \
  65         ac_cv_header_rpc_rpcent_h=no \
  66         ac_cv_lib_rpc_main=no \
  67         ac_cv_path_PCAP_CONFIG=""
  68 
  69 MAKE_FLAGS :=

再次执行编译命令就可以了。

make -j16 package/network/utils/tcpdump compile

编译好的静态链接tcpdump和tcpdump-mini二进制附上。

在路由器上开始抓到包

tcpdump -i br-lan -s 0 -w iptv.pcap host 192.168.2.113

完了用scp把抓包文件传回到Mac上,直接用Charles就可以打开。
我这边都是rtsp协议的直播,所以直接查找关键词rtsp就可以找到列表页了,找到以后就是用正则提取一下电视台名称播放地址
查找关键词就找到播放列表页
用到的正则也很简单ChannelName="(.*?)".*ChannelURL="(?:.*?((?:rtsp|http).*?(?:smil|m3u8).*?END.*?))",最后就是根据个人习惯调整一下列表的顺序了。
广东电信这里抓到的播放列表在此

08月 05

记利用Xposed解除华为EMUI第三方桌面限制

自从入了魅族魅蓝E3的坑,等了一年也没等到BootLoader解锁的方法,也受够了那个没几秒就一次的WiFi断流。
苦苦寻觅,终于找到价格在2k上下,性能过得去,非异形屏,非背面指纹,拍照还可以,最重要一点,可以解锁BootLoader,可以装xposed的机子 -- 二手 华为 Mate 10。

机子到手随即在深水宝让人给解锁BootLoader了,开启了Magisk->Root->Xposed的折腾之路。

或许是距离我太久没碰过华为手机了(上一台华为手机还是C8850),发现刷入Magisk,安装Xposed的方法跟其他机型有很大区别,爬文了解了之后,算是把Magisk+Root+Xposed搞定了。

装上最熟悉的Nova Launcher却发现不能设置为默认桌面,华为什么脑残设定嘛!心想祭出冰箱冻结就好了,没想到事情却没这么简单,使用冰箱添加支付宝扫码快捷方式后,发现没有任何反应,冰箱的快捷方式权限已经给了啊!再去论坛爬文,发现还是华为脑残设定。。。这下子没这么好办了,冰箱管不到这块了。爬文良久没找到解决办法,只能硬着头皮自己来了。

既然默认应用设置把第三方桌面灰了不让我点,那就从这里入手,用开发者助手找出这里的资源ID,包名,将系统设置的apk传到Mac上JEB静态反编译走起。

第三方桌面被禁用
找出资源ID作为突破口

拿着0x7f0a07a8就到JEB去搜索,找到位于com.android.settings.applications.PreferredSettings这个类的onCreateView方法里,但是这个方法看不出什么有价值的线索,JEB字体太小,看的眼睛都疼了,还是把dex拉出来,用jadx直接把dex还原成Java源文件吧。
庆幸的是,这些代码并没有做混淆,还原成Java源文件后,方法名和变量名都是原始命名,这样看起来就容易多了。
7f0a07a8使用地方

用IntelliJ IDEA打开源码看,舒服多了,翻翻这个类,发现PreferredSettings.buildPreferredActivitiesList这个方法有点嫌疑,build什么List,可惜jadx反编译失败了,还是要回到jeb去看。Jeb反编译也不算很好,出来一堆goto,耐着性子找亮点。
发现这有重大嫌疑,Anti?Protection?Launcher?进去看看呗!
验证桌面权限
在这个类里,看到了华为桌面的包名com.huawei.android.launcher了,先写个hook,把AntiMalProtectionUtils.checkLauncherPermisson始终返回true试试!
华为桌面的包名

XposedBridge.hookAllMethods(loadPackageParam.classLoader.loadClass("com.android.settings.AntiMalProtectionUtils"), "checkLauncherPermisson", new XC_MethodHook() {
    @Override
    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
        param.setResult(true);
    }
});

重启一看,红色提示文字消失了,第三方桌面可以选择了,但是应用快捷方式还是添加不了,常规返回Home时,还是回到的华为桌面。
难道跟AntiMalProtectionUtils.getHwDefLauncherPkg这个方法有关?

public static String getHwDefLauncherPkg() {
    return "com.huawei.android.launcher";
}

改成返回Nova桌面的包名试试?

XposedBridge.hookAllMethods(loadPackageParam.classLoader.loadClass("com.android.settings.AntiMalProtectionUtils"), "getHwDefLauncherPkg", new XC_MethodHook() {
    @Override
    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
        param.setResult("com.teslacoilsw.launcher");
    }
});

结果还是不行,再仔细看AntiMalProtectionUtils.checkLauncherPermisson这个方法,按照它的正常流程走的话,ActivityManager.checkUidPermission应该要返回0,那就hook这个方法试试吧!

XposedBridge.hookAllMethods(loadPackageParam.classLoader.loadClass("android.app.ActivityManager"), "checkUidPermission", new XC_MethodHook() {
    @Override
    protected void beforeHookedMethod(XC_MethodHook.MethodHookParam param) throws Throwable {
        if (param.args[0] == "com.huawei.permission.sec.SDK_LAUNCHER")
            param.setResult(0);
    }
});

重启一试,成了!!!
反手就把华为桌面丢冰箱里了,没想到的是,这个老流氓,重启后竟然自动解冻了,还又成了默认桌面了!
这下就尴尬了,难道每次重启都要手动重新选一次桌面?这用户体验极差啊!
依稀记得看到过什么Launcher disabled之类的方法的,再翻翻去~~~
检测华为桌面被冻结

看到这个方法,解法很明显了,int res = this.mPm.getApplicationEnabledSetting(hwDefLauncherPkg);res的返回值不是23就好了。

XposedBridge.hookAllMethods(loadPackageParam.classLoader.loadClass("android.app.ApplicationPackageManager"), "getApplicationEnabledSetting", new XC_MethodHook() {
    @Override
    protected void beforeHookedMethod(XC_MethodHook.MethodHookParam param) throws Throwable {
        if (param.args[0] == "com.huawei.android.launcher")
            param.setResult(1);
    }
});

重启,设置Nova为默认桌面,冻结华为桌面,再重启,华为桌面没解冻了,默认桌面还是Nova,终于搞定了!
然而还是高兴的太早,屏幕手势的底部上滑失效了。。。
算了,我投降了。我不冻结华为桌面了,你一边凉快去吧。。。

最终达成效果:自由选择第三方桌面,自由使用Android 7开始的应用快捷方式。
随意选择桌面 随意选择桌面 开启应用快捷方式

完整Xposed源码在此

10月 31

高恪固件SS/SSR/Koolproxy插件编译教程

自从高恪魔改固件的消息在恩山公开了,然后再有人拿去贩卖后,作者就说了不再发布新版本了,随着koolproxy的更新,Telegram群里的呼声也越来越高,还是在GitHub上放出了源码了,但是不提供ipk,也不提供魔改固件.

一大堆小白先是求别人编译好的ipk,没得到后就真的硬着头皮请教如何自行编译了.
在群里教了若干个群友后,觉得这真的太累了,每个人的编译环境都不一样,遇到的问题也不一样,
眼看群里很多人就差这么一点点了,愣是弄不出来,我都替他们着急了...

所以,还是给他们弄个教程吧.

遂录制了这个使用Docker镜像作为编译环境的视频,能确保每个人的编译环境都一致,后面的是就好办了嘛~

PS1. 视频录制用的是asciinema,Linux/Mac 用户可以安装并下载cast文件在本地回放.
PS2. 视频编译的是K2P的插件,用到的SDK和Toolchain自行到这里下载.

08月 21

使用反向代理从外网管理家里的NAS服务器

把EA6500V2升级成了一个X86的NAS,各种服务就多起来了,但是在内网,各个服务都监听的80/443端口,我外网IP撑死也就两个,电信的家用宽带80端口又不能用,443端口的话,即使咗做端口映射,IP也不够分啊!

还好之前写了个ddns.sh进行动态域名解析,那从外网管理各种服务就当然要通过域名来搞了~
怎么搞?Nginx反向代理了解一下~

撸起袖子加油干~
一个服务一个子域名!

  • 路由器一个
  • ESXI一个
  • Ubuntu Server管理的Webadmin一个
  • 个人网盘一个
  • 你现在看到的站点一个
  • 放静态资源的站点一个
  • ......

先来一个ESXI的,

server {
    server_name xxx.brillianttech.top;
    listen 443 ssl http2;
    ssl                  on;
    ssl_certificate      /usr/local/share/ssl/brillianttech.top.pem;
    ssl_certificate_key  /usr/local/share/ssl/brillianttech.top.key;
    access_log off;
    error_log off;

    location / {
        #Proxy Settings
        proxy_redirect     off;
        proxy_set_header   Host             $host:$server_port;
        proxy_set_header   X-Real-IP        $remote_addr;
        proxy_set_header X-Forwarded-Host $host:$server_port;
        proxy_set_header X-Forwarded-Server $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass      //192.168.2.254;

        proxy_connect_timeout      90;
        proxy_send_timeout         90;
        proxy_read_timeout         90;
        proxy_buffer_size          128k;
        proxy_buffers              32 32k;
        proxy_busy_buffers_size    256k;
        proxy_temp_file_write_size 256k;
    }
}

加好配置文件nginx -s reload,用手机断掉WIFI一试,成了!
在用电脑打开,试试在网页打开虚拟机的显示器,囧了.
无法连接

    location /ticket {
        proxy_redirect off;
        proxy_pass //192.168.2.254;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $http_host;
    }

打开调试器看,原来用的WebSocket,想到之前用Websocket伪装的梯子搞过Websocket转发,搬过来...
加上这个location,果然好了!
连接成功
刚好koolshare lede发新版了,打算升级一下,上传镜像的时候竟然失败了,经验告诉我,肯定是Nginx不受这么大的文件,
赶紧补上proxy_max_temp_file_size 0;client_max_body_size 4g;解决掉~
最终nginx的配置文件就是这样子了

client_max_body_size 4g;
server {
    server_name esxi.brillianttech.top;
    listen 443 ssl http2;
    ssl                  on;
    ssl_certificate      /usr/local/share/ssl/brillianttech.top.pem;
    ssl_certificate_key  /usr/local/share/ssl/brillianttech.top.key;
    access_log off;
    error_log off;
    location /ticket {
        proxy_redirect off;
        proxy_pass //192.168.2.254;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $http_host;
    }
    location / {
        #Proxy Settings
        proxy_redirect     off;
        proxy_set_header   Host             $host:$server_port;
        proxy_set_header   X-Real-IP        $remote_addr;
        proxy_set_header X-Forwarded-Host $host:$server_port;
        proxy_set_header X-Forwarded-Server $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass      //192.168.2.254;

        proxy_max_temp_file_size 0;
        proxy_connect_timeout      90;
        proxy_send_timeout         90;
        proxy_read_timeout         90;
        proxy_buffer_size          128k;
        proxy_buffers              32 32k;
        proxy_busy_buffers_size    256k;
        proxy_temp_file_write_size 256k;
    }
}

然后还值得一说的就是配置koolshare lede时,要隐藏掉X-XSS-Protection,

proxy_hide_header X-XSS-Protection ;

否则会在控制台报这样一个错误,而且软件中心用起来也会有问题.

Error parsing header X-XSS-Protection: 1; mode=block, 1; mode=block: expected semicolon at character position 13. The default protections will be applied.

根本原因是为了安全,在nginx.conf中已经配置过了,lede自己也有这个响应头,输出到浏览器的时候就重复了.

    add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;";
    add_header X-Robots-Tag none;
    add_header X-Download-Options noopen;
    add_header X-Permitted-Cross-Domain-Policies none;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header Referrer-Policy "same-origin" always;