跳转至

IP 网络基础

学习目标

学完本章后,学习者应该能够:

  1. 理解 MAC 地址、ARP、IP 地址、子网掩码和路由。
  2. 理解 NAT、ICMP、ping、traceroute 的作用。
  3. 能解释服务访问跨网段目标时大致发生了什么。
  4. 能用基础命令观察 IP 和路由问题。

MAC、ARP 与 IP

IP 地址用于跨网络寻址,MAC 地址用于同一链路内通信。

当主机要把 IP 包发给同一局域网内的目标时,需要知道目标 MAC 地址。ARP 用来根据 IP 查询 MAC:

谁是 192.168.1.10?请告诉 192.168.1.5

如果目标不在同一网段,主机会把包发给默认网关,由网关继续转发。

子网掩码与路由

子网掩码用于判断目标 IP 是否在同一网段。

例如:

IP:   192.168.1.20
Mask: 255.255.255.0
网段: 192.168.1.0/24

路由表决定“去某个目标网络,下一跳是谁”。

NAT

NAT 会修改 IP 包中的源地址或目标地址。

常见场景:

  • 家用路由器让多台设备共享公网 IP。
  • Kubernetes Service 做服务转发。
  • 云厂商 NAT Gateway 让内网机器访问公网。
  • 负载均衡把公网流量转到内网实例。

NAT 让网络更灵活,也会让排障变复杂,因为日志里的源 IP 可能已经被改写。

ICMP、ping 与 traceroute

ICMP 常用于网络控制和诊断。

  • ping:测试目标是否可达,观察延迟和丢包。
  • traceroute / tracert:观察到目标路径上的路由跳点。

它们是网络排障入口,但不是最终答案。很多网络会禁用或限制 ICMP。

Go 后端实际应用例子

例子一:识别客户端真实 IP

服务经过代理后,RemoteAddr 可能是代理地址,不是用户真实 IP。常见做法是读取可信代理写入的头:

func ClientIP(r *http.Request) string {
    if ip := r.Header.Get("X-Forwarded-For"); ip != "" {
        parts := strings.Split(ip, ",")
        return strings.TrimSpace(parts[0])
    }
    if ip := r.Header.Get("X-Real-IP"); ip != "" {
        return ip
    }
    host, _, err := net.SplitHostPort(r.RemoteAddr)
    if err != nil {
        return r.RemoteAddr
    }
    return host
}

注意:这些 Header 只能信任来自可信代理的请求,不能直接相信公网客户端传入的值。

例子二:服务绑定地址

http.ListenAndServe("127.0.0.1:8080", handler)
http.ListenAndServe("0.0.0.0:8080", handler)

127.0.0.1 只监听本机回环地址,外部机器无法访问。0.0.0.0 表示监听所有网卡地址。部署时经常因为绑定地址错误导致“本机能访问,别人访问不了”。

常见误区

  • 误区一:IP 地址就是机器身份。

IP 可能变化,也可能经过 NAT、代理或负载均衡。身份认证不能只依赖 IP。

  • 误区二:ping 不通就一定服务不可用。

ICMP 可能被禁用,但 TCP 端口仍然可用。要结合 curlnc 或业务协议测试。

  • 误区三:拿到 X-Forwarded-For 就是真实 IP。

这个 Header 可以伪造,必须结合可信代理链和网关配置使用。

线上问题案例

某服务迁移到容器后,启动日志显示监听 127.0.0.1:8080。Pod 内部 curl 正常,但 Service 访问失败。原因是服务只监听回环地址,没有监听容器网卡地址。

修复方式是监听 0.0.0.0:8080,并确认 readiness probe、Service targetPort 和容器端口一致。

实战任务

排查“本机能访问服务,其他机器访问不了”:

  1. 查看服务监听地址和端口。
  2. 查看本机 IP 地址。
  3. 检查防火墙或安全组。
  4. 判断是否绑定了 127.0.0.1
ipconfig
netstat -ano
Test-NetConnection 127.0.0.1 -Port 8080
ip addr
ss -lntp
nc -vz 127.0.0.1 8080
参考答案

先看服务是否监听在 127.0.0.1:8080 还是 0.0.0.0:8080。如果只监听 127.0.0.1,只有本机能访问,其他机器访问不了。然后确认目标机器 IP、端口是否正确,防火墙、安全组、容器端口映射是否允许访问。

在容器和 Kubernetes 中,还要检查容器监听地址、Service targetPort、Pod readiness 状态和网络策略。

面试题

1. IP 地址和 MAC 地址有什么区别?

参考答案

IP 地址用于网络层寻址,负责跨网段找到目标主机或下一跳。MAC 地址用于链路层,在同一局域网内把帧送到具体网卡。

跨网段通信时,IP 目标地址通常不变,但每一跳的链路层 MAC 地址会变化。

2. NAT 解决什么问题?带来什么代价?

参考答案

NAT 通过修改源地址或目标地址,让内网主机共享公网 IP、隐藏内部网络,或实现服务转发。它节省公网地址,也方便构建私有网络。

代价是连接追踪更复杂,真实源 IP 可能丢失,端口资源可能耗尽,排障时需要同时看 NAT 前后的地址和日志。

3. 为什么服务绑定 127.0.0.1 后外部访问不了?

参考答案

127.0.0.1 是本机回环地址,只能被本机访问。服务绑定这个地址时,不会监听外部网卡上的连接。

如果希望其他机器、容器 Service 或负载均衡访问,通常应该监听 0.0.0.0 或指定可达网卡地址。