--- title: '傳輸層 - TCP / UDP' disqus: kyleAlien --- 傳輸層 - TCP / UDP === ## OverView of Content 如有引用參考請詳註出處,感謝 :smile: 傳輸層的協定能讓網路層(IP)的包、應用層的需求連接,其中最常見的就是 TCP、UDP 協議 [TOC] ## 傳輸層 概述 ### TCP 概述 * TCP 是傳輸層的一項協定,TCP 之所以流行是因為它對應用沒有太多要求,只須知道開啟、讀取、寫入、關閉... 等等行為即可(就跟處理檔案差不多) * TCP 的實現大多都包裹在系統核心之中,它幫我們處理了以下事項 1. 傳送時將數據切分打包 2. 接收時將數據拆分 3. 檢查錯誤、盡可能的修復 > 當然如果我們停留在應用層級是不需要知道這麽多資訊,大致如下圖 ``` mermaid graph TD; 客戶端發送-HelloWorld-->客戶端核心-拆數據-He_llo_Wor_ld; 客戶端核心-拆數據-He_llo_Wor_ld-->Internet; Internet-->遠端核心-解數據-He_llo_Wor_ld; 遠端核心-解數據-He_llo_Wor_ld-->遠端核心組裝&修復; 遠端核心組裝&修復-->遠端應用收到-HelloWorld; ``` ### UDP 概述 * UDP 單次傳輸就可以構成完整的傳輸(不用糾正封包、不關心亂序),但 **UDP 仍有連接埠(Port)的概念** :::warning * 雖然 UDP 有連接埠的概念,不過它不用使用連接埠來進行連接!該連接埠只是用來發送資料,而遠端是否要回覆都可以 > 所以 UDP 的速度會比 TCP 快,但相對的不穩定 ::: ## 連接埠 Port 就算視同種類的服務,只要編號(連接埠 Port)不同,該服務就可被視為令一個連線 > 連接埠 Port 是一個數字 ### IP & Port 關係 * 簡單來說 **Mac、IP 是++唯一++的地址,就像大樓門牌號碼** >  * Port 是在同地址的下,不同的分配位子 >  ### TCP 連接埠、連接 - netstat * 使用 TCP 連線時,應用會在本地開啟一個連接埠(Port)與遠端主機的一個連接埠(Port)連接 ``` mermaid graph TD; 本機Port_12345-->遠端Port_443; ``` :::warning * 這種 Port 的連接是建立在 NetworkManager 連線之上 ::: 可以使用 `netstat` 觀察當前主機與哪些遠端的 Port 有連接關係 ```shell= # -n 不做 DNS 解析 # -t 只顯示 tcp netstat -n -t ``` >  ### 伺服器 & 常見 Port * 什麼是 Port 號 ? 是拿來幹嘛的 ? 就像是 **同大樓中共用地址 (可能地址都是 123),但有不同的樓層房號 (房號 1 ~ 50 號) 這就是 Port 號** :::success * Port 號有幾個呢 ? **一個 Port 規定為 16 位元,也就是 2^16^ 個不同端口** ::: * 一台伺服器通常會處理不只一種服務,有可能有網頁、郵件、檔案傳輸... 等等,如果要從另外一台裝置透過外部訪問(網路 IP),就需要指定 Port 號 > 不同 Port 代表不同服務 其中有包含 **特殊端口號** | 端口號 | 功能 | 補充 | | -------- | -------- | -------- | | 0 ~ 1023(2^10^) | 系統端口號(標準、知名埠) | 不可隨意使用,`Http:80`、`FTP:21`、`TELNET:23` | | 1024 ~ 49151 | 登記端口號 | 讓第三方有登記的應用使用,透過 IANA 登記 | | 49152 ~ 65535 | 暫時端口號 | 可以自由使用,通常由系統隨機挑選使用(以保證不會發生衝突) | * 透過通訊埠編號(Port)識別時,我們有幾個常見的公認通訊 Port(Well-Known),**範圍為 ++0 ~ 1023++**,**在這個範圍內的 Port 請不要隨意佔用** | 常見 Port 號 | 用途 | | -------- | -------- | | 20 | FTP 傳送資料 | | 21 | FTP 控制 | | 22 | SSH (Secure Shell) | | 23 | Telnet 傳送 **未加密** 內容的文字傳輸協定 | | 25 | SMTP 接收、發送郵件 | | 80 | HTTP 網頁伺服器 | | 110 | POP3 接收郵件 | | 123 | NTP NetWork Time Protocol | | 443 | Https 在 Http 基礎加上 SSH 加密傳輸內容 | :::info - 在由瀏覽器上基本是不需要指定 Port 號 ```shell= www.google.com:443 ``` ::: 另外我們可以查看 `/etc/services` 文件看看有哪些公認的連接埠 ```shell= cat /etc/services ``` >  ### 路由器的 Port * 在路由器內也有使用通訊埠編號 (Port),內部大部份是內建了 1. NAT (`Network Address Translation`):將全球 IP 位址轉為私人 IP 位址 > 這樣就換變成 1 個 全球 IP 位址對應 多個私人位置 ``` mermaid graph TD; 全球_IP-117.122.1.32-->路由器_NAT; 路由器_NAT-->裝置A_B_C-117.122.1.32; ``` 2. NAPT (`Network Address Port Translation`):在 NAT 的機制下加上 Port 號,讓每個私人 IP 都有 Port 號 ``` mermaid graph TD; 全球_IP_117.122.1.32-->路由器_NAPT; 路由器_NAPT-->裝置A_117.122.1.32:80001; 路由器_NAPT-->裝置B_117.122.1.32:80002; 路由器_NAPT-->裝置C_117.122.1.32:80003; ``` ### Port 建立 TCP 連接 * 要建立傳輸層連接,應用會先發送一系列特別的封包,先初始化一個本機連接埠(Port)到選端的連接埠 * **客戶端**:通常發起連接端稱之為客戶端 > 客戶端 Port 通常是隨意挑選一個未使用的 Port,這種 Port 又稱為 **動態連接埠** * **伺服器**:接收(監聽)資料端稱為 伺服器 > 伺服器端的 Port 則是固定公認的 可以使用 `netstat` 查看本地正在監聽的 Port ```shell= # -l 監聽中 netstat -n -t -l ``` > 下圖中可以看到某些服務正監聽本地(127.0.0.1)的 25, 631, 5939 連接埠 > >  :::info * 可以使用 `lsof` 搭配 `grep` 命令查看是哪個應用正在監聽該連接埠 ::: ## TCP & UDP * TCP / UDP 為++全雙工++;並且該協議是 **==傳輸層== 控制協定,TCP 又稱為++可靠協議++,UDP 又稱為++不可靠協議++**,以下會詳細介紹 TCP 的握手協定 :::info * 那是否每個通訊方式都需要經過 OSI 協定的傳輸層呢? 不用,並非每個傳輸協定都要經過傳輸層;像是 **Ping 傳輸命令就不需要經過傳輸層**(它基於網路層協定運作) ::: > 網路層: ICMP 控制報文協議、IGMP internet 管理協議 > > 鏈路層: ARP 地址解析、RARP 地址加密協定 >  :::info Android 最底層的是使用工具 **`tcpdump`** (指令式)、上層使用 `fiddle`、`charls`,並使用 `waveshark` 分析 ::: ### TCP 數據包結構 * 每一次都會傳輸都會發送這種格式的數據,**在三次握手 \ 四次揮手時會操作到一系列的 Flag (紅色框)** >  ### 三次握手 * 小寫代表序列號,大寫代表數據包中的 Flag 狀態,**注意流程** 1. **第一次 (Client to Server) :** `SYN = 1`、**`seq = J` ++系統隨機生成、不可固定++ (因為數據如果斷線後重連,同序列號會導致無法確認是否是同一資料)** 2. **第二次 (Server to Client) :** `SYN = 1`、`ACK = 1`、**`ack = J + 1` (才能確認是否有收到),seq = K 改為 established 建立連接狀態** 3. **第三次 (Client to Server) :** `ACK = 1`、`ack = K + 1` * 交換完初始序號後,就可以開始傳送數據了,**如果連上後不發送數據會自動斷開 (超時機制)** >  :::warning * **為何是三次握手、不是四次、五次 ?** > **主要是為了 TCP 的考靠性,該可靠性是在確認序列號 (比對序列號)**,**==主要是為了++交換 TCP 的初始序列號 ISN++==**,這樣才能確認是否是相同連線,3 次以上握手是多餘的 ::: ### TCP 握手漏洞 - STN Flood * **SYN 攻擊,大量發送偽造園地址的攻擊報文,發送到服務端,造成服務端上的==半開連結隊列溢出==,阻止其他用戶訪問** > 原理 : > > Client 偽造 IP 地指向 Server 端發出請求 (一次握手),而服務端自然響應 (二次握手) 但無法發送到指定 IP,所以**服務端會一直等待第三次握手,而處於半開連結狀態 (等待第三次握手)**,這會導致資源耗損 :::success **解決方案: 無效連接監控釋放、防火牆** ::: ### 四次揮手 * 斷開一個 TCP 連接時,需要客戶端共發起 4 次確認訊息,C/S 都可以發出揮手,以下以客戶端主動斷開 1. **Client :** `FIN = 1` **(發起斷線),Client 狀態轉為 FIN_WAIT_1** 2. **Server :** `ACK = 1` **(同意斷線),Client 狀態轉為 FIN_WAIT_2,轉為半連接狀態** 3. **Server :** `FIN = 1` **(確定斷線請求)** 4. **Client :** `ACK = 1` **(發送確定斷線請求),Client 狀態轉為 TIME_WAIT,並==等待 2MSL 的時間,超過後就默認真正斷開==** * **MSL : Maxnum Segment Lifetime**,2MSL 是數據包來回時間 >  :::warning * **為何是四次揮手 ? 三次可以嗎 ?** > 因為是 **++全雙工++ 的原因**,導致雙方都要確認斷線需要四次,但是**要三次也是可以 (Server、Client 端的 FIN 同時發送)** * 為何需要 `TIME_WAIT` ? 1. 保證 Server 端真的接收到 Client 端斷線訊息,這樣 Server 端才可以正確的關閉連線 2. 保證 Client 端可以收到 Server 端回覆的訊息,這樣 Client 端才可以正確地關閉連線 3. 意外連線關閉 * 如果超過 `TIME_WAIT`,雙方也會進行 Port 關閉 ::: ## TCP 通訊原理 ### Socket * TCP 用主機的 `IP 地址` + `Port 號` 作為 TCP 連接的端點,這種端點稱為 Socket * TCP 的 Socket 的**內核中都有一個發送緩衝區和一個接收緩衝區** ### 可靠性 * 除了透過之前說過的三次握手++交換序列號++,還有一個 **==確認號==,確認每次數據的傳輸,如下圖** >  * 當數據接收失敗 or 遺失,**過一段++特定時間間格++就會在傳輸一次** >  * 因為 TCP / IP是全雙工,不會有一傳一收的問題,也就**沒有先發先到的問題** :::success * 如何知道數據發送完畢 ? > 收到確認性信號,就可以保證傳完,而傳到哪裡為止是由上層應用層決定 ::: ### 窗口機制 * 滑動窗口機制,這個窗口就包含在 TCP 的數據包中,而**確切的窗口大小是由 ==接收端決定==,因為接收端可以調整其數據接收的大小** (能力強就可調高) 1. 保證數據不會因為緩衝不足而丟失,當傳超出緩存時就會要求重新傳 2. 可調整傳輸速度 >  ## 傳輸層 - 工具 ### 連線工具 `netcat`、`telnet` * 我們可以透過 `telnet`、`netcat` 指令來連接傳輸層 * 使用 `telnet` 連接 google ```shell= telnet www.google.com 80 ``` >  * 使用 `netcat` 連接 google ```shell= netcat www.google.com 80 ``` >  ### `nmap` - 查看主機 Port * `nmap` 指令可以查看目標主機有開放哪些 Port 可以給我們使用 :::success * 最好使用兩個角度(本機、另一個網域的裝置)來查看 `nmap` 指令,因為該指令獲取到的資訊可能不是第一手(**有可能已經被防火牆過濾完**) ::: ```shell= # 查看 google 主機的 ip 位置 host www.google.com # 查看 google 網域開放了哪些可訪問的 port nmap 142.251.43.4 ``` >  ## Appendix & FAQ :::info ::: ###### tags: `網路基礎`
×
Sign in
Email
Password
Forgot password
or
Sign in via Google
Sign in via Facebook
Sign in via X(Twitter)
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
Continue with a different method
New to HackMD?
Sign up
By signing in, you agree to our
terms of service
.