Skip to content

Latest commit

 

History

History
385 lines (299 loc) · 13.3 KB

08-network-services.md

File metadata and controls

385 lines (299 loc) · 13.3 KB

08. 网络服务与应用

网络通了之后,机器要对外提供能力。本章讲四个最典型的服务:Web、DNS、时间、打印。

这一层解决什么问题

把"网络可用"变成"服务可用"。每个服务都有共同的骨架:

监听端口 → 读取配置 → 处理请求 → 记录日志 → 由 systemd 监护

学会一个服务的排查路径,其他服务都能套用。

一、Nginx:Web 服务器与反向代理

1.1 定位

nginx 现在主流用法不是"当 Web 服务器",而是反向代理 + TLS 终结 + 静态资源。

用法 说明
静态文件服务器 直接返回文件
反向代理 转发到后端应用(Python/Node/Java)
TLS 终结 证书、HTTPS 卸载
负载均衡 多后端分发
API 网关(轻量) 路由、限流

1.2 配置文件结构

/etc/nginx/
├── nginx.conf              # 主配置
├── conf.d/*.conf           # 发行版约定的片段目录
├── sites-available/        # Debian 系:可用站点
├── sites-enabled/          # Debian 系:启用(→ available 的软链接)
├── snippets/               # 可复用片段
└── mime.types

配置的层级模型(理解嵌套关系是关键):

main(全局)
 ├─ events { }              # 连接处理模型
 └─ http {                  # 所有 HTTP 相关
     ├─ server {            # 一个虚拟主机(监听某个端口/域名)
     │   ├─ location / { }  # 按 URI 路由
     │   └─ location /api/ { }
     └─ upstream backend { } # 后端服务器组

一份实用的配置(静态 + 反向代理):

# /etc/nginx/sites-available/example.com
upstream app_backend {
    server 127.0.0.1:8080;
    server 127.0.0.1:8081;
    keepalive 32;
}

server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;

    # HTTP → HTTPS
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    http2 on;
    server_name example.com;

    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_protocols       TLSv1.2 TLSv1.3;
    ssl_session_cache   shared:SSL:10m;

    root  /var/www/example.com;
    index index.html;

    access_log /var/log/nginx/example.access.log;
    error_log  /var/log/nginx/example.error.log warn;

    location /static/ {
        expires 30d;
        add_header Cache-Control "public, immutable";
    }

    location /api/ {
        proxy_pass http://app_backend/;
        proxy_set_header Host              $host;
        proxy_set_header X-Real-IP         $remote_addr;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_read_timeout 60s;
    }
}

启用站点:

$ sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
$ sudo nginx -t                    # ← 语法检查,改完必做
$ sudo systemctl reload nginx      # 平滑重载(不断连接)
$ sudo systemctl restart nginx     # 重启(会断连接)

1.3 常见配置陷阱

陷阱 说明
proxy_pass http://host/ 尾斜杠 有无尾斜杠语义不同:有则替换 location 前缀,无则拼接原 URI
location 匹配优先级 =(精确)> ^~(前缀优先)> ~/~*(正则)> 普通前缀
server_name 不匹配 落到 default_server,可能返回错误站点
root vs alias root 拼接 URI,alias 替换 location 部分
reload 不生效 配置加载成功但未 reload;或 upstream 有缓存

nginx -T 打印合并后的完整配置(含 include 展开)。当你不确定实际生效的配置是什么时,用这个而不是人肉追 include。

1.4 排障

$ sudo nginx -t                              # ① 语法
$ sudo nginx -T | grep -A5 proxy_pass        # ② 实际生效的配置
$ systemctl status nginx                     # ③ 服务状态
$ sudo journalctl -u nginx -n 50             # ④ 服务日志
$ sudo tail -f /var/log/nginx/error.log      # ⑤ 错误日志 ← 最有用
$ sudo tail -f /var/log/nginx/access.log     # ⑥ 访问日志
症状 原因
502 Bad Gateway 后端没起来 / 端口错 / SELinux(setsebool -P httpd_can_network_connect 1)
403 Forbidden 目录权限、SELinux 标签(restorecon)、缺 index
404 root/alias 配错、路径拼接问题
504 Timeout 后端太慢,调 proxy_read_timeout
413 Request Entity Too Large client_max_body_size 太小(上传大文件常见)
端口冲突起不来 ss -tlnp | grep :80,常见是 apache 或另一个 nginx

SELinux 是 502 的隐形元凶:nginx 连本地后端属于"网络连接",被 SELinux 默认策略阻止。ausearch -m AVC -ts recent 能看到。

二、DNS 服务端

2.1 三个选择

软件 定位 适用
dnsmasq 极轻量,集成 DHCP + DNS + TFTP 局域网、家庭路由、开发环境
unbound 轻量递归/缓存解析器 本地递归解析、隐私优先
BIND9 全功能权威 + 递归 企业级、需要权威区文件

2.2 dnsmasq(局域网最常用)

# /etc/dnsmasq.conf
interface=eth0
dhcp-range=192.168.1.100,192.168.1.200,12h
dhcp-option=3,192.168.1.1          # 网关
dhcp-option=6,192.168.1.1          # DNS
domain=lan
address=/app.lan/192.168.1.10      # 静态 DNS 记录
server=8.8.8.8                     # 上游
cache-size=1000
log-queries                        # 排障时开

动态 DNS 记录(读 /etc/hosts 风格的文件,改完发 HUP 即生效):

addn-hosts=/etc/dnsmasq-hosts
$ sudo systemctl reload-or-restart dnsmasq
$ dig @192.168.1.1 app.lan           # 验证
$ sudo journalctl -u dnsmasq -f

2.3 unbound(本地递归解析)

# /etc/unbound/unbound.conf.d/local.conf
server:
    interface: 127.0.0.1
    access-control: 127.0.0.0/8 allow
    do-daemonize: yes
    hide-identity: yes
    hide-version: yes
    qname-minimisation: yes
    # 转发模式(或完全递归)
    forward-zone:
        name: "."
        forward-addr: 223.5.5.5
        forward-addr: 1.1.1.1
$ unbound-checkconf
$ sudo systemctl restart unbound
$ dig @127.0.0.1 example.com
$ sudo unbound-control stats_noreset | head

2.4 客户端视角的 DNS(回到 07)

分清"服务端"和"客户端":本章讲的是怎么提供 DNS 服务。客户端怎么使用 DNS(resolv.conf、nsswitch.conf、systemd-resolved)在 07 章。

三、时间同步(NTP 客户端)

3.1 为什么时间准很关键

时间不对会导致:TLS 证书校验失败、集群认证失败、日志顺序混乱、make 不重新编译、Kerberos 直接拒绝。

3.2 现代方案:chrony

ntpd 已基本被 chrony 取代(对不稳定网络、休眠唤醒的机器表现更好)。

$ sudo apt install chrony          # 或 dnf install chrony
$ systemctl status chronyd

$ chronyc tracking                 # 当前同步状态与偏差 ← 主要排障命令
$ chronyc sources -v               # 时间源及状态(`^*` = 当前使用的源)
$ chronyc sourcestats              # 统计
$ chronyc makestep                 # 立即跳变修正(默认缓慢调整)
# /etc/chrony/chrony.conf
pool 2.debian.pool.ntp.org iburst
# 或用国内源
# server ntp.aliyun.com iburst
driftfile /var/lib/chrony/chrony.drift
makestep 1.0 3                     # 前 3 次同步允许直接跳变
rtcsync
allow 192.168.1.0/24               # 允许局域网客户端同步(当作内网 NTP 服务器)

3.3 其他方案

方案 特点
systemd-timesyncd 极简 SNTP 客户端,够用,默认在多数桌面系统
ntpd 经典 NTP 实现,功能全但笨重
ntpdate 一次性同步,已废弃(会跳变时间,可能损害服务)
gpsd + chrony 无外网时用 GPS 授时
$ timedatectl                       # 一站式看时间、时区、同步状态 ← 先看这个
$ timedatectl set-timezone Asia/Shanghai
$ timedatectl set-ntp true          # 启用网络时间同步
$ date -R
$ sudo hwclock --show               # 硬件时钟(RTC)
$ sudo hwclock --systohc            # 系统时间写入硬件钟(UTC 建议)

双系统时间错 8 小时的根因:Windows 默认把硬件钟当本地时间,Linux 默认当 UTC。解决:让 Linux 用本地时间 timedatectl set-local-rtc 1(不推荐),或让 Windows 用 UTC(改注册表,推荐)。

3.4 自建内网 NTP

# chrony 服务端加 allow;客户端指向它
$ chronyc clients                   # 看谁在同步你

注意:NTP 用 UDP 123。防火墙要放行,且要允许已建立连接的返回流量(conntrack 处理)。只放行入站 123 通常够。

四、CUPS:打印服务

4.1 定位

CUPS(Common Unix Printing System)是 Linux/Unix 的事实标准打印架构,也支持 macOS。

应用 → CUPS(cupsd,端口 631)→ 驱动(filter/PPD/IPP Everywhere)→ 打印机

4.2 基本操作

$ systemctl status cups
$ lpstat -p -d                      # 打印机列表与默认打印机
$ lpstat -t                         # 全部状态
$ lp -d printer file.pdf            # 打印
$ lpoptions -d printer              # 设默认
$ lpadmin -p HP -E -v ipp://192.168.1.20/ipp/print -m everywhere   # 添加打印机
$ cancel -a printer                 # 取消所有任务
$ cupsctl --remote-admin            # 允许远程管理(⚠️ 安全风险)

Web 管理界面:http://localhost:631

4.3 驱动模型的变化(重要)

时代 方式
老 厂商提供二进制的 PPD + filter 驱动
现在 IPP Everywhere / driverless:打印机自己宣布能力,无需专有驱动
过渡 gutenprint、foomatic(开源驱动库)
$ lpinfo -v                         # 发现可用设备/后端
$ lpinfo -m | grep -i "everywhere"  # 可用驱动模型
$ sudo systemctl restart cups

4.4 排障

$ sudo tail -f /var/log/cups/error_log      # ← 主要日志
$ sudo cupsctl --debug-logging              # 开详细日志
$ lpstat -t
$ sudo journalctl -u cups -n 50
症状 原因
任务卡住不动 打印机离线、IP 变了、防火墙拦了 631/9100
无法发现网络打印机 未装 avahi(mDNS)、防火墙拦 5353
打印乱码 驱动/PPD 不匹配,改用 IPP Everywhere
权限拒绝 用户在 lpadmin 组?lp/lpadmin 组配置

网络打印机的两个入口:CUPS(631)和打印机的直接 RAW 端口(9100)。转发打印给其他机器时常常是 9100,排查要分别测。

五、通用排障方法论

任何网络服务的排查都可以套这个模板:

# ① 进程在跑吗
$ systemctl status <service>
# ② 在监听吗(端口 + 监听地址)
$ ss -tulnp | grep <port>
# ③ 配置语法对吗
$ <service> -t / --check-config
# ④ 日志说什么
$ journalctl -u <service> -n 100 ; tail -f /var/log/<service>/*
# ⑤ 本机能连吗
$ curl -v http://127.0.0.1:<port>/
# ⑥ 防火墙/MAC 放行了吗
$ sudo nft list ruleset ; getenforce ; sudo aa-status
# ⑦ 权限与文件属主对吗
$ ls -l /var/log/<service>/ ; ps -o user= -C <service>

跨主机访问不通的检查顺序(从近到远):

检查点 命令
监听地址是否 0.0.0.0/:: ss -tlnp
本机防火墙 iptables -L / nft list ruleset / ufw status
SELinux/AppArmor getenforce / aa-status
上游防火墙/安全组 云控制台 / 交换机 ACL
中间链路 mtr、tcpdump 两端同时抓包
应用层 curl -v、看服务端 access log

两端同时抓包的技巧:在客户端 tcpdump -i any host server,服务端 tcpdump -i any host client。看包到没到,一眼分辨是"没送到"还是"送了没回"。这是网络排障最有效的手段。

常见误区

  • nginx -t 只是语法检查,配置逻辑错误它查不出来。
  • reload 不一定生效,有些改动(如换监听端口、改 events)必须 restart。
  • DNS 服务端和客户端是两回事,别混着调。
  • 时间同步不是装完就准,要 chronyc tracking 确认偏差收敛。
  • CUPS 的 631 和打印机的 9100 是两个不同入口。
  • 改完配置不重启服务 —— 排障时最常见的浪费。

待补充

  • TLS 证书管理(Let's Encrypt / acme.sh / 自签 CA)
  • nginx 高级:限流、缓存、gzip/brotli、WebSocket 代理
  • HAProxy / Traefik / Caddy 对比
  • BIND9 权威区文件与 DNSSEC 签名
  • 邮件服务器(postfix + dovecot + SPF/DKIM/DMARC)
  • 文件共享:Samba / NFS / WebDAV
  • 反向代理后的真实客户端 IP(X-Forwarded-For 与 real_ip 模块)
  • 内网服务发现(mDNS/avahi、Consul、etcd)
  • 打印服务的容器化(CUPS in Docker)

← 上一章:网络基础与配置 · 返回目录 · 下一章:防火墙与内核网络参数 →