涉及场景:
新机器交付后发现网络不通,不知道怎么查
搭建 Kubernetes 集群时 Pod 之间网络不通
配置负载均衡器或 VPN 时搞不清网段该怎么写
阿里云、AWS、腾讯云上配置 VPC 安全组和路由表
排查 Docker 容器网络、Calico/Flannel/Weave 网络问题
写 iptables/nftables 防火墙规则
遇到 ARP、ICMP、TCP/UDP 端口问题不知道从哪儿下手
IP 地址基础 二进制和十进制的转换 IP 地址是一个 32 位的二进制数,通常写成 4 个十进制字节,用点分隔。IPv4 地址范围从 0.0.0.0 到 255.255.255.255,共约 42 亿个地址。
1 2 3 4 5 6 7 8 十进制转二进制(按字节) 192 = 11000000 168 = 10101000 1 = 00000001 1 = 00000001 192.168.1.1 的二进制: 11000000.10101000.00000001.00000001
快速转换技巧:记住 2 的幂次方。
1 2 3 4 5 6 2^7 = 128 2^6 = 64 2^5 = 32 2^4 = 16 2^3 = 8 2^2 = 4 2^1 = 2 2^0 = 1 192 = 128 + 64 = 11000000 168 = 128 + 32 + 8 = 10101000 255 = 128+64+32+16+8+4+2+1 = 11111111
验证转换结果:把二进制各位对应的值加起来,看是否等于十进制。
1 2 3 4 5 6 7 8 9 10 ip addr show ifconfig ip addr show eth0 ip link show
IP 地址的分类(历史知识,现在已不强制) 早期 IPv4 将 IP 分为五类:
类别
范围
用途
网络/主机位数
A 类
0.0.0.0 - 127.255.255.255
大型网络
8/24
B 类
128.0.0.0 - 191.255.255.255
中型网络
16/16
C 类
192.0.0.0 - 223.255.255.255
小型网络
24/8
D 类
224.0.0.0 - 239.255.255.255
多播/组播
不适用
E 类
240.0.0.0 - 255.255.255.255
保留
不适用
运维中实际接触最多的是 C 类(192.168.x.x)和私有地址段:
1 2 3 4 私有 IP 地址范围(RFC 1918,可在内网自由使用): 10.0.0.0 - 10.255.255.255 (10/8 整段) 172.16.0.0 - 172.31.255.255 (172.16/12 段,16 个 B 类) 192.168.0.0 - 192.168.255.255 (192.168/16 段,256 个 C 类)
云服务器、容器网络、虚拟机默认都用私有地址。公有云的安全组就是控制这些私有 IP 的访问权限。
特殊 IP 地址 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 127.0.0.1 ::1 169.254.0.0/16 fe80::/10 0.0.0.0/0
查看本机 IP 和网络信息 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 ip addr show ip addr show eth0 ip route show ip route ip neigh show arp -a ss -tlnp netstat -tlnp ss -tnp netstat -tnp ip -s link show eth0
子网掩码与 CIDR 什么是子网掩码 子网掩码用来区分 IP 地址中哪些是网络部分,哪些是主机部分。32 位子网掩码中,1 对应网络位,0 对应主机位。
1 2 3 4 5 6 7 8 9 子网掩码示例:255.255.255.0 二进制:11111111.11111111.11111111.00000000 IP 地址 192.168.1.100 和子网掩码 255.255.255.0: 192.168.1 = 网络部分(前三字节) 100 = 主机部分(最后一字节) 网络地址 = IP & 子网掩码 = 192.168.1.100 & 255.255.255.0 = 192.168.1.0 广播地址 = 网络地址 | (~子网掩码) = 192.168.1.0 | 0.0.0.255 = 192.168.1.255
子网掩码两种写法:
点分十进制 :255.255.255.0
CIDR 表示法 :/24(表示前 24 位是网络位)
常用 CIDR 掩码速算:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 /32 = 255.255.255.255 主机数:1 /31 = 255.255.255.254 主机数:2(点对点链路) /30 = 255.255.255.252 主机数:4 /29 = 255.255.255.248 主机数:8 /28 = 255.255.255.240 主机数:16 /27 = 255.255.255.224 主机数:32 /26 = 255.255.255.192 主机数:64 /25 = 255.255.255.128 主机数:128 /24 = 255.255.255.0 主机数:256(常用,256 - 2 = 254 可用) /23 = 255.255.254.0 主机数:512 /22 = 255.255.252.0 主机数:1024 /21 = 255.255.248.0 主机数:2048 /20 = 255.255.240.0 主机数:4096 /16 = 255.255.0.0 主机数:65536 /8 = 255.0.0.0 主机数:16777216
计算可用主机数:2^(32-CIDR) - 2(减去网络地址和广播地址)
CIDR 块的大小选择 选择太小的 CIDR 块会浪费 IP,选择太大的不方便管理。实际运维中的选择:
1 2 3 4 5 6 7 /30 或 /31:点对点链路,如两台服务器直连、路由器互联接口 /29:小型业务,如少数几台机器的服务集群 /28:中型业务,如一个部门的小型服务器集群 /27:中等规模,如一个业务线的基础设施 /26:较大规模,如一个业务线的完整基础设施 /25 或 /24:大规模,如整个 Kubernetes 集群、整个 VPC 子网 /16 或 /8:超大规模,如整个数据中心的网段划分
子网划分实战 假设你有一个 192.168.0.0/24 网段,需要划分给 4 个部门,每个部门约 50 台机器。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 原始网段:192.168.0.0/24 二进制掩码:11111111.11111111.11111111.00000000 可用 IP:192.168.0.1 - 192.168.0.254(254 台) 划分方案(每个子网需要 /26,即 64 个地址): 部门 A:192.168.0.0/26 网络地址:192.168.0.0 可用范围:192.168.0.1 - 192.168.0.62 广播地址:192.168.0.63 部门 B:192.168.0.64/26 网络地址:192.168.0.64 可用范围:192.168.0.65 - 192.168.0.126 广播地址:192.168.0.127 部门 C:192.168.0.128/26 网络地址:192.168.0.128 可用范围:192.168.0.129 - 192.168.0.190 广播地址:192.168.0.191 部门 D:192.168.0.192/26 网络地址:192.168.0.192 可用范围:192.168.0.193 - 192.168.0.254 广播地址:192.168.0.255
在 Linux 上验证子网划分:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 apt install ipcalc yum install ipcalc ipcalc 192.168.0.0/26 ipcalc 192.168.0.64/26 ipcalc 192.168.0.128/26 ipcalc 192.168.0.192/26 ipcalc 192.168.0.0/26 Address: 192.168.0.0 Netmask: 255.255.255.192 Wildcard: 0.0.0.63 Network: 192.168.0.0/26 HostMin: 192.168.0.1 HostMax: 192.168.0.62 Broadcast: 192.168.0.63 Hosts/Net: 62 ipcalc 192.168.0.0/24 -s 64 64 64 64
判断两个 IP 是否在同一个网段 运维中常需要判断两台机器是否可以直接通信(不需要网关)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 python3 << 'EOF' def ip_in_subnet(ip, subnet): ip_parts = [int(x) for x in ip.split('.' )] subnet_cidr = int(subnet.split('/' )[1]) subnet_mask = (0xFFFFFFFF >> (32 - subnet_cidr)) << (32 - subnet_cidr) net_parts = [0,0,0,0] for i in range(4): net_parts[i] = (subnet_mask >> (8 * (3-i))) & 0xFF ip_int = (ip_parts[0]<<24) + (ip_parts[1]<<16) + (ip_parts[2]<<8) + ip_parts[3] subnet_int = (net_parts[0]<<24 ) + (net_parts[1]<<16) + (net_parts[2]<<8) + net_parts[3] return (ip_int & subnet_mask) == (subnet_int & subnet_mask) print(ip_in_subnet("192.168.1.100", "192.168.1.0/24")) # True print(ip_in_subnet("192.168.2.100", "192.168.1.0/24")) # False EOF
默认网关 网关的作用 同一网段的设备可以直接通信,跨网段通信需要通过网关转发。网关是一个网段通往其他网段的”大门”,通常是路由器或三层交换机的接口 IP。
1 2 3 4 5 6 场景:192.168.1.10 想访问 192.168.2.20 1. 192.168.1.10 发现 192.168.2.20 不在本地网段(192.168.1.0/24) 2. 192.168.1.10 把数据包发给默认网关(通常是 .1,如 192.168.1.1) 3. 网关路由器查看自己的路由表,决定把包转发到哪里 4. 最终数据包到达 192.168.2.20
查看和配置网关 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ip route show route -n ip route add default via 192.168.1.1 dev eth0 ip route del default via 192.168.1.1 arp 192.168.1.1
云服务器网关配置 阿里云、AWS、腾讯云的 VPC 网络中,子网的网关由云平台统一管理,通常是网段的第一个 IP(如 192.168.1.1)。
1 2 3 4 5 6 7 阿里云 VPC 网段常用: VPC: 192.168.0.0/16 交换机(子网):192.168.1.0/24 交换机网关:192.168.1.1(自动分配) 云服务器网卡配置的网关必须是 192.168.1.1 云服务器安全组控制的是入方向和出方向规则
VLAN 虚拟局域网 VLAN 的作用 一个物理交换机上可以划分多个 VLAN,实现广播域隔离。不同 VLAN 的设备即使连在同一台交换机上,也无法直接通信,需要通过三层路由转发。
1 2 3 4 5 6 7 8 9 场景:服务器有三个网络用途 - 管理网络:192.168.1.0/24(VLAN 100) - 业务网络:192.168.2.0/24(VLAN 200) - 存储网络:192.168.3.0/24(VLAN 300) 配置后: - 同一 VLAN 内的服务器可以互相通信 - 不同 VLAN 的服务器需要通过路由/网关才能通信 - 广播包不会穿越 VLAN 边界
Linux 配置 VLAN 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 modprobe 8021q ip link add link eth0 name eth0.100 type vlan id 100 ip addr add 192.168.1.10/24 dev eth0.100 ip link set eth0.100 up ip link show type vlancat /proc/net/vlan/config ip link del eth0.100
交换机的 VLAN 端口模式 实际运维中,交换机配置比 Linux 命令更重要。常见端口模式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 Access 口:连接终端设备(服务器、PC) - 属于单个 VLAN - 收到的帧不带 VLAN tag - 发出的帧不带 VLAN tag - 配置示例:switchport mode access; switchport access vlan 100 Trunk 口:连接其他交换机或路由器 - 允许通过多个 VLAN - 收到的帧带 VLAN tag - 发出的帧带 VLAN tag - 配置示例:switchport mode trunk; switchport trunk allowed vlan 100,200,300 Hybrid 口:华为设备特有,兼具两者特点 - 可以灵活配置哪些 VLAN 打 tag,哪些不打
路由基础 路由表的工作原理 每台 IP 网络设备(主机、路由器、三层交换机)都有路由表。发包时,设备根据路由表决定把包发到哪里。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ip route show route -n
路由匹配规则(最长前缀匹配):
1 2 3 4 5 6 7 假设目标 IP 是 10.20.30.40,路由表有: 1. 0.0.0.0/0 (默认路由,匹配 0 位) 2. 10.0.0.0/8 (匹配 8 位) 3. 10.20.0.0/16 (匹配 16 位) 4. 10.20.30.0/24 (匹配 24 位) 最长匹配原则:选择第 4 条,匹配 24 位
添加和删除路由 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ip route add 10.10.0.0/16 via 192.168.1.1 dev eth0 ip route add 10.10.10.20/32 via 192.168.1.1 dev eth0 ip route add blackhole 10.10.10.0/24 ip route del 10.10.0.0/16 via 192.168.1.1 dev eth0 10.10.0.0/16 via 192.168.1.1 dev eth0 up ip route add 10.10.0.0/16 via 192.168.1.1 dev eth0
策略路由(高级) Linux 支持基于源地址、fwmark、UID 等条件的策略路由。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ip rule show ip rule add from 192.168.1.0/24 table 100 ip route add default via 192.168.1.1 dev eth0 table 100 iptables -A PREROUTING -s 10.0.0.0/8 -j MARK --set-mark 1 ip rule add fwmark 1 table 200 ip route add default via 10.0.0.1 dev eth1 table 200
DNS 基础 DNS 的作用 域名系统负责把人类可读的域名转换成 IP 地址。运维中遇到”机器能 ping 通 IP,但 ping 不通域名”的问题,基本就是 DNS 故障。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 cat /etc/resolv.conf nslookup www.baidu.com dig www.baidu.com host www.baidu.com resolvectl status resolvectl query www.baidu.com systemctl restart systemd-resolved systemctl restart nscd nslookup www.baidu.com 8.8.8.8 dig @8.8.8.8 www.baidu.com
/etc/hosts 本地解析 在 DNS 不可用或需要自定义解析时,使用 /etc/hosts。
1 2 3 4 5 6 7 127.0.0.1 localhost localhost.localdomain 192.168.1.100 db-master.internal db-master 192.168.1.101 db-slave.internal db-slave 10.244.1.5 redis-01.default.svc.cluster.local redis-01
网络故障排查流程 排查思路 网络故障排查遵循分层排除法,从底层到高层:
1 2 3 4 5 第1层:物理层 - 网线、光纤、网卡灯是否亮 第2层:数据链路层 - MAC 地址、ARP、交换机端口 第3层:网络层 - IP 地址、子网掩码、路由表、网关 第4层:传输层 - TCP/UDP 端口、防火墙状态 第5层:应用层 - HTTP 响应、DNS 解析、证书
常用排查命令 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 ip addr show eth0 ping -c 3 192.168.1.1 ping -c 3 8.8.8.8 ping -c 3 192.168.2.100 nc -zv 192.168.1.100 22 nc -zv 10.0.0.50 3306 telnet 192.168.1.100 80 ip route show traceroute -m 10 8.8.8.8 tracepath 8.8.8.8 nslookup www.baidu.com dig +short www.baidu.com iptables -L -n -v iptables -L INPUT -n -v iptables -L OUTPUT -n -v ss -tlnp netstat -tlnp ss -tnp netstat -tnp ip neigh show arp -a
常见故障案例 案例 1:服务器获取到 169.254.x.x 地址 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ip link show eth0cat /etc/network/interfacescat /etc/sysconfig/network-scripts/ifcfg-eth0 dhclient -r eth0 dhclient eth0 ip addr add 192.168.1.100/24 dev eth0 ip route add default via 192.168.1.1
案例 2:同网段机器 ping 不通 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 ip addr show eth0 ip addr show eth0 ping -c 1 192.168.1.20 arp -a | grep 192.168.1.20 iptables -L INPUT -n ip link show eth0
案例 3:跨网段机器 ping 不通 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ip route show ping -c 1 192.168.1.1
案例 4:DNS 解析正常但无法访问 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 nc -zv www.baidu.com 443 nc -zuv 8.8.8.8 53 ip route show traceroute -m 5 www.baidu.com iptables -L OUTPUT -n -v ip link show eth0 ping -c 3 -M do -s 1400 8.8.8.8echo $http_proxy echo $https_proxy env | grep -i proxy
网络排查流程图 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 开始:网络不通 | v ping 127.0.0.1 成功? |-- 否 --> 本机 TCP/IP 协议栈问题,检查内核参数 | ip link set eth0 up | v ping 本机 IP 成功? |-- 否 --> 网卡 down 或 IP 配置错误 | ip link set eth0 up | ip addr add x.x.x.x/xx dev eth0 | v ping 网关 IP 成功? |-- 否 --> 本网段 ARP 问题或网关本身问题 | 检查网线、交换机端口 | 检查网关是否通电 | v ping 目标 IP 成功? |-- 否 --> 中间网络问题 | traceroute 追查在哪一跳丢包 | 检查沿途路由器路由表 | v ping 域名 成功? |-- 否 --> DNS 问题 | 检查 /etc/resolv.conf | 检查 DNS 服务器 | v telnet/curl 目标端口 成功? |-- 否 --> 防火墙或服务问题 | 检查 iptables/nftables | 检查目标服务是否监听 | v 解决
Docker/Kubernetes 网络基础 Docker 网络模式 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 docker network ls docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container_name docker exec -it container_name ip addr docker exec -it container_name cat /etc/resolv.conf docker exec -it container_a ping -c 1 container_b {"dns" : ["8.8.8.8" , "114.114.114.114" ] }
Kubernetes 网络模型 Kubernetes 网络模型要求:
所有 Pod 可以直接通过 IP 互访,无需 NAT
节点可以与所有 Pod 互访,无需 NAT
Pod 看到的 IP 和其他 Pod 看到的相同
常见 CNI 插件对比:
CNI
网段示例
特点
Flannel
10.244.0.0/16
简单,VXLAN 封装
Calico
10.244.0.0/16
支持 BGP,性能好
Cilium
10.244.0.0/16
eBPF 加速,可观测性强
Weave
10.32.0.0/16
简单,加密传输
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 kubectl get nodes -o wide kubectl get pods -o wide --all-namespaces kubectl get svc -o wide kubectl get nodes -o jsonpath='{.items[*].spec.podCIDR}' kubectl get nodes -o jsonpath='{.items[*].status.addresses[?(@.type=="InternalIP")].address}' kubectl exec -it pod_name -- ip addr kubectl exec -it pod_name -- cat /etc/resolv.conf kubectl exec -it pod_name -- ping -c 1 8.8.8.8 kubectl describe pod pod_name kubectl logs -n kube-system -l k8s-app=calico-node journalctl -u kubelet | grep -i cni
防火墙基础 iptables 基础 Linux 防火墙按链(chain)和表(table)组织。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 iptables -L -n -v iptables -L INPUT -n -v iptables -A INPUT -p tcp --dport 22 -j ACCEPT iptables -A INPUT -p tcp --dport 80 -j ACCEPT iptables -A INPUT -p tcp --dport 443 -j ACCEPT iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A INPUT -j DROP service iptables save iptables-save > /etc/iptables/rules.v4 iptables-restore < /etc/iptables/rules.v4
nftables 新一代防火墙 CentOS 8+ 推荐使用 nftables,语法更简洁。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 nft list ruleset nft add table ip filter nft add chain ip filter input { type filter hook input priority 0 \; } nft add rule ip filter input tcp dport 22 accept nft add rule ip filter input ct state established,related accept nft add rule ip filter input counter drop nft list ruleset > /etc/sysconfig/nftables.conf
生产环境网络安全建议 最小权限原则 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 iptables -A INPUT -p tcp --dport 22 -s 10.0.0.0/8 -j ACCEPT iptables -A INPUT -p tcp --dport 22 -j DROPecho "sshd: 10.0.0.0/8" >> /etc/hosts.allowecho "sshd: ALL" >> /etc/hosts.denyecho 1 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcastsecho 0 > /proc/sys/net/ipv4/conf/all/accept_source_routeecho 0 > /proc/sys/net/ipv4/conf/default/accept_source_routeecho 1 > /proc/sys/net/ipv4/conf/all/rp_filterecho 1 > /proc/sys/net/ipv4/conf/default/rp_filterecho 0 > /proc/sys/net/ipv4/conf/all/accept_redirectsecho 0 > /proc/sys/net/ipv4/conf/default/accept_redirects
内网安全 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 iptables -A INPUT -p tcp --dport 3306 -s 10.0.1.0/24 -j ACCEPT iptables -A INPUT -p tcp --dport 3306 -j DROPbind 10.0.1.0/24 rename-command FLUSHALL "" rename-command FLUSHDB "" rename-command SHUTDOWN "" ss -tnp | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head -20
永久生效的网络优化参数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 net.core.somaxconn = 65535 net.core.netdev_max_backlog = 65535 net.ipv4.tcp_max_syn_backlog = 65535 net.ipv4.tcp_fin_timeout = 15 net.ipv4.tcp_keepalive_time = 300 net.ipv4.tcp_keepalive_probes = 3 net.ipv4.tcp_keepalive_intvl = 15 net.ipv4.tcp_rmem = 4096 87380 6291456 net.ipv4.tcp_wmem = 4096 65536 6291456 net.ipv4.tcp_window_scaling = 1 net.netfilter.nf_conntrack_max = 1048576 net.netfilter.nf_conntrack_tcp_timeout_established = 432000 sysctl -p
总结 网络基础是运维的必修课,核心知识点:
IP 地址和子网:
IP 是 32 位二进制数,4 字节点分十进制表示
子网掩码区分网络位和主机位,CIDR 是简化写法
私有地址段:10.0.0.0/8、172.16.0.0/12、192.168.0.0/16
两个 IP 是否同网段:分别和掩码做 AND,结果相同则同网段
网关和路由:
同网段直接通信,跨网段走网关
路由表按最长前缀匹配
默认网关用 0.0.0.0/0 表示
故障排查顺序:
先 ping 127.0.0.1 确认本机协议栈正常
再 ping 本机 IP 确认网卡正常
然后 ping 网关确认链路正常
最后 ping 目标逐段定位
常用命令:
ip addr:查 IP 配置
ip route:查路由表
ip neigh:查 ARP 表
ping:测试连通性
traceroute:追踪路由
nslookup/dig:测 DNS
ss/netstat:查端口
iptables:配防火墙