###### tags: `1111` `lsa` `ncnu`
# Week 10 (2022/11/18)
[TOC]
- Book mode: https://hackmd.io/@ncnu-opensource/book
---
# TCP/IP
## 複習
- 同一網域 透過 switch 用 MAC address 溝通
- 不同網域 透過 Router 用 IP address 溝通
## Transport Layer
### UDP(User Datagram Protocol)
- 
- Checksum: 確認資料是否丟失
- UDP是不可靠的
- 沒有像 TCP 一樣的握手建立連線流程,socket 創建後就直接將封包發往指定 IP 地址上的指定端口號應用程式
- UDP 不需要 ACK 響應來確認對方是否收到消息,這有可能造成封包的亂序到達以及丟失問題,缺乏壅塞控制。
- UDP 可以依照想要的速率發送封包(不過真實的封包傳輸速率還是要看網路核心中的帶寬限制)
- 優點:比較快、資料大小較小
### Port(通訊埠(ㄅㄨˋ)口)
- 接收方與傳送方皆需要 port(連線通道)來傳遞資料
- 舉例: IP 為門牌號碼, port 為哪個窗口
- https: 443, www: 80
- 為TCP Header 的 Sourse Port 與 Destination
查詢port service 方式: `/etc/service`
### TCP
- 相對UDP還要來的可靠
- 三向交握
- 
- `Sequence Number`: 若 TCP 資料過大,需切割放進不同封包,記錄封包序號,以便重組 TCP 資料
- `Acknowledgement Number`: 若接收端有收到這個確認碼告知 client 端封包被正確收下了。
- `window`: 控制封包流量,若緩衝區已滿,window=0,應停止傳送
- control bit

- SYN: 1為希望與對方線進行同步處理(建立連線)
- ACK: 1 為回應封包
- Fin: 為通知對方結束連線(等對方確認)
- 缺點:較慢
- 優點:因為有**三向交握**故相較可靠
- 為什麼 Tcp 十分可靠 $\to$ 三向交握(在做行為前都會先向對方做確認)

1. 發送方發一個帶有 SYN=1 的封包,並發送一個 sequence number = 10001 給收方
2. 收方確認後回覆:
1. ACK=1 與 ack=10001 (剛剛接收到的 sequence) +1
2. SYN=1 與 sequence=20001 (收方也要回傳要求連線)
3. 發送方回傳:
1. ACK=1 與 sequence=20001+1
4. 確定連線,開始傳送資料。
:::info
#### Seqence Number & ACK
- 為什麼要 sequence?
- 讓對方回應時可以針對這個 sequence 發送對應 ack ,確認封包是否已被接收和確認對方收到多少。
> 因為有 Seqence Number,所以可以切割過大的封包來傳送,相較於沒有 Seqence Number 的 UDP,就不能把封包切割後傳送[color=yellow]
- 依照你傳過去的封包大小和 Sequence num 做加總後回傳
- 讓對方回應時可以針對這個 Sequence 發送對應 ACK,確認封包是否已被接收和確認對方收到多少
- server 可以根據 sequence number 知道你得到的封包長度是否正確、是否有遺失封包
- 正確收到封包: `sequence number` + `封包大小` = ACK 回傳數字

:::
:::info
#### TCP/UDP 比較
| | TCP | UDP |
| ------- | ----------- | ----- |
| 可靠性 | 可靠 | 不可靠 |
| 封包確認 | ACK | - |
| 速度 | 慢 | 快 |
| 傳輸方式 | 封包按順序傳輸 | 封包以串流方式傳輸 |
| 錯誤檢查與修正 | 有 | 無 |
| 逾時處理 | 逾時重傳、高速重傳(指定封包) | 逾時重傳(全部封包) |
| 雍塞控制 | 有 | 無 |
| 適用服務 | **要求可靠運輸的服務**, ex :SSH、文字聊天、電子郵件、檔案傳輸...等不能漏缺資訊的服務 | **講求速度的即時服務** ex: 串流媒體、網路電話 |
:::
## Application Layer
- 傳送單位為 message

### HTTP
> TCP [color=pink]
1. DNS 解析:查這個 Domain name 相對應的 IP 在哪
2. 建立 TCP/IP 連線
> 包括尋找 IP/MAC addr 和 TCP 三向交握
3. 決定要送出 Get 還是 Post
- Get:瀏覽器將 headers 與 data 同時送出,因此只會產生一個 TCP 封包,最後伺服器端回應 200 與 資料 。
> 一個 TCP 封包是指在建立三向交握之後的,那時會有 3 個封包。
- Post:瀏覽器將 headers 送出,等到伺服器端回應 100 continue 後再傳送 data,因此會產生 2 個 TCP 封包,最後伺服器回應 200 與 data
:::info
### 狀態碼
- 1XX:參考資訊 例如:POST headers 後得到 100(繼續)、101(切換通訊協定)。
- 2XX:成功,例如:200 客戶端要求成功。
- 3XX:重新導向,例如:301 永久導向、302 暫時導向、304 未修改。
- 4XX:用戶端錯誤,例如:401 拒絕存取、403 禁止使用、404 找不到。
- 5XX:伺服器錯誤,例如:500伺服器錯誤
:::
### FTP
> TCP [color=pink]
- FTP 是應用於檔案傳輸、檔案共享使用,將共享檔案存放於 FTP 伺服器,讓一般使用者可以透過網路來下載或上傳。他的重要是在異質性電腦之間,以及遠距離的檔案共享。

> 監控連線: 21 port,傳輸資料: 20 port
1. FTP 檔案傳輸系統採用 **主從式模式**,FTP伺服器端隨時監視埠口 21(TCP/21) 是否有連線要求,FTP 客戶端需要連線時,便由著名埠口 21 連結到 FTP 伺服器
> 主從式: client 向 server 發 request 才會有 response
2. 伺服器端同意連線後(驗證使用者及使用密碼),便建立並保持著控制連線,以便隨時間換訊息,當需要傳輸檔案時,再建立資料連線,傳輸後立即釋放該資料連線,一般伺服器端地連線資料連線都建在埠口 20(20/tcp)
3. 雙方透過資料連線來存取各自檔案系統(File System)中的檔案
### DNS
> UDP: 大部分時候
> TCP: :one:當封包過大時 :two:要確保此 DNS 資料庫資料和其他 DNS 相同時[color=pink]

- UDP 協議: DNS 查詢的資料包較小、機制簡單; UDP 協議的額外開銷小、有著更好的性能表現。
- TCP 協議: DNS 查詢由於 DNSSEC 和 IPV6 的引入迅速膨脹,導致DNS回應經常超過 MTU (傳輸單元最大值)造成資料的分片和丟失,我們需要依靠更加可到的 TCP 協定完成資料的傳輸。
> 隨著 DNS 查詢中包含的資料不斷增加,TCP 協定頭以及三向交握帶來的額外開銷比例逐漸降低,不再是佔據總傳輸資料大小的主要部分
- 一般情況皆使用 UDP,因為在查找網址時較講求速度,就算掉包了再重送就好
> 注意!DNS 可能會同時使用 TCP 與 UDP 協定。
- UDP 封包大小較小,資料大小超過 512 位元組的限制時會被截斷,如果從 DNS 得到回應,3~5 秒後會使用 TCP 重送。
> TCP 會對封包
- DNS 區域轉送 (Zone Transfer),DNS 要確保資料庫(主 DNS 與副 DNS)資料相同,當有變動時,會用區域轉送來保持資料一致,此時會用 TCP 傳送。
### Anycast
- 尋找最短路徑的策略

#### AS

- Internet 是由不同網絡組成的網路,自製系統是組成 Internet 的大型網絡。更具體地說,自製系統 (AS)是具有統一路由方式的巨型網絡或網絡群組。連接到 Internet 的每台計算機或設備都連接到一個 AS。
#### BGP
- AS 通過 BGP 通知其到其他 AS 和路由器的路由策略。BGP 是在 AS 之間路由數據包協議。如果沒有這些路由訊息,大規模運行將很快變得不切實際:數據包將丟失或花費太長時間才能達到目的地
- 每個 AS 使用 BGP 通知他們負責的 IP 地址以及他們連接的其他 AS。BGP 路由器從世界各地的 AS 中獲取所有這些訊息,並將其放入稱為路由表的數據庫中,以確定從 AS 到 AS 的最快路徑。當數據包到達時,BGP 路由器會參考其路由表來確定數據包接下來應轉到哪個 AS。
- 全世界有許多 AS,BGP 路由器不斷更新路由表,當網路失去連線時,新增網路增加時,AS 擴漲或收縮其 IP地址空間,所有這些訊息都必須通過 BGP 通知,以便 BGP 路由器可以調整其路由表
> 儲存一些已知 AS 的最短路徑,不知道路徑的時候,問附近的 AS,知道路徑的 AS 會回傳他知道的最短路徑。
> 不知道怎麼去的時候問別人去目的地的最短路徑
網路分成一塊一塊 (AS),每塊之間要溝通卻不知道怎麼走時就可以問 BGP,他會給你最短路徑
### TCP/IP 統整
| 層級 | 資料型態 | 負責事項 | 常見協定 | 傳送依據 |
| -------- | --- | --- | -------- | -------- |
| Application | message | 定義應用程式如何提供服務 | HTTP, FTP, DNS, SMTP, SSH | |
| Transport| segment | 負責傳輸過程的流量控制、錯誤處理、資料重送等工作。 | TCP, UDP, RTP, SCTP | port |
| Network | packet | 決定資料如何傳送到目的地。 | IP, ICMP | IP Address |
| Data Link | frame | 負責網路對硬體的溝通。 | Ethernet、Wifi | MAC Address |
### HPPT/1 瓶頸
- Single Request Connection
- HTTP 的連線一次只能處理一個 Request,而大部份的瀏覽器每個 domain 最多允許6條連線,每條連線在開啟之初都必須要先進行TCP Handshakes。
- Exclusive Client-initiated Requests
- 只有 Client 可以發出 Request , Server 要等到 Client 主動發出請求,才能把資源丟過去。
- Uncompressed Request and Response Headers
- header的大小從約 200bytes 到大於 2KB,且很多重複的訊息
### HTTP/2 SPDY
**SP**ee**DY**
- 改善網頁的 Page Load Time
- Server 可以主動傳訊息
- 可以連續發 request
- Mulitiplexed Request
> one connection for unlimited request
- 一條 SPDY 的連線在協定中並沒有限制 request 的次數,因此只需要開啟一條 TCP 連線。

- compressed headers
- 將 client 和 server 之間的訊息拆成 Control Frame 和 Data Frame
- Server Push Strems
- Server 可以主動將 Client 需要的資源 push 到瀏覽器的快取中,不需要透過 Client Request 觸發 Stream
- Client 第一次存取某個網頁時,Server 就會自動 pushㄧ些 Client 需要的資源到快取中,下一次瀏覽相同網頁時就能減少載入畫面的時間
- Always Over TLS
### HTTP/3 QUIC
**Q**uick **U**DP **I**nternet **C**onnection

1. 封包丟失機率較高
2. 較長 Round Trip Time (RTT)
> RTT: 傳送訊息到回覆的時間
> 因為需要三向交握
3. Connection Migration
:::info
### Connection Migration
- TCP 連線所需條件
- source port
- destination port
- source ip
- destination ip
- 更換 IP 就須需要重新連線
> WIFI連線轉移到4G網路連線
- QUIC
- 64 bits 的獨立 Connection ID
- 省下一直進行三方交握的時間,已經連線過的就不需要再三向交握
:::

[圖源](https://medium.com/@chester.yw.chu/http-3-%E5%82%B3%E8%BC%B8%E5%8D%94%E8%AD%B0-quic-%E7%B0%A1%E4%BB%8B-5f8806d6c8cd)
- 初始交握 (Initial Handshake)
- 客戶端會傳送一個哈囉信息(CHLO,Client Hello)到服務端,觸發服務端回傳一個代表交握未建立或是公鑰已經過期的拒絕訊息: REJ封包
:::info
- REJ 封包
- Server Config: 包含服務端的長期DH公鑰 (Diffie-Hellman Public Key)
- Certificate Chain: 用來對服務端進行認證的憑證串鏈
- Signature of Server Config:經過數位簽章過的Server Config,讓客戶端可以驗證這些資訊確實是由服務端發出。
- Source-Address Token:經過認證加密過後的客戶端IP資訊
:::
- 驗證Server 確認無誤後,回傳 Complete CHLO 其中包含 Request 資料一併用初始密鑰加密後回傳給服務端
- 都沒問題後服務端傳送 SHLO (Server Hello) 的封包,封包中包含了服務端所產生的短期 DH 公鑰。
> 每一次建立連線都會產生新的短期 DH工要與密鑰,接下來要進行的,就是更換初始密鑰。
#### 封包遺失恢復 (Loss Recovery)
- TCP
- ACK 封包 seq num 每次都會一樣
- 發送端為每一個封包標記一個編號(sequence number),接收端在收到封包時,就會回傳一個帶有對應編號的 ACK 封包給發送端
- 當發送端在超過一定時間 (Retransmiting Timeout, RTo)之後還沒有收到回傅的 ACK ,就會認為封包己經丢失,啟動重新傅送的機制
- 因為重傳使用同一個sequence number,是接收端再收到初始封包後回傳的ACK(較長RTT),還是接收端在收到重傳封包後回傳的ACK(較短RTT)
- QUIC
- 初始與重傳的每一個封包都改用一個新的編號,unique packet number
> TCP 的每個封包初始編號都一樣,所以會造成若第一封(<font color="red">A</font>)未回應,過一段時間再發第二封(<font color="blue">B</font>)後,回應回來的封包(<font color="orange">C</font>)會不知道是在回應第一封(<font color="red">A</font>)還是第二封(<font color="blue">B</font>)
## OSI

> 理論上的架構,沒有明確規定每層應該要使用怎麼樣的協定
| Layer | 設備種類 | 負責功能 | 協定 |
| ----- | -------- | -------- | -------- |
|Application|WAF (Web application firewall)|定義介面給應用程式|HTTP FTP SMTP|
|Presentation|WAF|轉成網路的標準格式 加解密 加解壓縮|SSH Telnet|
|Session|WAF|開啟和關閉兩個裝置之間的通訊| |
|Transport|firewall|流量控制 錯誤控制 資料完整偵測|TCP UDP|
|Network|router|為資料尋找抵達目的地的最佳實體路徑| IP ICMP|
|Data-Link|switch|位於相同網路的兩個裝置之間的資料傳輸|有線-802.3 無線-802.11|
|Physical|hub <br/> repeater|資料傳輸的實體設備| t |

# iptables
## 概念介紹
- 用途
:::success
- 擋掉不想要的網路流量 (黑名單)
- 允許想要的流量 (白名單)
- 轉傳封包
:::
## 零件介紹
- 
> 綠色是 table [color=green]
### Chain
> 時間點
:::success
- INPUT: 進入主機的封包
- OUTPUT: 主機送出的封,
- FORWARD: 轉送 (不會經過本機) 的封包
- PREROUTING: 進行路由前 (封包決定要往哪邊走之前)
- POSTORTING: 進行路由後
:::
### Rule
> 設定給 IP tables 的條件、規則
- 
> rule 是有順序性的,如果有符合前一個 rule,做了某個 action,就不會再往下執行,若沒有符合的 rules 就執行 policy
:::success
- 可設定的 rule 狀態:
- ACCEPT
- DROP
- 封包直接丟掉,Client 也不知道封包的去向
- REJECT
- 會回傳告知 Client 封包不行通過
- 之類的
:::
### Policy
- 預設行為
### Table
- Filter
- 過濾封包
- NAT(Network Address Translation)
- 來源與目的之 IP 或 port 的轉換
:::info
**其他少用的 Tables**
- Mangle
- 跟封包的 metadata 有關
- raw
- security
:::

## 操作
### 查看
- `sudo ipatables [-t table] -L [-nv --line-numbers]`
- `-t`: 選擇 table,例如 nat 或 filter,預設 filter
- `-L`: 列出 table 的規則
- `-n`: 不反查
> 工作會比較快
- `-v`: 列出更多資訊
- `--line-numbers`: 顯示出行號
> 每條路都加上編號
#### 範例
- `sudo iptables -L`
- 列出 filter 三個 chain 的規則
- `iptables -t nat -L -n`: 列出 nat 三個 chain(INPUT、FORWARD、OUTPUT) 的規則
- 
- `target`: 進行的動作
> 常見的有 ACCEPT 是放行,REJECT 是拒絕是斷線
- `prot`: 使用的封包協定,主要有 TCP, icmp...
- `opt`: 額外選項說明
- `source`:針對哪個來源的 IP
- `destination`: 針對哪個目的的 IP
### 添加
- `iptables -t nat -A output ! -d 127.0.0.1/24 -m addrtype --dst LOCAL -j DOCKER`
- `-A`: append
- `-j`: 代表要做的動作
- iptables 指令定義是一條在 table 內的 rule
- 架構
- table: 要放在哪個 table
- chain: 封包的達到時間點
- match: match 的條件
- module: 使用那些 iptable modules
- target: 支援的行為或是跳到其他 chain
- ACCEPT、DROP、REJECT、RETURN、LOG......
### 定義 Policy
- `iptables [-t] -P <INPUT, OUTPUT, FORWARD> <ACCEPT, DROP, ...>`
#### policy 範例
- 設定 FORWARD policy,預設 DROP
```=
sudo iptables -P FORWARD DROP
```
> 輸入完後:
> 
### **新增一條規則**
- `iptables [-t] [-A or -I] <INPUT, OUTPUT, FORWARD...> -j <ACCEPT, DROP, REJECT> [-i -o -p -s -d]`
- `-A`:==append==,在最後面新增一條規則
- ex: -A INPUT
- `-I`:==insert==,插入一條規則,預設放在最前面,也可以指定要放在第幾條,會把原本存在的rule都往後擠
> rule 是有順序的
- `iptables -I <INPUT, OUTPUT,FORWARD...> -j <ACCEPT,DROP,REJUCT> [number]`
- `-j`:==jump==,如果符合規則要做什麼動作(ACCEPT,DROP,REJECT之類)
- `-i`:==in interface== 封包進入的網路介面(網卡),與 INPUT chain 配合
- ex: -i eth0
- `-o`:==out interface== 封包出去的網路介面,與 OUTPUT chain 配合
- ex: -o lo
- `-p`:==protocol==,協定 TCP、IP、ICMP 之類,可以看是哪種封包
> 設定你想要的封包的協定,如果符合了,就可以做 `-j` 的動作
- ex: -p tcp
- `-s`: ==source address==,封包來源位置
- ex: -s 192.168.0.1
- `-d`: ==destination address==,封包的目標位置
- ex: -d 10.22.22.173
:::info
- `-s` `-d`想要表示非某個 IP 時,可以在前面加上驚嘆號`!`
- ex: `iptables -A INPUT ! -d 192.168.0.1 -j DROP`
- `-p` 當後面的參數是 tcp 或 udp 時,可以用
- `sport`:source port,來源 port 號,可以是連續的,例如1024:65535
- `dport`: destination port, 目標 port 號
- 範例 `iptables -A INPUT -p tcp --dport 22 -j DROP`
- DROP 掉 22 port 的 tcp 封包
:::
#### 新增-範例
- DROP 掉來自 192.168.0.1 的流量
```=
sudo iptables -A INPUT -s 192.168.0.1 -j DROP
sudo iptables -L -n
```
> 
:::info
### `-A` & `-I`
- 使用 `-A` 來新增 rules,會在原有的 rules 往下增加
- 使用 `-I` 來新增 rules,會在原有的 rules 之上往上 insert

:::
- 擋掉 eth0 這張網卡進來的連線
```=
sudo iptables -A INPUT -i eth0 -j DROP
```
- 擋掉 192.168.0.1 這個 ip 進來的連線
```=
sudo iptables -A INPUT -s 192.168.0.1 -j DROP
```
- 擋掉 http 連線
```=
sudo iptables -A INPUT -p tcp --dport 80 -j DROP
```
### 清除
- `sudo iptables [-t] -D <INPUT,OUTPUT,FORWAED...> <rule 編號>`
- `-D`: ==delete==,刪除某個 chain 裡面第幾號的 rule
> 可以下指令查也可以自己數
- `sudo iptables [-t] -F <INPUT,OUTPUT,FORWARD...>`
- `-F`: ==flush==,清除掉整個 chain 裡面的 rule
#### 清除-範例
- 刪除 NAT 的 PREROUTING 裡的第三條 rule
```=
sudo iptables -t nat -D PREROUTING 3
```
### 情境

- 讓 good user 可以存取到 http server (policy 要是 DROP)
```=
iptables -A INPUT -i eth1 -s 192.168.0.101 -j ACCEPT
```
- 讓 bad user 無法存取到 http server (policy 要是 ACCEPT)
```=
iptables -A INPUT -i eth1 -s 192.168.0.102 -j DROP
```
### 儲存
> iptables 做的改變若沒有做 save&restore,在重新開機後都會清除。[color=yellow]
- `iptables-save`
- 顯示 iptables 目前所有的設定
- `iptables-restore`
- 將 iptables-save 的資料套用回來
#### 常用作法
- 將 iptables-save 的結果寫入檔案
```=
sudo iptables-save > iptables.conf
```
- 需要將儲存起來的檔案回復時
```=
sudo iptables-restore < iptables.conf
```
#### iptables-apply
- 嘗試設定新的 iptables 規則,然後詢問使用者是否 OK,不 OK 就會變回舊的
- 中間會有等待時間 timeout
- 如果新規則讓使用者斷掉連線,那使用者就無法回應, timeout 之後就會變回舊的
- 預設 rulefile(iptables-save 輸出的內容) 路徑
- `/etc/network/iptables.up.`
:::warning
## 小實作
- 不要讓來自 192.168.1.1 的封包進來
- 允許要去 80 port 的 tcp 進來
- 預設其他都 DROP
### 實作結果

:::