--- 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` ::: > ![](https://i.imgur.com/KtDFSX2.png) 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 層架構==** (有些更簡潔,會省略資料層) > ![](https://i.imgur.com/cqbnOIW.png) 以下為每層的數據單元、常用通訊協定 | 階層 | 資料單元 | 常用通訊協定 | | -------- | -------- | -------- | | `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 拆包裝 > > ![](https://i.imgur.com/uN4EEZX.png) * TCP / IP 在存取資料時基礎基礎單位就是 **封包**,在 OSI 網路 7 層模型中,會根據不同協定位資料做不同的包裝,基本上我們是不會直接操作到封包 ``` mermaid graph TD; 本機-應用層-->本機-表現層; 本機-表現層-->本機-傳輸層; 本機-傳輸層-->本機-網路層; 本機-網路層-->本機-資料鏈節層; 本機-資料鏈節層-->本機-實體層; 本機-實體層 ``` * Linux 中可以使用 `ping`、`tracepath` 命令傳送封包到指定 IP 位置 1. **`ping` 命令**:檢查主機是否有回應 ```shell= ping 8.8.8.8 ``` > ![](https://i.imgur.com/T9xY5GR.png) 2. **`tracepath` 命令**:追蹤網路封包傳送訊息 ```shell= tracepath -b 8.8.8.8 ``` > ![](https://i.imgur.com/wIukjOO.png) ### Phycical 物理層 * 可理解為軟體轉換硬體線路的一層,**負責物理傳輸**,**將類比與數位型是之間的轉換(轉為 01 高低電壓)** eg. **網卡、RJ45、集線器、中繼站...等等** > ![](https://hackmd.io/_uploads/BkQSHQr93.png) ### Data 資料層 (數據鏈路層) * 主要功能是如何在 **不可靠的物理線路上進行數據的可靠傳輸**;它會 ***++包裝實體乙太網路地址資訊++*** > 該層有稱為 **鏈路層**、網路介面層 * 從網路層接收到的 **數居被分割為特定物理層可傳輸的「幀」** **幀的內容有傳送、發送方的地址、糾錯 & 控制訊息 (類似 `CRC` 驗證)**,如果接收方出錯會發送通知要對方重新發送一幀 :::info **資料層的單位為: ==幀== (幀為結構體)** ::: 運作在 OSI 資料層的裝置有… 1. **集線器** > ![image](https://hackmd.io/_uploads/HyVbRsHf0.png) 2. **交換器** > ![image](https://hackmd.io/_uploads/ByToAsHzR.png) ### NetWork 網路層 - 路由器 * **網路層的重點在於,它與硬體、作業系統無關**,在任何機台上 **只要符合網路層的協議** 都可以發送、接收 * 決定如何將數據發送方,到路由接收方,**建立網路連結,提供上層使用,*++IP 協議就在這一層++*,它會決定封包目的地** > **IP 協議規定網路所用的包的傳輸規則**(協議) 該層也用來規定識別來源的主機(`src`)、目的主機(`dest`) :::info **網路層的單位為: ==數據包==** ::: * **路由器**: 由於 **網路是無中心的拓樸** 結構,主機(電腦)可以至於不只一個子網路中,通常其中會 **有一個區域管理機台(管理多個 PC 裝置),負責轉發接收到的資料到裝置、代替裝置傳遞資料到外部**,這種機台稱為路由器 > ![](https://hackmd.io/_uploads/SJpUqQrq2.png) :::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` 命令查看當前裝置有的網路介面 > ![](https://hackmd.io/_uploads/rJl5GBUqh.png) :::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 ``` > ![](https://hackmd.io/_uploads/SyQYEDc5h.png) * 如果 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` | 無線網路介面 | > ![](https://hackmd.io/_uploads/B1xW3mB52.png) ### 子網路 - 私人網路 * 一般來講每個公司會將分配到的全球 IP 位置,再經過 **閘道(路由)分配 子網路 給每台電腦** (閘道有全球 IP,而閘道下分配的就是私人網路 IP) :::info * 網際網路是由多個子網路組成 > ![](https://hackmd.io/_uploads/SytLAXBqn.png) ::: 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` > ![](https://hackmd.io/_uploads/rkuKWzY5h.png) * **伺服器端** 可以在 Linux 上執行 DHCP 的服務,用來管理 IP 位置 > 一個子網路中最好只有一個 DHCP 伺服器,這樣可以節省 DHCP 分配 IP 位置的複雜度(省去溝通、重複...等等問題) ### 路由器 * 如果傳送到外部網路就不會知道傳送路線,此時就要參考 **==Routing Table 路由表==**,並有以下兩種狀況 :::success 如果是要傳送到同網域中的機台,封包會直接被傳送到指定目的 (也就是內網) ::: 1. 知道要傳送的位址後,封包就會往該網路的閘門傳送 2. 不知道路線,資料就會往預設閘門傳送(並不斷往上層路由傳送) * 在實際情狀中,**閘門就是指路由器**,路由會檢查封包的傳送目的地,如果在路由表中有找到 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`),也就是本機內網 ::: > ![](https://hackmd.io/_uploads/S1qN-4Hc3.png) ### 路由器 - 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` 鏈 > ![](https://hackmd.io/_uploads/Skk8V8cc2.png) 3. 輸出 `Output` 鏈 > ![](https://hackmd.io/_uploads/BkJ3N8c92.png) :::success * 當然除了這些鏈之外,還有像是 `PRETOUTING`、`POSTROUTING`... 等等,完整的規則可以搜尋 `Linux netfilter packet flow` > ![](https://hackmd.io/_uploads/ByjErIqch.png) ::: ## 網路層 - 工具 以下兩種網路層工具都涉及 **協定**,透過尋找路由、連接問題 ### ping 查找 * **`ping` 工具**: 它是最常見的網路工具之一,它會發送一個 **ICMP 請求** 封包給一台主機,當目標主機接收到時就會回覆一個封包 :::warning * 由於安全性問題,**並不是每個主機都會回覆 ICMP 請求** ::: ```shell= # ping 自己的閘道 ping 192.168.8.1 ``` 其中較為 **重要的是 `icmp_seq` 序列號、`time` 來回時間** > ![](https://hackmd.io/_uploads/HkpnZPH92.png) 如果目標主機無法收到封包的話會回覆 `Host Unreachable` > ![](https://hackmd.io/_uploads/BkAAfDrqh.png) ### traceroute 追蹤 * **`traceroute` 工具**: `traceroute` 工具是 **基於 ICMP 協議的工具**,它可以用來 **追蹤封包到達主機的 ++所有路徑++** ```shell= # traceroute 到 google 路徑 traceroute 142.251.42.228 ``` > ![](https://hackmd.io/_uploads/r1n7NDSqn.png) :::warning * `traceroute` 可能會不連續、不回傳 ::: ### netstat - 網路服務工具 * `netstat` 涉及傳輸層、網路層,使用該指令可以查看到相對應的統計資訊,常見 options 如下 | Options | 說明 | | - | - | | `-t` | TCP 連接阜 | | `-u` | UDP 連接阜 | | `-l` | 列印監聽該裝置的連接阜 | | `-a` | 列出所有活動中的連線 | | `-n` | 不使用 DNS 解析(可以加快速度) | > ![](https://hackmd.io/_uploads/HksEMlfi3.png) ### lsof - 追蹤連接阜 * `lsof` 能追蹤打開的所有檔案,其中也 **包括正在使用、監聽連接阜的程式**;使用格式如下 ```shell= lsof -i[protocol][@host][:port] ``` 範例: ```shell= # 查看 IPv4 的連線相關檔案 lsof -i4 ``` > ![](https://hackmd.io/_uploads/HyP-mlMih.png) ```shell= # 查看 IPv4 的連線相關檔案,並阻止 DNS 解析 lsof -n i4 ``` > ![](https://hackmd.io/_uploads/rJj1BeMo2.png) ### 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 ``` > ![](https://hackmd.io/_uploads/HJPbOxGo2.png) * **運算子**:使用運算子可以添加多個條件一起使用 | 運算子 | 說明 | | - | - | | `and` | 與條件 | | `or` | 或條件 | | `!` | 非條件 | ```shell= sudo tcpdump 'tcp and port 5938 and not udp' ``` :::success * 多條件時建議使用引號 ::: > ![](https://hackmd.io/_uploads/r1wuteMjn.png) ## Appendix & FAQ :::info ::: ###### tags: `網路基礎` `Linux 基礎`