---
title: '網路分層、網路層 IP、路由'
disqus: kyleAlien
---
網路分層、網路層 IP、路由
===
## OverView of Content
如有引用參考請詳註出處,感謝 :cat:
以下使用 Ubuntu 22.0.4 系統;
要了解網路可以由兩個點出發
^1.^ 資料要發往哪裡? ^2.^ 接收方怎麼知道接收了什麼?
[TOC]
## 基礎用語
### 網路硬體
* 了解基本的硬體使用
| 名稱 | 作用原理 | 使用 |
| -------- | -------- | -------- |
| 集線器 | **==半雙工==**,收到資料後,發給每一個接上的裝置,再由裝置決定是否接收 | 花費時間,又製造不並要的流量,**幾乎不常見** |
| 交換器 | **==全雙工==**,只把資料傳送到目標電腦,不會消耗多餘資源 | **必須按照 MAC 地址分辨出個別的裝置,所以作用在 ++==資料連結層==++** |
| 路由器 | 比起上面兩個裝置高級 | **作用在 ==網路層==,可訪問++不同網段++的裝置** |
交換器會把連接到的裝置上的 MAC 地址取出,並存在一個 **++CAM資料表中++**,當收到資料時會讀取資料層的 MAC 地址並參照 CAM(`Content Addressable Memory table`)
### 流量類型:廣播、群播、單播
* **有分為三種,廣播、群播、單播**
1. **廣播 `broadcast packet`**:(也稱之為單播廣播)
又可分為 **資料層、網路層** 的廣播,通常網路層可使用範圍中最大的 IP 地址,**通常最大的地址都作為廣播地址** (並非絕對),**它的作用範圍到路由器為止(不會傳至路由器 IP)**
:::info
* 以子網路 mask `255.255.255.0` 來說,廣播地址的最後一碼就是 `192.168.0.25`
:::
> 
2. **群播 `multicast`**:(也稱為多播)
目的在於 **儘量節省網路頻寬**,當單一來源要傳送至多個目的時,通常必須多次傳輸,但使用群播就可以減少流量
> 只能依靠 **++特殊的通訊協定++** 才能使用群播,減少傳輸的流量,通常是用一個特殊的地址,它會收集所以要傳輸的地址
:::info
* 以 IPv4 協定來說,**群播的地址為 `224.0.0.`0 到 `239.255.255.255` 之間**;IPv6 則是 `FF` 開頭的 IP 地址
* **群播地址不同於單播廣播地址,它是一個範圍,而不僅僅是子網中的一個地址**
* Java 應用群播案例請看 [「**MulticastSocket-介紹:群播-IP**」](https://hackmd.io/zbVv5CAsTWK84JprGAmsjQ?both#MulticastSocket-%E4%BB%8B%E7%B4%B9%EF%BC%9A%E7%BE%A4%E6%92%AD-IP)
:::
```mermaid
graph TB;
外部請求回應 --> 路由器
路由器 -.-> 群播
群播 --> Local_PC_1
群播 --> Local_PC_2
群播 --> Local_PC_3
```
3. **單播 `unicast packet`**:
單一傳輸,一個裝置至另一個裝置,**單播的細節要看使用的通訊協定**
## 網路分層
* 按照**工業標準的 OSI 模型**,通訊協定可以依照各自的功能加以區分
* 網路分層的目的是為了將複雜的作業分割出責任,每一層都有專屬的任務,但依照實現又會有所不同,**主要有分為 7 層、5 層**
**主流的 ==TPC / IP 就是實現 5 層架構==** (有些更簡潔,會省略資料層)
> 
以下為每層的數據單元、常用通訊協定
| 階層 | 資料單元 | 常用通訊協定 |
| -------- | -------- | -------- |
| `Phycical` 物理層(最底層) | 位元 | `RJ45`、`乙太網路卡` |
| `Data` 資料層 | 訊框 \ 幀 | `Ethernet`、`TokenRing`、`FDDI`、`AppleTalk` |
| `NetWork` 網路層 | 封包 \ 數據包 | `IP`、`IPX`、`ICMP`、`IGMP` |
| `Transport` 傳輸層 | 區段 | `TCP`、`UDP`、`SPX` |
| `Session` 會議層 | 資料 | `NetBIOS`、`SAP`、`SDP`、`NWLink` |
| `Present` 表達層 | 資料 | `ASCII`、`MPEG`、`JPEG`、`MIDI` |
| `Application` 應用層 | 資料 | `Http`、`SMTP`、`FTP`、`Telent` |
> **會議層**:**負責發起連線、維持、中斷,==負責通訊的管理==**
>
> **表示層**:**對來自應用層的數據格式進行解釋,主要進行 ==++壓縮、解壓縮、加密解密++==**,對語法覆與相應的函意,並按照一定個格式傳入會議層
### 協定堆疊 - 封包 PDU
* 上述的七層協定使用的方式稱為 **++協定堆疊++ (`protocol Stack`),在封裝的過程所做出的 ==協定資料單元 (PDU, `Protocol data unit`)==**
> 傳輸就是 PDU 在包裝、接收則是 PDU 拆包裝
>
> 
* TCP / IP 在存取資料時基礎基礎單位就是 **封包**,在 OSI 網路 7 層模型中,會根據不同協定位資料做不同的包裝,基本上我們是不會直接操作到封包
``` mermaid
graph TD;
本機-應用層-->本機-表現層;
本機-表現層-->本機-傳輸層;
本機-傳輸層-->本機-網路層;
本機-網路層-->本機-資料鏈節層;
本機-資料鏈節層-->本機-實體層;
本機-實體層
```
* Linux 中可以使用 `ping`、`tracepath` 命令傳送封包到指定 IP 位置
1. **`ping` 命令**:檢查主機是否有回應
```shell=
ping 8.8.8.8
```
> 
2. **`tracepath` 命令**:追蹤網路封包傳送訊息
```shell=
tracepath -b 8.8.8.8
```
> 
### Phycical 物理層
* 可理解為軟體轉換硬體線路的一層,**負責物理傳輸**,**將類比與數位型是之間的轉換(轉為 01 高低電壓)**
eg. **網卡、RJ45、集線器、中繼站、分流器… 等等**
> 
* 另外我們更常見的運作在 OSI 物理層的裝置就是「**集線器**」:
**集線器**(`Hub`):以半雙工模式(`half-duplex mode`)運作,一次只能收或是發,它算是實體層中的中繼裝置(`repeating device`),現在已經很少見
:::warning
* 之所以少見是因為它會把封包無條件地發送到區網所有的子裝置中,導致不必要的網路流量
:::
> 
```mermaid
graph LR
物理層 <-.-> Hub <-.-> 資料層
```
### Data 資料層 (數據鏈路層)
* 主要功能是如何在 **不可靠的物理線路上進行數據的可靠傳輸**;它會 ***++包裝實體乙太網路地址資訊++***
> 該層有稱為 **鏈路層**、網路介面層
* 從網路層接收到的 **數居被分割為特定物理層可傳輸的「幀」**
**幀的內容有傳送、發送方的地址、糾錯 & 控制訊息 (類似 `CRC` 驗證)**,如果接收方出錯會發送通知要對方重新發送一幀
:::info
**資料層的單位為: ==幀== (幀為結構體)**
:::
* 運作在 OSI 資料層的裝置就是「**交換器**」:
**交換器**(`Switch`):它以全雙工模式運作(`full-duplex devices`),可以同時收發資料,它不會把封包發到每個子網路中,優化了集線器的缺點
> 
```mermaid
graph LR
資料層 <-.-> Switch <-.-> 網路層
```
### NetWork 網路層 - 路由器
* **網路層的重點在於,它與硬體、作業系統無關**,在任何機台上 **只要符合網路層的協議** 都可以發送、接收
* 決定如何將數據發送方,到路由接收方,**建立網路連結,提供上層使用,*++IP 協議就在這一層++*,它會決定封包目的地**
> **IP 協議規定網路所用的包的傳輸規則**(協議)
該層也用來規定識別來源的主機(`src`)、目的主機(`dest`)
:::info
**網路層的單位為: ==數據包==**
:::
* 運作在 OSI 網路層的裝置就是「**路由器**」:
> 
由於 **網路是無中心的拓樸** 結構,主機(電腦)可以至於不只一個子網路中,通常其中會 **有一個區域管理機台(管理多個 PC 裝置),負責轉發接收到的資料到裝置、代替裝置傳遞資料到外部**,這種機台稱為路由器
> 
```mermaid
graph LR
網路層 <-.-> 路由器 <-.-> 傳輸層
```
:::danger
* **網路 IP 地址不能重複**,通常表達方式都是以 10 進制來表達網路地址,方便人們查看(`地址-A`.`地址-B`.`地址-C`.`地址-D`)
* `地址-A`、`地址-D` 的範圍是 `1 ~ 254`
* `地址-B`、`地址-C` 的範圍是 `0 ~ 255`
:::
### Transport 傳輸層
* 傳輸層又稱為 **協議(協定)層**,最有主流的**有 *++TCP(可靠傳輸) / UDP(不可靠傳輸) 傳輸協議++***
:::info
**傳輸層層的單位為: ==數據段==**
:::
### Application 應用層
* 當由下至上,傳輸層收到應用層的數據時,要進行對數據的解讀,解讀就會相關到格式,Ex: `HTTP`、`FTP`、`TENLENT`、`SMTP`、`POP3`
:::info
**應用層就是決定 ==數據格式==**
:::
## 物理層 - 乙太網卡
網卡就是硬體物理(實體)層,其中最常見的就是乙太網,而 **乙太網也有很多種,從有線到無線**(都在 `IEEE 802` 標準中),它們有以下共性
:::success
**乙太網不是物理設備**,它是物理設備的一個 **協定規則**… 並且它會 **作用在物理層、資料層之間**
:::
1. 乙太網的設備都 **有 MAC 地址**,而 **Mac & 網路層的 IP 沒有關係**,它在所處的 LAN 區域網路中必須是唯一,48 bit 組成,像是 `11:99:55:22:22:00`
> 但是在大型區域中,**MAC 地址是可能重複的**(很多開發版的 MAC 會是相同的)
>
> 並且部份網卡的 MAC 地址是可以重新設定的
2. 乙太網會將數據包裝為 **「框」的形式** 發送,並且 **框中會包含 MAC 地址** 的資訊!
> 只包含 MAC 地址,不會包含 IP 位置
3. **乙太網就是一個網路中的子網路**
> 假設同一台電腦有兩個乙太網設備,那 **兩個乙太網也沒辦法直接溝通**,必須透過 Route 才能相互通訊(建立橋樑)
``` mermaid
graph LR;
subgraph 乙太網_A
網路界面A
end
subgraph 乙太網_B
網路界面B
end
乙太網_A -.-> |x 不可直接通訊| 乙太網_B
```
### Linux 抽象化網路 - 網路介面
* 網路層、實體層的連接方式如果要靈活就必須透過一個介面(協議)建立兩者之間的關係;藉此 **Linux 核心會創建一個 ++網路介面++**,透過網路介面將兩者對應起來
```java=
// 概念程式
Map<物理層標示, 網路層標示>
```
:::info
所以「網路界面」的概念,是軟體抽象的結果
:::
* **網路介面**:網路介面的成稱通常包括它的硬體類型 (eg. `eth` 乙太網、`wlan` 無線介面、`lo` 本機內網),可以使用 `ifconfig` 命令查看當前裝置有的網路介面
> 
:::info
* 更多乙太網設定可以使用 `ethtool` 工具
:::
### 目標主機的 MAC - IP、ARP
* **物理層傳遞的資料**(「框」中的資料):
封包經過 IP 層後會被封裝成乙太網認識的樣式(框),**乙太「框」中不包含目標 IP 位置資訊,++只會有目標 MAC 地址++**;
:::success
* 這表示網路傳輸不會帶有 IP 地址?
不,**網路傳輸仍會攜帶目的地的 IP 地址、來源地址**,只是不包含在乙太框的資料中,乙太框是包 MAC 地址的
:::
* Okay~ 那在封裝過程中,**怎麽知道目標主機的 MAC Adress 呢**?
* 這是透過 **ARP**(`Address Resolution Protocol`) 機制,它存在傳輸層、實體層之間,這個機制會幫我們 ^1.^ **維護一個 ARP 快取**,如果沒有快取則會幫我們 ^2.^ **自動尋找 MAC 地址**,不需要我們手動尋找目標的 MAC 地址
> ARP 屬於網路層協議(OSI 第 3 層)
可以透過以下命令查看本機的 ARP 快取
```shell=
arp -n
```
> 
* 如果 ARP 快取中沒有目標主機的 MAC 地址(這種情況下稱為 `ARP cache miss`),**本地主機就需要進行 ARP 解析來獲取目標主機的 MAC 地址**
1. 本地(來源)主機會建立一個 ARP 請求包(框),來取得目標 IP 對應的 MAC Address
2. 本地(來源)主機向目標子路路的整個實體層網路發出 **廣播**(這個廣播是攜帶 ARP 請求包的)
3. 當目標接收到時,就會回覆一個包含 `MAC` 地址的封包,返回給來源
4. 緩存到本地 ARP 快取
:::warning
* 如果本地網路都沒有目標 MAC 地址?
**ARP 只應用於本地子網路**,如果本地子網路沒有對應的 MAC address 那就會 **發送到路由器中**,可以使用以下指令查看對應的界面的 ARP 快取
> 也就是說路由器接收到後,會往上一層網路進行 ARP 訪問,最終找到對應的 MAC address 並反回到主機
```shell=
arp -i <interface>
```
:::
## 網路層 - IP 位址
IP 位址就是網際網路或其他網路的 `伺服器` or `路由器` 的 **++唯一++ 編號**,這樣才能在全世界不同的裝置中傳輸到目標裝置
這個 **IP 位址** 又分為 **私人位址**、**全球位置**
### IP 表示方式
* IP 目前有分為兩種 ^1^ `IPv4` (可能會被用完)、^2^ `IPv6` 格式
1. `IPv4` 格式:
**由 32 bit 組成**,為了方便我們查看,會將 32 bit 切分為 4 個 Byte 並透過十進位表示
:::warning
有幾個要注意的部份
* IPv4 的上限就是 2^32^
* 不會有負數
:::
```shell=
# 10 進位表示(方便人們讀取)
192.168.0.1
# 2 進位表示 (同上)
11000000 10101000 00000000 00000001
```
2. `IPv6` 格式:
為了避免 IPv4 使用完畢,所以發展出 IPv6,IPv6 **由 `128 bit` 組成**;為了方便我們查看,會將 128 bit 切分為 16 個 Byte 並透過十進位表示
```shell=
# IPv6 16 進位表示法
C0A8:0000:0000:0000:0000:0000:0000:0001
```
### IP 位置、網路介面 - ifconfig
**網路介面是軟體抽象化的結果**
* 使用 `ifconfig` 命令(或是 `ip`)可以查看到當前主機的 **網路層、實體層**... 等等細節
```shell=
ifconfig
```
下圖也可以看出 **網路介面**,資料就是從網路介面傳輸、接收,一台裝置中可以有多個網路介面(網路介面可以虛擬化)
| 網路介面 | 概述 |
| - | - |
| `eth0` | 乙太網路介面 |
| `lo` | 內網自身網路介面 |
| `wlan0` | 無線網路介面 |
> 
### 子網路 - 私人網路
* 一般來講每個公司會將分配到的全球 IP 位置,再經過 **閘道(路由)分配 子網路 給每台電腦** (閘道有全球 IP,而閘道下分配的就是私人網路 IP)
:::info
* 網際網路是由多個子網路組成
> 
:::
1. 子網路(私人網路)之可以相互存取(當然也可以禁止)
2. 不管是要訪問外部網路,還是內部網路 **都需要經過閘道**,標準的閘道器稱為 **==預設閘道==**,如果你的網路只有一個閘道那就是預設閘道
* **私人 IP 網路位址**
是在某個公開網路下所分配的位址,**私人 IP 並不會與公開網路 IP 衝突**;大部分路由器都有 `16 bit` 的私人位址(2^16^ 位址)
> 通常以 `192.168` 開頭的位置就是私人 IP 位置
:::success
詳細網路規範是由 [**RFC (Request For Comments)**](https://zh.wikipedia.org/zh-tw/RFC) 來規範
:::
### 網路分級 - Class & CIDR
* Class:以前在做網路分級時很常使用 Class 區分,這是一種比較概略的區分方式
| Class 等級 | IP 範圍 | 可分配的 IP 數量 |
| -------- | -------- | -------- |
| A | `0.0.0.0` ~ `127.255.255.255` | 16,777,214 |
| B | `128.0.0.0` ~ `191.255.255.255` | 65,534 |
| C | `192.0.0.0` ~ `223.255.255.255` | 254 |
:::info
* 也有 D、E 的 Class,但用在特殊用圖
:::
* **`CIDR` (`Classless Inter-Domain Routing`) 表示法**:將網路部份分為 **網路、主機**,網路部分使用遮罩擋住,剩餘則是主機
> 這比起 Class 更能有效的利用網路 IP 位址
假設子網路需要 400 個 IP 位址,可以**設定 `23 bit` 為網路、`9 bit` 為主機**,這樣就能分配到 2^9^ 位址(也就是 512 個位址)
> 同樣狀況如果使用 Class 分級就只能指定為 B Class,這樣會浪費很多空間
這 9 bit 就是私人主機位址可分配到的位置(與外界網路無關)
| 長形式遮罩 | CIDR 表示法 |
| - | - |
| 255.0.0.0 | 8(主機可分配 24) |
| 255.255.0.0 | 16(主機可分配 16) |
| 255.255.255.0 | 24(主機可分配 8) |
### 網路遮罩 & 前綴
* 使用 CIDR 表示時會分為 **網路、主機** 兩個部份,會配合使用 **網路遮罩 or 子網路遮罩** 這類特殊位置
1. **網路遮罩**:屬於 **網路部份的 bit 都是 1,主機部份都是 0**
```shell=
# 23 bit 網路遮罩表示如下
11111111 11111111 11111110 00000000
# 轉會 10 進位就是
255.255.254.0
```
2. **網路前綴**:網路前綴就是寫出網路位址所佔用的 bit 數量
```shell=
# 23bit 網路前綴表達方式如下
/23
# 可以配合網路位址一起表示
192.168.1.0/23
# 另一種表達方式
192.168.1.0/255.255.254.0
```
### 子網路 & IP 位置限制
* 子網路(主機位址)並不是都可以拿來分配(0 ~ 255 之間),其中有幾個 **通常會保留的位址**
1. **網路位址**(最大位址)
:::success
* 網路位址在設定時不會設定到,那 **網路位址是幹嘛的**?
這個網路位址的功能在於 **識別整個子網路**(一個電腦可以享有多個子網路),**子網路是所有主機共用的一部分**
> 並且通常 **由系統來自動處理**
```mermaid
graph TB;
subgraph PC
網路位址_192.168.0.0/24
網路位址_10.8.0.0/24
end
```
:::
2. **閘道**(路由)位址
閘道是個別主機用來訪問到路由器的位址,而路由器又會對外訪問到外部網路
```mermaid
graph LR;
subgraph PC
閘道_IP_192.168.0.1
end
subgraph 路由器
閘道_IP_192.168.0.1_ --> 對外_IP_10.100.9.0
end
閘道_IP_192.168.0.1 -.-> 閘道_IP_192.168.0.1_
對外_IP_10.100.9.0 -.-> 外部資源
```
3. **廣播位置**(通常為最小位址)
```shell=
# 1. 24 bit 網路位址
192.168.0.0/24
# 2. 閘道位址 (可以更改)
192.168.0.1
# 實際可分配的位址
192.168.0.2
192.168.0.3
192.168.0.4
...
192.168.0.254
# 3. 廣播位置
192.168.0.255
```
從這裡可以了解到每個 子網路至少要預留 3 個 IP 位置,所以 **將網路分割的太小不利於使用效率(會有太多預設位址,導致能分配的位址減少)**
## DHCP 概述
DHCP 就是動態幾基設定協定(`Dynamic Host Configuration Procotol`),它可以用來獲取 IP、子網路遮罩、DNS 服務器
除了可以自動取得網路設定之外,也可以避免 IP 衝突,減低網路更變帶來的影響;**DHCP 是一種服務器,它能讓子網路的主機對其發送請求,並回應子網路的主機網路定**
:::success
* **DHCP 網路設定是一種租借 IP 的設定,當到期時要請求 DHCP 伺服器取得新的網路設定**
* **通常路由器也充當 DHCP 伺服器**
:::
### IP 位址 & DHCP
* 路由器、伺服器這類對外提供服務的機器如果不固定 IP 位址,使用該服務的裝置就無法順利訪問 (當然可以透過 DNS 伺服器再找到正確的位址,但這就比較花時間)
> 如果有 **固定 IP 位址就不會產生這類型問題**
* 最常見的固定 IP 位址就是網路供應商([**ISP**](https://zh.wikipedia.org/wiki/%E4%BA%92%E8%81%94%E7%BD%91%E6%9C%8D%E5%8A%A1%E4%BE%9B%E5%BA%94%E5%95%86), `Internet Service Provider`) 提供的位址,通常 ISP 提供的位址就是全球 IP 位址
:::info
但由於全球 IP 位只有限,所以 ISP 會將沒用的 IP 位置再回收利用
:::
* **DHCP(`Dynamic Host Configuration Protocol`)自動分配**:
1. 全球網路 IP 的分配可以從 `DHCP` 伺服器空著的位址指派,所以每次指派可能都不一樣(這種 IP 稱為 `浮動 IP`、`動態 IP`),如果要固定可能要收錢
2. 私人網路 IP 也可以透過 DHCP 分配
### Linux 下的 DHCP
* Linux 下的 DHCP 分為客戶端、伺服器端
* **客戶端**
網路管理系統都很多中,但是基本上都是基於 `dhclient` 程式來工作
```shell=
# 使用前請移除所以預設閘道
sudo dhclient eth0
```
執行完上面指令後 `dhclient` 會將它的 PID 放置在 `/var/run/dhclient.pid` 中,並將 DHCP 的 **租借資訊** 放置在 `/var/lib/dhcp/dhclient.leases`
> 
* **伺服器端**
可以在 Linux 上執行 DHCP 的服務,用來管理 IP 位置
> 一個子網路中最好只有一個 DHCP 伺服器,這樣可以節省 DHCP 分配 IP 位置的複雜度(省去溝通、重複...等等問題)
## 路由器 Router
* 如果傳送到外部網路就不會知道傳送路線,此時就要參考 **==Routing Table 路由表==**,並有以下兩種狀況
:::success
如果是要傳送到同網域中的機台,封包會直接被傳送到指定目的 (也就是內網)
:::
1. 知道要傳送的位址後,封包就會往該網路的閘門傳送
2. 不知道路線,資料就會往預設閘門傳送(並不斷往上層路由傳送)
* 在實際情狀中,**閘門(`Gateway`)就是指路由器**,路由會檢查封包的傳送目的地,如果在路由表中有找到 IP 位址就會直接傳送過去,否則就會往上一層路由傳送,直到找到目標 IP,**這一系列的行為就稱為 ==路由==**(有點像是責任鏈)
:::info
從這邊我們可以知道,除了內網訪問以外,都需要通過閘道才能向外訪問
:::
可以透過以下命令台查詢當前主機的路由器
```shell=
route -n
```
| Flag 說明 | 說明 |
| - | - |
| U | 該路由是活動的 |
| G | 必須透過路由器才能存取 |
| H | 目標裝置是 Host |
| ! | 拒絕路由 |
:::success
* **route 的參數**:
下圖中觀察 Flag 有 `G` 符號的都是子路網路設備,都需要透過路由器的閘道 (`192.168.8.1`) 來對外訪問
> 而 `192.168.8.0` 不需要閘道 (`0.0.0.0`),也就是本機內網
:::
> 
### 路由器 - NAT
* 我們可以把 Linux 主機作為路由器,用 Linux 主機對外通訊,在將接收到的資料發配給主機之下的子網路(區域網路),如下圖
``` mermaid
graph BT;
外界網路-->Linux主機_對外通訊;
Linux主機_對外通訊-->內網分配閘道192.168.0.1/24;
Linux主機_對外通訊-->內網分配閘道10.20.0.1/24;
內網分配閘道192.168.0.1/24-->子網路A;
內網分配閘道192.168.0.1/24-->子網路B;
內網分配閘道10.20.0.1/24-->子網路C;
```
> 上圖中的子網路(私有網路)之間是不可相互通訊的,**子網路之間必須通過路由器才能通訊**
* NAT(`Network Address Translation`):**為了連接上外部網際網路,我們必須在路由器之上建立一個網路位置轉換,也就是 NAT**
它可以 **將單個外部 IP 分享給整個私有網路**,並且它目前 **只能運作在 IPv4 中**,因為他是為了解決 IPv4 貧乏的問題
:::success
* 對於外部網際網路而言,它只會認知到路由器,而不會知道路由器之下的私有網路如何分配;**在通訊時路由器更像是一個仲介**,簡易過程如下
1. 私有網路主機透過 Getway 發送資料給外部網際網路(假設要傳到 `172.168.44.3`)
2. 路由器 **攔截請求**,暫時不傳出去
3. 路由器開啟與目標(`172.168.44.3`)的連接
4. 路由器連接成功後,偽造一個已經連接的訊息傳給路由之下的私有網路主機
5. 之後的通訊,路由器就會作為一個仲介的角色插入
:::danger
* 路由器作為網路層,它不能認知所謂的連接阜(也就是 **它基本上只能 IP 對 IP 通訊,沒有 Port 的概念**),所以 NAT 需要頗析更多個資訊,幫我們獲取傳輸層的 Port 號
> **NAT 是介於網路層、傳輸層的實做**
:::
:::
## 防火牆
**防火牆是一種 ++軟體++、++硬體++ 的設定**,大多數路由器之中都包含防火牆,用來防衛外部網路的攻擊;它運作在以下時機點
* 接收封包時
* 傳送封包時
* 轉發資料包到其他主機、閘道之時
並且它會在以上這些檢查點做以下檢查
* 來源、目標的 IP
* 來源、目標的 Port (傳輸層的資訊)
* 訪火牆的網路界面
:::info
防火牆可以讓我們接觸到 Linux 核心處理 IP(網路層) 封包的子系統
:::
### Linux 防火牆 - 概述
* 在 Linux 中歸則是鏈式的,Linux 會根據某些判斷(可能是來源、目標、轉發...等等)來決定封包要使用的規則
**整個系統稱為 `iptables`,可以使用 `iptables` 指令在使用者空間建立、修改防火牆規則**
> 最新的是 `nfttables`,可以用來取代 `iptables`
* 我們最常接觸到的是過濾表(`filter tables`),它會控制基本的包流動,該表中包含 3 個基本鏈
1. 輸入 `Input` 鏈
2. 轉發 `Forward` 鏈
> 
3. 輸出 `Output` 鏈
> 
:::success
* 當然除了這些鏈之外,還有像是 `PRETOUTING`、`POSTROUTING`... 等等,完整的規則可以搜尋 `Linux netfilter packet flow`
> 
:::
## 網路層 - 工具
以下兩種網路層工具都涉及 **協定**,透過尋找路由、連接問題
### ping 查找
* **`ping` 工具**:
它是最常見的網路工具之一,它會發送一個 **ICMP 請求** 封包給一台主機,當目標主機接收到時就會回覆一個封包
:::warning
* 由於安全性問題,**並不是每個主機都會回覆 ICMP 請求**
:::
```shell=
# ping 自己的閘道
ping 192.168.8.1
```
其中較為 **重要的是 `icmp_seq` 序列號、`time` 來回時間**
> 
如果目標主機無法收到封包的話會回覆 `Host Unreachable`
> 
### traceroute 追蹤
* **`traceroute` 工具**:
`traceroute` 工具是 **基於 ICMP 協議的工具**,它可以用來 **追蹤封包到達主機的 ++所有路徑++**
```shell=
# traceroute 到 google 路徑
traceroute 142.251.42.228
```
> 
:::warning
* `traceroute` 可能會不連續、不回傳
:::
### netstat - 網路服務工具
* `netstat` 涉及傳輸層、網路層,使用該指令可以查看到相對應的統計資訊,常見 options 如下
| Options | 說明 |
| - | - |
| `-t` | TCP 連接阜 |
| `-u` | UDP 連接阜 |
| `-l` | 列印監聽該裝置的連接阜 |
| `-a` | 列出所有活動中的連線 |
| `-n` | 不使用 DNS 解析(可以加快速度) |
> 
### lsof - 追蹤連接阜
* `lsof` 能追蹤打開的所有檔案,其中也 **包括正在使用、監聽連接阜的程式**;使用格式如下
```shell=
lsof -i[protocol][@host][:port]
```
範例:
```shell=
# 查看 IPv4 的連線相關檔案
lsof -i4
```
> 
```shell=
# 查看 IPv4 的連線相關檔案,並阻止 DNS 解析
lsof -n i4
```
> 
### tcpdump - 擷取分發資料
:::info
* `tcpdump` 並不是每個發行板都預設安裝;使用以下指令先安裝 `tcpdump`
```shell=
sudo apt install tcpdump
```
:::
* **`tcpdump` 可以創建一個虛擬網路界面,並接收網路層接收到、傳輸的資料**;而我們可以對該指令添加一些 **過濾語法**,來找出指定的網路封包
* **基元**:過濾基礎元素
| 基元 | 說明 |
| - | - |
| `tcp` | 過濾出 TCP 協定的封包 |
| `udp` | 過濾出 UDP 協定的封包 |
| `port <port>` | 過濾出指定 Port 的封包 |
| `host <host>` | 過濾出指定 Host 的封包 |
| `net <network>` | 過濾出指定 Network 的封包 |
```shell=
sudo tcpdump tcp
```
> 
* **運算子**:使用運算子可以添加多個條件一起使用
| 運算子 | 說明 |
| - | - |
| `and` | 與條件 |
| `or` | 或條件 |
| `!` | 非條件 |
```shell=
sudo tcpdump 'tcp and port 5938 and not udp'
```
:::success
* 多條件時建議使用引號
:::
> 
## Appendix & FAQ
:::info
:::
###### tags: `網路基礎` `Linux 基礎`