前言

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

DNS劫持的主要表现为看视频,点击之后莫名其妙的跳到了某些广告网站。正常情况下,当我们点击某个链接的时候,会向一个称作DNS服务器的东西发出请求,把链接转换成机器能够识别的ip地址,其过程如下:

域名->ip地址的过程被称作DNS解析。在这个过程中,由于DNS请求报文是明文状态,可能会在请求过程中被监测,然后攻击者伪装DNS服务器向主机发送带有假ip地址的响应报文,从而使得主机访问到假的服务器。

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()]);

}

参考资料

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. Linux 2.6内核编译与配置安装升级
  2. Django 流式响应中文csv样例
  3. NS2安装错误系列(1)
  4. 神竜出击 合三为一!
  5. 两个条件一个为false就运行_Python入门基础实例讲解——两个数字比大小,并输出最大值...
  6. pytorch入门学习(三) 神经网络
  7. mysql主主互备架构
  8. Ubuntu 源码方式安装Subversion
  9. win7 java注册表_使用JAVA和JNA在64位Win 7上读/写Windows注册表
  10. MySQL5.6.26升级到MySQL5.7.9实战方案
  11. Fiddler 4——手机抓包工具
  12. 启动pe系统找不到计算机硬盘分区,pe系统看不到硬盘分区_pe系统里看不到硬盘...
  13. 【计算情与思】大学生学习和发展的思考和建议
  14. 推荐一款在线免费共享云桌面
  15. 元宇宙iwemeta:红杉资本 all in 区块链?
  16. 解决 docker 磁盘空间不足问题
  17. 磁力计很容易受到干扰
  18. IOS AppDelegate详解
  19. cocos creator教程【打造路径编辑系统】
  20. WebMagic 实现爬虫入门教程

热门文章

  1. 台式机dp接口_台式机外接显示器的注意事项
  2. python取整方法汇总
  3. 随机性的流量不值得追随!
  4. mmseg中的评价指标
  5. 电脑去水印软件哪个效果好
  6. js鼠标移入移出事件
  7. 通俗理解数据治理之主数据
  8. C#基础 ArrayList foreach 遍历示例
  9. 三星手机业务意外增长但增量不增收,利润增长依然靠芯片
  10. spin lock irqrestore中为什么先开中断后开抢占