要说为啥会出现httpdns(先不用管意思,后面解释),那么,首先要说一下,现在的dns解析,是不是有啥问题?
dns能有啥问题呢,就是输入一个域名xxx.com,dns服务器递归获取xxx.com背后的ip,看起来,人畜无害的技术。
但是,如果我就是负责维护某运营商的dns服务器的技术人员,手里很缺钱,我可能会想,是不是可以“科技向善”,搞点钱来画画?
比如,假设xxx.com网站很火,每天很多人访问,那我可以这样,xxx.com进行dns查询,本来应该返回的ip是1.1.1.1,我呢,我给返回另一个我手里的服务器的ip(2.2.2.2),那么,用户后续再访问xxx.com,就是访问我手里的2.2.2.2了。我的2.2.2.2服务器,做个反向代理,把用户请求转发到1.1.1.1,再把1.1.1.1的响应转回给用户,用户也不知道它的流量已经被劫持了,全得从我的2.2.2.2上过一道手,看起来还神不知鬼不觉。
我这时候想赚钱的话,完全可以去找广告商谈合作了,谁给钱多,我就:转发1.1.1.1的响应给用户时,加点广告,用户只要打开xxx.com,就会被强制弹广告,我呢,等着广告商给我送钱即可。
以上就是最简单的dns劫持的例子,大家看了后也不要觉得好像我可以,首先,你得进到运营商公司,掌握相关服务器;其次,现在好多流量都是https域名了,https防中间人篡改的功能还是很强的,所以,基本还是说,你劫持归劫持,你劫持了也不能改我流量,那你也很难加广告,所以还是可以防这种弹广告的。
我在百度搜了下dns劫持,发现这个行业还是真的很刑很赚钱,适合各位喜提毕业礼包的程序员们再就业(https://xw.qq.com/cmsid/20211203A014PC00)
dns解析现状问题2:调度不准前面有篇文章,讲gslb的,提到过如下事情:
依赖运营商帮我们做dns解析,不一定很靠谱,比如我们把xxx.com要解析到我们在深圳和北京的两个机房,一般来说,是期望可以根据用户所在的地区来返回就近的地址,如广东用户就返回xxx.com在深圳机房的地址,北京用户就给北京机房的地址。或者是dns运营商那边,也支持按用户的运营商路线来解析,
但是呢,总归来说,这个解析是掌握在别人手里,他要是靠谱,那就没问题;他那边要是解析不靠谱,那就问题较大,比如广东用户给你个北京机房地址,你说用户是不是得卡死在你的网站上,体验就完全不行。
httpdns的定义 定义dns劫持,发生在dns解析过程中,一般来说走的是udp协议;dns解析,无非就是要拿到xxx.com背后的ip,那我是不是可以自己开发一个服务,对外提供http接口,接口的功能就是:接收一个参数,即待查询的域名,如xxx.com;返回呢,就是xxx.com对应的ip或者ip列表或者ip列表再加点各个ip的负载情况(如有这个数据)。
api请求参数按理说我们是要自己去开发这么一个http服务的,但是,现在的各大云厂商也做了这个功能,我就直接贴点他们的资料:
比如上面这个云厂商,对外提供的接口,就是http://203.107.1.33/xx/d,其中,203.107.1.33是一个公网ip,是这个httpdns服务的对外ip,参数呢,主要就是两个:host和ip,host就是你要查的域名,ip是客户端的ip(如有,如果自身取不到自己的对外出口ip,服务也会默认取socket中的client ip,即客户端ip),所以,这个接口就模拟了dns服务器的dns查询功能。
这边也有两个请求示例:
api响应参数
- 示例1(默认来源IP):http://203.107.1.33/100000/d?host=www.xxx.com
- 示例2(指定来源IP):http://203.107.1.33/100000/d?host=www.xxx.com&ip=42.120.74.196
在该云厂商的网站上,也介绍了响应体的格式:
{
"host":"www.xxx.com",
"ips":[
"140.205.140.234"
],
"ipsv6":[
"2400:3200:1300:0:0:0:0:3e"
],
"ttl":57,
"origin_ttl":120
}
可以看到,ips也是支持返回多个的。假设是我们自己实现这个api呢,也和上面这个api差不多,ips这边,可能可以多点想法,比如把每个ip的当前状态也返回给客户端,客户端就可以按照一些策略来,比如选一个负载最低的;
我看云厂商这边呢,都是只返回ip,毕竟它不可能知道我们每个ip的更多信息;云厂商的做法,大概就是:
- 根据你的参数中的要查的域名,xxx.com,去dns系统查询背后的真实ip地址,如查到1.1.1.1(深圳)、2.2.2.2(北京)
- 根据客户端的ip(请求参数中的ip,如没传就从socket里取对端ip)来判断该返回xxx.com在北京的ip,还是深圳的ip;另外,我看到云厂商也支持你自己写一段代码,让你自定义策略。
只适合有客户端的场景,可以看到,这个方案是需要先去查询httpdns服务,才能拿到真实的ip;这就需要在客户端(安卓、ios、pc端均可)编码实现。
B/S这种场景是没办法了,浏览器不支持先去httpdns查真实ip,再发起访问。
为啥httpdns服务对外直接暴露ip因为httpdns就是要解决dns劫持问题,总不能自己再套一层dns吧;另外,这个ip是有要求的,需要全国各地的用户访问这个ip都要足够快,所以,这个ip所在服务器一般是要放在BGP机房,BGP机房简单理解就是各大主流运营商,如移动、电信、铁通、网通等等,都和这个机房直连,因此,各大运营商的用户访问这个机房的服务器都很快。
具体我也不是很懂,可以这么理解,市面上很多IDC公司提供数据中心租用、服务器托管等服务,它手里的机房呢,也是有差异的,有的可能主要接了电信运营商,适合南方用户访问,北方用户访问就很慢;有的就是适合北方用户访问;还有一些呢,就是同时接入了很多家运营商,各大运营商访问这个机房都比较快,即所谓BGP机房。
httpdns服务如何保证高可用httpdns服务,像前面我们看的那个云厂商,只有一个ip?其实不是的,是在该云厂商的很多机房有部署,有多个ip的。
httpdns使用http协议明文传输,不安全?考虑到服务IP防攻击之类的安全风险,为保障服务可用性,HTTPDNS同时提供多个服务IP,当某个服务 IP在异常情况下不可用时,可以使用其它服务IP进行重试。上述文档中使用的
203.107.1.33
是其中一个服务IP。HTTPDNS提供Android SDK和iOS SDK,两个平台的SDK中已经做了多IP轮转和出错重试的策略,通常情况下,建议开发者直接集成SDK即可,不需要自己手动调用HTTP API接口。
那就使用https,云厂商也是支持这么玩的,
客户端最佳实践HTTPS服务URL:
https://203.107.1.33/{account_id}/d
客户端最好不要依赖这个机制,万一httpdns服务出问题了呢,那我们的app不就完全不能用了吗,此时可以降级为使用传统的dns方案,劫持就劫持吧,其实概率也没那么大(毕竟太刑了);要是传统的dns方案还是有问题,客户端还可以预埋一些ip,到时候就从预埋的ip里选一个去访问,保证高可用。
云厂商提供了sdk的方案,也详细讲解了一些细节问题,比如,通过httpdns拿到了某个ip,为1.1.1.1,此时,就向1.1.1.1发起了https业务请求(假设我们的后端服务器都是使用https),此时就会遇到个问题:https一般是只支持域名访问(因为https服务器会返回证书给客户的,证书都是颁发给某个域名的,没听说颁发给某个ip的),此时用ip去访问https服务器,就会有一点问题。
云厂商毕竟是要赚钱的,这些问题的解决方案,在他们文档里倒是都有写。
我感觉我都成了推销的了,其实我就是讲下这个httpdns而已,广告费都没有,对吧。