Try   HackMD

IPv4 - IPv4 Header

課程影片

第 7C 講 路由器運作原理以及網路互連技術 L07 3

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

第 7F 講 路由器運作原理以及網路互連技術 L07 6

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Python Network Packet Sniffer Tutorial - 4 - Unpacking IP Packet Headers

Note: this series starts from Ethernet packet sniffing.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

IPv4 Header Format

參考 RFC791

    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 中:

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. */
};

saddrdaddr - 發送者與接收者的 IP

saddr 為發送方的 IPv4 位址,而 daddr 則為接送方的 IPv4 位址。

idfrag_off - 屬於哪一份資料的哪一個部分?

使用 IP 協定傳輸資料時,一個完整的資料有可能被切分成多個部分,稱為 fragment。除此之外,當路由器在轉送封包時,因為不同傳遞媒介的 MTU (maxima transmision unit) 有可能不同。如果從一個網路轉送給另外一個網路時,發現單一封包擠不進另外一個網路的 MTU 時,就有可能在轉送的過程中切割從這些封包。比如說:乙太網路單一訊框能承載的資料大小與 WiFi 不同,因此若路由器要將來自 WiFi 的封包轉送給乙太網路,就可能需要切割封包。這些切割的小片段稱為 fragement

這些切割的片段最終需要組合起來,而組合的依據就是 idfrag_offsetid 來確認這些封包的內容是否同屬於一個完整的資料,而 frag_offset 則表示這個封包裝得是原先封包哪一個部分的資料。他的單位並不是位元組,而是以 8 位元組為一個單位。也就是當 frag_offset

N 時,指得是「這個封包裝的 data,裝的是原先封包的資料中第
8N
位元組開始」的資料。

protocol - 上層協定是什麼?

protocol 欄位用來表示這一個 IP 封包是拿來裝「L4 中哪個協定」的資料(按:目前所在的 IP 協定是 L3)。

ttl - 還可以被轉送幾次?

雖然英文用語是 time to live,但實際上是一個用來表示「這個封包還可以被路由器轉送幾次」的計數器。這個欄位一開始會是個非零的數值,而每當封包被路由器轉送一次,這個數值就會減一。當一個路由器發現一個封包的 ttl 欄位歸零時,就會捨棄這個封包。

會有這個理由是:如果大量迷路的封包累積在網路中不斷地被轉送,會佔據大量的流量。為了不讓他們持續遺留在網路中於是設計這個機制。

flag - 封包的屬性

      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,表示「目前這個封包不是最後一個片段」; 反之就表示「它是最後一個片段」:

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

tos - 封包的種類

這 8 個位元又細分為幾個欄位。包含:

      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 個位元表示這個封包是一般資料的封包?或是網路的控制封包?

        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 中有定義:

#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

DTR

D 設為 1 表示 low delay,而 T 設為 1 表示 high throughputR 被設為 1 則表示 high reliability

      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 中有定義相關常數:

#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 - 校驗碼

這整個 headerchecksum(包含 option

version - IP 協定的版本

這個封包使用 IPv4 或是 IPv6。