%%
# 纲要
> 主干纲要、Hint/线索/路标
# Q&A
#### 已明确
#### 待明确
> 当下仍存有的疑惑
**❓<font color="#c0504d"> 有什么问题?</font>**
# Buffer
## 闪念
> sudden idea
## 候选资料
> Read it later
%%
# Linux 下网络相关工具
Linux/Unix 下的**网络配置与诊断工具包**:
- `net-tools`:**早期 Linux 发行版**中使用,包括 `ifconfig`、`netstat`、`route`、`arp`、`nameif` 等一系列工具。
- `iproute2`: **现代 Linux 发行版**中默认具备的网络工具包,提供**更强大的现代功能**,包括`ip addr`、`ip route` 、`ss` 等一系列命令行工具。
工具替代说明:
| | `net-tools` | `iproute2` | 备注 |
| ---------- | ----------- | ------------------- | --------------------------------- |
| | | | |
| **网络接口相关** | `ifconfig` | `ip addr`、`ip link` | 配置、查看网络接口的信息(IP 地址、子网掩码、MAC 地址等等) |
| **路由相关** | `route` | `ip route` | 管理路由表、配置默认网关等 |
| **ARP 相关** | `arp` | `ip neigh` | 管理 ARP 表 |
| **网络状态统计** | `netstat` | `ss` | 显示**网络连接、路由表、接口状态、统计信息**等。 |
| | `mii-tool` | `ethtool` | 查询和配置网络接口的**硬件属性** |
<br><br>
# ip 命令及其子命令
命令格式:`ip <子命令> [options...]`
| 子命令 | 缩写 | 作用说明 |
| --------- | --- | --------------------------- |
| `link` | `l` | 管理网络设备(如启用/禁用网卡接口,查看 MAC 等) |
| `address` | `a` | 管理 **IP 地址**(查看、设置 IP 地址) |
| `route` | `r` | 查看和配置**路由表** |
| `neigh` | `n` | 管理邻居(**ARP 缓存**、IPv6 邻居发现) |
![[_attachment/02-开发笔记/11-Linux/Linux 命令行/Linux-网络相关命令.assets/IMG-Linux-网络相关命令-7A80A5890664E5BD1C6D4808FA88A3EC.png|654]]
## 网络接口管理——`ip link`
```shell
ip l|link # 查看所有网卡接口
ip link set eth0 up # 启用 etho0 接口
ip link set eth0 down # 禁用 etho0 接口
ip -s link # 查看网络接口的统计信息
```
> [!example] `ip -s link` 查看接口吞吐量统计
> ![[_attachment/02-开发笔记/11-Linux/Linux 命令行/Linux-网络相关命令.assets/IMG-Linux-网络相关命令-34E2DB1243EAC6635A90FB3D3B469E2D.png|767]]
<br>
## IP 地址管理——`ip address`
```shell
# 查看所有网卡接口的IP地址
ip a|addr|address
# 查看指定网络接口的信息
ip a | grep eth0
# 配置IP地址: ip addr add <地址/网络前缀长度> dev <接口名>
ip addr add 192.168.1.100/24 dev eth0 # 添加 IP
# 删除IP地址: ip addr del <地址/网络前缀长度> dev <接口名>
ip addr del 192.168.1.100/24 dev eth0 # 删除 IP
```
旧的 net-tools 工具包命令:
```shell
# ---------------------------------------------net-tools 工具包
ifconfig # 查看所有网络接口的信息
ifconfig eth0 <IP地址> netmask <子网掩码> # 配置 IP 地址
ifconfig eth0 up # 启用接口
ifconfig eth0 down # 禁用接口
```
<br>
## 路由管理——`ip route`
```shell
ip route # 查看当前路由表
ip route add default via 192.168.1.1 dev eth0 # 设置默认网关
ip route del default # 删除默认路由
```
旧的 net-tools 工具包命令:
```shell
# ---------------------------------------------net-tools 工具包
route -n # 查看系统路由表( `-n`参数防止对 IP 地址的 DNS 解析,提升查询速度)
route add default gw <ip地址> # 添加默认网关
route del default gw <ip地址> # 删除默认网关
```
> [!example] `ip route` 路由表说明
>
> ![[_attachment/02-开发笔记/11-Linux/Linux 命令行/Linux-网络相关命令.assets/IMG-Linux-网络相关命令-37D60BE0AD04B7AD818A711D81F6149E.png|702]]
>
> - 首行为**默认路由**
> - `default` :标识默认路由;
> - `via 192.168.88.2`:默认网关的 IP 地址;
> - `dev ens33`:表示该路由**通过网络接口 `ens33` 转发**。
> - `proto dhcp`:该路由条目通过 DHCP 协议动态获取;
> - `metric 100`:跃点数,表示路由优先级,数字越小优先级越高。
> - 第二行为**直连路由**:表示访问 `192.168.88.0/24` 网段中的主机时直接通过 ens33 网卡发送,无需找网关。
> - `169.254.0.0/16`:目的网段
> - `scope link`:表示在 "**本地链路**" 上,即 "**==直连路由==**",此路由**仅适用于与本机网卡接口直连的设备**;
> - 第三行为**直连路由**
> - `192.168.88.0/24`:目的网段
> - `proto kernel`:表示该路由为**操作系统内核添加的静态路由**。
> - `src 192.168.88.131`:表示**源 IP 地址为 `192.168.88.131` 的数据包均使用此路由**
> - (针对单网卡 `ens33` 绑定了多个 IP 的情况)
<br>
## ARP 缓存管理——`ip neigh`
```shell
# 查看 ARP 表
ip neigh
# 增添静态ARP表项: ip neigh add <IP地址> lladdr <MAC地址> dev <接口名>
ip neigh add 192.168.1.10 lladdr aa:bb:cc:dd:ee:ff dev eth0 # 添加静态 ARP
# 删除指定ARP表项
ip neigh del 192.168.1.10 dev eth0
# 清空ARP缓存表
ip neigh flush all
```
旧的 net-tools 工具包命令:
```shell
# ---------------------------------------------net-tools 工具包
arp -a # 查看 ARP 表项
apr -s <IP地址> <MAC地址> # 增添指定ARP表项
arp -d <IP地址> # 删除指定ARP表项
```
> [!example] `ip neight` ARP 缓存说明
>
> ![[_attachment/02-开发笔记/11-Linux/Linux 命令行/Linux-网络相关命令.assets/IMG-Linux-网络相关命令-D4E65D4CB3529DB407DB234CD1DA80B1.png|513]]
>
> - 首列:邻居主机的 IP 地址
> - `dev ens33`:本机上**与该邻居直连的网络接口**;
> - `lladdr xxx`:邻居主机的 MAC 地址
> - 最后一列为 "**状态**",表示**该 ARP 缓存条目的 "有效性"**:
> - `STALE`:超过一定时间没通信了,**尚未过期**,但**下次通信需要重新验证**(ARP请求)
> - `REACHABLE`:最近刚通信过,**ARP 缓存有效**,可以直接使用
> - `DELAY`:系统准备重新验证地址,但还在等待状态
> - `INCOMPLETE`:正在解析(比如刚发 ARP 请求还没收到响应)
> - `FAILED`:无法解析地址,通信失败
<br><br>
# 网络状态统计
## `ss` 命令 ❇️
> `ss` 属于 `iproute2` 套件,性能更好,信息更全,是现代 Linux 网络调试首选。
`ss [options] [state <状态名>]`:查看所有**已建立的 TCP 连接**,默认等价于 `ss -t state established`
- `-a`:查看 **所有状态** 的套接字(包括 `LISTEN`、`ESTABLISHED`、`TIME-WAIT`、`CLOSE-WAIT` 等)
- `-n`:不解析主机名或服务名,直接**显示数字形式的 IP 地址和端口号**。
- `-p`:显示关联进程 PID(需 root)
- `-t`:仅显示 TCP 连接(仅显示**已建立的**,即 **==`ESTABLISHED` 状态==** 的 TCP 连接)
- `-u`:仅显示 UDP 连接
- `-l`:仅显示**监听状态**的连接
- `-s`:显示统计信息(TCP 、UDP 当前连接数等)
- `-o`:显示 **计时器** 信息(如 TCP 超时)
- `-e`:显示扩展信息
- `-r`:显示路由信息
- `-i`:显示**套接字内部信息**:TCP 状态、内核 TCP 控制块信息(rtt、rto、mss)
- `-m`:显示**每个套接字内存使用大小**
> [!NOTE] `-o` 选项作用
>
> 显示套接字的计时器(TCP timer)信息,例如包括:
>
> - TCP 重传定时器(`retrans`)
> - TCP 超时剩余时间(`timer`)
> - TCP 的 `keepalive` 状态
>
> ![[_attachment/02-开发笔记/11-Linux/Linux 命令行/Linux-网络相关命令.assets/IMG-Linux-网络相关命令-49C1D52CDE196240E4DFC24DBFBEADBE.png|800]]
>
> 输出格式:`timer:(<类型>,<剩余时间>,<计数>)<标志位>`,示例如下:
>
> - `timer:(keepalive, 28min, 0)`:keepalive 机制正运行,距离下次发送 keepalive 心跳包还有 28min,发送次数计数为 0。
> - `timer:(timewait, 57sec, 0)`:当前连接处于 `TIME-WAIT` 状态,剩余 57 秒超时才彻底关闭,重试次数计数为 0。
> - `timer:(on, 245ms, 0)`:当前有定时器处于激活状态(可能是重传、keepalive 等),距离下次触发剩余时间 245ms,计数次数 0。
> [!NOTE] `-i` 选项显示信息
>
> ![[_attachment/02-开发笔记/11-Linux/Linux 命令行/Linux-网络相关命令.assets/IMG-Linux-网络相关命令-442DB96507AE4B6195C7C31529B90706.png|793]]
>
> [!NOTE] `-m` 选项显示 socket 内存占用信息
>
> ![[_attachment/02-开发笔记/11-Linux/Linux 命令行/Linux-网络相关命令.assets/IMG-Linux-网络相关命令-B1548C4F7A6B091E7B7FAB658476E5BD.png|836]]
>
> - `r`:当前**实际分配的接收缓冲区**大小(单位均为 "字节")
> - `rb`:**最大可分配**的接收缓冲区上限
> - `t`:当前**实际分配的发送缓冲区**大小
> - `tb`:**最大可分配**的发送缓冲区上限
>
> ![[_attachment/02-开发笔记/11-Linux/Linux 命令行/Linux-网络相关命令.assets/IMG-Linux-网络相关命令-44F099BB3C9462E2DAD0B91FDD6F52D8.png|444]]
>
<br>
### 字段说明
![[_attachment/02-开发笔记/11-Linux/Linux 命令行/Linux-网络相关命令.assets/IMG-Linux-网络相关命令-C2F3DFD0612DB8EB3712BBD3CFD0058F.png|720]]
`Recv-Q` 与 `Send-Q` 有两种不同含义:
- 对于 `Established` 状态的连接:
- `Recv-Q`:**接收缓冲区** 中 **"尚未被应用层读取"** 的字节数;
- `Send-Q`:**发送缓冲区** 中 "**尚未被发送**" 或 "**尚未被对端确认**" 的字节数。
- 对于 `Listening` 状态的连接:
- `Recv-Q`:**当前 ==全连接队列== 中的连接数**
- `Send-Q`:**==全连接队列==容量上限**
> [!info] `ss` 的 man 手册里未给出上述说明,但可见 `man netstat`,含义相同:
>
> ![[_attachment/02-开发笔记/11-Linux/Linux 命令行/Linux-网络相关命令.assets/IMG-Linux-网络相关命令-9978266EE1D8F53FD522146BA176ECE0.png|744]]
>
> [!error] error:`man netstat` 手册中标注的是 **`syn backlog` 值**(半连接队列大小),这点似乎错误。
>
> 根据实测,`Send-Q` 对于 `LISTEN` 状态的套接字**显示的是传入给 `listen(, backlog)` 的值**,而这个值应当是 "**==全连接队列上限==**" [^1]。
>
> ![[_attachment/02-开发笔记/11-Linux/Linux 命令行/Linux-网络相关命令.assets/IMG-Linux-网络相关命令-91B061531901E6318DF7989410B64D2D.png|516]]
>
> 否则,也无法解释 `Send-Q` 值大于 `/proc/sys/net/ipv4/tcp_max_syn_backlog` 参数。
>
> ![[_attachment/02-开发笔记/11-Linux/Linux 命令行/Linux-网络相关命令.assets/IMG-Linux-网络相关命令-212084DF6645CA4C695FDBD37DFB8DBA.png|461]]
>
<br>
### 使用示例
常见用法:
```shell
ss -tn # 查看所有ESTABLISHED状态的TCP端口
ss -tan # 查看所有TCP端口(所有状态的)
ss -tln # 查看LISTN状态的TCP端口, 等价于 `ss -tn state LISTEN`
ss -tlnp # 查看LISTE状态的TCP端口及其进程PID
ss -tuln # 查看监听的TCP/UDP套接字
ss -tani # 查看所有TCP连接的详细参数信息
ss -tm # 查看TCP套接字的接收、发送缓冲区大小
ss -tn state SYN-RECV # 查看所有SYN_RECV 状态的连接
ss -tno state established # 查看所有已建立TCP连接的套接字,包括其 timer 状态(如 keepalive)
ss -tno state time-wait # 查看 TIME-WAIT 状态的连接,以及超时时间剩余.
ss -s # 查看网络统计信息
ss -o state established '( dport = :80 )' # 查看所有访问 80 端口的已连接套接
```
> [!tip] 可分析 TIME-WAIT 太多导致端口耗尽时,可使用 `ss -tan state TIME-WAIT`
> [!example] 示例:查看所有 TCP 监听端口
> ![[_attachment/02-开发笔记/11-Linux/Linux 命令行/Linux-网络相关命令.assets/IMG-Linux-网络相关命令-9A01E7CD886F2A10742E1986EB1C9285.png|679]]
<br><br>
## `netstat` 命令
> 属于 `net-tools` 工具集,已被官方标记为过时,推荐使用 `ss` 替代
`netstat [options] `:
- `-a`:查看所有状态的连接
- `-n`:不解析主机名或服务名
- `-p`:显示关联进程 PID(需 root)
- `-t`:仅显示 TCP 连接
- `-u`:仅显示 UDP 连接
- `-l`:仅显示**监听状态**的连接
- `-s`:显示 **统计信息**(TCP、UDP 当前连接数等)
- `-o`:显示 **计时器** 信息(如 TCP 超时)
- `-e`:显示扩展信息
- `-i`:显示网络接口列表
- `-r`:显示路由表(同 `route -n`)
> [!NOTE] 选项含义基本同 `ss` 命令
```shell
# ---------------------------------------------net-tools 工具包
netstat -an # 查看所有连接
netstat -tuln # 查看所有监听的TCP, UDP端口
netstat -tanp # 查看所有TCP端口, 包括其关联进程PID
netstat -s # 查看网络统计信息(出错包、连接数等)
netstat -i # 查看网络接口列表
```
> [!example] 查看所有 TCP 连接状态
> ![[_attachment/02-开发笔记/11-Linux/Linux 命令行/Linux-网络相关命令.assets/IMG-Linux-网络相关命令-D861D166B25AE84C631047A889A83AD8.png|725]]
<br><br><br>
# 查看网络连接与端口占用
查看**指定地址连接**、**端口被哪个进程占用**,可使用 `lsof -i` 命令,参见 [[02-开发笔记/11-Linux/Linux 命令行/Linux-系统信息相关命令#查看系统中已打开的文件对象⭐——lsof|Linux-系统信息相关命令-lsof]]。
##### 关于 `ss` 与 `lsof -i` 命令的使用
| | `SS` | `lsof -i` |
| ----------- | --------------------------------- | --------------------------------------------- |
| 侧重点 | **网络 socket 状态** | **打开的文件描述符**(包括网络 socket) |
| 使用场景 | **网络状态分析**、**查看所有监听端口**、**连接状态**等 | 查看**指定地址&端口的连接**,查看**哪个进程占用哪个端口** |
| 底层信息来源 | 直接读取 `/proc/net/*` 内核接口(高效) | 扫描 `/proc/<pid>/fd` 和 `/proc/<pid>/net/*`(较慢) |
| 性能 | 极快,适合实时统计 | 慢,尤其是链接较多时 |
| socket 状态分析 | 支持 | 不支持,只显示打开的连接 |
> [!example] `ss` 与 `lsof -i` 关于 TCP 连接的输出对比
>
> ![[_attachment/02-开发笔记/11-Linux/Linux 命令行/Linux-网络相关命令.assets/IMG-Linux-网络相关命令-77980A1C4FB161DEAC8340BA28E75C44.png|801]]
>
>
<br><br>
# DNS 查询
两个命令均可:
```shell
# 查询域名对应的 IP 地址
# 方式一:
dig <domain>
# 方式二:
nslookup <domain>
```
<br><br>
# ping 工具
`ping [OPTIONS] <目标主机域名/IP>`
选项:
- `-c <count>`:指定发送的 **ICMP 请求数**。
- `-i <interval>` :设置**发送每个请求的间隔时间**(秒),默认为 1 秒。
- `-t <ttl>`:设置 IP 数据包中的 TTL 值
- `-n`:不解析主机名,只显示 IP 地址
- `-I <interface>`:指定发送请求所**使用的网络接口**
> [!caution] Linux 下 `ping` 命令与 windows 下 `ping` 命令的选项名有所差异!
>
> Windows 下命令选项如下:
> ![[_attachment/02-开发笔记/11-Linux/Linux 命令行/Linux-网络相关命令.assets/IMG-Linux-网络相关命令-EB3416805689C4143064385F34FECE52.png|519]]
<br><br>
# nc 工具(Netcat)
`nc` 全称 Netcat,是一个广泛使用的**网络调试工具**,可进行 TCP/UDP 连接、监听、端口扫描、数据传输、服务模拟等功能。
常用场景:
- 检查端口是否开放
- 建立 TCP 或 UDP 连接进行调试
- 模拟客户端/服务端
- 简易的文件传输
- 简易的网络通信测试
> [!tip] 在生产环境下,服务器通常会配置**禁用 ICMP**(即**禁用 ping**),此时可使用 `nc` 来判断两台主机之间的网络连通性。
>
> 例如 `nc -zv <目标IP> <端口号>`,只探测 TCP 端口,不发生数据。
>
<br>
## `nc` 命令说明
`nc [options] [destination] [port]`:
- `-l`:监听模式,用于**充当服务器**(listen),默认监听 TCP 端口
- `-u`:使用 UDP(**默认是 ==TCP==**)
- `-z`:**扫描模式**,不发送数据,**只探测端口是否开放**
- `-v`:显示详细信息(verbose);
- `-vv`:very verbose;
- `-n`:禁用 DNS,直接使用 IP 地址
- `-w <秒>`:设置超时时间
不带任何选项时,直接指定 IP 地址和端口号,将**发起 TCP 连接并进入==交互模式==**(此后 stdin 内容都将发送给目标,收到数据将显示到 stdout)
#### 使用示例
```shell
# 检查80端口是否开放
nc -zv 192.168.1.10 80
# 多端口扫描: 端口返回
nc -zv 192.168.1.10 20-100 # 扫描20-100端口
nc -zv 192.168.1.10 22,80,443 # 扫描指定的多个端口
# 指定连接超时时间
nc -zvw 2 192.168.1.10 22 # 2s超时时间
# 启动TCP服务监听
nc -l 8888
# 文件传输
nc -l 9999 > recv.txt # 服务端命令, 开启TCP端口监听, 数据写入指定文件
nc 192.168.1.100. 9999 < send.txt # 客户端命令, 向指定地址发送数据
```
> [!example] 检测 80 端口是否开放
> ![[_attachment/02-开发笔记/11-Linux/Linux 命令行/Linux-网络相关命令.assets/IMG-Linux-网络相关命令-A427E07A889645381F54DE387A41AB0A.png|528]]
<br><br>
%%
# nmap 工具
nmap 全称 Network Mapper,是一个专业的**网络扫描**工具,广泛用于安全审计、网络运维和故障排查等场景,支持**端口扫描、主机发现、服务识别**等。
> [!info] Ubuntu 下未自带 nmap
> [!example] `nc` 与 `nmap` 检测远程主机端口是否开启时的输出差异
> ![[_attachment/02-开发笔记/11-Linux/Linux 命令行/Linux-网络相关命令.assets/IMG-Linux-网络相关命令-AB352567D10605E50B249DBD1FE20915.png|465]]
>
%%
<br><br>
# 参考资料
# Footnotes
[^1]: 《UNIX 网络编程卷 1:套接字联网 API》(P87)