便捷配置安卓电脑HTTPS抓包代理

大类
Env
技术标签
原理研究-Android
环境增强
优先级
Medium
开始日期
Nov 16, 2022
状态
Maintaining
Public
Public
最后更新
Nov 18, 2022

现状

  • 电脑的IP并不是固定的,时不时会变,且配置DDNS并不现实
    • 谁给内网IP配DDNS啊
    • 电脑有时候插网线,有时候连wifi,还有时候是手机USB热点,鬼知道应该给哪个东西配DDNS
  • 在安卓里编辑VPN配置是个非常困难的事情
    • Clash:不自带编辑器,没有GUI配置
    • Surfboard:自带编辑器,没有GUI配置
  • 同时,托管配置直接不允许任何编辑,更不方便我们改调试代理的地址
 

思考

  • 在iOS上,我直接把我的代理地址填做了DESKTOP-XXXXXX.local这样的mDNS地址,这使得我可以直接利用iOS内建的mDNS支持,让他自动解析我电脑的地址,这样就不用我来每次修改、确认地址了。
    • 但是在Android上,系统并没有内建这样的支持,这样的套路gg了
  • 歪门邪道:我自己手动解析,然后把地址填到hosts里面
    • Magisk支持systemless hosts,可以让/system/etc/hosts可写
      • 甚至重启后甚至可以恢复,完全不虚我写坏了
    • Termux支持avahi-daemon,可以解析mDNS域名
      • 可以自己写,但是有写好的东西为什么不用呢?
 

实现

配置avahi

  • pkg install avahi-daemon
  • 随后需要配置两个东西:
      1. 开启dbus:vim $PREFIX/etc/avahi/avahi-daemon.conf,修改enable_dbus=yes
      1. 修复dbus校验:vim $PREFIX/etc/dbus-1/system.d/avahi-dbus.conf
          • 在<policy context="default">下,新增:
          <allow own="*"/><allow user="*"/><!-- XXX: MISTY PATCH -->
  • 配置上服务的自启动
    • termux-services非常狗,必须用他的mkdir -p的方法建目录,否则supervise文件夹出不来
      • 分两步建目录,log文件夹里的supervise出不来
      • 手动删除后,不会自动重建supervise
    • dbus run:不能让他daemonize,否则他会一直被重启,而且如果pid文件存在他就直接拒绝启动(虽然可以nopid,但是我怕有程序专门检测pid存不存在来判断dbus活不活)
      • #!/data/data/com.termux/files/usr/bin/sh rm -f $PREFIX/var/run/dbus/pid DBUS=$PREFIX/bin/dbus-daemon exec $DBUS --system --nofork
    • avahi run:需要等待dbus-daemon起来
      • #!/data/data/com.termux/files/usr/bin/sh for i in {1..10}; do if pgrep -x dbus-daemon >/dev/null; then break fi sleep 1 done AVAHI=$PREFIX/bin/avahi-daemon exec $AVAHI
 

解析mDNS域名、更新hosts

  • 通过调用avahi-resolve-host-name就可以了
import subprocess def getDomain(dom): out = subprocess.check_output(['avahi-resolve-host-name', '-4', '-n', dom], encoding='utf-8') if out.startswith("Failed"): raise Exception(out) try: domain, ip = out.strip().split('\t') print("domain resolved:", dom, "ip:", repr(ip)) assert set(ip) - set('1234567890.') == set() return ip except Exception as e: #print(e) raise Exception(out) def getDomainSafe(dom): try: return getDomain(dom) except Exception as e: print("domain resolve fail:", str(e)) return None DOMAINS = [ "DESKTOP-697LVJS.local", "LAPTOP-1Q45LAA4.local", ] def doUpdate(): domainIPs = [getDomainSafe(c) for c in DOMAINS] with open("/system/etc/hosts", "r") as f: hostsContent = f.read() hostLines = hostsContent.split('\n') def updateHostLines(domain, ip): newLine = "%s %s" % (ip, domain) for i,l in enumerate(hostLines): if domain in l: hostLines[i] = newLine break else: hostLines.append(newLine) for i in range(len(DOMAINS)): domain = DOMAINS[i] ip = domainIPs[i] if ip is not None: updateHostLines(domain, ip) if hostLines and hostLines[-1] != '': hostLines.append('') hostContent = '\n'.join(hostLines) with open("/system/etc/hosts", "w") as f: f.write(hostContent) print("finish updating hosts!") if __name__ == "__main__": doUpdate()
 

自动更新

  • 配置cron:pkg install cronie
  • crontab -e添加:
* * * * * $PREFIX/bin/sudo -E sh -c "$PREFIX/bin/python3 ~/refresh_mdns_hosts.py > ~/refresh_mdns_hosts.log 2>&1"