DNS劫持指在劫持的网络范围内拦截域名解析的请求,分析请求的域名,把审查范围以外的请求放行,否则返回假的IP地址或者什么都不做使请求失去响应,其效果就是对特定的网络不能反应或访问的是假网址。

DNS服务器的作用是将我们所能理解的域名解析成计算机直接读取的ip地址串,这个过程如上图所示。但是在这个解析的过程中,可能会发生域名劫持。由于DNS请求报文是明文状态,可能会在请求过程中被监测,然后攻击者伪装DNS服务器向主机发送带有假ip地址的响应报文,从而使得主机访问到假的服务器。

最常见的DNS劫持是笔者在看视频的时候,被劫持跳转到了某个广告页(万恶的运营商)。一般来说,对付网页劫持的方案我们通过NSURLProtocol来完成。

NSURLProtocol

NSURLProtocol是苹果提供给开发者的黑魔法之一,大部分的网络请求都能被它拦截并且篡改,以此来改变URL的加载行为。这使得我们不必改动网络请求的业务代码,也能在需要的时候改变请求的细节。作为一个抽象类,我们必须继承自NSURLProtocol才能实现中间攻击的功能。

是否要处理对应的请求。由于网页存在动态链接的可能性,简单的返回YES可能会创建大量的NSURLProtocol对象,因此我们需要保证每个请求能且仅能被返回一次YES

+ (BOOL)canInitWithRequest: (NSURLRequest *)request;

+ (BOOL)canInitWithTask: (NSURLSessionTask *)task;

是否要对请求进行重定向,或者修改请求头、域名等关键信息。返回一个新的NSURLRequest对象来定制业务

+ (NSURLRequest *)canonicalRequestForRequest: (NSURLRequest *)request;

如果处理请求返回了YES,那么下面两个回调对应请求开始和结束阶段。在这里可以标记请求对象已经被处理过

- (void)startLoading;

- (void)stopLoading;

当发起网络请求的时候,系统会像注册过的NSURLProtocol发起询问,判断是否需要处理修改该请求,通过一下代码来注册你的子类

[NSURLProtocol registerClass: [CustomURLProtocol class]];

DNS解析

一般情况下,考虑DNS劫持大多发生在使用webView的时候。相较于使用网页,正常的网络请求即便被劫持了无非是返回错误的数据、或者干脆404,而且对付劫持,普通请求还有其他方案选择,所以本文讨论的是如何处理网页加载的劫持。

LocalDNS

LocalDNS是一种常见的防劫持方案。简单来说,在网页发起请求的时候获取请求域名,然后在本地进行解析得到ip,返回一个直接访问网页ip地址的请求。结构体struct hostent用来表示地址信息:

struct hostent {

char *h_name;                     // official name of host

char **h_aliases;                 // alias list

int h_addrtype;                   // host address type——AF_INET || AF_INET6

int h_length;                     // length of address

char **h_addr_list;               // list of addresses

};

C函数gethostbyname使用递归查询的方式将传入的域名转换成struct hostent结构体,但是这个函数存在一个缺陷:由于采用递归方式查询域名,常常会发生超时。但是gethostbyname本身不支持超时处理,所以这个函数调用的时候放到操作队列中执行,并且采用信号量等待1.5秒查询:

+ (struct hostent *)getHostByName: (const char *)hostName {

__block struct hostent * phost = NULL;

dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);

NSOperationQueue * queue = [NSOperationQueue new];

[queue addOperationWithBlock: ^{

phost = gethostbyname(hostName);

dispatch_semaphore_signal(semaphore);

}];

dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, 1.5 * NSEC_PER_SEC));

[queue cancelAllOperations];

return phost;

}

然后通过函数inet_ntop把结构体中的地址信息符号化,获得C字符串类型的地址信息。提供getIpAddressFromHostName方法隐藏对ipv4和ipv6地址的处理细节:

+ (NSString *)getIpv4AddressFromHost: (NSString *)host {

const char * hostName = host.UTF8String;

struct hostent * phost = [self getHostByName: hostName];

if ( phost == NULL ) { return nil; }

struct in_addr ip_addr;

memcpy(&ip_addr, phost->h_addr_list[0], 4);

char ip[20] = { 0 };

inet_ntop(AF_INET, &ip_addr, ip, sizeof(ip));

return [NSString stringWithUTF8String: ip];

}

+ (NSString *)getIpv6AddressFromHost: (NSString *)host {

const char * hostName = host.UTF8String;

struct hostent * phost = [self getHostByName: hostName];

if ( phost == NULL ) { return nil; }

char ip[32] = { 0 };

char ** aliases;

switch (phost->h_addrtype) {

case AF_INET:

case AF_INET6: {

for (aliases = phost->h_addr_list; *aliases != NULL; aliases++) {

NSString * ipAddress = [NSString stringWithUTF8String: inet_ntop(phost->h_addrtype, *aliases, ip, sizeof(ip))];

if (ipAddress) { return ipAddress; }

}

} break;

default:

break;

}

return nil;

}

+ (NSString *)getIpAddressFromHostName: (NSString *)host {

NSString * ipAddress = [self getIpv4AddressFromHost: host];

if (ipAddress == nil) {

ipAddress = [self getIpv6AddressFromHost: host];

}

return ipAddress;

}

扩展

localDNS直接进行解析获取的ip地址可能不是最优选择,另一种做法是让应用每次启动后从服务器下发对应的DNS解析列表,直接从列表中获取ip地址访问。这种做法对比递归式的查询,无疑效率要更高一些,需要注意的是在下发请求过程中如何避免解析列表被中间人篡改。

因为请求地址可能无效,需要以ip映射host的映射表来保证在访问无效的地址之后能重新使用原来的域名发起请求。另外确定ip无效后应该维护一个无效地址表,用来域名解析后判断是否继续使用地址访问。整个域名解析过程大概如下

WebKit

WKWebView是苹果推出的UIWebView的替代方案,但前者还不够优秀以至于使用后者开发的大有人在。另外使用NSURLProtocol实现防DNS劫持功能的时候,在调起canInitWithRequest:后就再无下文。通过查阅资料发现想实现WebKit的请求拦截需要调用一些私有方法,让 WKWebView 支持 NSURLProtocol文章已经做了很好的处理,在文中的基础上,笔者对注册协议的过程多加了一层处理(毕竟苹果爸爸坑起我们来绝不手软):

static inline NSString * lxd_scheme_selector_suffix() {

return @"SchemeForCustomProtocol:";

}

static inline SEL lxd_register_scheme_selector() {

const NSString * const registerPrefix = @"register";

return NSSelectorFromString([registerPrefix stringByAppendingString: lxd_scheme_selector_suffix()]);

}

static inline SEL lxd_unregister_scheme_selector() {

const NSString * const unregisterPrefix = @"unregister";

return NSSelectorFromString([unregisterPrefix stringByAppendingString: lxd_scheme_selector_suffix()]);

}

本文demo:LXDAppMonitor

https://github.com/JustKeepRunning/LXDAppMonitor

本文来源于:iOS监控:DNS劫持-变化吧博客

特别声明:以上文章内容仅代表作者本人观点,不代表变化吧博客观点或立场。如有关于作品内容、版权或其它问题请于作品发表后的30日内与变化吧联系。

ios如何解除dns被劫持_iOS监控:DNS劫持相关推荐

  1. ios如何解除dns被劫持_iOS监控-DNS劫持

    前言 DNS劫持指在劫持的网络范围内拦截域名解析的请求,分析请求的域名,把审查范围以外的请求放行,否则返回假的IP地址或者什么都不做使请求失去响应. DNS劫持的主要表现为看视频,点击之后莫名其妙的跳 ...

  2. ios如何解除dns被劫持_iOS - DNS劫持

    ******科普** 1.DNS劫持的危害 不知道大家有没有发现这样一个现象,在打开一些网页的时候会弹出一些与所浏览网页不相关的内容比如这样奇(se)怪(qing)的东西 图一 或者这样 图二 ,其实 ...

  3. 监控 DNS 流量,预防安全隐患五大招!

    2019独角兽企业重金招聘Python工程师标准>>> 尽管 IT 管理员尽心尽责地监控设备.主机和网络是否存在恶意活动的迹象,却往往出力不讨好.主机入侵检测和端点保护对很多公司来说 ...

  4. 云漫圈 | 什么是DNS?什么是DNS污染?什么又是DNS劫持?

    戳蓝字"CSDN云计算"关注我们哦! 文章转载自公众号:漫画编程 2019年1月23日下午,我正在公司疯狂的撸着代码,沉浸在我的代码世界中,正在欣赏着自己刚刚写下的一行lambda ...

  5. java 实现dns劫持_JavaScript 防 http 劫持与 XSS

    原标题:JavaScript 防 http 劫持与 XSS 原文作者: 作为前端,一直以来都知道HTTP劫持与XSS跨站脚本(Cross-site ing).CSRF跨站请求伪造(Cross-site ...

  6. 路由dns劫持,路由器DNS劫持简单实现和防范分析

    路由器DNS劫持变的越来越普遍.目前来说,这种技术是比较高端的一种方式,非接触随时可控,可以直接劫持你的站点跳转到一些非可信网站.一般用户很难觉察到,就算觉察到了取证举报更难.这里,我用最简单简单的方 ...

  7. DNS劫持原理、dns劫持有什么办法解决、DNS劫持原理与操作

    DNS(域名系统)的作用是把网络地址(域名,以一个字符串的形式)对应到真实的计算机能够识别的网络地址(IP地址),以便计算机能够进一步通信,传递网址和内容等.由于域名劫持往往只能在特定的被劫持的网络范 ...

  8. 网络安全:、dns被劫持怎么解决DNS域名劫持的几种解决方法

    dns的快慢与稳定与否,关系着浏览时的正常;更有甚者,dns的健康与否,更会直接影响各个拨号客户端的健康. 现在国内上网的用户,大多家用的都是用的网通或者电信的adsl,这中间还分各省地区的拨号服务器 ...

  9. 网易dns劫持检测,dns被劫持检测方法有哪些?

    1.遇到这种情况,首先是先看看其它人的电脑或手机等设备连接网络是否正常,是. 2.电脑重启后还不行,可以尝试将自己的DNS地址固定为一些免费的.速度比较快的. DNS(Domain Name Syst ...

最新文章

  1. boost:进程管理
  2. 第一课 第四节 数据转换
  3. SEO -- 搜索引擎优化
  4. Leaflet中实现添加比例尺控件与自定义版权控件与链接
  5. Linux的awk命令使用心得
  6. 别瞎学了,这几门语言要被淘汰了!
  7. [性能测试]:关于MQ协议脚本开发
  8. 线程池如何保证所有子线程运行完再执行主线程
  9. 百篇论文分类整理看数据增广最新研究进展
  10. C#实战之CAD二次开发005:打印pdf
  11. 计算机实验室建设论证报告,计算机实验室实习报告-报告.doc
  12. editormd富文本编辑器
  13. MII/MDIO接口详解
  14. 凯立德地图导航2022年懒人包 安卓版
  15. 【c语言】算数转换解析+试题
  16. 测试开发 - 十年磨一剑(序)
  17. Segmentation笔记4-Boundary-Aware Network for Fast and High-Accuracy Portrait Segmentation
  18. Oracle数据库有哪些应用结构?
  19. 对RAM,ROM,NOR/NAND FLASH等常见内存设备类型的理解
  20. Web3D展示框架whs.js:基于Three.js的Web3d应用程序的超快3D框架

热门文章

  1. 【源码】史蒂芬森加速迭代方法的matlab实现
  2. 抓住中国势能 三星的“脱胎换骨”
  3. 如何用WinImage制作任意大容量的ima或img磁盘文件
  4. windows系统证书导入方法
  5. QT入门看这一篇就够了——超详细讲解(40000多字详细讲解,涵盖qt大量知识)
  6. 吉林大学计算机 王恩,【十佳研究生】王恩:越努力,越幸运
  7. vs MD /MDD /ML /MT /MTD的简单介绍
  8. Django中间件Middleware
  9. 看到一个伙计遇到的服务端编程遇到的问题 赶紧复制过来
  10. python数据分析与应用实训题答案第七章_应用回归分析,第7章课后习题参考答案...