HTTP(S)

原文連接css

最近又看了一遍 [HTTP權威指南],每次想寫一份總結的時候都會拖延症爆發,今天決定總結下咱們天天都在接觸的HTTP。html

OSI (Open System Interconnect)


先列一張可以體現不一樣協議在OSI七層模型中的表格webpack

層級 層級名稱 應用
7 應用層 例如HTTP、SMTP、SNMP、FTP、Telnet、SIP、SSH、NFS、RTSP、XMPP、Whois、ENRP、TLS
6 表示層 例如XDR、ASN.一、SMB、AFP、NCP
5 會話層 例如ASAP、ISO 8327 / CCITT X.22五、RPC、NetBIOS、ASP、IGMP、Winsock、BSD sockets
4 傳輸層 例如TCP、UDP、RTP、SCTP、SPX、ATP、IL
3 網絡層 例如IP、ICMP、IPX、BGP、OSPF、RIP、IGRP、EIGRP、ARP、RARP、X.25
2 數據鏈路層 例如以太網、令牌環、HDLC、幀中繼、ISDN、ATM、IEEE 802.十一、FDDI、PPP
1 物理層 例如線路、無線電、光纖

先從 TCP/IP 提及


IPS(Internet Protocol Suite)又叫作互聯網協議套件、是一套網絡傳輸協議家族,也就是咱們熟悉的TCP/IP協議族,(又由於TCP、IP爲不一樣層級的協議,當多個層級的協議共同工做時相似計算機科學中的堆棧、因此又叫作TCP/IP協議棧)nginx

TCP/IP 中包含一系列用於處理數據通訊的協議web

  • TCP (傳輸控制協議) - 應用程序之間通訊
  • UDP (用戶數據報協議) - 應用程序之間的簡單通訊
  • IP (網際協議) - 計算機之間的通訊
  • ICMP (因特網消息控制協議) - 針對錯誤和狀態
  • DHCP (動態主機配置協議) - 針對動態尋址

這裏要說一下TCP、HTTP、socket的關係json

實際上socket只是一個Api,方便咱們去調用底層封裝好的TCP/IP協議,可是socket與TCP/IP並無必然的關係,socket接口在設計的時候就但願也可以適應其餘協議,而HTTP是基於TCP之上的應用層協議,有一個頗有趣的比喻就是若是TCP是高速路,那麼HTTP就是高速路上的貨車。瀏覽器

好,下面重頭戲來了,TCP三次握手(創建鏈接)四次揮手(斷開鏈接)安全

客戶端 - Client、 服務端 - Server
兩個整型變量 J、Kbash

三次握手(創建鏈接)網絡

  1. Server socket綁定端口,等待消息
  2. (first) Client 打開socket(connect) 、發送 SYN J
  3. (second) Server 收到消息,向客戶端發送 SYN K、 ack J+1
  4. (third) Client 收到應答、發送 ack K+1
  5. Server 開始讀取Client發送的信息

至此、鏈接創建完成、這裏有一個問題,爲何創建鏈接不是2次握手、爲何不是4次握手?

剛好是三次的緣由是三次剛恰好,4次浪費網絡資源不必,而若是改成2次,那麼client在向server發送第一次握手的時候由於某些緣由捨棄了此次鏈接(或是因其餘緣由被迫強制關閉)而並無通知Server,那麼若是隻須要2次握手無疑會形成server會一直處於盲等狀態。

四次揮手(鏈接拆除)

三個整型變量 x、y、z

與創建鏈接不一樣的是、斷開鏈接能夠由任意一方發起

  1. 主動方發送fin=一、ack=z、seq=x
  2. 被動方發送ack=x+一、seq=z
  3. 被動方發送fin=一、ack=x、seq=y
  4. 主動方發送ack=y、seq=x

那麼,爲什麼揮手要揮4次呢,緣由在於拆除鏈接時收到fin報文,僅僅表明對方再也不發送數據,而接收到fin報文的一方可能還有數據沒發送完,因此被動方的fin和ack要分開發送。

HTTP 鏈接


那麼什麼是HTTP鏈接呢,所謂HTTP,就是基於TCP/IP協議的上層應用層協議, 因此咱們能夠理解HTTP鏈接就是以TCP/IP爲傳輸層協議,以HTTP協議做爲應用層協議的鏈接

就好比咱們在瀏覽器輸入 k.felixplus.top/ 、會先經過 TCP握手創建鏈接,這個時候傳輸的數據會經過HTTP協議進行解析,最後到達咱們的瀏覽器進行繪製展現

HTTPS


HTTPS = HTTP + (TLS/SSL)

其中,TLS/SSL 爲 HTTP 提供了安全加密傳輸的功效

相比之下,HTTPS比HTTP多提供瞭如下幾點:

  1. 數據完整性:內容傳輸通過完整性校驗
  2. 數據隱私性:內容通過對稱加密,每一個鏈接生成一個惟一的加密密鑰
  3. 身份認證:第三方沒法僞造服務端(客戶端)身份

那麼,HTTPS的一次傳輸過程是怎樣的呢,先說結論:

  1. Server 被動監聽
  2. Client 發送鏈接請求
  3. Server 返回公鑰
  4. Client 生成隨機值(對稱加密的私鑰)經過Server返回的公鑰加密
  5. Client 將密文發送回Server 並等待確認
  6. 雙方開始使用客戶端生成的對稱加密密鑰進行通信

在繼續以前咱們須要先來回顧一下什麼是對稱加密,什麼是非對稱加密:

對稱方式 加密方法 風險 加解密速度
非對稱 數據的加解密由一個密鑰解決 風險較高 加解密速度快
對稱 數據使用公鑰加密、私鑰解密 風險較小 加解密速度慢

從這裏不難看出,HTTPS同時使用到對稱加密和非對稱加密的緣由是若是數據傳輸量很大,一直使用非對稱加密會消耗更多資源,產生沒必要要的浪費,而在傳輸數據以前先經過非對稱加密發送客戶端生成的私鑰在安全性能上足以勝任,因此這裏並無徹底使用非對稱加密。

下面是使用 curl 命令debug HTTPS 請求的輸出

curl -v https://aground.felixplus.top
複製代碼
* Rebuilt URL to: https://aground.felixplus.top/
*   Trying 47.75.98.166...
* TCP_NODELAY set
* Connected to aground.felixplus.top (47.75.98.166) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/cert.pem
  CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-CHACHA20-POLY1305
* ALPN, server accepted to use h2
* Server certificate:
*  subject: CN=aground.felixplus.top
*  start date: Feb 15 10:01:34 2019 GMT
*  expire date: May 16 10:01:34 2019 GMT
*  subjectAltName: host "aground.felixplus.top" matched cert's "aground.felixplus.top" * issuer: C=US; O=Let's Encrypt; CN=Let's Encrypt Authority X3 * SSL certificate verify ok. * Using HTTP2, server supports multi-use * Connection state changed (HTTP/2 confirmed) * Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0 * Using Stream ID: 1 (easy handle 0x7feef980b800) > GET / HTTP/2 > Host: aground.felixplus.top > User-Agent: curl/7.54.0 > Accept: */* > * Connection state changed (MAX_CONCURRENT_STREAMS updated)! < HTTP/2 200 < server: nginx/1.14.0 (Ubuntu) < date: Mon, 25 Mar 2019 07:13:40 GMT < content-type: text/html < content-length: 2121 < last-modified: Tue, 19 Mar 2019 09:57:48 GMT < vary: Accept-Encoding < etag: "5c90bd1c-849" < accept-ranges: bytes < * Connection #0 to host aground.felixplus.top left intact <!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="shortcut icon" href="/panda.png"/><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"/><meta name="theme-color" content="#000000"/><link rel="manifest" href="/manifest.json"/><title>AGround</title><link href="/static/css/2.4126af51.chunk.css" rel="stylesheet"><link href="/static/css/main.85ae910b.chunk.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(l){function e(e){for(var r,t,n=e[0],o=e[1],u=e[2],f=0,i=[];f<n.length;f++)t=n[f],p[t]&&i.push(p[t][0]),p[t]=0;for(r in o)Object.prototype.hasOwnProperty.call(o,r)&&(l[r]=o[r]);for(s&&s(e);i.length;)i.shift()();return c.push.apply(c,u||[]),a()}function a(){for(var e,r=0;r<c.length;r++){for(var t=c[r],n=!0,o=1;o<t.length;o++){var u=t[o];0!==p[u]&&(n=!1)}n&&(c.splice(r--,1),e=f(f.s=t[0]))}return e}var t={},p={1:0},c=[];function f(e){if(t[e])return t[e].exports;var r=t[e]={i:e,l:!1,exports:{}};return l[e].call(r.exports,r,r.exports,f),r.l=!0,r.exports}f.m=l,f.c=t,f.d=function(e,r,t){f.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},f.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(r,e){if(1&e&&(r=f(r)),8&e)return r;if(4&e&&"object"==typeof r&&r&&r.__esModule)return r;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:r}),2&e&&"string"!=typeof r)for(var n in r)f.d(t,n,function(e){return r[e]}.bind(null,n));return t},f.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return f.d(r,"a",r),r},f.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},f.p="/";var r=window.webpackJsonp=window.webpackJsonp||[],n=r.push.bind(r);r.push=e,r=r.slice();for(var o=0;o<r.length;o++)e(r[o]);var s=n;a()}([])</script><script src="/static/js/2.5167ae78.chunk.js"></script><script src="/static/js/main.05967284.chunk.js"></script></body></html>% 複製代碼
相關文章
相關標籤/搜索