android手机免root修改hosts

android手机免root修改hosts

痛点在哪里

开发及测试过程中经常需要切换开发、测试、预发布等环境,切换环境是通过修改hosts实现的。

android设备修改hosts看似简单,实际却会遇上不少麻烦,特别是在公司的网络环境中。你可能会遇到这种情况:

adb shell进去修改/etc/hosts,发现只读无法修改,需要root权限。尝试各种方法还是root失败后,转而想要通过电脑代理的方法避开root,但是这种方法需要把电脑也转网到staff-wifi,转网后一堆开发软件设置的代理也得跟着改,linux环境变量也得跟着改,总之一堆麻烦,而且从staff-wifi转回开发网或办公网还需要审核,想想就放弃了。。。

总结几种方法

1、root手机,修改/etc/hosts。

缺点:手机越来越难root,比如华为已经不允许申请手机解锁码。

2、手机和电脑连到同一个wifi(比如staff-wifi),手机设置代理到电脑(fiddler启动电脑代理服务),修改电脑的hosts。

缺点:依赖于电脑,而且因为手机无法连入开发网或办公网,电脑可能需要转网。

3、拦截DNS请求,直接返回所需要的A记录。

思来想去,如果可以修改DNS的回包,不是也相当于修改hosts的效果嘛!但怎么改?会不会也有root权限问题?

如何实现方法3

经历了一番痛苦后,笔者决定写个工具来实现改hosts的效果,一劳永逸,于是一番查找:

cap

km上搜了一下,发现公司有个内部开源项目 -- cap,看介绍非常强大,基于底层hook技术随便抓包改包,看样子应该可以实现篡改DNS的需求。但是笔者只是想实现改hosts的效果,cap显得有点重,作为备选方案吧。

VpnService

后面发现android提供了vpn服务框架,基础类是VpnService,免root,能够全局拦截网络请求、修改网络包。

能够拦截,还能够修改,嗯,很好!

逮着VpnService如何修改网络请求,一番google,发现有人已经实现了笔者需要的效果而且开源了,项目 Virtual-Hosts

好吧,有人实现了,而且代码写的挺不错,就用它了。接下来分析一下这个项目。

Virtual-Hosts 分析

简单来说分两步:1、VpnService拦截DNS请求。2、构造DNS回包并写回VpnService。

1、拦截DNS请求

使用VpnService拦截DNS请求很容易实现,对VpnService简单配置,然后startService就可以了。以IPV4为例,配置如下:

    //vpn地址,可以随意设置
    private static final String VPN_ADDRESS = "192.0.2.111";
    //DNS地址,填个正常的dns地址即可
    private static final String VPN_DNS4 = "8.8.8.8";
    ...
    Builder builder = new Builder();
    builder.addAddress(VPN_ADDRESS, 32);
    //设置DNS服务器
    builder.addDnsServer(VPN_DNS4);
    //所有到VPN_DNS4的请求都走这个vpn。
    //配合builder.addDnsServer(VPN_DNS4),就实现了所有DNS请求都走vpn,因此能够拦截到所有DNS请求。
    builder.addRoute(VPN_DNS4, 32);

2、构造DNS回包并返回

接下来处理拦截到的包。

    FileChannel vpnInput = new FileInputStream(vpnFileDescriptor).getChannel();
    ByteBuffer bufferToNetwork = ByteBufferPool.acquire();
    //取出一个拦截到的请求包
    int readBytes = vpnInput.read(bufferToNetwork);
    //解析包并构造出Packet
    Packet packet = new Packet(bufferToNetwork);
    if (packet.isUDP()) {
        deviceToNetworkUDPQueue.offer(packet);
    } else if (packet.isTCP()) {
        deviceToNetworkTCPQueue.offer(packet);
    }

这里的DNS请求走UDP,因此会走到UDPOutput:

    Packet currentPacket = inputQueue.poll();
    //handle_dns_packet里面利用开源库 dnsjava 解析DNS请求并构造回包,填入需要的A记录
    ByteBuffer packet_buffer= DnsChange.handle_dns_packet(currentPacket);
    //写入到队列,用于返回给VpnService
    this.outputQueue.offer(packet_buffer);

回包给VpnService:

    FileChannel vpnOutput = new FileOutputStream(vpnFileDescriptor).getChannel();
    ByteBuffer bufferFromNetwork = networkToDeviceQueue.poll();
    vpnOutput.write(bufferFromNetwork);

传送门:dnsjava

到这里就走通了通过拦截DNS请求实现修改hosts效果的整个过程,以上只是简单分析,感兴趣可以细读代码。

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

发表于

个人技术分享

1 篇文章2 人订阅

我来说两句

1 条评论
登录 后参与评论

相关文章

来自专栏码代码的陈同学

Rancher无法启动healthcheck和lb

一个新产品临近上线,全部采购了腾讯云ECS服务器,安装了Rancher 1.6.17做容器编排。在添加主机到服务器集群时,rancher的 healthchec...

27411
来自专栏杨建荣的学习笔记

Mycat读写分离配置实践

工作这些年来,也去了一些地方,有了一些见闻,隐隐感觉很多文化和猫有着千丝万缕的联系。就拿IT行业来说吧,猫有着很高的曝光率,比如大名鼎鼎的tomcat,是...

2985
来自专栏散尽浮华

Linux下selinux简单梳理

在linux环境下执行某些程序时,偶尔会遇到来一个关于selinux的强制模式不可执行的情况,这种情况下需要关闭selinux或者将enforcing改为per...

2056
来自专栏北京马哥教育

高薪全栈工程师必备Linux 基础

Linux 几乎无处不在,不论是服务器构建,还是客户端开发,操作系统的基础技能对全栈来说都是必备的。 系统的选择 Linux发行版本可以大体分为两类,一类是商...

3478
来自专栏工科狗和生物喵

Dell-Windows10下装Ubuntu 16.04 双系统,Ubuntu引导开启-经验贴,满干货!

正文之前 历时一天半。各种折腾,各种修复引导。网络上大概翻了,二三十个教程。然后在windows下尝试修复引导。在ubuntu下试图修复引导。最后发现是自己模式...

9697
来自专栏携程技术中心

Qnext大会 | App Slicing在携程APP上的实践

原创专栏|祁一鸣 ? 2016年4月加入携程, 任机票研发部技术专家。毕业于美国常春藤名校Dartmouth College本科,曾先后在硅谷的Oracle, ...

2927
来自专栏康怀帅的专栏

CoreOS 容器 Rkt 简单介绍

由于 Docker 已经成为事实上的容器老大,这里暂且将 rkt 内容放入 docker 文件夹。哈哈 官方网站:https://coreos.com/rkt/...

3987
来自专栏SAP最佳业务实践

SAP最佳业务实践:ETO–项目装配(240)-8给作业分配技术文档

image.png CJ20N给作业分配技术文档 为帮助雇员操作,可以将保存在文档管理系统中的文档分配给WBS元素和作业。在这个操作中,会将一份技术图纸分配给一...

36710
来自专栏JadePeng的技术博客

开源APM系统skywalking介绍与使用

SkyWalking 创建与2015年,提供分布式追踪功能。从5.x开始,项目进化为一个完成功能的Application Performance Managem...

1430
来自专栏IT笔记

前后端分离之SpringBoot项目Token认证

写在开始 有人说,爱上一座城,是因为城中住着某个喜欢的人。其实不然,爱上一座城,也许是为城里的一道生动风景,为一段青梅往事,为一座熟悉老宅。或许,仅仅为的只是这...

4009

扫码关注云+社区