江边闲话集

12/07/2018

从浏览器中输入URL到页面加载发生了什么 – Part 1

Filed under: I.T — 张太国 @ 10:34

背景

“从浏览器中输入URL到页面加载的发生了什么“,这是一道经典的面试题,涉及到的知识面非常多,但作为一个自认为对网络知识掌握的比较好的老码农来说,回答这个问题自然不在话下。如果这道题目如果在面试出现,对我来说就是送分题啊。尽管如此,我还是愿意花一些时间根据我自己的理解回答一下这个题目,看我自己到底掌握的有多深,同时也把自己的知识梳理一下。

这让我想起另外一件往事,这道题有点类似于“在手机上浏览器上输入一个URL,手机做了一些什么”,我当时学习通信里的核心网时就给自己提出过这个问题。

我非常愿意将这个面试题的答案共享出来,一是希望得到大家的意见,二是也希望对那些不是特别熟的人起到一些帮助。

因为文章较长,我将它们分为三大部份,后面会提供该文章的完整PDF版本,供大家下载。

从本文里学到什么?

正如前面所说,这篇文章涉及到的知识面非常丰富,我相信您绝对可以从本文里学到很多基础知识,还有一些高级话题。

  1. DNS的解析原理,常用命令,端口等
  2. TCP/IP模型,三次握手,四次挥手。
  3. HTTP/HTTPS的原理和解析。
  4. 浏览器render一个页面
  5. Web安全性问题
  6. 抓包,分析TCP模型,三次握手,SSL/TLS,让学起来不再枯燥。
  7. 其他一些高级话题。

自认为是目前写的最详细的一篇文章了,因为里面有理论,有实战,应该会起到一个比较好的效果。

总概: 几大步骤

总的来说,当你输入在浏览器里输入一个URL到页面加载,发生的顺序如下:

  1. DNS查询
  2. TCP连接
  3. 发送HTTP请求
  4. Server处理HTTP请求并返回HTTP报文
  5. 浏览器解析并render页面
  6. HTTP连接断开
后面将对以上步骤详细介绍。

DNS查询

DNS解析流程

假设输入的URL是包含域名的,那肯定会涉及到DNS解析。当然,如果URL仅仅是IP,那就不会涉及到DNS的。域名的出现是为了方便记忆,因为域名比IP好记。我们这里假设URL包含域名。

解析的步骤大致如下图:

首先,在本地域名服务器中根据域名查询IP地址,如果没有找到的情况下,本地域名服务器会向根域名服务器发送一个请求。
如果根域名服务器也不存在该域名时,本地域名会向com顶级域名服务器(TLD)发送一个请求,依次类推下去。
直到最后本地域名服务器得到google的IP地址并把它缓存到本地,供下次查询使用。
可以参考页面https://www.verisign.com/en_US/website-presence/online/how-dns-works/index.xhtml ,该页面诠释了DNS的过程。
需要说明的是Root DNS Server一般有13个,后面有个点(.),别忘了。
a.root-servers.net.
c.root-servers.net.
j.root-servers.net.
b.root-servers.net.
i.root-servers.net.
d.root-servers.net.
k.root-servers.net.
f.root-servers.net.
l.root-servers.net.
h.root-servers.net.
m.root-servers.net.
g.root-servers.net.
e.root-servers.net.

DNS的优化

我们发现,一个DNS查询在没有缓存的情况下会有6步,这将是一个耗时的过程,如果DNS 查询时间过长,甚至会影响到用户体验。
那么现阶段是怎么优化的呢?缓存。DNS是存在着多级缓存,从离浏览器的距离排序的话,有以下几种: 浏览器缓存,系统缓存,路由器缓存,IPS服务器缓存,根域名服务器缓存,顶级域名服务器缓存,主域名服务器缓存。
我们以Chrome为例子,输入chrome://net-internals/#dns,我们会看到如下界面:
这里的Capacity: 1000,代表缓存1K条,那么每条记录缓存多久呢?参看
timeout 1
这里的1代表1分钟。
如果是系统缓存,一般分2种情况:
Linux 操作系统
见下图,一般在/etc/hosts下。
Windows操作系统
一般在C:\Windows\System32\Drivers\etc\hosts
谈到这里,我给大家分享一个特别有用的技巧
我们在做开发和测试时,会有一种情况,经常会去访问某个(测试)URL,例如http://192.168.1.8:8080/admin/login, 如果这样的话,我们极有可能存在一个问题,觉得每次输入ip真的很麻烦。怎么解决?那么我们可以这么做,利用DNS的原理,将某个伪hostname(abc-test)加入到hosts里,只需加入一条记录:
192.168.1.8. abc-test
这样就可以用http://abc-test:8080/admin/login去访问了,简单易用,对吧。

DNS负载均衡

不知道大家有没有注意或思考过一个问题,Google在全球都有服务器,不同的国家或区域访Google,是不是都很快,这就是Google GSLB的作用。也就是说不同的区域访问Google返回的IP是不一样的,甚至在同一个办公室访问Google,返回回来的IP也有可能是不一样的。
为什么呢?这里用的就是DNS负载均衡,不然Google怎么去支持全球几十亿客户的请求呢。总之,DNS会根据你的位置或IP返回一个合适的IP给你用。除了Google,一些CDN的SP例如Akamai、AWS、Azure、阿里云都有类似的服务。

DNS Record(记录)

DNS记录是一个非常重好的概念。DNS记录类型如下表。
记录类型
含义简介
A(Address)
指定域名对应的IPv4地址
AAAA
指定域名对应的IPv6地址
NS(Name Server)
指定该域名由哪个DNS服务器来进行解析
MX(Mail Exchanger)
邮件交换记录,用于电子邮件系统发邮件时根据收信人的地址后缀来定位邮件服务器
CNAME
别名记录,多个域名映射到同一台计算机(如同一主机提供mail和www服务)
TXT
主机名或域名的说明
TTL(Time-To-Live)
DNS服务器中保存的时间
PTR
将一个主机地址映射到对应的域名
HINFO
说明映射到特定 DNS 主机名的 CPU 类型和操作系统类型
在这里只介绍常用的A Record, CNAME,MX,NS。
A记录
A记录是用的最多的一种类型。
A (Address) 记录是用来指定主机名(或域名)对应的IP地址记录。用户可以将该域名下的网站服务器指向到自己的Web Server上。
同时也可以设置该域名的子域名。通俗来说A记录就是服务器的IP,域名绑定A记录就是告诉DNS,当你输入域名的时候给你引导向设置在DNS的A记录所对应的服务器。
后面的抓包分析会对A记录进行分析,让您有直观认识。
CNAME记录
CNAME记录是另一种用的比较多的记录,可以将一个域名或者子域名指向另外一个主机名。
最常用的使用场景是什么呢?没错,CDN就是这种方式。举个例子,例如公司A想把自己的图片放在Akamai的CDN上,A的子域名是img.abc.com, 而 Akamai的CDN服务域名是img.akaimacdn.com. 但是A公司期望用自己的域名吗,而不是Akamai的域名。为了实现这个目标,怎么办?是的,使用CNAME,只需要将子域名img.abc.com指向到img.akaimacdn.com。问题又来了,在哪里设置呢?肯定是在公司A这边的DNS server上,而不是Akamai那边。
后面的抓包分析会对MX进行分析,让您有直观认识。
MX记录
MX(Mail Exchanger)记录,字面意思很直观,知道它用来做邮件路由,用户可以将域名下的邮件服务器指向到自己的邮件服务器上,然后可以自己操控所有的邮箱设置。所以只需在线填写服务器的IP地址,即可以将域名下的邮件全部转到您自己设定相应的邮件服务器上。
NS记录 
NS记录用来解析服务器记录,表明由哪台服务器对该域名进行解析,这里的NS记录只对子域名生效。
例如用户希望由12.34.56.78这台服务器解析sub1.mydomain.com,则需要设置 sub1.mydomain.com的NS记录。
这里涉及到一个问题,细心的我们会发现A记录也有该功能,这里就涉及到优先级的问题了。NS记录优先于A记录。如果一个主机地址同时存在NS记录和A记录,则A记录不生效。

DNS常用命令和工具

只介绍2个常用的命令dig和nslookup。
dig
dig是一个DNS查询工具。
[warren]$ dig
; <<>> DiG 9.9.5-3ubuntu0.16-Ubuntu <<>>
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 57775
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 13, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;.                              IN      NS
;; ANSWER SECTION:
.                       16265   IN      NS      a.root-servers.net.
.                       16265   IN      NS      c.root-servers.net.
.                       16265   IN      NS      j.root-servers.net.
.                       16265   IN      NS      b.root-servers.net.
.                       16265   IN      NS      i.root-servers.net.
.                       16265   IN      NS      d.root-servers.net.
.                       16265   IN      NS      k.root-servers.net.
.                       16265   IN      NS      f.root-servers.net.
.                       16265   IN      NS      l.root-servers.net.
.                       16265   IN      NS      h.root-servers.net.
.                       16265   IN      NS      m.root-servers.net.
.                       16265   IN      NS      g.root-servers.net.
.                       16265   IN      NS      e.root-servers.net.
;; Query time: 0 msec
;; SERVER: 208.113.157.202#53(208.113.157.202)
;; WHEN: Thu Nov 29 18:04:06 PST 2018
;; MSG SIZE  rcvd: 239
再看看dig 京东的域名www.jd.com 会有什么效果。
; <<>> DiG 9.10.6 <<>> www.jd.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 2675
;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;www.jd.com.                   IN    A
;; ANSWER SECTION:
www.jd.com.            300  IN    CNAME    www.jd.com.gslb.qianxun.com.
www.jd.com.gslb.qianxun.com. 300 IN CNAME    www.jdcdn.com.
www.jdcdn.com.        300  IN    A     61.174.55.1
;; Query time: 3 msec
;; SERVER: 192.168.1.1#53(192.168.1.1)
;; WHEN: Fri Nov 30 10:07:37 CST 2018
;; MSG SIZE  rcvd: 106
红色部分为有CNAME记录和A记录。
nslookup
nslookup适用于Windows,Linux,macOS等操作系统。
nslookup www.jd.com
Server:            192.168.1.1
Address:   192.168.1.1#53
Non-authoritative answer:
www.jd.com      canonical name = www.jd.com.gslb.qianxun.com.
www.jd.com.gslb.qianxun.com    canonical name = www.jdcdn.com.
Name:      www.jdcdn.com
Address: 61.174.55.1

 

DNS抓包分析

说了这么多,有些同学可能还是觉得只有概念,没法完全理解。所以,我们还是来点实战更为实际,这也是我更进一步了解DNS的工作方式,因为在我看来想了解根本,最有效的方法是抓包,然后深入查探DNS的packet。
本文都会使用Wireshark,相信大家都用过这个工具吧。如果没用过,可以下载一个,入门很简单的,别担心。
A记录
下面是抓包图,过滤条件是dns,即protocol为DNS。
请参看第89和90包,这是查询www.jd.com 的request和response。
第89包细节图如下:
我们可以看到上图,Name是www.jd.com, Type是A记录。
另外,我们可以看到其他信息,DNS是通过UDP传送。其实,有时候也是通过TCP来传送。那么什么时候用TCP,什么时候用UDP?很简单,当response的packet大于512字节时,就用TCP,反之,则用UDP。再回头看着89包,长度为70,所以用UDP了。那多问一个问题,什么情况下DNS查询包超过512?CNAME就有可能。可以参考下面的CNAME抓包。
端口是多少呢?53,是的,DNS用的是53端口,非常重要,一般防火墙要打开,否则DNS解析不了,也意味着无法访问域名的website。
那么返回什么呢?继续看第90包。
我们可以看到www.jd.com 的DNS A记录,IP地址是61.174.55.1。
CNAME
下图是查询www.taobao.com 的抓包。
同时我们也可以看到www.taobao.com.danuoyi.tbcache.com 有多条A记录,这里就是传说的DNS 负载均衡。

DNS标准和协议

DNS是有标准和协议的,就跟HTTP类似的。DNS标准和协议在IETF里。大家可以参考https://en.wikipedia.org/wiki/Domain_Name_System 的 RFC documents部分。
我认为学习协议,框架,或技术,最佳的方法就是阅读官方资料。例如,这里学习DNS可以直接看RFC文档,学习Angular,可以访问其官网

DNS 10问

如果面试,下面10问基本可以覆盖全了,答案在上面已经说过了:
  1. 为什么要用域名?
  2. DNS解析的基本流程?
  3. DNS的根域名是什么,有几个Server?TLD DNS是什么?
  4. DNS的优化策略是什么?在各个环节怎么做的?Chrome和各个操作系统怎么做的?
  5. DNS负载均衡是什么,为什么要用?
  6. DNS的记录类型有哪些?CNAME一般用在哪些场合?举例子说明一下。
  7. DNS的常用工具和命令有哪些?
  8. DNS查询是用TCP还是UDP?一般用哪个端口?
  9. DNS抓包抓过吗?Wireshark有用过吗?
  10. 请说明一下www.google.com 和google.com的区别,如何设置它们的DNS?
本章介绍完DNS,下一章节介绍TCP/IP,三次握手,四次挥手,以及SSL/TLS,内容绝对不能错过。

No Comments

No comments yet.

RSS feed for comments on this post.

Sorry, the comment form is closed at this time.

Powered by WordPress