Preface
最近在看 《鸟哥的Linux私房菜–服务器架设》 这本书,感觉受益匪浅,特别是关于网络、各种协议、安全等方面的知识讲得比较透彻。所以整理了一篇博客,也算顺便温习一遍上学时计算机网络学的知识
- 本片博客主要介绍 TCP/IP 协议及各层之间的职责
- 图片使用微软的 Office Lens 拍取鸟哥书中图片截取而来
Overview
最初,网络的数据传递被划分为如下七个层次,亦即 OSI七层协议 (or Open System Interconnection)
可以看到,数据包从一个应用程序传递到网络上的另一个应用程序,是一层一层传递的过程,每一层只认识对方相同层级的数据,而数据头(Header)就包含了互相认识的信息,所以数据自顶向下被层层Header包裹起来,最后在物理介质上传输
通俗理解,网络协议干的事就是让数据能精确投递到另一个人手中,你比如说网络层的IP数据包的 Header 就包含了源IP地址、目的IP地址等信息,再比如传输层的源端口号、目的端口号
而如今的 TCP/IP协议 是由 OSI七层协议 简化而来的
实际上就是简化合并了一些没那么重要的层,相反,从 TCP/IP 的命名就可以看出传输层和网络层的重要性
Link Layer
网络接口层需要知道的就是MAC数据帧,能被网络接口设备(即网卡)处理的数据包裹,也是最终物理层编码成比特流的数据
以太网(Ethernet)是现有局域网采用的最通用的通信协议标准,主要定义了局域网内的传输协议(比如CSMA/CD),还有数据帧的格式、大小等。以太网的传输主要就是网卡对网卡的传输
数据从一个网卡出,以数据帧(frame) 在链路上传递,再从另一个网卡进,所以MAC数据帧必须包含了来源和目标的网卡卡号
MAC地址(or Media Access Control),其实指的就是网卡卡号(Hardware Address,硬件地址),每张以太网卡出厂就会有个独一无二的卡号
可以看到我的 MAC地址,以及 MTU(or Maximum Transmission Unit)为1500,也就是说一个数据帧最大传输 1500bytes
1
2en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
ether 8c:85:90:85:e3:c7
Internet Layer
在网络层传输的是IP数据包,IP 的全称是 Internet Protocol ,目前有IPv4和IPv6两个版本,本文涉及的为IPv4
IP数据包的 Header,Version 版本(如IPv4),Total Length 该IP数据包总长度,最长 2^16-1 即 65535 bytes(字节为单位)
Identification辨识码,IP数据包会被封装成数据帧在网络上传输,那就一定不能大于数据帧的 MTU ,如果IP数据包超过数据帧的最大长度,则需要分片,辨识码用于辨识、重组属于同一数据包的IP数据包
Time To Live( or TTL)存活时间,最大255,每经过一个路由器减一,为0时该IP数据包将会被直接抛弃
Protocol Number协议代码,用于记录数据包使用的协议,常见的有 TCP、UDP、ICMP
IP Address
我们经常说的IP地址相当于主机在网络中的身份号码。因为是IPv4,所以是32位地址,我们平时用 “ . “ 分隔每8位,再用十进制表示,所以才有了类似 192.168.0.1 这种IP地址,IPv4 可表示 0.0.0.0 ~ 255.255.255.255 共 2^32 个IP地址
- IP由网段号(Net_ID) 和主机号(Host_ID) 组成,Net_Id 相同意味着处于同一物理网络中,Host_ID 区分该网络中的不同主机
IP 分组
IP被分组用于不同范围的网络,通常我们会接触到的是A、B、C三组,以 Net_ID 前几位区别
1
2
3
4
5
6Class 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
3Class 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
3Class 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
311000000.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
211000000.10101000.00000000.0 0000000
11000000.10101000.00000000.1 0000000这样就划分出了两个子网,表示方式为 192.168.0.0/25 和 192.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
3127.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 被 Network 和 Broadcast 占用,一般网关设置为最后几个可用 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地址
- 现在再看电脑上网络设置相关字段应该都明白其意思了
Transport Layer
网络层的 IP 数据包只负责将数据送到正确的目标主机去,但这个数据包有没有被正确接收就是传输层的任务了,传输层常见协议有两个,一个是可靠的、面向连接的 TCP 协议,一个是不可靠的、无连接的 UDP 协议
TCP
- TCP 数据包的报头
➤ 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,表示发送端希望双方建立同步处理,即建立连接
- 常见端口号
TCP 的三次握手
TCP 协议正是通过三次握手协议了来确认两个主机的连接
如图,假设左边是客户端,右边是服务器端。
➠ 客户端向服务端发送一个 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数据包的报头就很简单了
另外,很多的软件其实是同时提供 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