前置知识: Git

网络与安全

5 min中级

TCP/IP 协议栈、DNS/HTTP/HTTPS、防火墙、SSL/TLS、SSH 安全与网络故障排查。

学习目标

本文是「运维与中间件」模块的第 4 篇,难度定位为进阶。重点内容:TCP/IP 协议栈、DNS/HTTP/HTTPS、防火墙、SSL/TLS、SSH 安全与网络故障排查。

主要章节:

    1. TCP/IP 协议栈
    1. DNS
    1. HTTP/HTTPS
    1. 防火墙
    1. SSH 安全
    1. VPN
  • ……共 19 个章节

1. TCP/IP 协议栈

1.1 OSI 七层 vs TCP/IP 四层

OSITCP/IP协议数据单元
应用层应用层HTTP, DNS, SSH, FTP数据
表示层应用层TLS/SSL, JPEG数据
会话层应用层RPC, NetBIOS数据
传输层传输层TCP, UDP段/数据报
网络层网络层IP, ICMP, ARP包
数据链路层网络接口层Ethernet, PPP帧
物理层网络接口层电信号、光纤比特

1.2 TCP 三次握手与四次挥手

flowchart TD
    T0["三次握手:"]
    T1["Client          Server"]
    T2["SYN"]
    T3["SYN+ACK"]
    T4["ACK"]
    T5["四次挥手:"]
    T6["Client          Server"]
    T7["FIN"]
    T8["ACK"]
    T9["FIN"]
    T10["ACK"]
    T0 --> T1
    T1 --> T2
    T1 --> T3
    T1 --> T4
    T4 --> T5
    T5 --> T6
    T6 --> T7
    T6 --> T8
    T6 --> T9
    T6 --> T10

1.3 常用端口

端口协议用途
22SSH远程登录
53DNS域名解析
80HTTPWeb 服务
443HTTPS安全 Web
3306MySQL数据库
5432PostgreSQL数据库
6379Redis缓存
8080HTTP Alt代理/应用
9090Prometheus监控

2. DNS

2.1 DNS 解析流程

浏览器缓存 → 系统缓存 → 路由器缓存 → ISP DNS
    → 根域名服务器 → 顶级域名服务器 → 权威域名服务器

2.2 DNS 记录类型

类型描述示例
AIPv4 地址example.com → 93.184.216.34
AAAAIPv6 地址example.com → 2606:2800:220:1:...
CNAME别名www.example.com → example.com
MX邮件服务器example.com → mail.example.com
TXT文本记录SPF、DKIM 验证
NS域名服务器example.com → ns1.dns.com
SRV服务记录_http._tcp → server:port

2.3 DNS 排查

# DNS 查询
dig example.com              # 完整查询
dig +short example.com       # 仅显示 IP
nslookup example.com         # Windows 兼容
host example.com             # 简洁输出

# 指定 DNS 服务器
dig @8.8.8.8 example.com

# 反向解析
dig -x 93.184.216.34

# 追踪解析过程
dig +trace example.com

# DNS 缓存清理
sudo systemd-resolve --flush-caches    # systemd-resolved
sudo rndc flush                         # BIND

3. HTTP/HTTPS

3.1 HTTP 请求方法

方法用途幂等安全
GET获取资源是是
POST创建资源否否
PUT更新资源是否
DELETE删除资源是否
PATCH部分更新否否
HEAD获取头信息是是

3.2 HTTP 状态码

范围类别常见码
1xx信息100 Continue
2xx成功200 OK, 201 Created, 204 No Content
3xx重定向301 永久, 302 临时, 304 未修改
4xx客户端错误400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found, 429 Too Many Requests
5xx服务端错误500 Internal Error, 502 Bad Gateway, 503 Unavailable, 504 Timeout

3.3 HTTPS 与 TLS

sequenceDiagram
    participant C as Client
    participant S as Server
    C->>S: ClientHello(支持的加密套件)
    S-->>C: ServerHello + Certificate(选择的套件 + 证书)
    C->>S: Key Exchange
    S-->>C: Finished
    Note over C,S: 加密通信
# 查看证书信息
openssl s_client -connect example.com:443 -showcerts

# 检查证书过期时间
echo | openssl s_client -connect example.com:443 2>/dev/null | \
  openssl x509 -noout -dates

# 生成自签名证书
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem \
  -days 365 -nodes -subj "/CN=localhost"

4. 防火墙

4.1 iptables

# 查看规则
iptables -L -n -v
iptables -t nat -L -n

# 允许 SSH
iptables -A INPUT -p tcp --dport 22 -j ACCEPT

# 允许已建立的连接
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# 允许本地回环
iptables -A INPUT -i lo -j ACCEPT

# 允许 HTTP/HTTPS
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT

# 默认拒绝
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

# 保存规则
iptables-save > /etc/iptables/rules.v4

4.2 firewalld

# 基本操作
systemctl start firewalld
systemctl enable firewalld
firewall-cmd --state

# 区域管理
firewall-cmd --get-zones               # 列出区域
firewall-cmd --get-default-zone        # 默认区域
firewall-cmd --set-default-zone=public

# 开放端口
firewall-cmd --add-port=80/tcp --permanent
firewall-cmd --add-service=http --permanent
firewall-cmd --reload

# 查看规则
firewall-cmd --list-all
firewall-cmd --list-ports

# 富规则(精细控制)
firewall-cmd --add-rich-rule='
  rule family="ipv4"
  source address="10.0.0.0/8"
  port port="3306" protocol="tcp"
  accept' --permanent

4.3 UFW(Ubuntu)

# 基本操作
ufw enable
ufw status verbose

# 开放端口
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw allow from 10.0.0.0/8 to any port 3306

# 拒绝
ufw deny 3306/tcp
ufw delete allow 8080/tcp

# 限流(防暴力破解)
ufw limit 22/tcp

5. SSH 安全

5.1 SSH 密钥认证

# 生成密钥对
ssh-keygen -t ed25519 -C "user@host"
# 或 RSA
ssh-keygen -t rsa -b 4096 -C "user@host"

# 复制公钥到服务器
ssh-copy-id user@server
# 或手动
cat ~/.ssh/id_ed25519.pub | ssh user@server "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"

# SSH 配置文件
cat ~/.ssh/config
Host myserver
    HostName 192.168.1.100
    User deploy
    Port 22
    IdentityFile ~/.ssh/id_ed25519
    ForwardAgent yes

5.2 SSH 加固

# /etc/ssh/sshd_config
Port 2222                          # 修改默认端口
PermitRootLogin no                 # 禁止 root 登录
PasswordAuthentication no          # 禁用密码认证
PubkeyAuthentication yes           # 启用密钥认证
MaxAuthTries 3                     # 最大尝试次数
AllowUsers deploy admin            # 限制允许的用户
ClientAliveInterval 300            # 空闲超时
ClientAliveCountMax 2              # 超时次数
LoginGraceTime 30                  # 登录超时
X11Forwarding no                   # 禁用 X 转发

# 重启 SSH
sudo systemctl restart sshd

5.3 SSH 隧道

# 本地端口转发
ssh -L 8080:localhost:80 user@server    # 本地 8080 → 服务器 80

# 远程端口转发
ssh -R 9090:localhost:3000 user@server  # 服务器 9090 → 本地 3000

# 动态端口转发(SOCKS 代理)
ssh -D 1080 user@server

# 跳板机
ssh -J bastion user@internal-server

6. VPN

6.1 WireGuard

# 安装
sudo apt install wireguard

# 生成密钥
wg genkey | tee privatekey | wg pubkey > publickey

# 服务端配置 /etc/wireguard/wg0.conf
[Interface]
PrivateKey = <server_private_key>
Address = 10.0.0.1/24
ListenPort = 51820
PostUp = iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

[Peer]
PublicKey = <client_public_key>
AllowedIPs = 10.0.0.2/32

# 客户端配置
[Interface]
PrivateKey = <client_private_key>
Address = 10.0.0.2/24
DNS = 8.8.8.8

[Peer]
PublicKey = <server_public_key>
Endpoint = <server_ip>:51820
AllowedIPs = 0.0.0.0/0  # 全部流量走 VPN
PersistentKeepalive = 25

# 启动
sudo wg-quick up wg0
sudo systemctl enable wg-quick@wg0

7. 网络故障排查

7.1 排查流程

flowchart TD
    T0["物理层 → 数据链路层 → 网络层 → 传输层 → 应用层"]
    T1["curl, telnet"]
    T2["ss, netstat"]
    T3["ping, traceroute, ip route"]
    T4["arp, ethtool"]
    T5["ethtool, mii-tool"]
    T0 --> T1
    T0 --> T2
    T0 --> T3
    T0 --> T4
    T4 --> T5

7.2 常用排查命令

# 连通性
ping -c 4 8.8.8.8                    # ICMP 连通
traceroute example.com               # 路由追踪
mtr -rwzbc 100 example.com          # 持续路由统计

# 端口连通
telnet example.com 443               # TCP 连通
nc -zv example.com 443               # 端口扫描
curl -v https://example.com          # HTTP 测试

# DNS 排查
dig example.com                      # DNS 解析
nslookup example.com                 # DNS 查询

# 路由排查
ip route                             # 路由表
ip route get 8.8.8.8                 # 到目标的路径

# 抓包分析
tcpdump -i eth0 port 80              # 抓 HTTP 包
tcpdump -i eth0 host 10.0.0.1        # 抓特定主机
tcpdump -i eth0 -w capture.pcap      # 保存到文件

# 连接统计
ss -tlnp                             # TCP 监听
ss -s                                # 连接概览
netstat -an | grep :80 | wc -l       # 80 端口连接数

7.3 常见故障与解决

故障现象可能原因排查方法
无法 ping 通防火墙/路由iptables -L, ip route
DNS 解析失败DNS 配置/服务器dig, cat /etc/resolv.conf
连接超时防火墙/服务未启动telnet, ss -tlnp
连接拒绝服务未监听ss -tlnp, systemctl status
连接重置防火墙/应用崩溃tcpdump, 应用日志
间歇性超时网络拥塞/MTUmtr, ping -M do -s 1472

8. 小结

网络与安全是运维的核心能力:

  1. TCP/IP 是网络通信的基础,理解协议栈有助于定位问题
  2. DNS 故障是最常见的网络问题,需掌握 dig/nslookup 排查
  3. HTTPS/TLS 是 Web 安全的基石,需了解证书管理和握手过程
  4. 防火墙配置需遵循最小权限原则,默认拒绝、按需开放
  5. SSH 加固是服务器安全的第一道防线,必须禁用密码登录
  6. 网络排查遵循从底层到高层的思路,逐步缩小问题范围

docker network create 创建网络

基本写法:创建桥接网络 docker network create <网络名>

# 创建自定义桥接网络
docker network create mynet

基本写法:指定子网创建网络 docker network create --subnet <CIDR> <网络名>

# 创建指定子网的网络
docker network create --subnet 172.20.0.0/16 mynet

基本写法:创建 overlay 网络 docker network create -d overlay <网络名>

# 创建跨主机 overlay 网络
docker network create -d overlay myoverlay

docker network ls 查看网络

基本写法:列出所有网络 docker network ls

# 列出所有 Docker 网络
docker network ls

基本写法:过滤网络 docker network ls --filter driver=<驱动>

# 只列出桥接网络
docker network ls --filter driver=bridge

docker network inspect 查看网络详情

基本写法:查看网络详情 docker network inspect <网络名>

# 查看 mynet 网络的详细信息
docker network inspect mynet

基本写法:查看网络中的容器 docker network inspect --format '{{range .Containers}}{{.Name}} {{end}}' <网络名>

# 列出网络中的所有容器
docker network inspect --format '{{range .Containers}}{{.Name}} {{end}}' mynet

docker network connect 连接容器到网络

基本写法:连接容器到网络 docker network connect <网络名> <容器>

# 将 web 容器连接到 mynet 网络
docker network connect mynet web

基本写法:指定 IP 连接 docker network connect --ip <IP> <网络名> <容器>

# 指定 IP 连接容器到网络
docker network connect --ip 172.20.0.5 mynet web

基本写法:使用别名连接 docker network connect --alias <别名> <网络名> <容器>

# 给容器设置网络别名
docker network connect --alias dbhost mynet web

docker network disconnect 断开网络

基本写法:断开容器与网络连接 docker network disconnect <网络名> <容器>

# 将 web 容器从 mynet 断开
docker network disconnect mynet web

基本写法:强制断开 docker network disconnect -f <网络名> <容器>

# 强制断开容器网络
docker network disconnect -f mynet web

docker network rm/prune 删除网络

基本写法:删除网络 docker network rm <网络名>

# 删除 mynet 网络
docker network rm mynet

基本写法:删除所有未使用网络 docker network prune

# 清理所有未使用的网络
docker network prune -f

容器使用自定义网络

基本写法:启动容器时指定网络 docker run --network <网络名> <镜像>

# 启动容器并加入 mynet 网络
docker run -d --name web --network mynet nginx

基本写法:指定网络别名 docker run --network <网络名> --network-alias <别名> <镜像>

# 给容器设置网络别名
docker run -d --name app --network mynet --network-alias api node

网络驱动类型

基本写法:bridge 桥接网络 docker network create -d bridge <网络名>

# 创建默认桥接网络
docker network create -d bridge mybridge

基本写法:host 主机网络 docker run --network host <镜像>

# 容器使用主机网络
docker run --network host nginx

基本写法:none 无网络 docker run --network none <镜像>

# 启动无网络的容器
docker run --network none alpine

端口映射

基本写法:映射单个端口 docker run -p <宿主端口>:<容器端口> <镜像>

# 映射 8080 到容器 80
docker run -p 8080:80 nginx

基本写法:映射多个端口 docker run -p <端口1>:<端口1> -p <端口2>:<端口2> <镜像>

# 映射多个端口
docker run -p 80:80 -p 443:443 nginx

基本写法:绑定指定 IP docker run -p <IP>:<宿主端口>:<容器端口> <镜像>

# 绑定到指定 IP
docker run -p 127.0.0.1:8080:80 nginx

基本写法:随机端口映射 docker run -P <镜像>

# 随机映射到宿主机端口
docker run -P nginx

DNS 与服务发现

基本写法:容器间通过名称访问 docker run --name <容器名> --network <网络名> <镜像>

# 在同一网络中通过容器名访问
docker run -d --name db --network mynet mysql
docker run -d --name web --network mynet nginx
# web 容器可通过 db 名称访问 mysql

基本写法:自定义 DNS 服务器 docker run --dns <DNS服务器> <镜像>

# 指定 DNS 服务器
docker run --dns 8.8.8.8 nginx

网络问题排查

基本写法:查看容器网络配置 docker inspect --format '{{.NetworkSettings}}' <容器>

# 查看容器网络设置
docker inspect --format '{{json .NetworkSettings.Networks}}' web

基本写法:测试容器间连通性 docker exec <容器> ping <目标容器>

# 测试 web 到 db 的连通性
docker exec web ping db

基本写法:查看容器端口映射 docker port <容器>

# 查看 web 容器的端口映射
docker port web