TCP三次握手四次揮手
握手
一.伺服器監聽:
int main(int argc, char const *argv[])
{
int fd = socket(AF_INET, SOCK_STREAM, 0);
bind(fd, ...);
listen(fd, 128);
accept(fd, ...);
...
}
在伺服器 listen 的時候,主要是進行了全/半連線佇列的長度限制計算,以及相關的記憶體申請和初始化
二.客戶端發起SYN包:
int main()
{
fd = socket(AF_INET, SOCK_STREAM, 0);
connect(fd, ...);
...
}
客戶端在 connect 的時候,把本地 socket 狀態設定成了 TCP_SYN_SENT,選了一個可用的埠,接著發出 SYN 握手請求並啟動失敗重傳定時器
3.服務端響應SYN
伺服器響應 ack 是主要工作是判斷下接收佇列是否滿了,滿的話可能會丟棄該請求,否則發出 synack。申請 request_sock 新增到半連線佇列中,同時啟動失敗重傳定時器
4.客戶端相應SYNACK
客戶端響應來自服務端的synack時,清除了connect時設定的重傳定時器,把當前的socket狀態設定為ESTABLISHED,開啟保活計時器後發出第三次握手的ack確認
5.伺服器響應ACK
伺服器把當前半連線佇列元素刪除,建立新的sock後加入到全連線佇列中,socket狀態設定為ESTABLISHED
6.伺服器accept
accept的重點工作就是從全連線的佇列中取出一個返回給使用者程式
揮手
1.客戶端傳送fin服務端,客戶端狀態:fin_wait_1,服務端狀態:close_wait
2.服務端傳送ack客戶端,客戶端狀態:fin_wait_2,服務端狀態:close_wait
3.服務端傳送fin客戶端,客戶端狀態:time_wait,服務端:last_ack
4.客戶端傳送ack服務端,客戶端狀態:time_wait,服務端close
5.60秒後(可配置),客戶端狀態:close
TCP粘包/拆包
TCP建立連線之後,傳送和接受資料都有一個可配置的緩衝區
傳送端:要傳送的資料小於TCP緩衝區的大小時會等湊多幾個資料包夠緩衝區大小一次性傳送出去,這裡會發生粘包
接受端:沒有及時處理接受緩衝區的資料時,這裡會發生粘包
傳送端:要傳送的資料大於TCP緩衝區的大小時,將會發生拆包
傳送端:待傳送資料大於最大報文長度(MSS),將會發生拆包
解決方案:
將資料分為兩部分,一部分是頭部,一部分是內容體;其中頭部結構大小固定,且有一個欄位宣告內容體的大小。
HTTP1.0/1.1/2.0/HTTPS
HTTP1.0 短連線,瀏覽器每次請求都要和伺服器建立一個TCP連結,請求完成立即斷開TCP連結,每個圖片,js,css檔案都要建立一次TCP連結,影響效能和頻寬
HTTP1.1 預設支援長連線,一個網頁內所有html,js,css,image...請求共享一個TCP連線,還允許不用等上一次請求返回就發出下一次請求
connection 預設 keep-alive,如果不希望使用長連線則HEADER 設定 connection:close,無論是request header還是 response header中包含了connection:close,tcp連線都會馬上中斷
提供了了身份認證,狀態管理,cache快取機制的請求頭和響應頭
支援斷點續傳
HTTP2.0
多路複用
二進位制分幀
首部壓縮
服務端推送
HTTPS
頒發證照
找可靠的CA機構購買證照,放到自己伺服器站點上,或者用let's encrypt自己操作生成免費證照,不過一般瀏覽器不承認可靠性
證照原理
自己生成一對公私鑰,把公鑰上傳到CA機構,CA機構用自己的私鑰對你的公鑰進行數字簽名並頒發證照,可靠的CA機構的公鑰則維護在瀏覽器或者作業系統,使用者客戶端驗證證照的真偽
HTTPS握手過程
1.先建立TCP連線,客戶端傳送SYN包到伺服器443埠(預設)
2.伺服器傳送SYN+ACK到客戶端
3.客戶端傳送ACK到伺服器 完成TCP三次握手
4.客戶端傳送Hello訊息,包含了隨機數1和客戶端能支援的加密演算法集合,SSL版本等資訊
5.服務端傳送Hello訊息,包含了隨機數2和確定了加密演算法,自此客戶端和服務端都有兩個隨機數1,2
6.伺服器下發證照
7.客戶端從瀏覽器或作業系統獲取CA機構的公鑰對證照驗證真偽,驗證透過後,解密得到伺服器的公鑰,再生成一個隨機數3,使用伺服器的公鑰對隨機數3進行非對稱加密生成PreMaster Key傳送給伺服器
8.伺服器用自己的私鑰解密PreMaster Key得到隨機數3,至此客戶端和伺服器都有三個隨機數1,2,3
9.兩邊根據伺服器確認的演算法,對這三個隨機數連線起來的字串進行加密生成一份秘鑰,用於報文的對稱加密
10.客戶端用客戶端這邊生成的秘鑰加密報文傳送Client Finish訊息給伺服器,伺服器用伺服器這邊生成的秘鑰解密報文,能解出來說明秘鑰協商一致
11.伺服器用伺服器這邊生成的秘鑰加密報文傳送Server Finish訊息給客戶端,客戶端用客戶端這邊生成的秘鑰解密報文,能解出來說明秘鑰協商一致
12.到這裡,雙方已安全協商出了相同的對稱加密秘鑰,接下來所有報文都會有這個秘鑰進行對稱加密
13.想知道這個秘鑰在客戶端和伺服器分別儲存在哪裡,有知道的大神請留言,在fd檔案裡面?系統核心維護?
網路攻擊
中間人攻擊
建立HTTPS連線的時候,在伺服器把證照發給客戶端時,被中間人攔截下來,偽造了一箇中間人的證照發給客戶端,客戶端用偽造的公鑰加密隨機KEY發給中間人,中間人用偽造的私鑰解密得到隨機KEY,再用攔截下來的真正的公鑰加密隨機KEY發給伺服器,實現中間人賺差價,悶聲發大財
所以客戶端要校驗證照的可靠性,所以才需要可靠的證照頒發機構,可靠的證照頒發機構的根證照都是作業系統維護的,瀏覽器拿到伺服器的證照去找作業系統判斷證照的真假
CSRF (Cross-site request forgery) 跨站請求偽造
攻擊原理:
使用者登入A網站後,瀏覽器獲得A網站的cookie,然後B網站有個按鈕跳轉A網站刪除所有部落格的連結,使用者就會在不知情的情況下清空所有部落格
攻擊例項:
1.登入www.a.com,刪除部落格連結:www.a.com/blog/delete/1
2.www.b.com 有一張圖片<img src="www.a.com/blog/delete/1"/>
3.使用者一開啟www.b.com,瀏覽器就會向www.a.com發起刪除部落格的請求,實現攻擊
不止img標籤可以實現攻擊,frame,script標籤也可以, flash也可以
如果網站被XSS攻破,就可以模擬表單進行提交,那麼CSRF加Token也不管用
解決方案:
1.驗證碼,不是萬能,只能作為輔助手段,且很影響體驗
2.檢車http頭referer,不是萬能,有時瀏覽器不會傳送referer,referer也可以偽造
3.Anti CSRF Token
增刪改敏感操作的請求帶上一個隨機數Token,儲存在伺服器端的SESSION裡面,這樣偽造請求就沒辦法猜到請求的全部引數
讀操作不在CSRF攻擊範圍
GET方式:
http://host/path/delete?uid=1&blog=2&token=DD3A4D42A6E57D6F9F22DFB3D1BD2851
POST方式:
<form action="path" method="POST">
<input type="hidden" name="__token__" value="DD3A4D42A6E57D6F9F22DFB3D1BD2851">
</form>
GET方式有可能會被XSS攻擊,,透過Referer方式洩露,儘量還是使用POST
XSS (Cross-Site Scripting)
透過注入HTML+JS篡改網頁,使用者瀏覽網頁的時候,控制使用者瀏覽器進行攻擊,留言板,評論區,站內信是XSS攻擊的高發地,攻擊者在留言板輸入
<script>alert("法海你不懂愛")</script>
如果伺服器直接輸出攻擊者的留言,那麼訪問留言板的其他使用者都會收到,這只是簡單的alert,複雜點就用js獲取你的cookie,幫你呼叫轉賬介面,改密碼介面,然後透過同樣的方式蠕蟲式傳播等等
解決方案:
1.HttpOnly
伺服器設定Cookie的時候新增HttpOnly,禁止js訪問帶有HttpOnly屬性的Cookie,解決Cookie劫持攻擊
2.表單驗證碼,指令碼可以把驗證碼圖片URL傳送到遠端伺服器來識別驗證碼
3.輸出檢查
除了富文字的輸出外,在變數渲染的時候,可以使用編碼或轉義的方式防禦XSS攻擊,PHP的函式是htmlentities() 和 htmlspecialchars()
htmlentities 轉化所有html標籤和中文
htmlspecialchars只轉義 & ' " < > 這五個字元,有中文的時候最好用這個,實在要使用 htmlentities 時,要注意為第三個引數傳遞正確的編碼
DDOS
GET POST 區別
GET:
1.可收藏書籤
2.儲存在瀏覽器歷史記錄中
3.能被快取
4.url長度字元限制(IE:2083字元,Firefox:65536字元,Chrome:8182字元,Opera:190000字元)
POST:
1.不可收藏書籤
2.退回重新提交表單
3.不能儲存歷史記錄
4.不能被快取
5.資料長度無限制
WEBSOCKET
Websocket是瀏覽器與伺服器進行全雙工通訊的應用層協議,基於TCP傳輸協議,複用HTTP的握手通道
優點:
1.實時性更強,更好的二進位制支援
2.建立連線後,協議控制的資料包頭部較HTTP協議小很多
建立連線:
HTTP 狀態碼
301:永久重定向,瀏覽器再次請求該連結的時候,直接請求瀏覽器快取的Location跳轉就可以,無需訪問伺服器
302:臨時重定向,瀏覽器再次請求該連結的時候,除非設定了Cache-Control 或 Expired 暗示瀏覽器快取,否則都會直接訪問伺服器重新獲取Location跳轉
本作品採用《CC 協議》,轉載必須註明作者和本文連結