当前位置:首页>Linux>Linux、Nginx学习第六周:IP、端口、防火墙:从 ping 不通讲到 iptables / nftables

Linux、Nginx学习第六周:IP、端口、防火墙:从 ping 不通讲到 iptables / nftables

  • 2026-10-07 04:21:37
Linux、Nginx学习第六周:IP、端口、防火墙:从 ping 不通讲到 iptables / nftables

技术工作里有个高频对话:

「网站打不开了,是不是网络挂了?」 「我这边 ping 通的啊。」 「我 telnet 端口也不通…」 「……」

每次这种对话,背后都是一套排查链路:DNS → 路由 → 防火墙 → 监听 → 应用。任意一环出问题表现都可能是「访问不到」,但用的命令、看的指标完全不同。

这一篇按真实排查流程串一遍 IP / 端口 / 防火墙,从 ping 不通讲到 iptables / nftables 一份完整 ruleset。新人学完能独立处理 80% 的"网络不通"场景。


一、心智模型:访问链路的 5 个关卡

浏览器 / 客户端     │     ├─ ① DNS 解析:域名 → IP     │    工具:dig / nslookup / cat /etc/resolv.conf     │     ├─ ② 三层联通:本机 → 目标 IP     │    工具:ping / traceroute / mtr     │     ├─ ③ 四层联通:本机 → 目标 IP:端口     │    工具:telnet / nc / curl     │     ├─ ④ 服务端防火墙:包能不能进到应用     │    工具:iptables-save / nft list ruleset / ufw status     │     ├─ ⑤ 应用监听:端口是不是真的在听     │    工具:ss -lntp / netstat -lntp     │     └─ ⑥ 应用本身:能不能正确处理请求          工具:tail -f 应用日志

新人最常犯的错:跳过前面几关直接怀疑应用挂了。正确顺序是从 ① 往下排,每一关都验证一下,省得回头又怀疑。


二、IP 与子网:CIDR 一句话讲明白

IP 地址 192.168.1.10/24 里的 /24 是什么?

  • 32 位 IPv4 中,前 24 位是网络位、后 8 位是主机位
  • /24
     等价于子网掩码 255.255.255.0,能容纳 2^8 - 2 = 254 台主机(首尾两个保留)

常见 CIDR 速查:

CIDR
掩码
可用主机数
适用场景
/32
255.255.255.255
1
单 IP(路由 / 防火墙规则常用)
/30
255.255.255.252
2
点对点连接
/29
255.255.255.248
6
小型 VLAN
/24
255.255.255.0
254
常见办公网 / 一个 C 段
/16
255.255.0.0
65534
一个 B 段
/8
255.0.0.0
16777214
一个 A 段

必背的特殊地址段

127.0.0.0/8           回环(127.0.0.1 是 localhost)10.0.0.0/8            私网 A 段(云上 VPC 常用)172.16.0.0/12         私网 B 段(Docker 默认 bridge 在 172.17.x)192.168.0.0/16        私网 C 段(家庭路由 / 小办公网)169.254.0.0/16        链路本地(DHCP 失败时自分配,云上元数据 169.254.169.254)0.0.0.0/0             "任意 IP",防火墙规则里常出现

新人易混点:

  • 0.0.0.0
    :作为源 IP 表示"未指定";作为监听 表示"所有接口";作为防火墙规则 表示"任意源"
  • 127.0.0.1
     vs 0.0.0.0:监听 127.0.0.1 只接受本机访问,监听 0.0.0.0 接受所有网卡访问。应用配错经常导致"本机能访问、外部访问不到"

三、看本机网络:ip 命令族

ifconfig / route / arp 这些老命令在多数现代发行版已经不预装了,统一用 ip 命令:

bash
# 看所有网卡 + IPip addrip a            # 简写# 1: lo: <LOOPBACK,UP,LOWER_UP> ...#     inet 127.0.0.1/8 scope host lo# 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> ...#     inet 10.0.0.5/24 brd 10.0.0.255 scope global eth0# 看路由表ip routeip r# default via 10.0.0.1 dev eth0 proto dhcp# 10.0.0.0/24 dev eth0 proto kernel scope link src 10.0.0.5# 看 ARP 缓存ip neighip n# 10.0.0.1 dev eth0 lladdr 00:50:56:01:23:45 REACHABLE# 临时给网卡加 IP(重启失效)sudo ip addr add 10.0.0.99/24 dev eth0# 加路由sudo ip route add 192.168.10.0/24 via 10.0.0.254

新旧命令对照表:

老命令
新命令
ifconfigip addr
 / ip link
route -nip route
arp -aip neigh
netstat -lntpss -lntp
netstat -rnip route

新机器上永远用 ip / ss,老命令在 Alpine / 最新 Ubuntu 上可能根本没装。


四、端口:TCP / UDP 与监听

端口分类

0-1023        Well-known,特权端口(**绑定需要 root**)              80 http / 443 https / 22 ssh / 53 dns / 25 smtp1024-49151    Registered,注册端口              3306 mysql / 6379 redis / 5432 postgres / 8080 http-alt49152-65535   Dynamic,动态端口(客户端连接时内核自动分配)

新人常见误区:

  • “我把应用配在 80 端口跑不起来” → 不是 root 用户绑不上 1024 以下端口(解决:用 systemd 的 AmbientCapabilities=CAP_NET_BIND_SERVICE,或者用 8080+ 用户端口)
  • “客户端口号一直是 49152+” → 内核 ip_local_port_range 控制,可调 1024-65535

TCP 和 UDP 一句话区别

  • TCP
    :有连接、有顺序、有重传、慢但可靠 —— HTTP / SSH / 数据库
  • UDP
    :无连接、不保证顺序、不重传、快 —— DNS 查询 / 视频流 / QUIC(HTTP/3)

看本机监听了什么

bash
ss -lntp# Netid   State   Local Address:Port   Peer Address:Port   Process# tcp     LISTEN  0.0.0.0:80           0.0.0.0:*           users:(("nginx",pid=1234,fd=6))# tcp     LISTEN  127.0.0.1:5432       0.0.0.0:*           users:(("postgres",pid=5678,fd=4))# tcp     LISTEN  0.0.0.0:22           0.0.0.0:*           users:(("sshd",pid=999,fd=3))# 参数含义# -l listening  只看监听# -n           不解析为服务名(数字显示)# -t           TCP# -u           UDP(看 UDP 加这个)# -p           显示进程# 看活跃的 TCP 连接ss -tnp# 看连接数ss -tan state established | wc -lss -tan state time-wait | wc -l

新人最最最高频问题:「我的 mysql 远程连不上」→ 多半是 bind-address = 127.0.0.1,只监听本机回环。ss -lntp | grep mysql 一眼看出来。


五、防火墙现状:四个工具一张表

这是 Linux 防火墙世界让新人最头大的地方——同一件事有四套工具:

工具
适用发行版
学习成本
底层
持久化
iptables
老 CentOS 7 / 老 Ubuntu
高(复杂语法)
netfilter(旧)
iptables-save / restore
nftables
(nft)
Ubuntu 22+ / CentOS 8+ 默认
中
netfilter(新)
/etc/nftables.conf
firewalld
RHEL/CentOS/Rocky 默认
低(包装层)
iptables 或 nftables
自动持久化
ufw
Ubuntu 默认
最低
iptables(部分发行版已切 nft)
自动持久化

新人应该用哪个:

  • Ubuntu / Debian → ufw(最省心)
  • CentOS / RHEL / Rocky → firewalld
  • 需要精细控制或自动化 → nft(写 ruleset 文件)
  • 不要再裸写 iptables 规则
    (语法古怪、新发行版已边缘化)

六、ufw 实战(Ubuntu 新人首选)

bash
# 看状态sudo ufw status verbose# Status: inactive    (表示还没启用)# 默认策略sudo ufw default deny incoming     # 默认拒绝入流量sudo ufw default allow outgoing    # 默认允许出流量# 放行常用服务(用名字,自动从 /etc/services 查端口)sudo ufw allow ssh                  # 等价 allow 22/tcpsudo ufw allow http                 # 80/tcpsudo ufw allow https                # 443/tcp# 按端口sudo ufw allow 8080/tcpsudo ufw allow 53                   # tcp + udp 都开(DNS 用)# 限定源 IP(只允许办公网访问 SSH)sudo ufw allow from 10.0.0.0/24 to any port 22# 启用sudo ufw enable# 第一次启用会警告:要确认 SSH 规则已放行,不然敲完 enable 会立刻被踢出去# 删规则sudo ufw status numbered# [ 1] 22/tcp ALLOW IN  Anywhere# [ 2] 80/tcp ALLOW IN  Anywheresudo ufw delete 2

ufw 新人铁律:

  1. 启用前一定先 allow ssh
    ——否则远程秒断
  2. 改默认策略到 deny incoming,不要无脑 allow
    ——白名单优于黑名单

七、firewalld 实战(CentOS 系新人首选)

firewalld 引入了**区域(zone)**概念,常见有 public / internal / trusted 等。

bash
# 看状态sudo systemctl status firewalldsudo firewall-cmd --state# running# 看当前区域sudo firewall-cmd --get-default-zone# public# 看 public 区域开了什么sudo firewall-cmd --zone=public --list-all# services: ssh dhcpv6-client# ports:# ...# 放行服务sudo firewall-cmd --permanent --add-service=httpsudo firewall-cmd --permanent --add-service=https# 放行端口sudo firewall-cmd --permanent --add-port=8080/tcp# 限定源 IPsudo firewall-cmd --permanent --zone=trusted --add-source=10.0.0.0/24sudo firewall-cmd --permanent --zone=trusted --add-service=ssh# 重载生效(**必须 reload,否则只在运行时生效,重启就丢**)sudo firewall-cmd --reload# 删sudo firewall-cmd --permanent --remove-service=httpsudo firewall-cmd --reload

--permanent 和 reload 是配对的:不加 permanent 是临时改,重启丢;加了 permanent 不 reload 又不立刻生效。养成 --permanent ... ; --reload 一气呵成的习惯。


八、nftables 实战:一份完整 ruleset 样板

nft 是新一代防火墙,Ubuntu 22+ / Debian 11+ / CentOS 8+ 默认走它(即使你 iptables -L 也是 nft 在后面跑兼容层)。

直接写一份完整 ruleset,能用于一台典型 Web 服务器:

bash
sudotee /etc/nftables.conf <<'EOF'#!/usr/sbin/nft -fflush rulesettable inet filter {# 入站    chain input {type filter hook input priority 0; policy drop;# 1. 已建立 / 相关连接放行        ct state established,related accept# 2. 本机回环必须放行        iif lo accept# 3. ICMP(ping)放行        ip protocol icmp accept        ip6 nexthdr icmpv6 accept# 4. SSH 放行(建议限源 IP 段,二选一,不要同时启用)        tcp dport 22 ip saddr 10.0.0.0/24 accept       # 推荐:只允许内网网段# tcp dport 22 accept                          # 备选:公网全开放(仅在堡垒机/单机调试场景)# 5. HTTP / HTTPS 放行        tcp dport { 80, 443 } accept# 6. 其他全部 drop(已由 policy drop 兜底)# 默认 drop,所以不需要显式写    }# 出站(一般全放)    chain output {type filter hook output priority 0; policy accept;    }# 转发(如果不是路由器一般全 drop)    chain forward {type filter hook forward priority 0; policy drop;    }}EOF# 校验语法sudo nft -c -f /etc/nftables.conf# 启用sudo systemctl enable --now nftables# 看当前规则sudo nft list ruleset

几个关键设计:

  • ct state established,related accept
     必须放第一条——否则出去的请求收不到回包(响应包不算 new 状态会被 drop)
  • iif lo accept
     必须有——很多本机服务(Postgres / Redis)只听 127.0.0.1,回环必须通
  • policy drop
     是兜底,比每条都写 drop 更安全
  • tcp dport { 80, 443 }
     用集合写法,比写两条紧凑

九、典型排查:ping 通但 telnet 不通

最经典的网络排查 case:

bash
# Step 1:ping 通了ping -c 3 192.168.1.10# 3 packets transmitted, 3 received, 0% packet loss# → 三层 IP 联通没问题# Step 2:telnet 端口不通telnet 192.168.1.10 80# Trying 192.168.1.10...# telnet: Unable to connect to remote host: Connection refused

两种可能:

Connection refused        → 包到了主机,但没人监听 / 防火墙明确 rejectConnection timed out      → 包根本没到主机(中间链路阻断 / 防火墙 drop)

refused vs timed out 是关键信号:

  • refused = 目标主机内核回了 RST → 要么应用没起,要么防火墙 reject
  • timeout = 没收到任何回包 → 多半在中间链路(云安全组 / 网络 ACL / drop 防火墙)

继续排:

bash
# 上 192.168.1.10 看ssh 192.168.1.10ss -lntp | grep ':80'# 如果没输出 → 应用根本没监听# 如果有 LISTEN 127.0.0.1:80 → 监听了但只听本地# 看防火墙sudo ufw status                    # Ubuntusudo firewall-cmd --list-all       # CentOSsudo nft list ruleset              # nftables# 看应用日志sudo journalctl -u nginx --since "10 min ago"

十、典型排查:ping 慢但 curl 快(反之亦然)

bash
ping baidu.com         # 50mscurl -o /dev/null -s -w "%{time_total}\n" https://baidu.com   # 5s

可能原因:

  1. DNS 解析慢
    :time curl baidu.com,再单独 time dig baidu.com 对比;DNS 解析占大头时换 8.8.8.8 / 114.114.114.114
  2. TLS 握手慢
    :curl -w "@curl-format.txt" ... 拿到各阶段耗时
  3. TCP 三次握手慢
    :包从本机到对端 RTT 高
  4. 应用响应慢
    :服务器端处理时间长

完整 curl 计时格式:

bash
cat > /tmp/curl-format.txt <<'EOF'    DNS:        %{time_namelookup}s    Connect:    %{time_connect}s    TLS:        %{time_appconnect}s    First Byte: %{time_starttransfer}s    Total:      %{time_total}sEOFcurl -w "@/tmp/curl-format.txt" -o /dev/null -s https://example.com

新人最易忽略的现象:ping 走 ICMP,curl 走 TCP。云上 ICMP 可能被默认 drop,ping 不通不等于服务不通,反过来 ping 通也不代表服务能用。


十一、云上的「安全组」:两层防火墙必须协同

云服务器跟物理机最大区别:外面还有一层云平台的"安全组"。

                ┌─────────────┐互联网 ──→ ① 云安全组 ──→ ② OS 防火墙 ──→ ③ 应用监听                              │                       两层都通才行

云防火墙在 OS 之前生效,OS 上 ufw allow 了,云安全组没放行,外面照样进不来。

典型踩坑:

  • 阿里云 / AWS 默认安全组只放 22,新开的 80 / 443 全靠后台 → 「nginx 启动了、ufw 也开了、外网就是访问不到」
  • 临时调试在 OS 上 ufw allow xxx 后又疑惑没生效 → 去云控制台看安全组

新人记一句:云上「访问不到」永远先看安全组,再看 OS 防火墙。


十二、排查工具速查表

场景
工具
命令
看本机 IP
ip aip a show eth0
看路由
ip rip r
看监听端口
ss -lntpss -lntp
看活跃连接
ss -tnpss -tan state established
测连通
pingping -c 3 host
测端口
nc -zvnc -zv host 80
路径追踪
mtrmtr -r -c 30 host
HTTP 详细
curl -vcurl -v https://host
DNS
digdig +short host
抓包
tcpdumptcpdump -i eth0 port 80 -nn

写在最后

  • 网络排查永远走五关:DNS → 三层联通 → 四层联通 → 防火墙 → 监听 → 应用
  • 新机器统一用 ip / ss
    ,ifconfig / netstat 已经被边缘化
  • 0.0.0.0 vs 127.0.0.1 监听差别巨大
    :本机能访问但外面访问不到,多半是只听了 127.0.0.1
  • ufw 启用前先 allow ssh
    ,否则远程秒断
  • firewalld 改完要 --reload
    ,permanent 不 reload 不生效
  • 不要再写裸 iptables
    ,新机器用 nft / firewalld / ufw
  • Connection refused vs Connection timed out 含义完全不同
    ——前者多半是服务问题,后者多半是网络/防火墙问题
  • 云服务器永远先看安全组
    ,再去看 OS 防火墙

最新文章

随机文章