键入网址到网页显示,期间发生了什么?

  • 浏览器解析请求的 URL
    http: + // + domain.com + / + index.html
    协议  + // + 服务器地址  + / + 文件路径
  • 生成 HTTP 请求报文
    GET / HTTP/1.1
    Accept: */*
  • DNS 查询
    浏览器先查有没这个域名的缓存,
    如果没有就去问操作系统层面有没这个域名的缓存,
    如果没有就去操作系统的 hosts 文件查询有没配置.
    如果没有就去本地 DNS 服务器 (我电脑默认自动获取)
    HTTP[快问快答系列]
    如果本地 DNS 服务器也没有域名的缓存就会去问根服务器拿 IP
    根服务器不负责解析域名,只返回顶级域名的服务器地址,比如.com 域名的服务器地址
    本地 DNS 服务器去问.com 域名服务器地址拿 IP
    .com 域名服务器返回负责这个二级域名的 DNS 服务器地址
    本地 DNS 服务器去问二级域名 DNS 服务器拿 IP
    成功拿到 IP 并在本地 DNS 服务器,浏览器和操作系统都缓存起来
  • 协议栈
    浏览器通过 DNS 查询到的 IP 和解析 URL 查询到的端口用操作系统提供的 socket 库连接服务器,通过三次握手建立 tcp 连接,客户端和服务器双方生成通信 socket 文件

    $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
    socket_connect($socket, 'ip', '端口');
  • TCP 层 可靠传输
    建立好 tcp 连接之后,HTTP 报文加上 TCP 报文头部,如果报文长度超过了 MSS 长度就会拆解分包发送
  • IP 层 远程定位
    TCP 报文头部加上 IP 报文头部
  • MAC 层 两点传输
    IP 报文头部加上 MAC 报文头部
  • 网卡把报文转换成电信号,发送到交换机,再发送到路由器,路由器转发上层路由器一直到达服务器
  • 服务器按同样的步骤组装返回报文,原路返回逐层去掉头部最终返回到浏览器的 http 报文长这个样子
    HTTP/1.1 200 OK
    Date: Mon, 23 May 2005 22:38:34 GMT
    Content-Type: text/html; charset=UTF-8
    Content-Length: 155
    Connection: close
    <html>
    <head>
      <title>An Example Page</title>
    </head>
    <body>
      <p>Hello World, this is a very simple HTML document.</p>
    </body>
    </html>

GET 与 POST 的区别

  • GET
    浏览器对 GET 请求的 URL 会有长度限制,对 GET 请求可以缓存,也可以保存书签,历史记录,只支持 url 编码
  • POST
    POST 请求的数据在浏览器 URL 上不可见,支持 url 编码,multipart/form-data 等编码,
  • 总结
    以上是 GET 和 POST 在浏览器上的区别,在 HTTP 协议上,并没有本质的区别,一般 GET 用来获取数据,POST 用来提交数据,GET 也可以像 POST 一样传 body, 只不过 RFC 规范不建议你这么做

HTTP 缓存有哪些实现方式?

  • 强制缓存
    Cache-Control 是 HTTP/1.1 的标准,而 Expires 则是 HTTP/1.0 的标准,Cache-Control 的优先级高于 Expires。通常使用 Cache-Control, 比较灵活。

    Cache-Control:
    public:响应可以被客户端和代理服务器缓存。
    private:响应只能被客户端缓存,不能被代理服务器缓存。
    no-cache:客户端和代理服务器都不能缓存响应,需要重新获取。
    no-store:响应不能被缓存或存储。
    max-age:响应的最大有效时间,单位为秒。
    s-maxage:覆盖 max-age,仅适用于共享缓存,例如代理服务器。
    Expires:过期时间:响应的绝对过期时间,使用 GMT 格式表示。
  • 协商缓存
    协商缓存需要配合强制缓存中 Cache-Control 来使用,只有在未能命中强制缓存的时候,才能发起带有协商缓存字段的请求。服务器根据一下两种方式判断文件没有修改则返回 304 Not Modified,不会返回资源

      1.请求头If-Modified-Since和响应头Last-Modified
      2.请求头If-None-Match与响应头部ETag 

HTTP 常见的状态码有哪些?

  • 1xx 类状态码属于提示信息,是协议处理中的一种中间状态,实际用到的比较少。
  • 200 : 表示一切正常。
  • 204 : 与 200 OK 基本相同,但响应头没有 body 数据
  • 206 : 应用于 HTTP 分块下载或断点续传
  • 301 : 永久重定向
  • 302 : 临时重定向,说明请求的资源还在
  • 304 : 表示资源未修改,重定向已存在的缓冲文件
  • 400 : 客户端请求的报文有错误
  • 403 : 服务器禁止访问这个资源
  • 404 : 资源在服务器上不存在
  • 500 : 服务器发生了错误
  • 501 : 客户端请求的功能服务端还没法开发好
  • 502 : phpfpm 发生错误时,nginx 返回的状态码
  • 503 : 服务器当前很忙,暂时无法响应客户端

HTTP/1.1 相比 HTTP/1.0 提高了什么性能?

  • 使用长连接的方式改善了 HTTP/1.0 短连接造成的性能开销。

HTTP/2 做了什么优化?#

HTTP/2 协议是基于 HTTPS 的,所以 HTTP/2 的安全性也是有保障的。

  • 头部压缩
    HTTP/2 会压缩头(Header)如果你同时发出多个请求,他们的头是一样的或是相似的,那么,协议会帮你消除重复的部分
    这就是所谓的 HPACK 算法:在客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,以后就不发送同样字段了,只发送索引号,这样就提高速度了。
  • 二进制格式
    全面采用了二进制格式,头信息和数据体都是二进制,并且统称为帧,收到报文后,无需再将明文的报文转成二进制,而是直接解析二进制报文,这增加了数据传输的效率
  • 并发传输
    引出了 Stream 概念,多个 Stream 复用在一条 TCP 连接。
  • 服务器推送

主动向客户端发送消息。

HTTP/2 有什么缺陷?#

HTTP/2 通过 Stream 的并发能力,解决了 HTTP/1 队头阻塞的问题,看似很完美了,但是 HTTP/2 还是存在 “队头阻塞” 的问题,只不过问题不是在 HTTP 这一层面,而是在 TCP 这一层。
HTTP/2 是基于 TCP 协议来传输数据的,TCP 是字节流协议,TCP 层必须保证收到的字节数据是完整且连续的,这样内核才会将缓冲区里的数据返回给 HTTP 应用,那么当「前 1 个字节数据」没有到达时,后收到的字节数据只能存放在内核缓冲区里,只有等到这 1 个字节数据到达时,HTTP/2 应用层才能从内核中拿到数据,这就是 HTTP/2 队头阻塞问题。
所以,一旦发生了丢包现象,就会触发 TCP 的重传机制,这样在一个 TCP 连接中的所有的 HTTP 请求都必须等待这个丢了的包被重传回来

HTTP/3 做了哪些优化?

  • 无队头阻塞
  • 使用 QUIC 协议 底层是 UDP
  • 连接迁移 对移动设备非常友好

HTTPS 是如何建立连接的?其间交互了什么?#

首先三次握手建立 TCP 连接,成功之后马上建立 SSL/TCS 连接

SSL/TLS 协议基本流程:

  • 客户端向服务器索要并验证服务器的公钥。
  • 双方协商生产「会话秘钥」。
  • 双方采用「会话秘钥」进行加密通信。

SSL/TLS 协议详细流程:

  • ClientHello
    首先,由客户端向服务器发起 ClientHello 请求。
    在这一步,客户端主要向服务器发送以下信息:
    (1)客户端支持的 TLS 协议版本,如 TLS 1.2 版本。
    (2)客户端生产的随机数(Client Random),后面用于生成「会话秘钥」条件之一。
    (3)客户端支持的密码套件列表,如 RSA 加密算法。
  • SeverHello
    服务器收到客户端请求后,向客户端发出响应,也就是 SeverHello。服务器回应的内容有如下内容:
    (1)确认 TLS 协议版本,如果浏览器不支持,则关闭加密通信。
    (2)服务器生产的随机数(Server Random),也是后面用于生产「会话秘钥」条件之一。
    (3)确认的密码套件列表,如 RSA 加密算法。
    (4)服务器的数字证书。
  • 客户端回应
    客户端收到服务器的回应之后,首先通过浏览器或者操作系统中的 CA 公钥,确认服务器的数字证书的真实性。
    如果证书没有问题,客户端会从数字证书中取出服务器的公钥,然后使用它加密报文,向服务器发送如下信息:
    (1)一个随机数(pre-master key)。该随机数会被服务器公钥加密。
    (2)加密通信算法改变通知,表示随后的信息都将用「会话秘钥」加密通信。
    (3)客户端握手结束通知,表示客户端的握手阶段已经结束。
    服务器和客户端有了这三个随机数(Client Random、Server Random、pre-master key),接着就用双方协商的加密算法,各自生成本次通信的「会话秘钥」
  • 服务器的最后回应
    服务器收到客户端的第三个随机数(pre-master key)之后,通过协商的加密算法,计算出本次通信的「会话秘钥」。
    然后,向客户端发送最后的信息:
    (1)加密通信算法改变通知,表示随后的信息都将用「会话秘钥」加密通信。
    (2)服务器握手结束通知,表示服务器的握手阶段已经结束。
    至此,整个 TLS 的握手阶段全部结束。接下来,客户端与服务器进入加密通信,就完全是使用普通的 HTTP 协议,只不过用「会话秘钥」进行对称加密内容。

CA 证书签发过程#

  • 首先 CA 会把持有者的公钥、用途、颁发者、有效时间等信息打成一个包,然后对这些信息进行 Hash 计算,得到一个 Hash 值;
  • 然后 CA 会使用自己的私钥将该 Hash 值加密,生成 Certificate Signature,也就是 CA 对证书做了签名;
  • 最后将 Certificate Signature 添加在文件证书上,形成数字证书;
    吐槽一下动动手的事情竟然要卖几千块一年

客户端校验 CA 证书的流程是怎样的?

  • 首先客户端会使用同样的 Hash 算法获取该证书的 Hash 值 H1;
  • 通常浏览器和操作系统中集成了 CA 的公钥信息,浏览器收到证书后可以使用 CA 的公钥解密 Certificate Signature 内容,得到一个 Hash 值 H2 ;
  • 最后比较 H1 和 H2,如果值相同,则为可信赖的证书,否则则认为证书不可信。

HTTPS 一定安全可靠吗?#

不一定,如果客户端通过浏览器向服务端发起 HTTPS 请求时,被「假基站」转发到了一个中间人服务器,形成中间商赚差价,简称中间人攻击

  • 客户端向中间人服务器发起 https 请求
  • 中间人服务器返回自己的 CA 证书
  • 成功建立连接
  • 中间人成功解密获取客户端发送的加密报文
  • 中间人服务器再跟目标服务器建立 https 连接
  • 转发客户端的数据给目标服务器
  • 转发目标服务器的报文给客户端

这种攻击的前提是你信任了中间人服务器的 CA 证书,或者被木马植入了中间人的 CA 证书,https 协议本身是没漏洞的,中间人攻击本质是利用了客户端的漏洞,不关 https 的事情

为什么抓包工具能截取 HTTPS 数据?#

工作原理跟中间人攻击一致

如何避免被中间人抓取数据?#

通过 HTTPS 双向认证来避免这种问题。这样客户端也要有自己的 CA 证书,双方交换证书确认身份再建立连接

本作品采用《CC 协议》,转载必须注明作者和本文链接



遇强则强,太强另说
HTTP[快问快答系列]
标签: