如何把Android手机变成一个WIFI下载热点? — 报文转发及DNS报文拦截

随着WiFi的普及,移动运营商的热点也越来越多了,如中国移动的CMCC、中国电信的ChinaNet、中国联通的ChinaUnicom等,一般来说,连上此类的热点,打开浏览器上网时都会自动跳转到一个验证页面,最近有个项目也有类似的需求,Android手机自建热点,别的手机wifi连接此热点,打开浏览器,输入任意内容,自动跳转到一个下载列表页面,点击相应的链接即可下载相应的文件。

分析

考虑如下几种情况: - 浏览器输入IP地址,请求对应IP地址的80端口的内容 - 浏览器输入域名,先进行DNS解析域名,得到IP地址后,请求对应的80端口的内容 - 浏览器输入任意字符,一般浏览器内部设置一个默认的搜索引擎,此时地址栏的内容会作为搜索的关键字,加在搜索的url中

因此,需要解决如下问题: - 端口报文转发 - DNS报文拦截 - url重定向

端口报文转发

Android系统本身是Linux内核,1024以下端口都名花有主,如http是80,https是443,dns是53,对于这些1024以下端口的绑定需要root权限,但一般的App是没有root权限的,除非在 AndroidManifest.xml 文件中声明 android:sharedUserId=“android.uid.system”,并使用密钥文件进行签名:

java -jar signapk.jar platform.x509.pem platform.pk8 your.apk your_signed.apk

但问题是密钥文件属于手机厂商,显然不可能拿到这个密钥文件,当然,如果在模拟器里测试倒是可以的,从android源代码 build/target/product/security 里找到密钥文件,platform.pk8 和 platform.x509.pem,签名工具 signapk.jar 在 build/tools/signapk 下。

基于以上原因,一般Web服务器都绑定8080端口,手机浏览器如果输入IP地址,会访问Web服务器的80端口,这样就需要进行端口报文转发,对应dns报文拦截,无法监听53端口,同样需要端口转发,此外,浏览器的搜索引擎如果是google的话,使用https,同样也有这个问题。

iptables是个很好的防火墙管理工具,这里需要做如下配置:

iptables -t nat -A PREROUTING -d 0.0.0.0/0 -p tcp --dport 80 -j DNAT --to 192.168.43.1:8080
iptables -t nat -A PREROUTING -d 0.0.0.0/0 -p tcp --dport 443 -j DNAT --to 192.168.43.1:8443
iptables -t nat -A PREROUTING -d 0.0.0.0/0 -p udp --dport 53 -j DNAT --to 192.168.43.1:53530

说明:-t nat:指定nat表,-A:添加,PREROUTING:路由前处理,-d 0.0.0.0/0:任意目的地IP,-p tcp:协议,–dport 80:端口,-j DNAT:地址映射跳转,–to 192.168.43.1:8080:转发目的地,总的意思就是,到达防火墙的报文,不管去往那个IP地址,只要是发往80端口的tcp包,都转发到192.168.43.1的8080端口。剩下两条意思类似。

需要注意的是: 1、如果是App中的java代码调用,需要root权限,一般这么写:

String shell = "su -c iptables -t nat -A PREROUTING -d 0.0.0.0/0 -p tcp --dport 80 -j DNAT --to 192.168.43.1:8080";
Runtime.getRuntime().exec(shell);

2、Android手机设置为热点模式时,IP地址一般都会固定成192.168.43.1,这是由手机的dhcpcd服务指定的,一般不会去改dhcpcd服务的源代码然后重新编译,但这种写死的做法显然是不太合适的,通用的做法是自动取Ap的IP地址:

public static String getNetworkIpAddress(String name) {try {Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();while (interfaces.hasMoreElements()) {NetworkInterface networkInterface = (NetworkInterface) interfaces.nextElement();Enumeration<InetAddress> enumeration = networkInterface.getInetAddresses();while (enumeration.hasMoreElements()) {InetAddress inetAddress = (InetAddress) enumeration.nextElement();if (!inetAddress.isLoopbackAddress()&& inetAddress instanceof Inet4Address&& TextUtils.equals(name, networkInterface.getDisplayName())){return inetAddress.getHostAddress().toString();}}}} catch (Exception e) {e.printStackTrace();}return "";}public static String getApName(Context context) {try {ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);Method method = connectivityManager.getClass().getMethod("getTetheredIfaces");String[] names = (String[]) method.invoke(connectivityManager);return names[0];} catch (Exception e) {e.printStackTrace();}return "";}

看着挺复杂的,因为热点模式和连接到别的热点是完全不同的,取Ap名字时,用到了一个隐藏的方法,需要用反射的方式调用。

DNS报文拦截

DNS意思是域名解析协议,用户打开浏览器浏览网页时,不会记IP地址,而是记某些有含义的网址,DNS就是解决网址到IP地址的对应问题。DNS报文格式参考RFC1035文档,微软的网站上也有介绍:http://technet.microsoft.com/en-us/library/dd197470(v=ws.10).aspx ,这里主要介绍DNS报文的格式。

DNS报文格式

DNS报文一般由如下部分组成: - DNS header (fixed length,12 Bytes) - Question entries (variable length) - Answer resource records (variable length) - Authority resource records (variable length) - Additional resource records(variable length)

套用《TCPIP详解卷》中的一张图

DNS header(固定占12字节)

总共占12字节,结构如下: – 标识:报文的标识,占2字节,查询的报文里生成,响应的报文里复制此内容,用来标识是对相应查询的响应 – 标记:报文的标记位,占2字节,也就是16位,如下:

  • QR:0标识查询,1标识响应,
  • opcode:0为一般查询,1为反向查询(IP地址反查域名),2为查询服务器状态,一般为0
  • AA:是否为授权回答(authoritative - answer),可以理解为当前域名服务器是否对结果负责,如果从别的域名服务器查询过来的结果,显然不是当前域名服务器可掌控的,因此设为0
  • TC:是否被截断,UDP报文限定512字节(不包含IP及头部信息),如果超出将截断,此标记也被置1
  • RD:是否递归查询(Recursion Desired),如果为1,说明DNS服务器如果没有结果,那么DNS服务器会递归地找别的DNS服务器要结果,直到得到结果并返回,如果为0,则在没有结果的情况下,返回DNS列表
  • RA:是否支持递归查询,在响应报文中,一般都会支持递归查询
  • zero:必须为0
  • rcode:错误码,一般为0,表示没有错,如果不为0,表示有问题,错误码可以参考相关文档

–问题资源数:占2字节 –回答资源数:占2字节 –授权资源数:占2字节 –附加资源数:占2字节

Question entries(不定长)

不定长,结构如下: - 名字:域名的字符串表示,microsoft.com表示为:0x09microsoft0x03com0x00,需要注意的是长度的最高两位必须为0,因此字符长度不能超过63,也就是说最多0x3f,另外,参考rfc1053,为简化起见,域名总长度不能超过255 - 类型:相关含义可查手册,一般是0x0001,表示IP地址类型 - 类:一般是0x0001,表示普通的internet问题

Answer resource records(不定长)

不定长,结构如下: - 名字:同前面的查询名字,一般会以索引方式表示,引用到前面的字符,比如前面的 microsoft.com 字符在报文中的位置 - 类型:同前面的查询类型 - 类:同前面的查询类 - 生存时间:报文生存时间(TTL),占4字节,单位秒 - 资源长度:占2字节 - 资源内容:资源具体的内容,如IP地址:1.1.1.1 表示为 0x01010101

Authority resource records(不定长)

同上。

Additional resource records(不定长)

同上。

例子

经过以上的分析,来看个例子,打开wireshark抓包工具,监听网卡数据包,打开控制台,输入:host baidu.com,并抓取DNS报文。

上图为DNS查询:


21d50100000100000000000005626169647503636f6d0000010001
  • 21 d5:会话标识,应答中用于标识是哪个查询
  • 01 00:标记,二进制为0000 0001 0000 0000,参考标记位,RD被置1,标识是一个递归的查询
  • 00 01:问题数1
  • 00 00:回答资源数0
  • 00 00:授权资源数0
  • 00 00:额外资源数0
  • 05 62 61 69 64 75 03 63 6f 6d 00:域名名字,就是5baidu3com0这种格式,数字标识字符的数量,baidu有5个字符,所以是5baidu,域名字符串最后要跟一个0x00
  • 00 01:查询IP地址
  • 00 01:普通的internet查询

上图为DNS应答:


21d58180000100030000000005626169647503636f6d0000010001c00c000100010000017c00047b7d7290c00c000100010000017c0004dcb56f55c00c000100010000017c0004dcb56f56
  • 21 d5:标识,和之前的查询一一对应
  • 81 80:标记,二进制为1000 0001 1000 0000,QR、RD、RA被置1,表示支持递归查询的应答
  • 00 01:问题数1
  • 00 03:回答资源数3
  • 00 00:授权资源数0
  • 00 00:额外资源数0
  • 05 62 61 69 64 75 03 63 6f 6d 00:域名名字,参考前面的查询报文
  • 00 01:查询IP地址
  • 00 01:普通的internet查询
  • c0 0c:域名名字,应该和前面的一致,但是为了节省报文长度,这是个引用,怎么知道的呢?因为是c0,二进制是1100 0000,最高位两位置1了,05626169647503636f6d00这串字符前面有12个字节,因此相对位置是0c(从0开始)
  • 00 01:查询IP地址
  • 00 01:普通的internet查询
  • 00 00 01 7c:生存时间(Time to Live,TTL,单位秒),380秒
  • 00 04:资源长度,4个字节,表示接下来的4个字节是资源的实际内容
  • 7b 7d 72 90:资源内容,其实就是IP地址,123.125.114.144
  • c0 0c …:同上

从上面的DNS应答报文看,关注7b7d7290、dcb56f55、dcb56f56即可,分别对应三个IP地址:123.125.114.144、220.181.111.85、220.181.111.86

DNS报文拦截实现

了解了DNS报文的内容,下面需要做的就是,监听DNS端口,构造自己的报文返回即可,由于权限问题,一般Android的App是无法监听53端口的,这里可以监听53530端口,再通过iptables设置防火墙,将53端口的报文转发到53530端口即可,注意DNS是UDP包,代码参考如下

byte[] requestBuffer = new byte[256];
byte[] responseBuffer = new byte[256];
byte[] ipBuffer = { (byte) 0xc0, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00,0x00, 0x01, 0x7c, 0x00, 0x04, 0x01, 0x01, 0x01, 0x01 };
try {datagramSocket = new DatagramSocket(53530);DatagramPacket requestPacket = new DatagramPacket(requestBuffer,requestBuffer.length);while (!Thread.currentThread().isInterrupted()) {datagramSocket.receive(requestPacket);int requestLength = requestPacket.getLength();System.arraycopy(requestBuffer, 0, responseBuffer, 0, requestLength);System.arraycopy(ipBuffer, 0, responseBuffer, requestLength, ipBuffer.length);// 标志位responseBuffer[2] = (byte) 0x81;responseBuffer[3] = (byte) 0x80;// 响应数responseBuffer[6] = (byte) 0x00;responseBuffer[7] = (byte) 0x01;DatagramPacket response = new DatagramPacket(responseBuffer, requestLength + ipBuffer.length, requestPacket.getAddress(), requestPacket.getPort());datagramSocket.send(response);}
} catch (Exception e) {e.printStackTrace();
}

这样,所有的DNS解析请求都被转到1.1.1.1这个IP地址了。

url重定向

这个一般由Web服务器决定,Android有款ijetty,是开源的 http://code.google.com/p/i-jetty/, 可看看其中的源代码,修改其中的Handler就搞定了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/477860.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OpenKG 祝大家新春快乐

OpenKG 祝各位读者新春快乐&#xff0c;虎虎生威&#xff01;OpenKGOpenKG&#xff08;中文开放知识图谱&#xff09;旨在推动以中文为核心的知识图谱数据的开放、互联及众包&#xff0c;并促进知识图谱算法、工具及平台的开源开放。点击阅读原文&#xff0c;进入 OpenKG 网站。…

推荐中使用FNN/PNN/ONN/NFM优化特征交叉

文 | 水哥源 | 知乎sayingDNN时代来临的时候&#xff0c;LR没打过&#xff0c;也很难加入。FM打不过&#xff0c;但他可以加入FM的精髓&#xff0c;最上在于latent embedding&#xff0c;有了它才能把交互拆解到基底上&#xff1b;居中在于element-wise乘&#xff0c;能让两个特…

LeetCode 310. 最小高度树(图 聪明的BFS,从外向内包围)

文章目录1. 题目2. 解题2.1 暴力BFS2.2 聪明的BFS1. 题目 对于一个具有树特征的无向图&#xff0c;我们可选择任何一个节点作为根。图因此可以成为树&#xff0c;在所有可能的树中&#xff0c;具有最小高度的树被称为最小高度树。给出这样的一个图&#xff0c;写出一个函数找到…

Emma使用与分析

什么是Emma EMMA 是一个开源、面向 Java 程序测试覆盖率收集和报告工具。 它通过对编译后的 Java 字节码文件进行插装&#xff0c;在测试执行过程中收集覆盖率信息&#xff0c;并通过支持多种报表格式对覆盖率结果进行展示。 EMMA 所使用的字节码插装不仅保证 EMMA 不会给源代码…

论文浅尝 | WWW2022 - “知识提示”之知识约束预训练微调

本文作者 | 陈想&#xff08;浙江大学&#xff09;、张宁豫&#xff08;浙江大学&#xff09;、谢辛&#xff08;陈想&#xff09;、邓淑敏&#xff08;浙江大学&#xff09;姚云志&#xff08;浙江大学&#xff09;、谭传奇&#xff08;阿里巴巴&#xff09;&#xff0c;黄非&…

吐血整理:论文写作中注意这些细节,能显著提升成稿质量

文 | python编 | 小轶前言不知诸位在科研的起步阶段&#xff0c;是否曾有过如下的感受&#xff1a;总感觉自己写的论文就是和自己读过的论文长得不太一样&#xff0c;也不知道为啥。投稿的时候&#xff0c;审稿人也总是 get 不到论文的核心&#xff0c;只揪着论文的次要细节不放…

LeetCode 1237. 找出给定方程的正整数解

1. 题目 给出一个函数 f(x, y) 和一个目标结果 z&#xff0c;请你计算方程 f(x,y) z 所有可能的正整数 数对 x 和 y。 给定函数是严格单调的&#xff0c;也就是说&#xff1a; f(x, y) < f(x 1, y) f(x, y) < f(x, y 1)函数接口定义如下&#xff1a; interface Cu…

基于Wi-Fi的室内定位在美团总部的实践和应用(上)

室内定位技术的商业化必将带来一波创新高潮&#xff0c;尤其是在O2O领域&#xff0c;各种基于此技术的应用将出现在我们的面前。我们可以想象一些比较常见的应用场景&#xff0c;比如在大型商场里面借助室内导航快速找到目标商铺&#xff0c;商店根据用户的具体位置向用户推送更…

LeetCode 1266. 访问所有点的最小时间(数学)

1. 题目 平面上有 n 个点&#xff0c;点的位置用整数坐标表示 points[i] [xi, yi]。请你计算访问所有这些点需要的最小时间&#xff08;以秒为单位&#xff09;。 你可以按照下面的规则在平面上移动&#xff1a; 每一秒沿水平或者竖直方向移动一个单位长度&#xff0c;或者…

Coding Party 邀你出战!飞桨黑客马拉松线下场来啦

12月4-5日&#xff0c;这48H&#xff0c;与100开发者HACK Together“黑客”很酷&#xff1f;和“黑客”一起“战斗”是种什么样的体验&#xff1f;你参与这场“战斗”了吗&#xff1f;PaddlePaddle Hackathon 2021飞桨黑客马拉松&#xff0c;由百度飞桨联合深度学习技术及应用国…

技术动态 | 「知识图谱嵌入技术研究」最新2022综述

转载公众号 | 专知知识图谱(KG)是一种用图模型来描述知识和建模事物之间关联关系的技术. 知识图谱嵌入(KGE)作为一 种被广泛采用的知识表示方法,其主要思想是将知识图谱中的实体和关系嵌入到连续的向量空间中,用来简化操作, 同时保留 KG 的固有结构.它可以使得多种下游任务受益…

美团数据仓库-数据脱敏

背景与目标 在数据仓库建设过程中&#xff0c;数据安全扮演着重要角色&#xff0c;因为隐私或敏感数据的泄露&#xff0c;会对数据主体&#xff08;客户&#xff0c;员工和公司&#xff09;的财产、名誉、人身安全、以及合法利益造成严重损害。因此我们需要严格控制对仓库中的数…

全球仅3000人通过的TensorFlow开发人员认证到底有多香!

现在&#xff0c;我们每个人都已经习惯了社交网络&#xff0c;随时随地都能进行微信、QQ语音和视频通话。那么&#xff0c;你是否发现在不同场景下&#xff0c;这些社交软件音频、视频都是那么的流畅&#xff0c;这背后是什么科技在支撑这“声”与“话”的美好呢&#xff1f;这…

LeetCode 1043. 分隔数组以得到最大和(DP)

1. 题目 给出整数数组 A&#xff0c;将该数组分隔为长度最多为 K 的几个&#xff08;连续&#xff09;子数组。分隔完成后&#xff0c;每个子数组的中的值都会变为该子数组中的最大值。 返回给定数组完成分隔后的最大和。 示例&#xff1a; 输入&#xff1a;A [1,15,7,9,2,…

图谱实战 | 安全领域知识图谱建设与典型应用场景总结

转载公众号 | 老刘说NLP 安全知识图谱是网络安全领域专用知识图谱&#xff0c;也是知识图谱应用于安全业务的重要工业尝试。当前&#xff0c;安全领域中存在大量的业务数据&#xff0c;建模需求以及应用需求&#xff0c;了解安全领域知识图谱的建设方法以及典型应用场景&#x…

Hadoop安全实践

前言 在2014年初&#xff0c;我们将线上使用的 Hadoop 1.0 集群切换到 Hadoop 2.2.0 稳定版&#xff0c; 与此同时部署了 Hadoop 的安全认证。本文主要介绍在 Hadoop 2.2.0 上部署安全认证的方案调研实施以及相应的解决方法。 背景 集群安全措施相对薄弱 最早部署Hadoop集群时并…

论文浅尝 | KGQR: 用于交互式推荐的知识图谱增强Q-learning框架

笔记整理&#xff1a;李爽&#xff0c;天津大学链接&#xff1a;https://dl.acm.org/doi/pdf/10.1145/3397271.3401174动机交互式推荐系统(IRS)以其灵活的推荐策略和考虑最佳的长期用户体验而备受关注。为了处理动态用户偏好&#xff0c;研究人员将强化学习(reinforcement lear…

收藏清单:史上最全java自动化测试工具汇总

xUnit frameworks 单元测试框架 JUnit - 常用的测试框架TestNG - 测试框架 Test Data Supplier - TestNG DataProvider封装&#xff0c;让数据的生成更加灵活 TDD \ ATDD \ BDD 工具 JBehave - Behaviour-Driven Development (BDD)测试框架. BDD是从 test-driven development…

LeetCode 1014. 最佳观光组合

1. 题目 给定正整数数组 A&#xff0c;A[i] 表示第 i 个观光景点的评分&#xff0c;并且两个景点 i 和 j 之间的距离为 j - i。 一对景点&#xff08;i < j&#xff09;组成的观光组合的得分为&#xff08;A[i] A[j] i - j&#xff09;&#xff1a;景点的评分之和减去它…

聊聊推荐系统的高阶特征交叉问题

文 | 水哥源 | 知乎Saying1. DCN看起来给了我们很好的允诺&#xff0c;但是细细想来是有一些问题的&#xff0c;这里也可以参考大佬的意见2. 高阶FM的核心设计是先element-wise乘&#xff0c;再对embedding求和。核心优化方法是利用计算中的冗余构建递推关系&#xff0c;然后使…