0%

TCP/IP 协议

Preface

最近在看 《鸟哥的Linux私房菜–服务器架设》 这本书,感觉受益匪浅,特别是关于网络、各种协议、安全等方面的知识讲得比较透彻。所以整理了一篇博客,也算顺便温习一遍上学时计算机网络学的知识

  • 本片博客主要介绍 TCP/IP 协议及各层之间的职责
  • 图片使用微软的 Office Lens 拍取鸟哥书中图片截取而来

Overview

  • 最初,网络的数据传递被划分为如下七个层次,亦即 OSI七层协议 (or Open System Interconnection)
    IMG_0058-3

  • 可以看到,数据包从一个应用程序传递到网络上的另一个应用程序,是一层一层传递的过程,每一层只认识对方相同层级的数据,而数据头(Header)就包含了互相认识的信息,所以数据自顶向下被层层Header包裹起来,最后在物理介质上传输

通俗理解,网络协议干的事就是让数据能精确投递到另一个人手中,你比如说网络层的IP数据包Header 就包含了源IP地址、目的IP地址等信息,再比如传输层的源端口号、目的端口号

  • 而如今的 TCP/IP协议 是由 OSI七层协议 简化而来的
    IMG_0059

  • 实际上就是简化合并了一些没那么重要的层,相反,从 TCP/IP 的命名就可以看出传输层网络层的重要性


网络接口层需要知道的就是MAC数据帧,能被网络接口设备(即网卡)处理的数据包裹,也是最终物理层编码成比特流的数据

  • 以太网(Ethernet)是现有局域网采用的最通用的通信协议标准,主要定义了局域网内的传输协议(比如CSMA/CD),还有数据帧的格式、大小等。以太网的传输主要就是网卡对网卡的传输

  • 数据从一个网卡出,以数据帧(frame) 在链路上传递,再从另一个网卡进,所以MAC数据帧必须包含了来源和目标的网卡卡号
    C7A05D1BF522B158CE16E65E6BED7209

  • MAC地址(or Media Access Control),其实指的就是网卡卡号(Hardware Address,硬件地址),每张以太网卡出厂就会有个独一无二的卡号

  • 可以看到我的 MAC地址,以及 MTU(or Maximum Transmission Unit)为1500,也就是说一个数据帧最大传输 1500bytes

    1
    2
    en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
    ether 8c:85:90:85:e3:c7

    Screen-Shot-2018-01-02-at-9.58.18-PM


Internet Layer

在网络层传输的是IP数据包IP 的全称是 Internet Protocol ,目前有IPv4IPv6两个版本,本文涉及的为IPv4

  • IP数据包的 HeaderVersion 版本(如IPv4),Total Length 该IP数据包总长度,最长 2^16-165535 bytes(字节为单位)
    IMG_0061-1

  • Identification辨识码,IP数据包会被封装成数据帧在网络上传输,那就一定不能大于数据帧的 MTU ,如果IP数据包超过数据帧的最大长度,则需要分片,辨识码用于辨识、重组属于同一数据包的IP数据包

  • Time To Live( or TTL)存活时间,最大255,每经过一个路由器减一,为0时该IP数据包将会被直接抛弃

  • Protocol Number协议代码,用于记录数据包使用的协议,常见的有 TCP、UDP、ICMP
    498ADD4210B624434245C9BFF2F58F6A

IP Address

我们经常说的IP地址相当于主机在网络中的身份号码。因为是IPv4,所以是32位地址,我们平时用 “ . “ 分隔每8位,再用十进制表示,所以才有了类似 192.168.0.1 这种IP地址,IPv4 可表示 0.0.0.0 ~ 255.255.255.2552^32 个IP地址

  • IP由网段号(Net_ID)主机号(Host_ID) 组成,Net_Id 相同意味着处于同一物理网络中,Host_ID 区分该网络中的不同主机

IP 分组

  • IP被分组用于不同范围的网络,通常我们会接触到的是A、B、C三组,以 Net_ID 前几位区别

    1
    2
    3
    4
    5
    6
    Class A : 0xxxxxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx  ==> Net_ID 的开头是 0
    |--net--|---------host------------|
    Class B : 10xxxxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx ==> Net_ID 的开头是 10
    |------net-------|------host------|
    Class C : 110xxxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx ==> Net_ID 的开头是 110
    |-----------net-----------|-host--|
  • 从A到C随着 Net_ID 位数减少和 Host_ID 位数增加,意味着该组网络上的可用子网(主机)数减少,网络的作用范围变小,比如 Class B 常用于企业网络,Class C 常用于家庭网络

    1
    2
    3
    Class A :   0.xx.xx.xx ~ 127.xx.xx.xx
    Class B : 128.xx.xx.xx ~ 191.xx.xx.xx
    Class C : 192.xx.xx.xx ~ 223.xx.xx.xx
  • 私有 IP 也分别在 A, B, C 三个 Class 当中各保留一段作为私有 IP 网段

    1
    2
    3
    Class A:10.0.0.0    ~ 10.255.255.255
    Class B:172.16.0.0 ~ 172.31.255.255
    Class C:192.168.0.0 ~ 192.168.255.255

Network、Broadcast、Netmask

  • 通常 Host_ID 全为 0 用来表示整个网段的地址 **(Network IP)**,比如 192.168.0.0

  • Host_ID 全为 1 则表示为广播的地址 (Broadcast IP) ,广播可用于对局域网中所有主机传递数据,比如 192.168.0.255

  • Netmask(子网掩码) 标识了Net_ID 占用位数和可使用的 Host_ID 位数,比如 192.168.0.0 ~ 192.168.0.255 这个 Class C 网络,它的子网掩码就是 255.255.255.0,这个网络也可以 192.168.0.0/24 这样表示,格式为网段地址/Net_ID位数,比如 0.0.0.0/0 代表全网段

    1
    2
    3
    11000000.10101000.00000000.00000000      Network:   192.168.0.0
    11000000.10101000.00000000.11111111 Broadcast: 192.168.0.255
    |----------Net_ID---------|-host--|
  • 还可以继续进行子域的切分,比如 192.168.0.0 ~ 192.168.0.255 中拿出一位 Host_ID 作为 Net_ID

    1
    2
    11000000.10101000.00000000.0 0000000
    11000000.10101000.00000000.1 0000000
  • 这样就划分出了两个子网,表示方式为 192.168.0.0/25192.168.0.128/25,每个子网下可分配2^7个 Host

Loopback IP

除了预留的私有 IP 网段外,还预留了内部回环网段 127.0.0.0/8,默认的主机 (localhost) 的IP是 127.0.0.1,不需要网卡即可访问

  • 这个在查看/etc/hosts时可以看到这一行,IPv6 用::1表示

    1
    2
    3
    127.0.0.1	localhost
    255.255.255.255 broadcasthost
    ::1 localhost
  • 执行ifconfig看到的lo0也是回环地址的相关信息

    1
    2
    3
    4
    ➜ ifconfig 
    lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384
    options=1203<RXCSUM,TXCSUM,TXSTATUS,SW_TIMESTAMP>
    inet 127.0.0.1 netmask 0xff000000

Gateway/Router

网关/路由器的功能就是负责不同网络间的数据包传递 **(IP Forwarding)**,也就是不同 Net_ID 的网络间进行数据包的转发

  • 每台主机或者路由器内部都会维护一个路由表(Route table) ,发送 IP 数据包时查询该表。若目标 IP 与本机 IP 的 Net_ID 相同时(同一网络),则会直接通过局域网将数据包传送给目标主机。若不属于同一网络,则查询是否有相符合的设置,如果还没有,则将数据包发往默认网关(Default Gateway)

Route Table

  • 在 Ubuntu 下执行route,或者 Mac 中执行netstat -nr可以查看路由表

    1
    2
    3
    4
    5
    6
    7
    # route
    Kernel IP routing table
    Destination Gateway Genmask Flags Metric Ref Use Iface
    default 192.168.1.253 0.0.0.0 UG 0 0 0 eth0
    172.17.0.0 * 255.255.0.0 U 0 0 0 docker0
    127.0.0.1 * 255.0.0.0 U 0 0 0 lo0
    192.168.1.0 * 255.255.255.0 U 0 0 0 eth0

    Destination 就是目标网络的 Net_ID
    Gateway 是对应的网关,可以看到我的默认网关为 192.168.1.253 ,由于 Host_ID 全为 0 或 1 被 NetworkBroadcast 占用,一般网关设置为最后几个可用 IP,Gateway* 或者 0.0.0.0 表示数据包传输到该网络不需要通过网关,比如内网、回环
    Genmask 就是子网掩码,与 Destination 一起标识目的主机或者路由器所在的网段的地址
    Iface(or Interface),IP数据包将从哪个网卡接口转发
    Flags,标识位,U 表示该路由可用、G 表示需要经由 Gateway

DHCP

DHCP( or Dynamic Host Configuration Protocol动态主机配置协议)是一个局域网的网络协议,使用UDP协议工作,可以给内部网络自动分配IP地址

  • 现在再看电脑上网络设置相关字段应该都明白其意思了
    861DECFB-DB0E-4863-A958-4448C560B145

Transport Layer

网络层的 IP 数据包只负责将数据送到正确的目标主机去,但这个数据包有没有被正确接收就是传输层的任务了,传输层常见协议有两个,一个是可靠的、面向连接TCP 协议,一个是不可靠的、无连接UDP 协议

TCP

  • TCP 数据包的报头
    IMG_0091

Source Port、Destination Port,源端口号、目的端口号,用于区分数据包到底发往哪个应用程序。端口号 16 位,也就是说最大 65535
Sequence Number(数据包序号),TCP数据包要被装入IP数据包中,如果过大也需要分段,该字段记录每个数据包的序号用于重组
Acknowledge Number(响应序号),用于确认之前传递的数据包已被正确接收下
Code(or Control Flag状态控制码)有 6 位,表示 6 个不同的属性,为 1 则为真。主要关心的有下面两个:ACK(or Acknowledge)若为 1,代表该数据包为响应数据包SYN(or Synchronous)若为 1,表示发送端希望双方建立同步处理,即建立连接

  • 常见端口号
    IMG_0095

TCP 的三次握手

TCP 协议正是通过三次握手协议了来确认两个主机的连接

IMG_0096

如图,假设左边是客户端,右边是服务器端。
➠ 客户端向服务端发送一个 TCP 数据包,并请求连接 (SYN = 1),数据包序号为 10001
➠ 当服务器接到客户端的数据包后回传一个同时带有 (SYN=1, ACK=1) 的封包,表示
确认收到,也请求客户端连接
。其中 Acknowledge 是要给客户端确认用的,所以该数字比 Sequence Number 多一号 (ack = 10001 + 1 = 10002) 。而服务器也必须要确认客户端接收到服务器的数据包才行,所以也会随机产生一个 (seq = 20001) 发送给客户端
➠ 当客户端收到来自服务器端的 (ack = 10002) 就能够确认之前的数据包被正确接受了,同时发送一个数据包 (ACK = 1, ack = 20002) 给服务器表示确认收到服务端的数据包
➠ 服务器收到数据包后确认无误即可与客户端建立连接

UDP

TCP 面向连接,需要三次握手,传输的成本较高,并且还会有严密的检测机制,不符合要求的数据包会请求重传,所以是可靠传输。而与 TCP 不同,UDP 不提供可靠的传输模式,没有 TCP 的三次握手,传输的消耗自然较低,所以 UDP 适用与视频、音频等实时性要求较高,但数据准确性要求较低的场合

  • UDP数据包的报头就很简单了
    IMG_0098-1

  • 另外,很多的软件其实是同时提供 TCP 与 UDP 的传输协议的,举例来说,查询主机名的 DNS 服务就同时提供了 UDP/TCP 协议。由于 UDP 较为快速,会先使用 UDP 进行传输,当使用 UDP 无法取得正确的数据时,便转换为较为可靠的 TCP 传输。这样可以同时兼顾快速与可靠的传输


DNS

DNS(or Domain Name System,域名解析系统),需要有专门的 DNS 主机用于保存域名IP 的对应关系,一般我们连接上网络后,运营商会提供他们的DNS服务器,这样我们输入的www.baidu.com才会转换成对应的IP地址

  • 查看主机的 DNS 设置,一般保存在/etc/resolv.conf

    1
    nameserver 192.168.0.1
  • 该文件在你连接网络时会自动生成,不同的网络会有不同的 DNS 设置,比如我的阿里云服务器的配置如下,这就是阿里内部的DNS服务器的IP了

    1
    2
    3
    4
    # Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)            
    # DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
    nameserver 100.100.2.136
    nameserver 100.100.2.138