事无巨细 | 访问一个网站的过程

当我们访问某个网站的时候,究竟发生了什么事情呢?

建立连接:传输层及其之下

TCP 握手:在此之前

如果我们使用 http,那么目的端口就是 80。如果是 https,那么就是 443。TCP 首部的信息已经完全了,但是问题在于,我们应该如何把我们的握手信息发给服务器呢?

获取网站的 IP 地址

由于浏览器中我们使用了网址进行访问,因此我们需要通过 DNS 来将网址转换成 IP 地址。

缓存

一般来说,浏览器中存在着缓存,因此多次浏览一个网站时不会每次都需要访问 DNS 服务器。

除了浏览器,系统中也存在着缓存。特别是 hosts 文件中永久指定了网址与 IP 的转换。

DNS 服务器自己也会缓存之前查询过的网址。

查询

如果 DNS 没有缓存,则需要进行查询。DNS 服务器是多级的,首先存在一个根服务器,通过访问根服务器能知道 .com 域名的服务器,然后从 .com 服务器查询得到 baidu.com 的服务器,再然后得到 www.baidu.com 或者 tieba.baidu.com 的服务器。

路由器转发

有了 IP 地址之后,就可以制作 IP 分组,交由路由器进行转发。

路由器转发的时候需要查询他的路由表,上面记载着一个 IP 地址取最长前缀匹配后,应该转发到何处。

链路层转发

在链路层上,根据 ARP 表可以将 IP 转换为目标 MAC 地址,然后再根据 MAC 表决定在哪个端口转发。

TCP 三次握手

现在我们已经知道如何向服务器发送 TCP 包了,那么就需要通过三次握手建立 TCP 连接了。

第一次,客户端向服务端发送 SYN 包,发送自己的序号。

第二次,服务端向客户端发送 SYN + ACK 包,发送自己的序号并确认客户端的序号。

第三次,客户端向服务端发送 ACK 包,确认服务端发送过来的序号。

客户端的状态变化:CLOSED -> SYN_SENT -> ESTABLISHED

服务端的状态变化:LISTEN -> SYS_RECV -> ESTABLISHED

为什么是三次

为什么是三次握手呢?因为你不能确定通信链路是否可以双向沟通。

而接收 ACK 就代表对面可以接收到我们发送的消息。因此双方都需要接收 ACK,才代表连接已建立。

如果没有第三次 ACK,服务端就不知道自己是否能将信息发送到对方。

就比如面试的时候,你说,面试官好,能听到吗?面试官说:我听到了,好,我们开始面试吧。

但是这时候你却听不到面试官说啥,这时候开始面试,合理吗?面试官当然得说,我听到了,你听到吗?

这时候你才说,我听到了,面试正式开始。

如果某次握手失败了怎么办

如果第一次握手失败,当然是超时重来。

如果第二次握手失败,服务器没有收到用户的ACK,就会在某个时间后关闭连接。

如果第三次握手失败,服务器会等待一段时间,再重传 SYN-ACK。如果期间收到了客户端的 ACK,连接恢复。如果服务器重传多次后关闭了连接,那么面对客户端的 ACK,就会回复 RST,要求重新开始握手。

特别的,如果服务器接收到了两个 SYN,那么两个 SYN 都会被处理,而客户端通过收到两个 SYN-ACK 知道出现了重复,就会发送 RST。

TLS 握手

当我们完成了 TCP 握手之后,还需要做的事情就是确保整个流程是被加密的,否则就有可能导致泄密。

一般的 TLS 握手流程是这样的:

  1. 客户端向服务端发出握手请求(hello)
  2. 服务端向客户端发送自己的 CA 证书。注意,CA 是浏览器与操作系统集成好的,所以不存在伪造 CA 的问题。
  3. 客户端验证证书可信,就利用服务端的公钥,加密一个自己的私钥,并发送给服务端。
  4. 服务端接收到这个加密后的私钥,并用自己的密钥解开这个私钥,然后双方就通过这个私钥进行信息传递。

具体的 TLS 协议还涉及到不重数的概念,是为了防止握手篡改(例如删除握手过程中,客户端提供的可选择的加密方法)和重放攻击(复制客户端的报文,然后和服务端再次执行相同操作)。这里就不展开了。

获取数据:HTTP 协议

建立连接之后,就可以向服务端发送 HTTP 请求报文。

HTTP 请求报文包括类型 GET POST PUT DELETE 等等,他们分别对应查、增、改、删。

请求报文中除了报文类型,还包括了请求的资源、HTTP 协议版本(通常1.1),编码类型,连接长短,cookie等。

服务器在接收到 HTTP 请求之后,就会进行相应的处理。处理的部分可以扩展到负载均衡等话题,这里就暂且先放下,假定现在服务器已经构建好的响应报文。

响应报文里会包含状态码、传回的数据,还包括各种控制信息,例如缓存机制(缓存还是不要缓存),cookie 设置等待。

状态码

1 继续

100 是继续,代表服务器可以接收客户端的进一步请求。通常用于大文件传输的客户端请求上传阶段。 101 是切换协议,服务器要求客户端用另一种协议继续进行。比如服务器需要使用 websocket 协议保持与客户端的实时沟通,就需要升级到wss协议。

2 完成

200 表示请求成功,打开某个网页的时候就是 200. 204 没有返回内容,通常用于用户提交信息,这时候不需要用户做跳转。

3 重定向

重定向的相关状态码以 3 开头。

以百度为例,如果你访问了 http://www.baidu.com,或者https://baidu.com,那么服务器会发送 302/307 重定向让你选择使用 https 的网址 https://www.baidu.com

4 客户端请求的错

400 请求报文有问题 401 没有身份认证 403 禁止访问,你不配 404 请求页面不存在

5 服务器的错

500 服务器的内部错误 502 无效网关,简单的说就是访问服务器时经过了中间节点,但是中间节点并未收到目的服务器的信息,于是产生 502 错误。

你是谁

HTTP 是无状态的协议。早期的网络里面,因为访问的都是静态页面,所以HTTP 无状态可以让服务器不必维护每个用户的连接状态,使得服务器的开销会小一点。

Cookie

但是随着交互式 web 的兴起,就必然需要让服务器区分发起请求的分别是谁。

服务器会把 cookie 设置在响应报文里,而 cookie 是保存在客户端的,在发起 HTTP 请求的时候,放置在 HTTP 报文中一同传输过去。

Session

Session 是保留在服务器里的,当用户成功登录网站,网站会给用户发回一个身份 cookie。

之后你的一切与服务器的互动就借助这个 cookie 维系,你的身份、使用语言、访问记录等原本可能会记录在 cookie 上的东西就全部交由服务器来管理。

也正是如此,Session 是会增加服务器的开销的。

Token

token 是一种验证身份的方式,服务器为用户发放 token,用户在请求的时候加上 token 来确认已获得授权。

由于 token 不存放在 cookie 里,因此不容易被攻击者获取,以此确保用户信息有效,尤其是在防止跨站请求伪造攻击(CSRF)比较实用。

再次获取数据

一个网页通常不会一次传输完所有的数据给浏览器渲染,因为很多类似图片或者实时数据这样的东西,如果全部交由一个服务器来传输,会产生很高的负载。

所以,在第一次传入的网页中,通常会包含一些 javascript 代码和其它网址。比如,图片的地址被写为某个 CDN 的地址,这样浏览器会再次去请求这些服务器没有提供的内容。

断开连接

TLS 挥手?

既然有 TLS 握手,有没有 TLS 挥手呢?有的,但是并不像 TCP 那样复杂,只需要发送结束会话的消息即可。

但是存在一个问题,就是我们能不能通过 TCP FIN 直接关闭 TLS 呢?答案是不能,因为攻击者可以提前发送 FIN 来截断双方的通信。

TCP 四次挥手

  1. 客户端向服务端发出 FIN。
  2. 服务端返回 ACK,但是并不立刻关闭连接,因为此时还有其它数据需要传输。
  3. 服务端在数据传输完成后,发出 FIN。
  4. 客户端接收到 FIN,发送 ACK,等待 2WSL,连接关闭。
  5. 服务端接收到 ACK 连接关闭。

 客户端状态:ESTABLISHED -> FIN_WAIT_1 -> FIN_WAIT_2 -> TIME_WAIT -> CLOSED

服务端状态:ESTABLISHED -> CLOSE_WAIT -> LAST_ACK -> CLOSED

为什么是四次?

握手需要三次是因为 SYN 和 ACK 可以合并到同一个包内发送。服务器并不需要在接收到 SYN 后再进行准备工作,这些工作已经在 LISTEN 的时候就完成了。

而挥手的时候,服务器确实可能还需要有事务要处理并传输给用户。因此并不能像握手那样合并为 FIN + ACK。

为什么是 2MSL 而不是立刻关闭

服务端需要告诉客户端可以关闭,防止客户端一直挂在 FIN_WAIT_2 阶段太久。而客户端的 ACK 能让服务端安心地关闭。否则,服务端会在默认的 timeout 的时候再次发送 FIN。

而客户端如何确保自己的 ACK 是传达到了服务端的呢?MSL 是一个包在网络中存在的最大时间,2MSL 就是一个包一来一回的最大时间。

因为服务端不会等待超过一个 2MSL 再重发 FIN,相应的客户端也可以假定 2MSL 之后不会必然不会再有 FIN 发来,于是可以关闭连接。

否则客户端需要重新应答服务端的 FIN。

原文地址:https://www.cnblogs.com/KakagouLT/p/13627640.html