偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

為什么 TFO 可以將 TCP 降低到 0 次握手?

網(wǎng)絡(luò)
因?yàn)?TCP 協(xié)議棧不同版本間存在差異,所以本文的前提是 TCP 三次握手時(shí)不傳輸數(shù)據(jù),也就是傳統(tǒng)的 TCP 三次握手。

一、概述

在之前的文章 為什么 TCP 建立連接需要三次握手 中,關(guān)于下面 3 個(gè)問(wèn)題給出了簡(jiǎn)單的回答:

  • 第一次握手時(shí)可以攜帶應(yīng)用數(shù)據(jù)嗎?
  • 第二次握手時(shí)可以攜帶應(yīng)用數(shù)據(jù)嗎?
  • 第三次握手時(shí)可以攜帶應(yīng)用數(shù)據(jù)嗎?

簡(jiǎn)單來(lái)說(shuō),傳統(tǒng)的 TCP 建立連接時(shí)需要三次握手,而且這三次握手只發(fā)送簡(jiǎn)單的 SYN 和 ACK 報(bào)文。

從網(wǎng)絡(luò)帶寬的資源利用的角度來(lái)看,傳輸層的 TCP 頭部 + 網(wǎng)絡(luò)層的 IP 頭部,最少有 40 個(gè)字節(jié),為了發(fā)送幾個(gè)字節(jié)的報(bào)文數(shù)據(jù)包,而額外組裝了 40 個(gè)字節(jié)的頭部,這有點(diǎn)類似前面講 TCP 滑動(dòng)窗口時(shí),所謂的 “糊涂窗口綜合癥”。

從應(yīng)用優(yōu)化的角度來(lái)看,因?yàn)橐鹊?TCP 經(jīng)過(guò)三次握手建立連接之后才能發(fā)送應(yīng)用層數(shù)據(jù),所以會(huì)造成應(yīng)用程序首次發(fā)送數(shù)據(jù)時(shí)存在一定的延遲,尤其是短連接、移動(dòng)設(shè)備等場(chǎng)景中,這種副作用會(huì)加劇。

那么這種問(wèn)題如何解決呢?使用 TFO 解決方案。

?? PS: 因?yàn)?TCP 協(xié)議棧不同版本間存在差異,所以本文的前提是 TCP 三次握手時(shí)不傳輸數(shù)據(jù),也就是傳統(tǒng)的 TCP 三次握手,事實(shí)上,很多云計(jì)算服務(wù)商提供的 Linux 發(fā)行版本都對(duì)網(wǎng)絡(luò)協(xié)議棧進(jìn)行了優(yōu)化,會(huì)在 TCP 第三次握手時(shí)直接發(fā)送數(shù)據(jù),讀者自己抓包驗(yàn)證時(shí),可能會(huì)和本文結(jié)果存在一定差異。

二、TFO

TCP Fast Open (TFO) 是在傳統(tǒng)的三次握手基礎(chǔ)上進(jìn)行優(yōu)化,允許在握手過(guò)程中發(fā)送數(shù)據(jù),從而減少首次發(fā)送數(shù)據(jù)的延遲,提升網(wǎng)絡(luò)應(yīng)用性能。

1.實(shí)現(xiàn)原理:

TFO 的核心原理是在發(fā)送方和接收方通信中,引入 1 個(gè) Cookie 機(jī)制,這樣使發(fā)送方在后續(xù)重連接收方時(shí),能夠簡(jiǎn)化 TCP 三次握手。

顧名思義,TFO Cookie 中的 Cookie 和 Web 應(yīng)用層 中的 Cookie 機(jī)制一樣,第一次訪問(wèn)時(shí),需要登錄驗(yàn)證,然后由服務(wù)端驗(yàn)證后,后續(xù)訪問(wèn)中可以直接攜帶,無(wú)需再次登錄。

(1) 首次連接

  • 當(dāng)發(fā)送方第一次和接收方建立 TCP 連接時(shí),發(fā)送 1 個(gè) SYN 報(bào)文
  • 接收方返回 SYN-ACK 報(bào)文的同時(shí),附帶一個(gè)隨機(jī)生成的名為 TFO Cookie 的標(biāo)識(shí)符給發(fā)送方
  • 發(fā)送方收到 SYN-ACK 報(bào)文后,保存 TFO Cookie,發(fā)送 ACK 報(bào)文給接收方,完成三次握手,開始傳輸數(shù)據(jù)

(2) 后續(xù)連接

  • 當(dāng)發(fā)送方再次連接同一個(gè)接收方時(shí),可以在 SYN 報(bào)文中攜帶上次保存的 TFO Cookie,同時(shí)在 SYN 報(bào)文中附帶應(yīng)用層數(shù)據(jù) (也就是第一次握手時(shí)就直接發(fā)送數(shù)據(jù))
  • 接收方驗(yàn)證發(fā)送方的 TFO Cookie 后,將數(shù)據(jù)發(fā)送給應(yīng)用層處理,并返回 SYN-ACK 報(bào)文 (同時(shí)也可以發(fā)送數(shù)據(jù))
  • 發(fā)送方收到 SYN-ACK 報(bào)文后,發(fā)送 ACK 報(bào)文給接收方,完成三次握手

2.優(yōu)點(diǎn)

通過(guò) TFO,發(fā)送方在發(fā)送 SYN 報(bào)文時(shí)就可以直接攜帶數(shù)據(jù),接收方可以在第一次握手時(shí)直接處理數(shù)據(jù),并且在第二次握手時(shí)直接發(fā)送數(shù)據(jù),最終:

  • 發(fā)送方第一次發(fā)送數(shù)據(jù),減少了 1.5 個(gè) RTT 延遲
  • 接收方第一次發(fā)送數(shù)據(jù),減少了 1 個(gè) RTT 延遲

發(fā)送方第一次發(fā)送數(shù)據(jù),減少了 1.5 個(gè) RTT 延遲

接收方第一次發(fā)送數(shù)據(jù),減少了 1 個(gè) RTT 延遲

3.局限性

(1) 兼容性

需要通信雙方都支持 TFO, 如果其中一方不支持,連接自動(dòng)回退到傳統(tǒng)的 TCP 連接建立過(guò)程,此外,通信鏈路中的轉(zhuǎn)發(fā)設(shè)備 (NAT, 防火墻) 也會(huì)執(zhí)行這個(gè)兼容性機(jī)制。

(2) 安全性

雖然 TFO 的 Cookie 是由接收方生成并發(fā)送給發(fā)送方的,并且每個(gè) Cookie 都與發(fā)送方關(guān)聯(lián),但是增加了接收方的安全攻擊面,可能引發(fā)諸如 “TCP SYN Flood” 放大攻擊 等安全風(fēng)險(xiǎn)。

如果攻擊者從被入侵主機(jī)獲取到有效的 TFO Cookie,進(jìn)而偽造了大量的攜帶數(shù)據(jù)報(bào)文,那么接收方就需要大量的內(nèi)存來(lái)臨時(shí)存儲(chǔ)應(yīng)用數(shù)據(jù),最終導(dǎo)致內(nèi)存耗盡。

(3) 部署環(huán)境要求

對(duì)內(nèi)核版本有要求,且需要修改內(nèi)核參數(shù)。

(4) 應(yīng)用數(shù)據(jù)過(guò)大

如果發(fā)送方第一次要發(fā)送的數(shù)據(jù)大于 TCP 的 MSS, 依然需要拆包進(jìn)行多次發(fā)送,當(dāng)應(yīng)用數(shù)據(jù)過(guò)大時(shí),TCP Fast Open 帶來(lái)的優(yōu)勢(shì) (RTT 減少) 幾乎可以忽略。

三、模擬環(huán)境

TFO 需要發(fā)送方和接收方同時(shí)支持,如果任意一方不支持 TFO,連接會(huì)自動(dòng)回退到傳統(tǒng)的三次握手方式。

為了演示效果,筆者使用了 2 個(gè) Linux 服務(wù)器作為通信發(fā)送方和接收方,對(duì)應(yīng)的發(fā)行版本和內(nèi)核版本參數(shù)如下。

1.TFO 對(duì) Linux 內(nèi)核版本要求: >= 3.7。

# 發(fā)送方

## 發(fā)行版本 (WSL2 環(huán)境)
$ cat /etc/os-release 

PRETTY_NAME="Debian GNU/Linux 11 (bullseye)"
NAME="Debian GNU/Linux"
VERSION_ID="11"
VERSION="11 (bullseye)"
VERSION_CODENAME=bullseye
ID=debian

## 內(nèi)核版本
$ uname -r

5.10.0-21-amd64

# 接收方

## 發(fā)行版本
$ cat /etc/os-release

NAME="CentOS Linux"
VERSION="7 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="7"
PRETTY_NAME="CentOS Linux 7 (Core)"

## 內(nèi)核版本
$ uname -r

3.10.0-1160.53.1.el7.x86_64

2.內(nèi)核參數(shù)調(diào)整

TFO 啟用需要修改默認(rèn)內(nèi)核參數(shù):

  • 0:關(guān)閉 TFO
  • 1:?jiǎn)⒂冒l(fā)送方模式 TFO
  • 2:?jiǎn)⒂媒邮辗侥J?TFO
  • 3:同時(shí)啟用發(fā)送方和接收方模式 TFO
# 發(fā)送方啟用 TFO
$ echo 1 | sudo tee /proc/sys/net/ipv4/tcp_fastopen

# 接收方啟用 TFO
# 寫入 3 表示既啟用發(fā)送方 TFO 也啟用接收方 TFO
$ echo 3 | sudo tee /proc/sys/net/ipv4/tcp_fastopen

作為模擬實(shí)驗(yàn),筆者只是臨時(shí)修改了參數(shù),可以采用如下步驟進(jìn)行配置永久生效:

(1) 編輯 /etc/sysctl.conf 文件,添加配置項(xiàng)

net.ipv4.tcp_fastopen=3

(2) 運(yùn)行 sysctl -p 命令生效,重啟之后仍然有效

四、程序代碼

如果讀者使用主機(jī)的 curl 版本較高,可以直接使用如下方式直接開啟 TFO 機(jī)制方式訪問(wèn):

$ curl --tcp-fastopen http://example.com

# 可以使用如下方式確認(rèn) curl 版本是否支持 TFO
$ curl -V | grep -i TFO

因?yàn)楣P者所使用的服務(wù)器中的 curl 版本較低,所以這里編寫 Python 腳本代碼,核心代碼其實(shí)就是 2 個(gè)套接字的參數(shù)的設(shè)置而已。

1.接收方 (服務(wù)端) 代碼

將接收方作為服務(wù)端程序的方式來(lái)實(shí)現(xiàn),綁定/監(jiān)聽指定端口,然后接收來(lái)自發(fā)送方 (客戶端) 的 TCP 連接。

# service.py

import socket

def listen():
    # 初始化服務(wù)端監(jiān)聽對(duì)象
    listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # 參數(shù) 32 表示 TCP 協(xié)議棧
    # 未完成的 Fast Open 隊(duì)列長(zhǎng)度
    listener.setsockopt(socket.SOL_TCP, socket.TCP_FASTOPEN, 32)

    # 監(jiān)聽 12345 端口號(hào)
    # 為了模擬,所以不用主流端口號(hào)了 :-)
    listener.bind(('0.0.0.0', 12345))
    # 最大連接數(shù)設(shè)置為 1024
    listener.listen(1024)

    print("Server is listening on port 12345...")

    # 輪詢接收新的 TCP 連接
    while True:
        conn, addr = listener.accept()
        print(f"Accepted connection from {addr}")
        print(f"Received data: {conn.recv(1024)}")

        conn.send(b"Hello, Client")
        conn.close()

        print(f"Closed connection with {addr}")


if __name__ == "__main__":
    try:
        # 啟動(dòng)監(jiān)聽
        listen()
    except KeyboardInterrupt:
        # 捕獲 Ctrl + C 終止程序
        print("Server shutting down...")

2.發(fā)送方 (客戶端) 代碼

# client.py

import socket

# 初始化客戶端監(jiān)聽對(duì)象
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 參數(shù) 32 表示 TCP 協(xié)議棧
# 未完成的 Fast Open 隊(duì)列長(zhǎng)度
sock.setsockopt(socket.SOL_TCP, socket.TCP_FASTOPEN, 32)

# 向服務(wù)端發(fā)送數(shù)據(jù)時(shí)
# 設(shè)置 Fast Open 選項(xiàng)
sock.sendto(b"Hello, Server", socket.MSG_FASTOPEN, ("104.21.71.166", 12345))

print(f"Received data: {conn.recv(1024)}")

sock.close()

五、運(yùn)行程序?qū)嶒?yàn)

程序核心代碼 (總共 2 行) 準(zhǔn)備就緒,接下來(lái)開始運(yùn)行程序,驗(yàn)證 TCP Fast Open 過(guò)程。

服務(wù)端公網(wǎng) IP: 104.21.71.166

1. 啟動(dòng)服務(wù)端程序,并確認(rèn)監(jiān)聽狀態(tài)

# 在 1 個(gè)終端啟動(dòng)服務(wù)端程序

$ python3 server.py

# 在另外 1 個(gè)終端查看程序監(jiān)聽狀態(tài)是否正常

$ netstat -ant | grep 12345 | grep LISTEN

tcp        0      0 0.0.0.0:12345            0.0.0.0:*               LISTEN

2. 客戶端開始抓包

打開 WireShark, 監(jiān)聽對(duì)應(yīng)的網(wǎng)卡設(shè)備。

3. 運(yùn)行客戶端程序

# 為了驗(yàn)證效果,這里可以連續(xù)運(yùn)行幾次
# 每次運(yùn)行間隔 3 - 5 秒即可
$ python3 client.py

# 輸出省略
...

4. 查看客戶端 TCP 連接狀態(tài)

netstat -ant | grep 12345 | grep TIME_WAIT

# 輸出如下
# 連續(xù)運(yùn)行了多少次 client.py 
# 就會(huì)產(chǎn)生多少 TIME_WAIT 狀態(tài)的 TCP 連接
# 10.0.0.53 為客戶端的內(nèi)網(wǎng) IP 地址


tcp        0      0 10.0.0.53:38084         104.21.71.166:12345       TIME_WAIT  
tcp        0      0 10.0.0.53:37530         104.21.71.166:12345       TIME_WAIT  
tcp        0      0 10.0.0.53:37528         104.21.71.166:12345       TIME_WAIT  
tcp        0      0 10.0.0.53:38076         104.21.71.166:12345       TIME_WAIT  
tcp        0      0 10.0.0.53:38078         104.21.71.166:12345       TIME_WAIT  

...

一切運(yùn)行正常,接下來(lái)就可以去看 WireShark 的抓包結(jié)果了。

六、WireShark 抓包結(jié)果

首先使用 tcp.options.tfo 過(guò)濾條件,快速篩選出和 TCP Fast Open 有關(guān)的 TCP 報(bào)文。

下面對(duì) WireShark 抓包結(jié)果展開分析一下。

1.第一次建立連接

當(dāng)發(fā)送方第一次和接收方建立 TCP 連接時(shí),發(fā)送 1 個(gè) SYN 報(bào)文,以及設(shè)置 TCP Options 字段 TCP Fast Open 。

此時(shí)并沒(méi)有發(fā)送任何數(shù)據(jù),所以 WireShark 抓包結(jié)果中的 Len = 0。

接收方返回 SYN-ACK 報(bào)文的同時(shí),附帶一個(gè)隨機(jī)生成的名為 TFO Cookie 的標(biāo)識(shí)符給發(fā)送方。

發(fā)送方收到 SYN-ACK 報(bào)文后,保存 TFO Cookie,發(fā)送 ACK 報(bào)文給接收方,完成三次握手。

其中 TFO Cookie 的值為: d82d9074a6105a13。

三次握手完成后,開始傳輸數(shù)據(jù)。

2.后續(xù)建立連接

通過(guò)截圖可以看到,后續(xù)客戶端和服務(wù)端建立 TCP 連接時(shí),會(huì)在第一次握手時(shí)攜帶 FTO Cookie 并且直接發(fā)送數(shù)據(jù),所以 WireShark 抓包結(jié)果中的 Len = 13。

那么這個(gè) 13 是什么?就是客戶端發(fā)送的數(shù)據(jù),正好是 13 個(gè)字節(jié)。

conn.sendto(b"Hello, Server", ...)

后續(xù) TCP 連接建立 (第一次握手) 時(shí)就可以直接發(fā)送數(shù)據(jù) (篇幅所限,這里只截圖 2 個(gè)數(shù)據(jù)抓包詳情):

每個(gè)數(shù)據(jù)包中的 TFO Cookie 的值都是 d82d9074a6105a13,也就是第一次建立 TCP 連接時(shí),服務(wù)端發(fā)送 SYN-ACK 報(bào)文時(shí)攜帶的值。

責(zé)任編輯:趙寧寧 來(lái)源: 洋芋編程
相關(guān)推薦

2023-09-07 16:46:54

TCP數(shù)據(jù)傳遞

2019-12-12 10:36:43

TCPSYNIP

2021-04-30 13:32:17

TCP三次握手網(wǎng)絡(luò)協(xié)議

2022-07-25 07:07:35

TCP客戶端服務(wù)器

2019-05-14 10:09:06

TCP連接握手

2024-10-16 08:38:37

TCP編號(hào)信息

2021-05-28 09:08:20

TCP連接序列號(hào)

2019-05-05 05:39:23

TCP三次握手網(wǎng)絡(luò)協(xié)議

2024-07-10 12:00:42

2021-12-13 06:23:14

TCP三次握手網(wǎng)絡(luò)

2019-05-28 10:45:07

TCP3次握手數(shù)據(jù)傳輸

2021-09-09 08:47:57

TCP三次握手協(xié)議

2023-10-24 15:22:09

TCPUDP

2022-07-05 22:18:08

TCP網(wǎng)絡(luò)

2019-07-19 06:58:03

TCP三次握手網(wǎng)絡(luò)協(xié)議

2021-12-02 09:20:33

TCPLinux三次握手

2024-05-07 08:15:33

TCP四次揮手三次握手

2018-11-14 09:53:48

2024-04-07 00:02:00

TCP連接通道

2024-01-12 08:23:11

TCPACK服務(wù)器
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)