|
@@ -0,0 +1,744 @@
|
|
|
|
|
+# 技术方案文档 (TECH_DOC)
|
|
|
|
|
+
|
|
|
|
|
+Nginx Stream + SSL Preread 自动分流方案 — 完整技术文档
|
|
|
|
|
+
|
|
|
|
|
+> **版本**:v2.0
|
|
|
|
|
+> **最后更新**:2026-10-06
|
|
|
|
|
+> **维护者**:steven_roc
|
|
|
|
|
+> **持续更新**:本文档随项目演进持续更新
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 目录
|
|
|
|
|
+
|
|
|
|
|
+1. [方案概述](#1-方案概述)
|
|
|
|
|
+2. [架构设计](#2-架构设计)
|
|
|
|
|
+3. [配置文件结构](#3-配置文件结构)
|
|
|
|
|
+4. [环境要求](#4-环境要求)
|
|
|
|
|
+5. [软件依赖](#5-软件依赖)
|
|
|
|
|
+6. [端口规划](#6-端口规划)
|
|
|
|
|
+7. [配置详解](#7-配置详解)
|
|
|
|
|
+8. [SSL 证书管理](#8-ssl-证书管理)
|
|
|
|
|
+9. [安全策略](#9-安全策略)
|
|
|
|
|
+10. [日志管理](#10-日志管理)
|
|
|
|
|
+11. [性能调优](#11-性能调优)
|
|
|
|
|
+12. [部署与运维](#12-部署与运维)
|
|
|
|
|
+13. [故障排查](#13-故障排查)
|
|
|
|
|
+14. [端口扩展指南](#14-端口扩展指南)
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 1. 方案概述
|
|
|
|
|
+
|
|
|
|
|
+### 1.1 核心目标
|
|
|
|
|
+
|
|
|
|
|
+通过 Nginx 的 `stream` 模块 + `ssl_preread` 功能,在 **TCP 层**(OSI 第 4 层)检测入站流量的协议类型,实现:
|
|
|
|
|
+
|
|
|
|
|
+- **TLS 流量** → 由 Nginx HTTP 模块进行 SSL 终结 → 反向代理到内网 HTTP 服务
|
|
|
|
|
+- **明文 HTTP 流量** → 301 永久重定向到对应端口的 HTTPS 地址
|
|
|
|
|
+
|
|
|
|
|
+用户无论输入 `http://` 还是 `https://`,都能自动获得 HTTPS 加密访问。
|
|
|
|
|
+
|
|
|
|
|
+### 1.2 多子域名架构
|
|
|
|
|
+
|
|
|
|
|
+本方案支持多个子域名共享同一服务器 IP,通过不同端口区分服务:
|
|
|
|
|
+
|
|
|
|
|
+| 域名 | 外网端口 | 后端服务 | 用途 |
|
|
|
|
|
+|------|---------|---------|------|
|
|
|
|
|
+| chanking.zhonjin.com | 40130 | 127.0.0.1:5004 | 主 Web 服务 |
|
|
|
|
|
+| mqtt.zhonjin.com | 40715 | 127.0.0.1:8085 | MQTT 服务 |
|
|
|
|
|
+| baolin.zhonjin.com | 40716 | 127.0.0.1:5000 | 宝林服务 A |
|
|
|
|
|
+| baolin.zhonjin.com | 40719 | 127.0.0.1:5001 | 宝林服务 B |
|
|
|
|
|
+
|
|
|
|
|
+### 1.3 设计原则
|
|
|
|
|
+
|
|
|
|
|
+| 原则 | 说明 |
|
|
|
|
|
+|------|------|
|
|
|
|
|
+| **TCP 层分流** | stream 模块工作在 TCP 层,不解密 TLS,仅通过 ClientHello 预读判断协议 |
|
|
|
|
|
+| **SSL 终结集中化** | 所有 SSL 证书由 Nginx 统一管理,后端服务只需提供 HTTP |
|
|
|
|
|
+| **端口隔离** | 每个外网端口独立 stream server + 独立 map 变量,互不干扰 |
|
|
|
|
|
+| **域名隔离** | 不同子域名通过独立的 server_name 配置区分,支持各自的后端服务 |
|
|
|
|
|
+| **配置模块化** | 主配置与子域名配置分离,便于独立维护 |
|
|
|
|
|
+| **向后兼容** | 新增服务组不影响已有配置,所有模块松耦合 |
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 2. 架构设计
|
|
|
|
|
+
|
|
|
|
|
+### 2.1 整体架构图
|
|
|
|
|
+
|
|
|
|
|
+```
|
|
|
|
|
+ 外网用户请求
|
|
|
|
|
+ │
|
|
|
|
|
+ ┌─────────────┼─────────────┐
|
|
|
|
|
+ │ │ │
|
|
|
|
|
+ chanking:40130 mqtt:40715 baolin:40716/40719
|
|
|
|
|
+ │ │ │
|
|
|
|
|
+ └─────────────┼─────────────┘
|
|
|
|
|
+ │
|
|
|
|
|
+ ┌─────────┴─────────┐
|
|
|
|
|
+ │ Stream 模块 │
|
|
|
|
|
+ │ ssl_preread on │
|
|
|
|
|
+ │ 协议检测(TCP层) │
|
|
|
|
|
+ └─────────┬─────────┘
|
|
|
|
|
+ │
|
|
|
|
|
+ ┌────────────┼────────────┐
|
|
|
|
|
+ │ TLS │ │ 明文 HTTP
|
|
|
|
|
+ ▼ │ ▼
|
|
|
|
|
+ ┌────────────┐ │ ┌────────────┐
|
|
|
|
|
+ │ HTTPS 服务 │ │ │ HTTP 服务 │
|
|
|
|
|
+ │ (SSL 终结) │ │ │ (301 跳转) │
|
|
|
|
|
+ │ :5005 │ │ │ :5006 │
|
|
|
|
|
+ │ :5007 │ │ │ :5008 │
|
|
|
|
|
+ │ :5009 │ │ │ :5010 │
|
|
|
|
|
+ │ :5011 │ │ │ :5012 │
|
|
|
|
|
+ └──────┬─────┘ │ └──────┬─────┘
|
|
|
|
|
+ │ │ │
|
|
|
|
|
+ └───────────┼────────────┘
|
|
|
|
|
+ │
|
|
|
|
|
+ ┌─────────┴─────────┐
|
|
|
|
|
+ │ 反向代理 │
|
|
|
|
|
+ │ proxy_pass │
|
|
|
|
|
+ └─────────┬─────────┘
|
|
|
|
|
+ │
|
|
|
|
|
+ ┌────────────┼────────────┐
|
|
|
|
|
+ ▼ ▼ ▼
|
|
|
|
|
+ ┌──────────┐ ┌──────────┐ ┌──────────┐
|
|
|
|
|
+ │ :5004 │ │ :8085 │ │ :5000 │ ...
|
|
|
|
|
+ │ 内网服务 │ │ 内网服务 │ │ 内网服务 │
|
|
|
|
|
+ └──────────┘ └──────────┘ └──────────┘
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 2.2 数据流详解
|
|
|
|
|
+
|
|
|
|
|
+**HTTPS 请求流程:**
|
|
|
|
|
+1. 用户访问 `https://mqtt.zhonjin.com:40715`
|
|
|
|
|
+2. TCP 连接到达 Nginx stream 模块监听的 40715 端口
|
|
|
|
|
+3. `ssl_preread on` 预读 ClientHello,`$ssl_preread_protocol` 值为 `TLS`
|
|
|
|
|
+4. map `$backend_target_40715` 匹配 `default` → 转发到 `127.0.0.1:5007`
|
|
|
|
|
+5. HTTP 模块 5007 端口接收 TLS 连接,完成 SSL 终结
|
|
|
|
|
+6. `proxy_pass` 将请求转发到后端 `http://127.0.0.1:8085`
|
|
|
|
|
+7. 后端响应通过 Nginx 加密后返回用户
|
|
|
|
|
+
|
|
|
|
|
+**HTTP 请求流程:**
|
|
|
|
|
+1. 用户访问 `http://baolin.zhonjin.com:40716`
|
|
|
|
|
+2. TCP 连接到达 Nginx stream 模块
|
|
|
|
|
+3. `ssl_preread` 预读失败(非 TLS),`$ssl_preread_protocol` 值为空 `""`
|
|
|
|
|
+4. map `$backend_target_40716` 匹配 `""` → 转发到 `127.0.0.1:5010`
|
|
|
|
|
+5. HTTP 模块 5010 端口返回 `301 Moved Permanently`,`Location: https://baolin.zhonjin.com:40716$request_uri`
|
|
|
|
|
+6. 浏览器自动重定向到 HTTPS 地址
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 3. 配置文件结构
|
|
|
|
|
+
|
|
|
|
|
+### 3.1 文件布局
|
|
|
|
|
+
|
|
|
|
|
+```
|
|
|
|
|
+/etc/nginx/
|
|
|
|
|
+├── nginx.conf # 主配置(全局参数 + 40130 端口 + include 指令)
|
|
|
|
|
+├── conf.d/
|
|
|
|
|
+│ └── zhonjin_http.conf # 子域名 HTTP 服务配置(mqtt/baolin)
|
|
|
|
|
+└── stream.d/
|
|
|
|
|
+ └── zhonjin_stream.conf # 子域名 Stream 分流配置(mqtt/baolin)
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 3.2 文件职责
|
|
|
|
|
+
|
|
|
|
|
+| 文件 | 职责 | include 位置 |
|
|
|
|
|
+|------|------|-------------|
|
|
|
|
|
+| `nginx.conf` | 全局参数、服务组1(40130)、include 指令 | 主配置入口 |
|
|
|
|
|
+| `zhonjin_http.conf` | 子域名的 HTTPS server + HTTP 跳转 server | http 块内 |
|
|
|
|
|
+| `zhonjin_stream.conf` | 子域名的 stream map + stream server | stream 块内 |
|
|
|
|
|
+
|
|
|
|
|
+### 3.3 模块化优势
|
|
|
|
|
+
|
|
|
|
|
+- **独立维护**:新增子域名只需编辑对应的 include 文件,不影响主配置
|
|
|
|
|
+- **减少冲突**:不同团队的配置不会互相干扰
|
|
|
|
|
+- **易于审计**:配置分散在小文件中,便于审查
|
|
|
|
|
+- **热重载安全**:`nginx -t` 可验证所有 include 文件
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 4. 环境要求
|
|
|
|
|
+
|
|
|
|
|
+### 4.1 操作系统
|
|
|
|
|
+
|
|
|
|
|
+| 操作系统 | 版本要求 | 备注 |
|
|
|
|
|
+|----------|----------|------|
|
|
|
|
|
+| Ubuntu | 22.04+ | 推荐,原生支持 Nginx 1.24+ |
|
|
|
|
|
+| Ubuntu | 24.04 | 完全兼容,推荐用于新部署 |
|
|
|
|
|
+| Debian | 12+ | 原生支持 |
|
|
|
|
|
+| CentOS/RHEL | 9+ | 需使用 EPEL 源 |
|
|
|
|
|
+| Raspberry Pi OS | Bookworm+ | 兼容 Ubuntu 24.04 方案 |
|
|
|
|
|
+
|
|
|
|
|
+### 4.2 Nginx 版本要求
|
|
|
|
|
+
|
|
|
|
|
+| 功能 | 最低版本 | 推荐版本 | 说明 |
|
|
|
|
|
+|------|----------|----------|------|
|
|
|
|
|
+| stream 模块 | 1.9.0+ | 1.26+ | TCP 层代理核心 |
|
|
|
|
|
+| ssl_preread | 1.11.5+ | 1.26+ | TCP 层 TLS 预读 |
|
|
|
|
|
+| ssl_preread_buffer_size | 1.23.4+ | 1.26+ | 可选,大 ClientHello 支持 |
|
|
|
|
|
+| http2 指令 | 1.25.1+ | 1.26+ | 新版 `http2 on` 指令 |
|
|
|
|
|
+| stream include | 1.26+ | 1.26+ | stream 块内 include 指令 |
|
|
|
|
|
+
|
|
|
|
|
+### 4.3 硬件要求
|
|
|
|
|
+
|
|
|
|
|
+| 资源 | 最低配置 | 推荐配置 | 说明 |
|
|
|
|
|
+|------|----------|----------|------|
|
|
|
|
|
+| CPU | 1 核 | 2+ 核 | stream 模块 CPU 消耗较低 |
|
|
|
|
|
+| 内存 | 256MB | 512MB+ | SSL session cache 占用内存 |
|
|
|
|
|
+| 磁盘 | 1GB 可用 | 5GB+ | 日志存储需要空间 |
|
|
|
|
|
+| 网络 | 100Mbps | 1Gbps | 取决于业务流量 |
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 5. 软件依赖
|
|
|
|
|
+
|
|
|
|
|
+### 5.1 必装软件
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+# Ubuntu/Debian
|
|
|
|
|
+sudo apt update
|
|
|
|
|
+sudo apt install -y nginx-full # nginx-full 包含 stream 模块
|
|
|
|
|
+sudo apt install -y certbot python3-certbot-nginx # Let's Encrypt 证书管理
|
|
|
|
|
+
|
|
|
|
|
+# 验证 stream 模块已加载
|
|
|
|
|
+nginx -V 2>&1 | grep -o with-stream
|
|
|
|
|
+# 预期输出: with-stream
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 5.2 模块确认
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+# 动态模块方式(如使用动态加载)
|
|
|
|
|
+ls /usr/lib/nginx/modules/ngx_stream_module.so
|
|
|
|
|
+
|
|
|
|
|
+# 静态编译方式(nginx -V 检查)
|
|
|
|
|
+nginx -V 2>&1 | grep -E "with-stream|with-http_ssl_module|with-http_v2_module"
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 5.3 可选工具
|
|
|
|
|
+
|
|
|
|
|
+| 工具 | 用途 | 安装命令 |
|
|
|
|
|
+|------|------|----------|
|
|
|
|
|
+| `htop` | 进程监控 | `apt install htop` |
|
|
|
|
|
+| `tcpdump` | 网络抓包调试 | `apt install tcpdump` |
|
|
|
|
|
+| `openssl` | 证书/SSL 调试 | `apt install openssl` |
|
|
|
|
|
+| `curl` | HTTP 测试 | `apt install curl` |
|
|
|
|
|
+| `logrotate` | 日志轮转(系统自带) | 默认已安装 |
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 6. 端口规划
|
|
|
|
|
+
|
|
|
|
|
+### 6.1 完整端口映射表
|
|
|
|
|
+
|
|
|
|
|
+| 域名 | 外网端口 | HTTPS 内网端口 | HTTP 跳转端口 | 后端服务 | 用途 |
|
|
|
|
|
+|------|---------|---------------|-------------|---------|------|
|
|
|
|
|
+| chanking.zhonjin.com | 40130 | 5005 | 5006 | 127.0.0.1:5004 | 主 Web 服务 |
|
|
|
|
|
+| mqtt.zhonjin.com | 40715 | 5007 | 5008 | 127.0.0.1:8085 | MQTT 服务 |
|
|
|
|
|
+| baolin.zhonjin.com | 40716 | 5009 | 5010 | 127.0.0.1:5000 | 宝林服务 A |
|
|
|
|
|
+| baolin.zhonjin.com | 40719 | 5011 | 5012 | 127.0.0.1:5001 | 宝林服务 B |
|
|
|
|
|
+
|
|
|
|
|
+### 6.2 端口命名规则
|
|
|
|
|
+
|
|
|
|
|
+- **外网端口**(4xxxx):stream 模块监听,对外暴露
|
|
|
|
|
+- **HTTPS 内网端口**(50xx):HTTP 模块 SSL 终结入口
|
|
|
|
|
+- **HTTP 跳转端口**(50xx):HTTP 模块 301 跳转入口
|
|
|
|
|
+- **后端服务端口**:实际业务服务监听端口
|
|
|
|
|
+
|
|
|
|
|
+### 6.3 防火墙配置
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+# UFW 防火墙
|
|
|
|
|
+sudo ufw allow 40130/tcp
|
|
|
|
|
+sudo ufw allow 40715/tcp
|
|
|
|
|
+sudo ufw allow 40716/tcp
|
|
|
|
|
+sudo ufw allow 40719/tcp
|
|
|
|
|
+
|
|
|
|
|
+# 或使用 iptables
|
|
|
|
|
+sudo iptables -A INPUT -p tcp --dport 40130 -j ACCEPT
|
|
|
|
|
+sudo iptables -A INPUT -p tcp --dport 40715 -j ACCEPT
|
|
|
|
|
+sudo iptables -A INPUT -p tcp --dport 40716 -j ACCEPT
|
|
|
|
|
+sudo iptables -A INPUT -p tcp --dport 40719 -j ACCEPT
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+**注意**:内部端口(5005-5012)无需对外开放,stream 模块通过 localhost 转发即可。
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 7. 配置详解
|
|
|
|
|
+
|
|
|
|
|
+### 7.1 主配置(nginx.conf)
|
|
|
|
|
+
|
|
|
|
|
+主配置文件包含:
|
|
|
|
|
+- 全局参数(worker、events、日志格式)
|
|
|
|
|
+- `load_module` 加载 stream 模块
|
|
|
|
|
+- 服务组 1(chanking.zhonjin.com:40130)的完整配置
|
|
|
|
|
+- `include` 指令引入子域名配置
|
|
|
|
|
+
|
|
|
|
|
+```nginx
|
|
|
|
|
+# nginx.conf 末尾 include 指令
|
|
|
|
|
+http {
|
|
|
|
|
+ # ... 服务组 1 配置 ...
|
|
|
|
|
+ include /etc/nginx/conf.d/zhonjin_http.conf;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+stream {
|
|
|
|
|
+ # ... 服务组 1 的 stream 配置 ...
|
|
|
|
|
+ include /etc/nginx/stream.d/zhonjin_stream.conf;
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 7.2 Stream 模块配置
|
|
|
|
|
+
|
|
|
|
|
+```nginx
|
|
|
|
|
+stream {
|
|
|
|
|
+ # 独立 map 变量(每个端口唯一)
|
|
|
|
|
+ map $ssl_preread_protocol $backend_target_40715 {
|
|
|
|
|
+ "" 127.0.0.1:5008; # 明文HTTP → 301跳转
|
|
|
|
|
+ default 127.0.0.1:5007; # TLS流量 → SSL入口
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ server {
|
|
|
|
|
+ listen 40715 backlog=4096;
|
|
|
|
|
+ tcp_nodelay on;
|
|
|
|
|
+ ssl_preread on;
|
|
|
|
|
+ proxy_pass $backend_target_40715;
|
|
|
|
|
+ proxy_connect_timeout 10s;
|
|
|
|
|
+ proxy_timeout 3600s;
|
|
|
|
|
+ proxy_next_upstream off;
|
|
|
|
|
+ access_log /var/log/nginx/stream_access_40715.log stream_main;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+**关键参数说明:**
|
|
|
|
|
+
|
|
|
|
|
+| 参数 | 值 | 说明 |
|
|
|
|
|
+|------|-----|------|
|
|
|
|
|
+| `backlog` | 4096 | TCP 监听队列长度,高并发时增大 |
|
|
|
|
|
+| `tcp_nodelay` | on | 禁用 Nagle 算法,减少小包延迟 |
|
|
|
|
|
+| `ssl_preread` | on | 只读预读 ClientHello,不解密 |
|
|
|
|
|
+| `proxy_connect_timeout` | 10s | 与后端建立连接的超时 |
|
|
|
|
|
+| `proxy_timeout` | 3600s | 连接空闲超时,WebSocket 长连接需设大 |
|
|
|
|
|
+| `proxy_next_upstream` | off | 禁用重试,防止非幂等请求重复执行 |
|
|
|
|
|
+
|
|
|
|
|
+### 7.3 HTTPS Server 配置
|
|
|
|
|
+
|
|
|
|
|
+```nginx
|
|
|
|
|
+server {
|
|
|
|
|
+ listen 127.0.0.1:5007 ssl;
|
|
|
|
|
+ http2 on;
|
|
|
|
|
+ server_name mqtt.zhonjin.com;
|
|
|
|
|
+
|
|
|
|
|
+ ssl_certificate /etc/letsencrypt/live/zhonjin.com/fullchain.pem;
|
|
|
|
|
+ ssl_certificate_key /etc/letsencrypt/live/zhonjin.com/privkey.pem;
|
|
|
|
|
+ ssl_session_cache shared:SSL_mqtt:5m;
|
|
|
|
|
+ ssl_session_timeout 1d;
|
|
|
|
|
+ ssl_session_tickets off;
|
|
|
|
|
+ ssl_protocols TLSv1.2 TLSv1.3;
|
|
|
|
|
+ ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:...;
|
|
|
|
|
+ ssl_prefer_server_ciphers off;
|
|
|
|
|
+
|
|
|
|
|
+ add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
|
|
|
|
+
|
|
|
|
|
+ location / {
|
|
|
|
|
+ proxy_pass http://127.0.0.1:8085;
|
|
|
|
|
+ proxy_http_version 1.1;
|
|
|
|
|
+ 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_set_header Upgrade $http_upgrade;
|
|
|
|
|
+ proxy_set_header Connection $connection_upgrade;
|
|
|
|
|
+ proxy_connect_timeout 5s;
|
|
|
|
|
+ proxy_read_timeout 3600s;
|
|
|
|
|
+ proxy_send_timeout 60s;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 7.4 HTTP 跳转配置
|
|
|
|
|
+
|
|
|
|
|
+```nginx
|
|
|
|
|
+server {
|
|
|
|
|
+ listen 127.0.0.1:5008;
|
|
|
|
|
+ server_name mqtt.zhonjin.com;
|
|
|
|
|
+ return 301 https://$host:40715$request_uri;
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+**注意**:301 跳转 URL 中的端口号必须与对应的外网端口一致。`$host` 变量会自动保留用户访问的域名。
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 8. SSL 证书管理
|
|
|
|
|
+
|
|
|
|
|
+### 8.1 通配符证书方案
|
|
|
|
|
+
|
|
|
|
|
+所有子域名共用同一个通配符证书:
|
|
|
|
|
+
|
|
|
|
|
+```
|
|
|
|
|
+证书覆盖域名:
|
|
|
|
|
+ - zhonjin.com
|
|
|
|
|
+ - *.zhonjin.com(覆盖所有子域名)
|
|
|
|
|
+ ├── chanking.zhonjin.com
|
|
|
|
|
+ ├── mqtt.zhonjin.com
|
|
|
|
|
+ └── baolin.zhonjin.com
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 8.2 证书申请
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+# 申请通配符证书(DNS 验证)
|
|
|
|
|
+sudo certbot certonly --manual --preferred-challenges dns \
|
|
|
|
|
+ -d zhonjin.com -d "*.zhonjin.com"
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+按提示添加 DNS TXT 记录完成验证。
|
|
|
|
|
+
|
|
|
|
|
+### 8.3 证书路径
|
|
|
|
|
+
|
|
|
|
|
+| 文件 | 路径 | 说明 |
|
|
|
|
|
+|------|------|------|
|
|
|
|
|
+| 证书链 | `/etc/letsencrypt/live/zhonjin.com/fullchain.pem` | 包含中间证书 |
|
|
|
|
|
+| 私钥 | `/etc/letsencrypt/live/zhonjin.com/privkey.pem` | 证书私钥 |
|
|
|
|
|
+| 根证书 | `/etc/letsencrypt/live/zhonjin.com/chain.pem` | 仅中间 CA |
|
|
|
|
|
+
|
|
|
|
|
+### 8.4 自动续期
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+# 测试续期
|
|
|
|
|
+sudo certbot renew --dry-run
|
|
|
|
|
+
|
|
|
|
|
+# 添加 crontab 自动续期
|
|
|
|
|
+sudo crontab -e
|
|
|
|
|
+# 添加以下行(每天凌晨 3 点检查)
|
|
|
|
|
+0 3 * * * certbot renew --quiet --post-hook "nginx -s reload"
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 8.5 证书监控
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+# 检查证书有效期
|
|
|
|
|
+openssl x509 -in /etc/letsencrypt/live/zhonjin.com/fullchain.pem -noout -dates
|
|
|
|
|
+
|
|
|
|
|
+# 检查证书域名覆盖
|
|
|
|
|
+openssl x509 -in /etc/letsencrypt/live/zhonjin.com/fullchain.pem -noout -text | grep -A1 "Subject Alternative Name"
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 9. 安全策略
|
|
|
|
|
+
|
|
|
|
|
+### 9.1 SSL/TLS 安全配置
|
|
|
|
|
+
|
|
|
|
|
+| 配置项 | 值 | 说明 |
|
|
|
|
|
+|--------|-----|------|
|
|
|
|
|
+| `ssl_protocols` | TLSv1.2 TLSv1.3 | 禁用 SSLv3/TLSv1.0/1.1 |
|
|
|
|
|
+| `ssl_session_tickets` | off | 禁用 session tickets,增强前向安全 |
|
|
|
|
|
+| `ssl_prefer_server_ciphers` | off | 现代推荐做法,优先客户端偏好 |
|
|
|
|
|
+| HSTS | max-age=31536000 | 强制浏览器使用 HTTPS,1 年有效期 |
|
|
|
|
|
+
|
|
|
|
|
+### 9.2 网络安全
|
|
|
|
|
+
|
|
|
|
|
+- **内部端口不暴露**:所有 HTTP/HTTPS server 仅监听 `127.0.0.1`,外部无法直接访问
|
|
|
|
|
+- **server_tokens off**:隐藏 Nginx 版本号
|
|
|
|
|
+- **防火墙仅开放外网端口**:40130, 40715, 40716, 40719
|
|
|
|
|
+- **证书统一管理**:通配符证书覆盖所有子域名
|
|
|
|
|
+
|
|
|
|
|
+### 9.3 建议加固项
|
|
|
|
|
+
|
|
|
|
|
+```nginx
|
|
|
|
|
+# 可选:限制请求体大小(在 http 块中)
|
|
|
|
|
+client_max_body_size 100m;
|
|
|
|
|
+
|
|
|
|
|
+# 可选:添加安全响应头
|
|
|
|
|
+add_header X-Content-Type-Options "nosniff" always;
|
|
|
|
|
+add_header X-Frame-Options "SAMEORIGIN" always;
|
|
|
|
|
+add_header X-XSS-Protection "1; mode=block" always;
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 10. 日志管理
|
|
|
|
|
+
|
|
|
|
|
+### 10.1 日志文件清单
|
|
|
|
|
+
|
|
|
|
|
+| 日志文件 | 类型 | 说明 |
|
|
|
|
|
+|----------|------|------|
|
|
|
|
|
+| `/var/log/nginx/error.log` | error | 全局错误日志 |
|
|
|
|
|
+| `/var/log/nginx/access.log` | access | HTTP 服务访问日志 |
|
|
|
|
|
+| `/var/log/nginx/stream_error.log` | error | Stream 模块错误日志 |
|
|
|
|
|
+| `/var/log/nginx/stream_access_40130.log` | access | Stream 端口 40130 访问日志 |
|
|
|
|
|
+| `/var/log/nginx/stream_access_40715.log` | access | Stream 端口 40715 访问日志 |
|
|
|
|
|
+| `/var/log/nginx/stream_access_40716.log` | access | Stream 端口 40716 访问日志 |
|
|
|
|
|
+| `/var/log/nginx/stream_access_40719.log` | access | Stream 端口 40719 访问日志 |
|
|
|
|
|
+
|
|
|
|
|
+### 10.2 Logrotate 配置
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+# /etc/logrotate.d/nginx(系统通常已自带)
|
|
|
|
|
+/var/log/nginx/*.log {
|
|
|
|
|
+ daily
|
|
|
|
|
+ missingok
|
|
|
|
|
+ rotate 52
|
|
|
|
|
+ compress
|
|
|
|
|
+ delaycompress
|
|
|
|
|
+ notifempty
|
|
|
|
|
+ create 0640 www-data adm
|
|
|
|
|
+ sharedscripts
|
|
|
|
|
+ postrotate
|
|
|
|
|
+ [ -f /var/run/nginx.pid ] && kill -USR1 `cat /var/run/nginx.pid`
|
|
|
|
|
+ endscript
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 10.3 日志分析
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+# 查看最近 100 条 stream 访问记录
|
|
|
|
|
+tail -100 /var/log/nginx/stream_access_40715.log
|
|
|
|
|
+
|
|
|
|
|
+# 统计各端口流量
|
|
|
|
|
+wc -l /var/log/nginx/stream_access_*.log
|
|
|
|
|
+
|
|
|
|
|
+# 查看错误日志
|
|
|
|
|
+tail -f /var/log/nginx/stream_error.log
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 11. 性能调优
|
|
|
|
|
+
|
|
|
|
|
+### 11.1 内核参数优化
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+# /etc/sysctl.conf 添加
|
|
|
|
|
+net.core.somaxconn = 65535
|
|
|
|
|
+net.ipv4.tcp_max_syn_backlog = 65535
|
|
|
|
|
+net.ipv4.tcp_fin_timeout = 30
|
|
|
|
|
+net.ipv4.tcp_tw_reuse = 1
|
|
|
|
|
+net.ipv4.tcp_keepalive_time = 600
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+sudo sysctl -p
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 11.2 Nginx 工作进程
|
|
|
|
|
+
|
|
|
|
|
+```nginx
|
|
|
|
|
+worker_processes auto;
|
|
|
|
|
+worker_rlimit_nofile 65535;
|
|
|
|
|
+
|
|
|
|
|
+events {
|
|
|
|
|
+ worker_connections 8192;
|
|
|
|
|
+ multi_accept on;
|
|
|
|
|
+ use epoll;
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 11.3 SSL 性能优化
|
|
|
|
|
+
|
|
|
|
|
+```nginx
|
|
|
|
|
+ssl_stapling on;
|
|
|
|
|
+ssl_stapling_verify on;
|
|
|
|
|
+resolver 8.8.8.8 114.114.114.114 valid=300s;
|
|
|
|
|
+resolver_timeout 5s;
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 12. 部署与运维
|
|
|
|
|
+
|
|
|
|
|
+### 12.1 部署步骤
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+# 1. 安装 Nginx(含 stream 模块)
|
|
|
|
|
+sudo apt install -y nginx-full certbot python3-certbot-nginx
|
|
|
|
|
+
|
|
|
|
|
+# 2. 申请通配符 SSL 证书
|
|
|
|
|
+sudo certbot certonly --manual --preferred-challenges dns \
|
|
|
|
|
+ -d zhonjin.com -d "*.zhonjin.com"
|
|
|
|
|
+
|
|
|
|
|
+# 3. 创建配置目录
|
|
|
|
|
+sudo mkdir -p /etc/nginx/conf.d /etc/nginx/stream.d
|
|
|
|
|
+
|
|
|
|
|
+# 4. 部署配置文件
|
|
|
|
|
+sudo cp nginx.conf /etc/nginx/nginx.conf
|
|
|
|
|
+sudo cp zhonjin_http.conf /etc/nginx/conf.d/zhonjin_http.conf
|
|
|
|
|
+sudo cp zhonjin_stream.conf /etc/nginx/stream.d/zhonjin_stream.conf
|
|
|
|
|
+
|
|
|
|
|
+# 5. 测试配置
|
|
|
|
|
+sudo nginx -t
|
|
|
|
|
+
|
|
|
|
|
+# 6. 重载 Nginx
|
|
|
|
|
+sudo systemctl reload nginx
|
|
|
|
|
+
|
|
|
|
|
+# 7. 配置防火墙
|
|
|
|
|
+sudo ufw allow 40130/tcp
|
|
|
|
|
+sudo ufw allow 40715/tcp
|
|
|
|
|
+sudo ufw allow 40716/tcp
|
|
|
|
|
+sudo ufw allow 40719/tcp
|
|
|
|
|
+
|
|
|
|
|
+# 8. 验证服务
|
|
|
|
|
+curl -I http://chanking.zhonjin.com:40130 # 应返回 301
|
|
|
|
|
+curl -I https://chanking.zhonjin.com:40130 # 应返回 200
|
|
|
|
|
+curl -I http://mqtt.zhonjin.com:40715 # 应返回 301
|
|
|
|
|
+curl -I https://mqtt.zhonjin.com:40715 # 应返回 200
|
|
|
|
|
+curl -I http://baolin.zhonjin.com:40716 # 应返回 301
|
|
|
|
|
+curl -I https://baolin.zhonjin.com:40716 # 应返回 200
|
|
|
|
|
+curl -I http://baolin.zhonjin.com:40719 # 应返回 301
|
|
|
|
|
+curl -I https://baolin.zhonjin.com:40719 # 应返回 200
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 12.2 日常运维命令
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+# 查看 Nginx 状态
|
|
|
|
|
+sudo systemctl status nginx
|
|
|
|
|
+
|
|
|
|
|
+# 重载配置(不中断服务)
|
|
|
|
|
+sudo nginx -t && sudo systemctl reload nginx
|
|
|
|
|
+
|
|
|
|
|
+# 查看当前监听端口
|
|
|
|
|
+sudo ss -tlnp | grep nginx
|
|
|
|
|
+
|
|
|
|
|
+# 查看连接数
|
|
|
|
|
+sudo ss -tnp | grep nginx | wc -l
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 12.3 配置文件备份
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+# 备份当前配置
|
|
|
|
|
+sudo cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak.$(date +%Y%m%d)
|
|
|
|
|
+sudo cp /etc/nginx/conf.d/zhonjin_http.conf /etc/nginx/conf.d/zhonjin_http.conf.bak.$(date +%Y%m%d)
|
|
|
|
|
+sudo cp /etc/nginx/stream.d/zhonjin_stream.conf /etc/nginx/stream.d/zhonjin_stream.conf.bak.$(date +%Y%m%d)
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 13. 故障排查
|
|
|
|
|
+
|
|
|
|
|
+### 13.1 常见问题及解决
|
|
|
|
|
+
|
|
|
|
|
+| 问题 | 可能原因 | 排查方法 | 解决方案 |
|
|
|
|
|
+|------|----------|----------|----------|
|
|
|
|
|
+| `nginx -t` 报错 unknown directive | stream 模块未加载 | `nginx -V 2>&1 \| grep stream` | 安装 `nginx-full` 或加载模块 |
|
|
|
|
|
+| `nginx -t` 报错 include 文件找不到 | include 路径错误 | 检查文件是否存在 | 确认路径和目录权限 |
|
|
|
|
|
+| 端口无响应 | 防火墙阻挡 | `sudo ufw status` | 放行端口 |
|
|
|
|
|
+| HTTP 不跳转 | map 变量名冲突 | 检查 stream 中 map 变量是否唯一 | 每个端口使用独立变量名 |
|
|
|
|
|
+| SSL 握手失败 | 证书路径错误 | `openssl s_client -connect localhost:5007` | 检查证书路径和权限 |
|
|
|
|
|
+| 域名解析错误 | DNS 未配置 | `dig mqtt.zhonjin.com` | 添加 A 记录指向服务器 IP |
|
|
|
|
|
+| WebSocket 断开 | proxy_timeout 过短 | 检查 stream 和 http 超时配置 | 保持两者一致(3600s) |
|
|
|
|
|
+| 502 Bad Gateway | 后端服务未启动 | `curl http://127.0.0.1:8085` | 启动后端服务 |
|
|
|
|
|
+| 端口冲突 | 其他程序占用 | `sudo ss -tlnp \| grep :PORT` | 停止冲突程序或更换端口 |
|
|
|
|
|
+
|
|
|
|
|
+### 13.2 调试技巧
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+# 1. TCP 层面验证 stream 转发
|
|
|
|
|
+openssl s_client -connect mqtt.zhonjin.com:40715 -servername mqtt.zhonjin.com
|
|
|
|
|
+
|
|
|
|
|
+# 2. 检查 SSL 证书链
|
|
|
|
|
+echo | openssl s_client -connect mqtt.zhonjin.com:40715 -showcerts 2>/dev/null | openssl x509 -noout -dates
|
|
|
|
|
+
|
|
|
|
|
+# 3. 查看 stream 模块流量
|
|
|
|
|
+tail -f /var/log/nginx/stream_access_40715.log
|
|
|
|
|
+
|
|
|
|
|
+# 4. 抓包分析 TCP 流量
|
|
|
|
|
+sudo tcpdump -i any port 40715 -n -c 100
|
|
|
|
|
+
|
|
|
|
|
+# 5. 验证 HTTP 跳转
|
|
|
|
|
+curl -v http://mqtt.zhonjin.com:40715 2>&1 | grep Location
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 14. 端口扩展指南
|
|
|
|
|
+
|
|
|
|
|
+### 14.1 新增端口映射步骤
|
|
|
|
|
+
|
|
|
|
|
+当需要新增一组端口映射时(以 `newservice.zhonjin.com:40800` → 后端 6000 为例):
|
|
|
|
|
+
|
|
|
|
|
+**Step 1:在 `zhonjin_http.conf` 中添加 server 配置**
|
|
|
|
|
+
|
|
|
|
|
+```nginx
|
|
|
|
|
+# HTTPS 服务
|
|
|
|
|
+server {
|
|
|
|
|
+ listen 127.0.0.1:NEW_HTTPS_PORT ssl;
|
|
|
|
|
+ http2 on;
|
|
|
|
|
+ server_name newservice.zhonjin.com;
|
|
|
|
|
+ # ... SSL 配置(复制已有模式,注意 ssl_session_cache 名称唯一)
|
|
|
|
|
+ location / {
|
|
|
|
|
+ proxy_pass http://127.0.0.1:6000;
|
|
|
|
|
+ # ... proxy 配置
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+# HTTP 跳转
|
|
|
|
|
+server {
|
|
|
|
|
+ listen 127.0.0.1:NEW_HTTP_PORT;
|
|
|
|
|
+ server_name newservice.zhonjin.com;
|
|
|
|
|
+ return 301 https://$host:40800$request_uri;
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+**Step 2:在 `zhonjin_stream.conf` 中添加分流配置**
|
|
|
|
|
+
|
|
|
|
|
+```nginx
|
|
|
|
|
+map $ssl_preread_protocol $backend_target_40800 {
|
|
|
|
|
+ "" 127.0.0.1:NEW_HTTP_PORT;
|
|
|
|
|
+ default 127.0.0.1:NEW_HTTPS_PORT;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+server {
|
|
|
|
|
+ listen 40800 backlog=4096;
|
|
|
|
|
+ tcp_nodelay on;
|
|
|
|
|
+ ssl_preread on;
|
|
|
|
|
+ proxy_pass $backend_target_40800;
|
|
|
|
|
+ proxy_connect_timeout 10s;
|
|
|
|
|
+ proxy_timeout 3600s;
|
|
|
|
|
+ proxy_next_upstream off;
|
|
|
|
|
+ access_log /var/log/nginx/stream_access_40800.log stream_main;
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+**Step 3:更新防火墙并重载**
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+sudo ufw allow 40800/tcp
|
|
|
|
|
+sudo nginx -t && sudo systemctl reload nginx
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 14.2 端口编号建议
|
|
|
|
|
+
|
|
|
|
|
+| 端口范围 | 用途 | 示例 |
|
|
|
|
|
+|----------|------|------|
|
|
|
|
|
+| 40100-40199 | 核心 Web 服务 | 40130 |
|
|
|
|
|
+| 40700-40799 | 扩展服务组 | 40715, 40716, 40719 |
|
|
|
|
|
+| 40800-40899 | 预留扩展 | - |
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 附录
|
|
|
|
|
+
|
|
|
|
|
+### A. 配置文件清单
|
|
|
|
|
+
|
|
|
|
|
+| 文件 | 路径 | 说明 |
|
|
|
|
|
+|------|------|------|
|
|
|
|
|
+| nginx.conf | 项目根目录 | 主配置 |
|
|
|
|
|
+| zhonjin_http.conf | 项目根目录 | HTTP 服务配置 |
|
|
|
|
|
+| zhonjin_stream.conf | 项目根目录 | Stream 分流配置 |
|
|
|
|
|
+| zhonjin.com.conf | 项目根目录 | 配置总览说明 |
|
|
|
|
|
+
|
|
|
|
|
+### B. 相关文档
|
|
|
|
|
+
|
|
|
|
|
+- [CHANGELOG.md](./CHANGELOG.md) - 变更日志
|
|
|
|
|
+- [RASPBERRYPI_SETUP.md](./RASPBERRYPI_SETUP.md) - 树莓派部署指南
|
|
|
|
|
+- [QA_ARCHIVE.md](./QA_ARCHIVE.md) - 问答归档
|
|
|
|
|
+- [README.md](./README.md) - 项目说明
|