Linux 网络管理
一、Linux 处理数据包过程
当接收到外界主机发送数据时,在它从网卡流入后需要对它做路由决策,根据其目标决定是流入本机数据还是转发给其他主机,如果是流入本机的数据,则数据会从内核空间进入用户空间 (被应用程序接收、处理)。当用户空间响应(应用程序生成新的数据包) 时,响应数据包是本机产生的新数据,在响应包流出之前,需要做路由决策,根据目标决定从哪个网卡流出。如果不是流入本机的,而是要转发给其他主机的,则必然涉及到另一个流出网卡,此时数据包必须从流入网卡完整地转发给流出网卡,这要求 Linux 主机能够完成这样的转发。但 Linux 主机默认未开启 ip_forward 功能,这使得数据包无法转发而被丢弃。Linux 主机和路由器不同,路由器本身就是为了转发数据包,所以路由器内部默认就能在不同网卡间转发数据包,而 Linux 主机默认则不能转发。
另外,IP 地址是属于内核的 (不仅如此,整个 tcp/ip 协议栈都属于内核,包括端口号),只要能和其中一个地址通信,就能和另一个地址通信,而不管是否开启了数据包转发功能。例如某 Linux 主机有两网卡 eth0:172.16.10.5 和 eth1:192.168.100.20,某 192.168.100.22 主机网关指向 192.168.100.20,若它 ping 172.16.10.5,结果将是通的,因为地址属于内核,从 eth1 进来的数据包被内核分析时,发现目标地址为本机地址,直接就回应 192.168.100.22,回应数据包继续从 eth1 出去。
如果 Linux 主机有多块网卡,如果不开启数据包转发功能,则这些网卡之间是无法互通的。例如 eth0 是 172.16.10.0/24 网段,而 eth1 是 192.168.100.0/24 网段,到达该 Linux 主机的数据包无法从 eth0 交给 eth1 或者从 eth1 交给 eth0,除非 Linux 主机开启了数据包转发功能。
在 Linux 上开启转发功能有多种方法:
# echo 1 > /proc/sys/net/ipv4/ip_forward
# sysctl -w net/ipv4/ip_forward=1
以上两种方法是临时生效的,若要永久生效,则应该写入配置文件。linux 系统的 systemd 管理了太多的功能,sysctl 的配置文件也分化为多个,包括 /etc/sysctl.conf、/etc/sysctl.d/.conf 和 /usr/lib/sysctl.d/.conf,并且这些文件中默认都没有 net.ipv4.ip_forward 项。当然,直接将此项写入到这些配置文件中也都是可以的,建议写在 /etc/sysctl.d/*.conf 中,这是 systemd 提供自定义内核修改项的目录。例如:
# echo "net.ipv4.ip_forward=1" > /etc/sysctl.d/ip_forward.conf
可以使用以下几种方式查看是否开启了转发功能。
# sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 0
# cat /proc/sys/net/ipv4/ip_forward
0
# sysctl -a | grep ip_forward
net.ipv4.ip_forward = 0
net.ipv4.ip_forward_use_pmtu = 0
二、网络基本配置文件
网络连接配置文件:/etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
#关联的设备名称
BOOTPROTO={static|dhcp|none|bootp}
#表示引导协议static|none表示静态;dhcp表示动态
IPADDR=192.168.10.10
#设置IP地址
NETMASK=255.255.255.0
#设置子网掩码
GATEWAY=192.168.10.1
#设置网关
ONBOOT=yes|no
#开机时是否自动激活网络接口
HWADDR=00:1E:0B:8F:B0:D0
#硬件地址要与硬件中的地址保持一致可省
DNS1=202.106.0.20
#指定DNS地址
USERCTL=yes|no
#表示是否允许普通用户启用或禁用此接口
PEERDNS=yes|no
#表示是否在BOOTPROTO为dhcp时接受由dhcp服务器指定的dns地址
DEVICE=eth0
#关联的设备名称
BOOTPROTO={static|dhcp|none|bootp}
#表示引导协议static|none表示静态;dhcp表示动态
IPADDR=192.168.10.10
#设置IP地址
NETMASK=255.255.255.0
#设置子网掩码
GATEWAY=192.168.10.1
#设置网关
ONBOOT=yes|no
#开机时是否自动激活网络接口
HWADDR=00:1E:0B:8F:B0:D0
#硬件地址要与硬件中的地址保持一致可省
DNS1=202.106.0.20
#指定DNS地址
USERCTL=yes|no
#表示是否允许普通用户启用或禁用此接口
PEERDNS=yes|no
#表示是否在BOOTPROTO为dhcp时接受由dhcp服务器指定的dns地址
DNS 配置文件:/etc/resolv.conf/
nameserver 127.0.0.1
控制网络是否开启和 IPv6 是否有效和主机名设置文件:/etc/sysconfig/network
NETWORKING=YES|NO
NETWORKING_IPV6=yes|no
HOSTNAME=hostname
NETWORKING=YES|NO
NETWORKING_IPV6=yes|no
HOSTNAME=hostname
定义主机映像文件:/etc/hosts
172.168.10.1 www.baidu.com alias
三、网络管理工具
Linux 目前提供两种网络管理工具,一种是 network,一种是 NetworkManager。
network
network 是控制网络接口配置信息修改后,网络服务必须重新启动,来激活网络新配置,从而使得配置生效。这部分操作对服务而言和重新启动系统时是一样的作用。控制脚本是 /etc/init.d/network 这个文件,可以用这个文件后面加上下面的参数来操作网络服务。例如:
/etc/init.d/network restart
同样也可以用 service 这个命令来操作网络服务例如:
service network restart
NetworkManager
新的网络管理工具,可用检测网络、自动连接网络的程序。无论是无线还是有线连接,它都可以令您轻松管理。对于无线网络, 网络管理器可以自动切换到最可靠的无线网络。利用网络管理器的程序可以自由切换在线和离线模式。网络管理器可以优先选择有线网络,支持 VPN。网络管理器最初由 Redhat 公司开发,现在由 GNOME 管理。
NetworkManager 新版本增强设备以及协议的支持,NetworkManager 最新版有一个全新的漂亮的客户端界面 nmtui。”nmtui” 是 networkmanager 的一个图形化前端。在没有 X Window 的情况下可以用它来方便地配置及管理网络。
四、 网络管理 ip 命令
这是一个极其强大的命令,网络信息显示和管理都可以由 ip 命令来完成。它是一个严格模式化的命令。
1、获取 ip 命令的帮助
先简单说明下 ip 命令的基础和获取帮助的方法。
$ ip -h
Usage: ip [ OPTIONS ] OBJECT { COMMAND | help }
ip [ -force ] -batch filename
where OBJECT := { link | address | addrlabel | route | rule | neigh | ntable |
tunnel | tuntap | maddress | mroute | mrule | monitor | xfrm |
netns | l2tp | fou | macsec | tcp_metrics | token | netconf | ila |
vrf | sr | nexthop | mptcp }
OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] | -r[esolve] |
-h[uman-readable] | -iec | -j[son] | -p[retty] |
-f[amily] { inet | inet6 | mpls | bridge | link } |
-4 | -6 | -I | -D | -M | -B | -0 |
-l[oops] { maximum-addr-flush-attempts } | -br[ief] |
-o[neline] | -t[imestamp] | -ts[hort] | -b[atch] [filename] |
-rc[vbuf] [size] | -n[etns] name | -N[umeric] | -a[ll] |
-c[olor]}
可见命令非常复杂,有很多 options,还有很多 object,每个 Object 又对应不同的命令。但其实能用到的就几个 object:addr/route/neigh/link。
使用 ip object help 可以获取到该 object 的语法帮助。例如:
# ip addr help
在 ip 命令行下,任何 object 都可以写其全名,也可以写其缩写名,例如 address 这个 object,可以简写为 addr,也可以简写为一个字母 a。
# ip a help # 等价于ip address help和ip addr help
尽管还有一个 a 开头的 object 为 addrlabel。这时因为 ip 会从上述语法给出的 object 顺序从前向后匹配,例如 "ip m" 将匹配到 "ip maddr",如果想匹配别的,如 addrlabel,则写长一点即可 "ip addrl"。
2、ip addr
ip addr 用于管理网络设备上的 ip 地址,也可以查看 ip 地址的属性信息。
(1).ip addr add/del
ip address { add | del } IFADDR dev STRING
IFADDR := PREFIX [ broadcast ADDR ] [ anycast ADDR ] [ label STRING ]
以 add 为例:
dev NAME:指定要设置 IP 地址的网卡
local ADDRESS (default):接口的 IP 地址。IP 地址的格式依赖于是 ipv4 还是 ipv6。对于 ipv4 而言,给定地址,可能还需要给定 cidr 的掩码位长度
broadcast ADDRESS:接口的广播地址
label NAME:为该接口的 IP 地址设置 label 名,label 名称必须以网络接口名开头后接冒号,如 eth0:X
del 和 add 的参数相同,且 dev 是必须要给定的,其余的参数可选,因为 del 的时候是通配 del,如果删除时有多个满足条件的条目,则删除第一个条目。
增加 ip:
# ip addr add 192.168.100.45 dev eth0
# ip addr add 192.168.100.35/24 dev eth1
要删除 ip,则简单的多,但必须指定 dev,且最好也指定 cidr 的掩码长度:
# ip addr del 192.168.100.45 dev eth0
# ip addr del 192.168.100.35/24 dev eth1
(2).ip addr show
虽然也有几个选项,但是感觉没什么用,直接 ip addr show 就够了。因为 ip 命令可以缩写,所以可以写为
# ip a show
# ip a s
# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 00:0c:29:71:81:64 brd ff:ff:ff:ff:ff:ff
inet 192.168.100.70/24 brd 192.168.100.255 scope global eth0
inet6 fe80::20c:29ff:fe71:8164/64 scope link
valid_lft forever preferred_lft forever
(3).ip addr flush
用于批量删除地址,该命令其实非常危险,一个不小心就会误伤无辜,所幸的是 flush 的时候不给定任何参数或者没有任何条目可以匹配上的时候将不执行 flush 动作,总之该命令要小心使用。同样也必须给定 dev 参数。
例如删除 eth1 上所有地址。
# ip a flush dev eth1
删除 eth1 上所有的 secondary 地址。
# ip a f secondary dev eth1
3、ip route
该命令维护和查看内核中的路由表。
(1).ip route add/del/change/append/replace
语法格式为:
ip route { add | del | change | append | replace } dest[/cidr_mask] [ via ADDRESS ] [ dev STRING ]
其中 dest 为目标地址,可以是主机地址、网段地址,一般在地址后都会带上 cidr 格式的掩码长度,不带时默认为 32 位长度。如果 dest 为 "0/0" 或者写为 "default",则表示默认路由。
例如添加 / 修改 / 替换普通路由:
# ip route add/change/replace 172.16.10.0/24 via 192.168.10.20
添加 / 修改 / 替换默认路由:
# ip route add/change/replace default via 192.168.10.20
# ip route add/change/replace 0/0 via 192.168.100.2
删除某路由:
# ip route del 172.16.10.0/24
# ip route del default # 删除默认路由
(2).ip route show
列出路由表。语法格式为:
ip route show [to [ root | match | exact ] ADDR_pattern ] [ via ADDR ]
其中 to 关键字是默认关键字,用来匹配路由的目标地址。其后可以跟上修饰符 root/match/exact,exact 为默认修饰符,表示精确匹配掩码位长度,root 修饰符表示匹配的掩码位长度大于或等于 ADDR_pattern 给定的掩码位长度,match 修饰符匹配短于或等于 ADDR_pattern 掩码位长度。例如 "to match 16.0/16" 将能匹配到 "16.0/16"、"16/8" 和 "0/0",但却无法匹配 "16.1/16" 和 "16.0/24" 以及 "16.0.1/24",而 "to root 16.0/16" 将能匹配 "16.0/24" 和 "16.0.1/24"。
via 是根据下一跳的方式来列出路由条目。
例如:
# ip route show to match 192.168/24 | column -t
default via 192.168.100.2 dev eth0 proto static metric 100
其实无需那么花哨,简简单单的 "ip r" 多方便。
(3).ip route flush
批量删除路由表条目。参数和 ip route show 的参数一样。
例如删除由 eth1 出去的路由条目。
# ip route flush eth1
删除下一跳为 192.168.100.70 的路由条目。
# ip r flush via 192.168.100.70
删除目标为 192.168.0.0/16 网段的路由
# ip route flush 192.168/16
(4).ip route save/restore
用于保存当前的路由表以及恢复路由表。保存路由表时,路由表将以二进制裸数据的格式输出,也就是看不懂的二进制文件。恢复路由表时,要求设备的设置和保存路由表时是一样的,恢复时已存在于路由表中的路由条目将被忽略。
例如当前路由表信息如下:
ip r
default via 192.168.100.2 dev eth0 proto static metric 100
192.168.10.0/24 dev eth0 proto kernel scope link src 192.168.10.20
192.168.10.0/24 dev eth0 proto kernel scope link src 192.168.10.20 metric 100
192.168.100.0/24 dev eth0 proto kernel scope link src 192.168.100.54 metric 100
192.168.100.0/24 dev eth1 proto kernel scope link src 192.168.100.74 metric 101
保存当前路由表。
# ip route save > /tmp/route.txt
删除几条路由表。
# ip route flush dev eth0
ip r
192.168.100.0/24 dev eth1 proto kernel scope link src 192.168.100.74 metric 101
恢复路由表。
ip route restore < /tmp/route.txt
4、ip link
link 表示 link layer 的意思,即链路层。该命令用于管理和查看网络接口,甚至可以添加虚拟网络接口,将网络接口分组进行管理。
(1).ip link set
ip link set DEVICE { up | down | arp { on | off } | name NEWNAME | address LLADDR }
选项说明:
dev DEVICE:指定要操作的设备名
up and down:启动或停用该设备
arp on or arp off:启用或禁用该设备的 arp 协议
name NAME:修改指定设备的名称,建议不要在该接口处于运行状态或已分配 IP 地址时重命名
address LLADDRESS:设置指定接口的 MAC 地址
例如,禁用 eth1 网卡。
# ip link set eth1 down
修改网卡 eth1 的 MAC 地址。
# ip link set eth1 address 00:0c:29:f3:33:77
(2).ip link show
语法格式:
ip [ -s | -h ] link show [dev DEV]
选项说明:
-s:将显示各网络接口上的流量统计信息
-h:以人类可读的方式显式,即单位转换。
例如:
# ip -s -h link show dev eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000
link/ether 00:0c:29:f7:43:77 brd ff:ff:ff:ff:ff:ff
RX: bytes packets errors dropped overrun mcast
13.7M 20.0k 0 0 0 0
TX: bytes packets errors dropped carrier collsns
1.59M 9.97k 0 0 0 0