# IPv4 - IPv4 Header [TOC] ## 課程影片 ### 第 7C 講 路由器運作原理以及網路互連技術 L07 3 {%youtube YDc9bV_PfFQ %} ### 第 7F 講 路由器運作原理以及網路互連技術 L07 6 {%youtube zH4Ep41EgfI %} ### [Python Network Packet Sniffer Tutorial - 4 - Unpacking IP Packet Headers](https://youtu.be/oKUkbMz5q7Y) Note: this series starts from Ethernet packet sniffing. {%youtube oKUkbMz5q7Y %} ## IPv4 Header Format 參考 [RFC791](https://datatracker.ietf.org/doc/html/rfc791): ```c 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |Version| IHL |Type of Service| Total Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Identification |Flags| Fragment Offset | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Time to Live | Protocol | Header Checksum | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Source Address | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Destination Address | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Options | Padding | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ``` Linux 核心則定義在 [`include/uapi/linux/ip.h`](https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/ip.h#L86) 中: ```c struct iphdr { __u8 version:4, ihl:4; __u8 tos; __be16 tot_len; __be16 id; __be16 frag_off; __u8 ttl; __u8 protocol; __sum16 check; __be32 saddr; __be32 daddr; /*The options start here. */ }; ``` ## `saddr` 與 `daddr` --- 發送者與接收者的 IP `saddr` 為發送方的 IPv4 位址,而 `daddr` 則為接送方的 IPv4 位址。 ## `id` 與 `frag_off` --- 屬於哪一份資料的哪一個部分? 使用 IP 協定傳輸資料時,一個完整的資料有可能被切分成多個部分,稱為 *fragment*。除此之外,當路由器在轉送封包時,因為不同傳遞媒介的 MTU (*maxima transmision unit*) 有可能不同。如果從一個網路轉送給另外一個網路時,發現單一封包擠不進另外一個網路的 MTU 時,就有可能在轉送的過程中切割從這些封包。比如說:乙太網路單一訊框能承載的資料大小與 WiFi 不同,因此若路由器要將來自 WiFi 的封包轉送給乙太網路,就可能需要切割封包。這些切割的小片段稱為 *fragement*。 這些切割的片段最終需要組合起來,而組合的依據就是 `id` 與 `frag_offset`。 `id` 來確認這些封包的內容是否同屬於一個完整的資料,而 `frag_offset` 則表示這個封包裝得是原先封包哪一個部分的資料。他的單位並不是位元組,而是以 8 位元組為一個單位。也就是當 `frag_offset` 為 $N$ 時,指得是「這個封包裝的 `data`,裝的是原先封包的資料中第 $8N$ 位元組開始」的資料。 ## `protocol` --- 上層協定是什麼? `protocol` 欄位用來表示這一個 IP 封包是拿來裝「L4 中哪個協定」的資料(按:目前所在的 IP 協定是 L3)。 ## `ttl` --- 還可以被轉送幾次? 雖然英文用語是 *time to live*,但實際上是一個用來表示「這個封包還可以被路由器轉送幾次」的計數器。這個欄位一開始會是個非零的數值,而每當封包被路由器轉送一次,這個數值就會減一。當一個路由器發現一個封包的 `ttl` 欄位歸零時,就會捨棄這個封包。 會有這個理由是:如果大量迷路的封包累積在網路中不斷地被轉送,會佔據大量的流量。為了不讓他們持續遺留在網路中於是設計這個機制。 ## `flag` --- 封包的屬性 ```c Bit 0: reserved, must be zero Bit 1: (DF) 0 = May Fragment, 1 = Don't Fragment. Bit 2: (MF) 0 = Last Fragment, 1 = More Fragments. 0 1 2 +---+---+---+ | | D | M | | 0 | F | F | +---+---+---+ ``` ### `DF` --- 封包能不能被切割? 指定封包的屬性。比如說 `DF` 欄位表示這個封包可不可以被切割?如果 `flag` 中被設定了這個值,就表示這個封包不可以被切割。那麼要嘛就幫他找一條都不用分割的路徑,或是如果這樣的路徑找不到,就只能丟棄它。 ### `MF` --- 是不是某個封包的片段? 而 `MF` 位元表示「這個封包是某個被切割的封包的其中一個片段」。如果設為 `1`,表示「目前這個封包不是最後一個片段」; 反之就表示「它是最後一個片段」:  ## `tos` --- 封包的種類 這 8 個位元又細分為幾個欄位。包含: ```c Bits 0-2: Precedence. Bit 3: 0 = Normal Delay, 1 = Low Delay. Bits 4: 0 = Normal Throughput, 1 = High Throughput. Bits 5: 0 = Normal Relibility, 1 = High Relibility. Bit 6-7: Reserved for Future Use. 0 1 2 3 4 5 6 7 +-----+-----+-----+-----+-----+-----+-----+-----+ | | | | | | | | PRECEDENCE | D | T | R | 0 | 0 | | | | | | | | +-----+-----+-----+-----+-----+-----+-----+-----+ ``` ### Precedence 這個欄位的前 3 個位元表示這個封包是一般資料的封包?或是網路的控制封包? ```c Precedence 111 - Network Control 110 - Internetwork Control 101 - CRITIC/ECP 100 - Flash Override 011 - Flash 010 - Immediate 001 - Priority 000 - Routine ``` 相關常數在 [`include/uapi/linux/ip.h`](https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/ip.h#L30) 中有定義: ```c #define IPTOS_PREC_MASK 0xE0 #define IPTOS_PREC(tos) ((tos)&IPTOS_PREC_MASK) #define IPTOS_PREC_NETCONTROL 0xe0 #define IPTOS_PREC_INTERNETCONTROL 0xc0 #define IPTOS_PREC_CRITIC_ECP 0xa0 #define IPTOS_PREC_FLASHOVERRIDE 0x80 #define IPTOS_PREC_FLASH 0x60 #define IPTOS_PREC_IMMEDIATE 0x40 #define IPTOS_PREC_PRIORITY 0x20 #define IPTOS_PREC_ROUTINE 0x00 ``` ### `D`、`T`、`R` `D` 設為 `1` 表示 *low delay*,而 `T` 設為 `1` 表示 *high throughput*、`R` 被設為 `1` 則表示 *high reliability*: ```c Bit 3: 0 = Normal Delay, 1 = Low Delay. Bits 4: 0 = Normal Throughput, 1 = High Throughput. Bits 5: 0 = Normal Relibility, 1 = High Relibility. Bit 6-7: Reserved for Future Use. ``` 在 [`include/uapi/linux/ip.h`](https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/ip.h#L23) 中有定義相關常數: ```c #define IPTOS_TOS_MASK 0x1E #define IPTOS_TOS(tos) ((tos)&IPTOS_TOS_MASK) #define IPTOS_LOWDELAY 0x10 #define IPTOS_THROUGHPUT 0x08 #define IPTOS_RELIABILITY 0x04 #define IPTOS_MINCOST 0x02 ``` 這些欄位用來表示一個封包處理的優先程度。 ## 其他欄位 ### `tot_len` --- 封包的長度 封包的總長度。 ### `check` --- 校驗碼 這整個 *header* 的 *checksum*(包含 *option*) ### `version` --- IP 協定的版本 這個封包使用 IPv4 或是 IPv6。
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up