重新理解 Linux 网络(一):IP 地址不是机器的门牌号
作为运维或者开发,你一定每天都在跟 IP 地址打交道。
配置服务要写 IP。
排查网络要 ping IP。
线上访问不通,第一反应也是:
这个 IP 能不能通?
但我先问你几个问题:
如果这些问题你答不上来,不丢人。
因为很多人学网络时,对 IP 的理解都停在一句话上:
IP 地址就是网络里的门牌号。
这句话不能说错。
但放到 Linux 系统里,它很容易把你带偏。
这一篇,我们先不讲复杂的路由表,也不讲防火墙。
我们只解决一个最基础、也最容易被误解的问题:
Linux 里的 IP 地址,到底是绑定在“机器”上,还是绑定在“接口”上?
一、先看一个反直觉的现象
你在 Linux 上执行:
ip addr
可能会看到类似这样的输出:
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 link/loopback 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo inet 127.0.0.2/8 scope host lo2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 link/ether 52:54:00:12:34:56 inet 192.168.1.10/24 brd 192.168.1.255 scope global eth0 inet 192.168.1.11/24 brd 192.168.1.255 scope global secondary eth0
你看到了什么?
一个 lo 上有两个 127 开头的地址。
一块 eth0 网卡上,也有两个 192.168.1.x 地址。
如果你还停留在“一个设备一个 IP”的理解上,这里就会很别扭:
难道我的服务器突然变成了好几台?
当然不是。
问题出在我们对 IP 的理解太粗了。
二、IP 不是简单绑定给整台机器的
在 Linux 里,更准确的理解是:
IP 地址是配置在网络接口上的。
这里的“网络接口”,不一定是一块真实的物理网卡。
它可以是:
一台机器可以有多个接口。
一个接口也可以配置多个 IP。
所以一台 Linux 机器有多个 IP,完全正常。
你可以把层次关系理解成这样:
一台 Linux 主机 ├── lo │ ├── 127.0.0.1 │ └── 127.0.0.2 │ └── eth0 ├── 192.168.1.10 └── 192.168.1.11
这才是看懂 ip addr 的第一把钥匙。
三、为什么我们总以为“一台机器一个 IP”?
因为在日常场景里,确实经常长这样:
比如你的电脑拿到一个地址:
192.168.1.23
你每天都这么用,久而久之就会形成一个直觉:
这个 IP 就是这台机器。
但这只是最简单的情况。
到了服务器环境,事情就不一样了。
比如一台服务器上可能有:
这些地址可能分布在不同接口上,也可能挂在同一个接口上。
所以,“一台机器一个 IP”不是 Linux 的规则。
它只是你在简单网络环境里看到的表象。
四、一块网卡为什么能有多个 IP?
因为 IP 是三层地址,网卡是二层设备。
一块物理网卡负责把数据帧发出去。
但它上面可以挂多个三层地址。
这就像一个办公室只有一扇门,但门口可以挂多个牌子:
门还是那扇门。
牌子可以有多个。
在 Linux 里也是一样。
比如你给同一块网卡添加第二个 IP:
sudo ip addr add 192.168.1.11/24 dev eth0
再看:
ip addr show dev eth0
你可能会看到:
inet 192.168.1.10/24 brd 192.168.1.255 scope global eth0inet 192.168.1.11/24 brd 192.168.1.255 scope global secondary eth0
这不是多了一块网卡。
而是 eth0 这个接口上多了一个 IP 地址。
一个常见场景是:同一台服务器上跑多个站点,每个站点绑定不同 IP。
比如:
192.168.1.10 -> site-a.example.com192.168.1.11 -> site-b.example.com
Nginx 可以根据监听的 IP 区分服务:
server { listen 192.168.1.10:80; server_name site-a.example.com;}server { listen 192.168.1.11:80; server_name site-b.example.com;}
这就是“一块网卡多个 IP”的实际价值。
五、127.0.0.1 为什么永远是本机?
再来看最熟悉的地址:
127.0.0.1
很多人知道它是本机地址。
但不知道的是:
不止 127.0.0.1,整个 127.0.0.0/8 都是回环地址段。
也就是说,像下面这些地址,也属于回环地址:
127.0.0.1127.0.0.2127.10.20.30
你可以在 Linux 上试一下:
ping 127.0.0.2
通常会看到它能通:
PING 127.0.0.2 (127.0.0.2) 56(84) bytes of data.64 bytes from 127.0.0.2: icmp_seq=1 ttl=64 time=0.060 ms64 bytes from 127.0.0.2: icmp_seq=2 ttl=64 time=0.055 ms
为什么?
因为 Linux 内核看到目标地址是 127.0.0.0/8,就知道这是回环流量。
它不会把这个包发到真实网卡上。
它会直接在本机内部处理。
六、lo 是一块什么“网卡”?
lo 是 loopback interface,也就是回环接口。
它不是一块真实网卡。
它是内核虚拟出来的网络接口。
这也解释了一个小白经常疑惑的问题:
为什么我拔掉网线以后,还能 ping 127.0.0.1?
因为这个过程根本不经过网线。
也不经过物理网卡。
它发生在内核内部。
很多本地服务只监听 127.0.0.1,也是这个原因。
比如一个数据库只监听:
127.0.0.1:3306
那本机程序可以访问它。
但外部机器访问不了。
这不是服务没启动。
而是它压根没有监听外部接口上的 IP。
这个点非常重要。
很多新手第一次部署服务时,都会遇到这种情况:
本机 curl 能访问,换一台机器就访问不了。
这时候就要检查服务监听的是:
127.0.0.1
还是:
0.0.0.0
或者某个真实网卡上的 IP。
七、能不能删掉 127.0.0.1?
实验环境里,你确实可以对 lo 做一些操作。
比如给它再加一个回环地址:
sudo ip addr add 127.0.0.10/8 dev lo
然后访问:
ping 127.0.0.10
这通常也能通。
但这里要特别提醒一句:
不要在生产环境里删除默认的 127.0.0.1。
很多系统组件、脚本、服务和默认配置,都假设 localhost 能解析并访问到 127.0.0.1。
你为了验证一个概念,把它删掉,可能会引出一堆莫名其妙的问题。
所以这部分只需要理解机制,不要在正式机器上乱试。
八、eth0:0 到底是不是一块网卡?
很多老教程里会写:
sudo ifconfig eth0:0 192.168.1.11 netmask 255.255.255.0 up
然后你再用 ifconfig 看,会看到类似:
eth0eth0:0
很多人因此以为:
系统里真的多了一块叫 eth0:0 的网卡。
其实不是。
eth0:0 是早期工具展示 IP alias 的一种方式。
它不是一块独立的二层网卡。
真实的接口仍然是 eth0。
只是 eth0 上多挂了一个 IP 地址。
现在更推荐使用 iproute2 里的 ip 命令:
sudo ip addr add 192.168.1.11/24 dev eth0
这样表达更直白:
给 eth0 这个接口增加一个地址。
不再制造“多了一块网卡”的误解。
九、primary 和 secondary 要不要纠结?
你在 ip addr 输出里,可能会看到 secondary:
inet 192.168.1.11/24 scope global secondary eth0
这表示它是这个接口上的次级地址。
早期 Linux 对同一接口、同一网段里的多个 IPv4 地址,会区分主地址和次级地址。
这个设计和地址管理、ARP 行为等历史实现有关。
但作为新手,你先不用被它吓到。
日常理解成一句话就够了:
secondary 说明这个接口上不止一个同网段 IPv4 地址。
你真正要抓住的是:
先理解这一层,就已经够用了。
十、这一篇到底要记住什么?
如果这篇文章只让你记住一句话,那就是:
IP 地址不是简单绑定给整台机器的,而是配置在网络接口上的。
沿着这句话,很多现象就能解释了:
eth0:0 不是独立网卡,而是旧式 IP alias 的显示方式
当你真正理解这一点,再看 ip addr,就不会觉得它是一堆乱七八糟的输出。
你会开始看到它背后的结构:
主机下面有接口,接口下面有地址。
下一篇预告
不过,理解“IP 绑在哪里”还不够。
真实排障里,更常见的问题是:
IP 明明配上了,为什么还是不通?
下一篇我们继续讲:
- 公网 IP 和内网 IP 的区别,真的只是地址段不同吗?
下一篇,我们就把“地址怎么走出去”这件事讲明白。