第 7 章

网络工具全解

第7章:Linux 网络工具全解

网络是现代 Linux 系统的命脉。本章系统梳理 Linux 网络工具链:从 ip 系列命令替代已弃用的 ifconfig,到 ss/lsof 查看套接字状态,再到 curl/wget 的 HTTP 调试艺术、tcpdump 的抓包分析、SSH 进阶配置,以及 dig/nc 等诊断利器。掌握这些工具,你将能在任何网络问题前从容不迫。

7.1 网络接口管理:ip 命令族

ip 命令来自 iproute2 工具包,是 ifconfigroutearp 等传统工具的现代替代。ifconfig 在大多数发行版中已标记为弃用(deprecated),生产环境应优先使用 ip

# === ip addr — 管理 IP 地址 ===
ip addr show                        # 显示所有接口的 IP 地址(简写:ip a)
ip addr show eth0                   # 只显示 eth0 接口
ip addr add 192.168.1.100/24 dev eth0   # 添加 IP 地址
ip addr del 192.168.1.100/24 dev eth0   # 删除 IP 地址

# === ip link — 管理网络接口 ===
ip link show                        # 列出所有接口(简写:ip l)
ip link set eth0 up                 # 启用接口
ip link set eth0 down               # 禁用接口
ip link set eth0 mtu 9000           # 设置 MTU(巨帧)
ip link set eth0 promisc on         # 开启混杂模式(抓包用)

# === ip route — 路由表管理 ===
ip route show                       # 查看路由表(简写:ip r)
ip route add default via 192.168.1.1            # 添加默认网关
ip route add 10.0.0.0/8 via 192.168.1.254      # 添加静态路由
ip route del 10.0.0.0/8                         # 删除路由
ip route get 8.8.8.8                            # 查询特定目标的路由路径

# === ip neigh — ARP 表(替代 arp 命令)===
ip neigh show                       # 查看 ARP/NDP 邻居表
ip neigh flush dev eth0             # 清空接口的 ARP 缓存

# === 对比:旧命令 vs 新命令 ===
# ifconfig eth0          →  ip addr show eth0
# ifconfig eth0 up       →  ip link set eth0 up
# route -n               →  ip route show
# arp -n                 →  ip neigh show
# netstat -rn            →  ip route show

为什么抛弃 ifconfig? ifconfig 来自 net-tools 包,自 2001 年起停止维护,不支持现代 Linux 网络特性(如 VRF、网络命名空间、多路由表)。iproute2ip 命令由内核团队维护,始终与内核网络栈保持同步。Ubuntu 18.04 之后 net-tools 已不再预装。

7.2 端口与连接:ss / lsof

ss(Socket Statistics)是 netstat 的现代替代,直接读取内核的 socket 结构,速度更快、信息更全面。

# === ss — Socket 统计 ===
ss -tulnp          # 最常用:TCP+UDP 监听端口,不解析域名,显示进程
                   # -t TCP  -u UDP  -l listening  -n numeric  -p process
ss -s              # 显示汇总统计(各状态 socket 数量)
ss -an             # 所有连接(包含非监听状态)
ss -tnp state established   # 只显示已建立的 TCP 连接
ss -tnp dst 10.0.0.1        # 过滤目标地址
ss -tnp sport = :80         # 过滤本地端口 80

# 输出示例解读:
# Netid  State   Recv-Q  Send-Q  Local Address:Port  Peer Address:Port  Process
# tcp    LISTEN  0       128     0.0.0.0:22           0.0.0.0:*          users:(("sshd",pid=1234,fd=3))
# ↑协议  ↑状态   ↑接收队列 ↑发送队列 ↑本地地址:端口  ↑对端地址:端口    ↑进程信息

# === lsof -i — 通过文件查进程(网络版)===
lsof -i :8080       # 谁在占用 8080 端口
lsof -i tcp         # 所有 TCP 连接
lsof -i -nP         # -n 不解析主机名,-P 不解析端口名
lsof -i tcp:80 -n   # 谁在监听 TCP 80 端口

# === netstat 兼容命令(已弃用,但部分系统仍有)===
netstat -tulnp      # 等同 ss -tulnp
netstat -rn         # 等同 ip route show

7.3 curl 完整指南

curl 是 Linux 下最强大的 HTTP 客户端工具,支持 HTTP/HTTPS/FTP/SFTP 等数十种协议。它是 API 调试、文件下载、自动化脚本的利器。

# === 基本 HTTP 方法 ===
curl https://api.example.com/users              # GET 请求
curl -X POST https://api.example.com/users      # POST 请求
curl -X PUT  https://api.example.com/users/1    # PUT 请求
curl -X DELETE https://api.example.com/users/1  # DELETE 请求

# === 请求头与请求体 ===
curl -H "Content-Type: application/json" \
     -H "Authorization: Bearer YOUR_TOKEN" \
     -d '{"name":"Alice","age":30}' \
     -X POST https://api.example.com/users

# -d 发送 JSON/表单数据(application/x-www-form-urlencoded)
curl -d "username=alice&password=secret" https://example.com/login

# -F 发送 multipart/form-data(文件上传)
curl -F "file=@/path/to/photo.jpg" -F "title=My Photo" https://api.example.com/upload

# === 输出控制 ===
curl -o output.html https://example.com         # 保存到文件
curl -O https://example.com/file.tar.gz         # 用服务器文件名保存
curl -L https://short.url/abc                   # -L 跟随 301/302 重定向
curl -v https://example.com                     # -v 显示完整请求/响应头
curl -I https://example.com                     # 只获取响应头(HEAD 请求)
curl -s https://example.com                     # -s 静默模式(不显示进度)
curl -w "\nHTTP Status: %{http_code}\nTime: %{time_total}s\n" -o /dev/null \
     https://example.com                        # 自定义输出格式

# === 认证 ===
curl -u admin:password https://example.com/api  # Basic Auth
curl -H "Authorization: Bearer token123" https://api.example.com/data

# === TLS/SSL ===
curl --cacert /path/to/ca.crt https://internal.corp/api   # 指定 CA 证书
curl --cert client.crt --key client.key https://api/mtls  # 双向 TLS
curl --insecure https://self-signed.example.com           # 忽略证书错误(仅测试!)

# === 结合 jq 处理 JSON ===
curl -s https://api.github.com/repos/torvalds/linux \
  | jq '.stargazers_count'                      # 提取字段
curl -s https://api.example.com/users \
  | jq '.[] | {id, name}'                       # 遍历数组

# === 断点续传 ===
curl -C - -O https://example.com/large-file.iso  # -C - 从断点继续下载

# === 限速 ===
curl --limit-rate 1M -O https://example.com/file.iso   # 限制下载速度 1MB/s

# === 并发(使用 xargs)===
cat urls.txt | xargs -P 4 -I{} curl -s -O {}    # 4 并发下载

7.4 wget:递归下载与镜像网站

# 基本下载
wget https://example.com/file.tar.gz

# 断点续传(-c continue)
wget -c https://example.com/large-file.iso

# 后台下载(-b background,日志写入 wget-log)
wget -b https://example.com/file.iso

# 递归下载整个目录
wget -r -np -nH --cut-dirs=2 https://example.com/files/

# 镜像网站(保留目录结构、转换链接为本地路径)
wget --mirror --convert-links --page-requisites \
     --no-parent https://example.com/

# 限速与重试
wget --limit-rate=500k --tries=3 --wait=2 https://example.com/file.iso

# 安静模式(不显示进度条)
wget -q -O /dev/null https://example.com/

# 显示进度条(非交互模式下)
wget --progress=bar:force https://example.com/file.iso

# 指定 User-Agent
wget --user-agent="Mozilla/5.0" https://example.com/

curl vs wget 选哪个? curl 更适合 API 调试、脚本中处理 HTTP 响应、需要细粒度控制请求头/方法的场景。wget 更适合单纯的文件下载、递归镜像网站、后台批量下载。两者都支持断点续传,curl 通过 -C -,wget 通过 -c

7.5 tcpdump:抓包分析利器

tcpdump 是 Linux 下的命令行抓包工具,能实时捕获网络数据包并显示其内容,是网络故障排查和协议分析的核心工具。

# 基本用法
sudo tcpdump -i eth0               # 抓 eth0 上的所有包
sudo tcpdump -i any                # 抓所有接口
sudo tcpdump -i eth0 -n            # -n 不解析 IP/端口为域名(速度更快)
sudo tcpdump -i eth0 -v            # -v 更详细输出(-vv/-vvv 更多)
sudo tcpdump -i eth0 -c 100        # 只捕获 100 个包后退出

# 保存到文件(.pcap 格式,可用 Wireshark 打开)
sudo tcpdump -i eth0 -w capture.pcap
sudo tcpdump -i eth0 -w capture.pcap -G 3600 -W 24  # 每小时轮转,保留24个文件

# 读取 pcap 文件
sudo tcpdump -r capture.pcap
sudo tcpdump -r capture.pcap -n host 10.0.0.1

# 过滤表达式(BPF 语法)
sudo tcpdump -i eth0 host 192.168.1.100          # 过滤主机
sudo tcpdump -i eth0 src host 192.168.1.100      # 只看源地址
sudo tcpdump -i eth0 dst host 192.168.1.100      # 只看目标地址
sudo tcpdump -i eth0 port 80                     # 过滤端口
sudo tcpdump -i eth0 tcp                         # 只看 TCP
sudo tcpdump -i eth0 udp                         # 只看 UDP
sudo tcpdump -i eth0 tcp and port 443            # 组合过滤(and/or/not)
sudo tcpdump -i eth0 'tcp and (port 80 or port 443)'
sudo tcpdump -i eth0 'tcp[tcpflags] & tcp-syn != 0'   # 只看 SYN 包(连接建立)

# 实用组合:HTTP 请求头
sudo tcpdump -i eth0 -n -A 'tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)>2)) != 0)'

tcpdump 过滤表达式速查表

过滤表达式 含义 示例
host X 匹配源或目标地址 host 10.0.0.1
src host X 只匹配源地址 src host 10.0.0.1
dst host X 只匹配目标地址 dst host 8.8.8.8
net X/mask 匹配网段 net 192.168.0.0/16
port N 匹配端口(源或目标) port 443
portrange N-M 匹配端口范围 portrange 8000-9000
tcp / udp / icmp 按协议过滤 icmp
and / or / not 逻辑组合 tcp and not port 22
greater N 包大于 N 字节 greater 1000
less N 包小于 N 字节 less 64

7.6 SSH 进阶:密钥管理与 ProxyJump

密钥生成与部署

# === 生成 SSH 密钥对 ===
# Ed25519(推荐,更安全、更快)
ssh-keygen -t ed25519 -C "[email protected]"

# RSA 4096(兼容旧系统)
ssh-keygen -t rsa -b 4096 -C "[email protected]"

# 指定文件名(同时管理多对密钥时有用)
ssh-keygen -t ed25519 -f ~/.ssh/id_work -C "[email protected]"

# === 部署公钥到服务器 ===
ssh-copy-id [email protected]
ssh-copy-id -i ~/.ssh/id_work.pub [email protected]  # 指定密钥

# 手动部署(当 ssh-copy-id 不可用时)
cat ~/.ssh/id_ed25519.pub | ssh user@server "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"

# === ssh-agent:避免重复输入密码短语 ===
eval "$(ssh-agent -s)"             # 启动 ssh-agent
ssh-add ~/.ssh/id_ed25519          # 添加私钥到 agent
ssh-add ~/.ssh/id_work             # 添加工作密钥
ssh-add -l                         # 列出 agent 中的密钥
ssh-add -D                         # 清空 agent 中的所有密钥

# === 端口转发 ===
# 本地端口转发:将本地 8080 转发到远程服务器的 localhost:3306(访问远端 MySQL)
ssh -L 8080:localhost:3306 [email protected]

# 远程端口转发:将服务器 9090 转发回本地 localhost:8080(内网穿透)
ssh -R 9090:localhost:8080 [email protected]

# 动态端口转发(SOCKS5 代理)
ssh -D 1080 [email protected]

# === sshfs — 挂载远程目录 ===
sudo apt install sshfs
mkdir ~/remote-work
sshfs [email protected]:/var/www ~/remote-work
fusermount -u ~/remote-work          # 卸载

~/.ssh/config 配置文件

~/.ssh/config 是 SSH 的客户端配置文件,可以为不同主机设置别名、密钥、用户名、跳板机等,大幅减少输入。

# ~/.ssh/config 完整示例

# 全局默认设置
Host *
    ServerAliveInterval 60          # 每 60 秒发送心跳(防止超时断连)
    ServerAliveCountMax 3           # 3 次无响应后断开
    AddKeysToAgent yes              # 自动将密钥添加到 ssh-agent
    IdentityFile ~/.ssh/id_ed25519  # 默认密钥

# 工作服务器(直接访问)
Host work-web
    HostName 203.0.113.10
    User deploy
    Port 2222
    IdentityFile ~/.ssh/id_work
    # 使用:ssh work-web

# 内网服务器(通过跳板机 ProxyJump)
Host internal-db
    HostName 10.10.0.50
    User dbadmin
    ProxyJump work-web              # 先连 work-web,再跳转到 internal-db
    # 旧写法:ProxyCommand ssh -W %h:%p work-web
    # 使用:ssh internal-db

# GitHub(多账号管理)
Host github-personal
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_personal
    # 使用:git clone git@github-personal:username/repo.git

Host github-work
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_work
    # 使用:git clone git@github-work:org/repo.git

# 文件权限要求:
# chmod 600 ~/.ssh/config
# chmod 700 ~/.ssh/

ProxyJump 的威力: ProxyJump 支持多级跳转(如 ProxyJump jump1,jump2),每一跳都可以有独立的密钥和用户名配置。与旧的 ProxyCommand 相比,ProxyJump(SSH 7.3+)更安全,因为它不会将私钥暴露给跳板机。

7.7 nc/netcat 与 socat 网络调试

# === nc(netcat)— "网络界的瑞士军刀" ===

# 端口扫描(-z 扫描模式,-v 详细,-w 超时)
nc -zv 192.168.1.1 22           # 检测单个端口是否开放
nc -zv 192.168.1.1 20-80        # 扫描端口范围

# 简单 TCP 服务器(监听 9999 端口)
nc -l 9999                      # 监听并等待连接
nc -lk 9999                     # -k 持续监听(每次连接后不退出)

# 连接到服务器
nc 192.168.1.1 9999

# 传输文件(发送方)
nc -l 9999 > received_file.txt  # 接收端
nc 192.168.1.1 9999  /tmp/pipe

# === socat — nc 的进化版 ===
# 安装
sudo apt install socat

# 端口转发(将本地 8080 转发到 example.com:80)
socat TCP-LISTEN:8080,fork TCP:example.com:80

# TLS 测试
socat STDIO OPENSSL:example.com:443

# Unix socket 转 TCP
socat TCP-LISTEN:9999,fork UNIX-CONNECT:/var/run/docker.sock

# 文件传输(更快,无需多步骤)
socat -u FILE:file.tar.gz TCP-LISTEN:9999  # 发送端
socat -u TCP:192.168.1.1:9999 FILE:out.tar.gz  # 接收端

7.8 DNS 工具:dig / nslookup / host

# === dig — DNS 查询主力工具 ===
dig example.com              # 查询 A 记录(默认)
dig example.com A            # 明确查询 A 记录(IPv4)
dig example.com AAAA         # 查询 AAAA 记录(IPv6)
dig example.com MX           # 查询邮件交换记录
dig example.com NS           # 查询权威域名服务器
dig example.com CNAME        # 查询别名记录
dig example.com TXT          # 查询 TXT 记录(SPF/DKIM 等)
dig example.com SOA          # 查询授权信息

# 指定 DNS 服务器(绕过系统 /etc/resolv.conf)
dig @8.8.8.8 example.com     # 使用 Google DNS
dig @1.1.1.1 example.com     # 使用 Cloudflare DNS
dig @192.168.1.1 example.com # 使用内网 DNS

# 简洁输出(+short 只显示结果)
dig +short example.com
dig +short example.com MX

# 追踪完整解析链(+trace 从根 DNS 开始)
dig +trace example.com

# 反向 DNS 查询(IP → 域名)
dig -x 8.8.8.8

# === nslookup — 交互式 DNS 工具 ===
nslookup example.com
nslookup example.com 8.8.8.8    # 指定 DNS 服务器
nslookup -type=MX example.com   # 查询特定记录类型

# === host — 简洁查询 ===
host example.com
host -t MX example.com
host 8.8.8.8                    # 反向查询

# === 本地 DNS 配置文件 ===
# /etc/hosts — 本地静态解析(优先级高于 DNS)
cat /etc/hosts
# 127.0.0.1    localhost
# 192.168.1.10 internal-server db.local

# /etc/resolv.conf — DNS 服务器配置
cat /etc/resolv.conf
# nameserver 8.8.8.8
# nameserver 8.8.4.4
# search example.com   # 默认搜索域

# 刷新 DNS 缓存
sudo systemd-resolve --flush-caches          # systemd-resolved
sudo resolvectl flush-caches                 # 新版语法
sudo service nscd restart                    # nscd 缓存

7.9 网络诊断:ping / traceroute / mtr

# === ping ===
ping example.com                    # 持续 ping
ping -c 4 example.com               # 只 ping 4 次
ping -i 0.5 example.com             # 每 0.5 秒发一次
ping6 2001:4860:4860::8888          # IPv6 ping

# === traceroute — 路由跟踪 ===
traceroute example.com
traceroute -n example.com           # -n 不解析主机名(更快)
traceroute -T -p 80 example.com     # 使用 TCP(穿越部分防火墙)

# === mtr — ping + traceroute 的实时结合(推荐)===
sudo apt install mtr
mtr example.com                     # 实时动态视图
mtr -n --report example.com         # 非交互,报告模式(可用于记录)
mtr --report-cycles 20 example.com  # 发 20 次后输出报告

连接失败排查检查清单

  1. 物理/链路层: ip link show — 接口是否 UP?ethtool eth0 — 是否有链路信号?
  2. IP 地址: ip addr show — 是否有正确的 IP 地址?子网掩码是否正确?
  3. 网关路由: ip route show — 是否有默认网关?ping 网关 IP 是否可达?
  4. DNS: dig +short example.com @8.8.8.8 — 绕过本地 DNS 测试。cat /etc/resolv.conf 检查配置。
  5. 目标端口: nc -zv target 80 — 目标端口是否开放?ss -tulnp — 本地是否在监听?
  6. 防火墙: sudo iptables -L -nsudo ufw status — 是否有规则阻断连接?
  7. 抓包确认: sudo tcpdump -i eth0 host target -n — 数据包是否到达/离开本机?

7.10 iptables / ufw 防火墙基础

# === ufw(Ubuntu 防火墙,iptables 的友好前端)===
sudo ufw status verbose             # 查看状态和规则
sudo ufw enable                     # 启用防火墙
sudo ufw disable                    # 禁用防火墙

sudo ufw allow 22                   # 允许 SSH(端口 22)
sudo ufw allow 80/tcp               # 允许 HTTP
sudo ufw allow 443                  # 允许 HTTPS
sudo ufw deny 23                    # 拒绝 Telnet
sudo ufw allow from 192.168.1.0/24  # 允许来自特定子网

sudo ufw delete allow 80/tcp        # 删除规则
sudo ufw reset                      # 重置所有规则

# === iptables — 底层规则(需要 root)===
sudo iptables -L -n -v              # 列出所有规则(-n 不解析,-v 显示计数)
sudo iptables -L INPUT -n --line-numbers  # 显示行号

# 基本规则示例
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT      # 允许 SSH
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT      # 允许 HTTP
sudo iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT  # 允许已建立连接
sudo iptables -A INPUT -j DROP                           # 默认拒绝所有

# 保存规则(Ubuntu)
sudo iptables-save > /etc/iptables/rules.v4
sudo ip6tables-save > /etc/iptables/rules.v6

# 查看 nftables(现代防火墙,替代 iptables)
sudo nft list ruleset

远程操作防火墙注意: 通过 SSH 修改 iptables 规则时,务必先添加 ACCEPT 规则再添加 DROP 规则,且确保 SSH 端口(22)始终在 ACCEPT 列表中。一条错误的规则可能导致你被永久锁定在服务器外。建议在修改前设置一个定时任务自动恢复规则:echo "iptables -F" | at now + 5 min

章节总结: 本章覆盖了 Linux 网络工具的全景:ip 命令族管理接口和路由,ss 查看 socket 状态,curl 调试 HTTP/API,tcpdump 抓包分析,SSH 进阶配置让远程工作更高效,nc/socat 用于快速网络测试,dig 排查 DNS 问题,以及系统化的连接失败排查流程。下一章将深入 Linux 存储与磁盘管理。

  上一章
  ← 第6章:权限与用户管理


  下一章
  第8章:存储与磁盘 →
本章评分
4.6  / 5  (46 评分)

💬 留言讨论