系列导航
前言
在前面的章节中,我们已经拥有了域名和 SSL 证书。本章将配置 Nginx 作为反向代理服务器,为家庭服务(如 Plex 媒体服务器)提供安全的 HTTPS 访问。
什么是反向代理?
反向代理是位于后端服务器前面的服务器,它接收客户端请求并转发给后端服务器,然后将响应返回给客户端。
客户端 ───HTTPS请求───> Nginx ───转发请求───> 后端服务(Plex/Homepage)
(443端口) (反向代理) (内部地址)反向代理的好处:
- 统一入口:所有服务通过同一个域名访问
- SSL 终端:在 Nginx 处理 HTTPS,后端可使用 HTTP
- 安全隔离:后端服务不直接暴露在公网
- 负载均衡:可以分发请求到多个后端
重要:本章配置的 Nginx 会监听在
8443端口(而非标准的 443 端口),因为在下一章中我们会使用 Nginx Stream 模块在 443 端口进行 SNI 分流。
第一步:安装 Nginx 和 Stream 模块
首先安装 Nginx 及其 Stream 模块(用于下一章的 SNI 分流):
# 安装 nginx 和 stream 模块
apt install -y nginx libnginx-mod-stream安装完成后验证:
# 查看 nginx 版本
nginx -v
# 确认 stream 模块已安装
nginx -V 2>&1 | grep -o with-stream如果输出包含 with-stream,说明 Stream 模块已正确安装。
说明:
libnginx-mod-stream是 Nginx 的 Stream 模块,用于处理 TCP/UDP 层的流量转发。我们将在下一章使用它实现 443 端口的 SNI 分流。
第二步:优化 Nginx 主配置
关于 nginxconfig.io
nginxconfig.io 是 DigitalOcean 提供的一个优秀的 Nginx 配置生成工具。它可以根据你的需求生成安全、高性能的 Nginx 配置,包括 SSL 设置、安全头、反向代理等。
本教程中的配置片段参考了该工具的最佳实践,基于 nginxconfig 模版进行了少量微调。
首先,我们需要优化 Nginx 的主配置文件。
# 备份原配置
cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak
# 编辑主配置
vim /etc/nginx/nginx.conf将内容替换为:
user www-data;
pid /run/nginx.pid;
worker_processes auto;
worker_rlimit_nofile 65535;
# 加载模块(stream 模块将在下一章使用)
include /etc/nginx/modules-enabled/*.conf;
events {
multi_accept on;
worker_connections 65535;
use epoll;
}
http {
# 基础设置
charset utf-8;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
server_tokens off;
log_not_found off;
types_hash_max_size 2048;
types_hash_bucket_size 64;
client_max_body_size 16M;
# MIME 类型
include mime.types;
default_type application/octet-stream;
# 日志格式(支持 Proxy Protocol)
log_format main '[$time_local] $proxy_protocol_addr "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent"';
# 日志文件
access_log /var/log/nginx/access.log main;
error_log /var/log/nginx/error.log notice;
# SSL 会话缓存
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
# SSL 协议和加密套件(Mozilla Intermediate 配置)
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 1.1.1.1 8.8.8.8 valid=60s;
resolver_timeout 2s;
# WebSocket 支持
map $http_upgrade $connection_upgrade {
default upgrade;
"" close;
}
# 加载配置文件
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}配置说明
| 配置项 | 说明 |
|---|---|
worker_processes auto | 自动根据 CPU 核心数设置工作进程 |
worker_connections 65535 | 每个工作进程最大连接数 |
use epoll | 使用 epoll 事件模型(Linux 高性能) |
server_tokens off | 隐藏 Nginx 版本号 |
ssl_session_cache | SSL 会话缓存,提升性能 |
ssl_protocols | 只启用 TLS 1.2 和 1.3 |
第三步:创建通用配置片段
为了避免重复配置,我们创建一些可复用的配置片段。
# 创建配置目录
mkdir -p /etc/nginx/nginxconfig.io2.1 安全头配置
vim /etc/nginx/nginxconfig.io/security.conf# 安全响应头
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src 'self' http: https: ws: wss: data: blob: 'unsafe-inline'; frame-ancestors 'self';" always;
add_header Permissions-Policy "interest-cohort=()" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# 禁止访问隐藏文件(.git, .env 等)
location ~ /\.(?!well-known) {
deny all;
}2.2 反向代理配置
vim /etc/nginx/nginxconfig.io/proxy.conf# HTTP 版本和缓存
proxy_http_version 1.1;
proxy_cache_bypass $http_upgrade;
# 代理 SSL
proxy_ssl_server_name on;
# 代理头
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
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 X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
# 超时设置
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;2.3 通用配置
vim /etc/nginx/nginxconfig.io/general.conf# favicon.ico
location = /favicon.ico {
log_not_found off;
}
# robots.txt
location = /robots.txt {
log_not_found off;
}
# gzip 压缩
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml application/json application/javascript application/rss+xml application/atom+xml image/svg+xml;第四步:配置默认拒绝站点
为了安全起见,我们需要配置一个默认服务器,拒绝未知域名的访问。
vim /etc/nginx/conf.d/restrict.conf# HTTP 默认服务器 - 拒绝所有未匹配的请求
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
return 444;
}
# HTTPS 默认服务器 - 拒绝未匹配的 SNI
# 注意:监听 8443 端口,后续由 stream 模块转发
server {
listen 127.0.0.1:8443 ssl http2 proxy_protocol default_server;
set_real_ip_from 127.0.0.1;
real_ip_header proxy_protocol;
ssl_reject_handshake on;
return 444;
}说明:
return 444是 Nginx 特有的状态码,表示直接关闭连接,不返回任何响应ssl_reject_handshake on拒绝 TLS 握手,比返回错误页面更安全proxy_protocol表示这个端口接收 Proxy Protocol 头(用于获取真实客户端 IP)关于 Proxy Protocol 的详细原理,请参考下一章:Nginx Stream SNI 分流。
第五步:配置反向代理站点
现在我们来配置具体的反向代理站点。以博客服务为例:
vim /etc/nginx/sites-available/blog.conf# Blog 后端服务器
upstream blog_backend {
# 替换为你的后端服务地址(如家庭服务器上的博客服务)
server home.example.com:3000;
keepalive 8;
}
# HTTPS 服务器
server {
# 监听 8443 端口,启用 SSL、HTTP/2 和 Proxy Protocol
listen 127.0.0.1:8443 ssl http2 proxy_protocol;
server_name blog.example.com;
# 从 Proxy Protocol 获取真实 IP
set_real_ip_from 127.0.0.1;
real_ip_header proxy_protocol;
# SSL 证书配置
ssl_certificate /etc/acme-certs/example.com/fullchain.pem;
ssl_certificate_key /etc/acme-certs/example.com/key.pem;
# 安全配置
include nginxconfig.io/security.conf;
# 反向代理配置
location / {
proxy_pass http://blog_backend;
proxy_set_header Host $host;
include nginxconfig.io/proxy.conf;
}
# 通用配置
include nginxconfig.io/general.conf;
}
# HTTP 重定向到 HTTPS
server {
listen 80;
server_name blog.example.com;
return 301 https://$host$request_uri;
}配置说明
| 配置项 | 说明 |
|---|---|
listen 127.0.0.1:8443 | 只监听本地,由 stream 模块转发 |
proxy_protocol | 接收 Proxy Protocol 以获取真实 IP |
set_real_ip_from | 信任来自 127.0.0.1 的 Proxy Protocol |
keepalive 8 | 与后端保持 8 个长连接 |
第六步:启用站点配置
创建符号链接启用站点:
# 创建 sites-enabled 目录(如果不存在)
mkdir -p /etc/nginx/sites-enabled
# 删除默认站点(如果存在)
rm -f /etc/nginx/sites-enabled/default
# 启用 Blog 站点
ln -sf /etc/nginx/sites-available/blog.conf /etc/nginx/sites-enabled/第七步:测试并重启 Nginx
# 测试配置语法
nginx -t如果显示 syntax is ok 和 test is successful,说明配置正确。
# 重启 Nginx
systemctl restart nginx
# 查看状态
systemctl status nginx第八步:验证配置
由于我们的 Nginx 监听在 8443 端口,且需要 Proxy Protocol,目前还无法直接访问测试。
可以检查端口监听情况:
# 查看 Nginx 监听的端口
ss -tlnp | grep nginx你应该能看到:
LISTEN 0 511 127.0.0.1:8443 ... nginx
LISTEN 0 511 0.0.0.0:80 ... nginx在下一章配置完 Nginx Stream SNI 分流后,就可以通过 443 端口正常访问了。
添加更多站点
如果你需要添加更多反向代理站点,可以按照类似的模式:
vim /etc/nginx/sites-available/dashboard.confupstream dashboard_backend {
server 192.168.1.100:8080;
keepalive 8;
}
server {
listen 127.0.0.1:8443 ssl http2 proxy_protocol;
server_name dashboard.example.com;
set_real_ip_from 127.0.0.1;
real_ip_header proxy_protocol;
ssl_certificate /etc/acme-certs/example.com/fullchain.pem;
ssl_certificate_key /etc/acme-certs/example.com/key.pem;
include nginxconfig.io/security.conf;
location / {
proxy_pass http://dashboard_backend;
proxy_set_header Host $host;
include nginxconfig.io/proxy.conf;
}
include nginxconfig.io/general.conf;
}
server {
listen 80;
server_name dashboard.example.com;
return 301 https://$host$request_uri;
}启用站点:
ln -sf /etc/nginx/sites-available/dashboard.conf /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginxNginx 目录结构
配置完成后,你的 Nginx 目录结构应该如下:
/etc/nginx/
├── nginx.conf # 主配置文件
├── conf.d/
│ └── restrict.conf # 默认拒绝配置
├── sites-available/
│ ├── blog.conf # Blog 反向代理
│ └── dashboard.conf # Dashboard 反向代理
├── sites-enabled/
│ ├── blog.conf -> ../sites-available/blog.conf
│ └── dashboard.conf -> ../sites-available/dashboard.conf
├── nginxconfig.io/
│ ├── security.conf # 安全头配置
│ ├── proxy.conf # 代理配置
│ └── general.conf # 通用配置
└── modules-enabled/
└── (下一章配置 stream 模块)常见问题
问题 1:nginx -t 报错 "unknown directive"
确保已安装相关模块:
apt install libnginx-mod-http-headers-more-filter问题 2:SSL 证书找不到
确认证书路径正确,且权限允许 Nginx 读取:
ls -la /etc/acme-certs/example.com/问题 3:后端服务无法连接
- 确认后端服务正在运行
- 确认防火墙允许访问
- 使用
curl测试后端连接
总结
在本章中,我们完成了:
- ✅ 优化 Nginx 主配置
- ✅ 创建可复用的配置片段(安全、代理、通用)
- ✅ 配置默认拒绝未知域名访问
- ✅ 配置 Blog 等服务的反向代理
- ✅ 理解 Proxy Protocol 的作用
目前 Nginx 监听在 8443 端口,等待 Stream 模块的 SNI 分流。在下一章中,我们将配置 Nginx Stream 模块,实现:
- 443 端口的 SNI 分流
- Xray 流量和反向代理流量共存
- Xray 使用自己的证书("偷自己证书")