一篇展示我是如何更好地使用 Nginx 服务器的伪教程。
在所有之前的
声明:本文展示了我个人站点的 Nginx 服务器的安装、设置和优化的过程以及一些相关的简要说明。本文内容会随时调整和更新,同时这是一篇具有大量主观想法的指导性文章,如果有疑问或持有不同意见,还望友善地留言,我会尽可能地和你一同讨论并学习。
本站的系统环境与配置
在本站建立之时,已经是“现代”互联网标准通行的时代。相关标准和技术,如 HTTP2/TLS1.3/Gzip 等已是主流,HTTP3/QUIC/Brotli 等新标准新技术也已经被积极推行。这些都为我们带来了很多方便,如在 HTTP 时代,我们要为自己和用户之间传递的信息的安全担心,但在 HTTPS 时代,我们不用为其投入更多的精力,因为更安全的 TLS1.3 协议在为我们保驾护航。
我们现在有诸多更好更安全的新标准和新技术,本文接下来将简单地介绍如何在我们个人网站的 Nginx 上,去应用一些更加“现代”的东西。
本站现行的系统环境
截至 2023 年 9 月 16 日,本站的系统环境如下:
- 操作系统:
Ubuntu 22.04.3
- 系统内核:
Linux Kernel 6.5.3
本站的一些系统配置
我修改了一些与内核及网络有关的配置参数以优化性能。
/etc/sysctl.conf
#为系统使用 Google 的 TCP BBR 拥塞控制算法(内核版本需 4.9.0 及以上) net.core.default_qdisc = fq net.ipv4.tcp_congestion_control = bbr #一些与网络有关的参数 net.core.netdev_max_backlog = 262144 net.core.somaxconn = 262144 net.ipv4.neigh.default.gc_stale_time = 120 net.ipv4.tcp_max_orphans = 262144 net.ipv4.tcp_max_syn_backlog = 262144 #一些与内核有关的参数 fs.file-max = 655350 kernel.msgmax = 65535 kernel.msgmnb = 65535 kernel.sysrq = 1 vm.overcommit_memory = 1 vm.swappiness = 10 vm.vfs_cache_pressure = 50
/etc/security/limits.conf
* soft nofile 65535
* hard nofile 65535
* soft nproc 65535
* hard nproc 65535
安装 Nginx 服务器
下文命令均以 Ubuntu 20.04.2 (APT) 为例,如你正使用其他发行版或软件包管理器,请酌情更改到适当的命令。
通过源码编译安装
这里只演示相对基本的 Nginx 编译安装方式,并为其启用了 HTTP/3 (QUIC) 和 HTTP/2 支持,使用了 quictls 库使其支持 HTTP/3 下的 TLS 连接、添加了 ngx_brotli 模块使其支持 Brotli 压缩。如你需要更多自定义,可参看其官方文档。
安装依赖与组件
这里默认操作用户为 root,操作目录为/usr/src
。
安装编译依赖
apt install build-essential git -y
获取必要组件
cd /usr/src
#获取 Nginx
wget https://nginx.org/download/nginx-1.25.2.tar.gz
tar -xzf nginx-1.25.2.tar.gz && rm nginx-1.25.2.tar.gz
#获取 quictls
git clone https://github.com/quictls/openssl
#获取 Pcre2
wget https://github.com/PCRE2Project/pcre2/releases/download/pcre2-10.42/pcre2-10.42.tar.gz
tar -xzf pcre2-10.42.tar.gz && rm pcre2-10.42.tar.gz
#获取 Zlib
wget https://github.com/cloudflare/zlib/archive/refs/tags/v1.2.8.tar.gz
tar -xzf v1.2.8.tar.gz && rm v1.2.8.tar.gz
#获取 ngx_brotli 模块
git clone https://github.com/google/ngx_brotli
cd ngx_brotli && git submodule update --init --recursive && cd ..
修改 Server: nginx 字段
为了个性化标识(好看),你可以修改 Nginx 默认发送的 HTTP 响应头中的 Server: nginx 字段为其他值,只需修改以下文件:
src/core/nginx.h
#define NGINX_VER "nginx/" NGINX_VERSION
src/http/ngx_http_header_filter_module.c
static u_char ngx_http_server_string[] = "Server: nginx" CRLF;
src/http/ngx_http_special_response.c
static u_char ngx_http_error_tail[] = "<hr><center>nginx</center>" CRLF
src/http/v2/ngx_http_v2_filter_module.c
static const u_char nginx[5] = "\x84\xaa\x63\x55\xe7"; #这里是经 hpack 编码后的字段,你可以使用 https://github.com/ScottHelme/HPACK-Encode 提供的工具进行编码 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0, "http2 output header: \"server: nginx\""); } pos = ngx_http_v2_write_header_str("server", "nginx");
开始编译并安装
cd nginx-1.25.2
./configure --with-openssl=../openssl --with-pcre=../pcre2-10.42 --with-zlib=../zlib-1.2.8 --with-http_ssl_module --with-http_v2_module --with-http_v3_module --with-cc-opt=-I../openssl/build/include --with-ld-opt=-L../openssl/build/lib --add-dynamic-module=../ngx_brotli
make && make install
加载 ngx_brotli 模块
在 Nginx 配置文件的 Main 区中添加以下内容后重启 Nginx。
load_module /usr/lib/nginx/module/ngx_http_brotli_filter_module.so;
load_module /usr/lib/nginx/module/ngx_http_brotli_static_module.so;
有关load_module
参数的相关信息可参见其官方文档。
修改 Nginx 配置项
下文所展示的配置需要你根据实际情况自行调整。
下文展示的配置可以正常实现的前提为:你已添加 ngx_brotli 模块、已获得 SSL 证书(推荐泛域名)。我使用的相对模块化的加载方式为不同的功能区进行了划分,如果你也喜欢这样,可以照做。
全局配置
Nginx 配置文件为nginx.conf
,以下是我的配置内容及一些相关说明:
#运行 Nginx 的用户(需要确保有足够的权限)
user nginx;
pid /run/nginx.pid;
worker_processes auto;
worker_rlimit_nofile 65535;
#加载编译的 ngx_brotli 模块
load_module /usr/lib/nginx/module/ngx_http_brotli_filter_module.so;
load_module /usr/lib/nginx/module/ngx_http_brotli_static_module.so;
pcre_jit on;
events {
multi_accept on;
#epoll 是一个高版本 Linux 内核中的高性能模型
use epoll;
worker_connections 65535;
}
http {
#我将一些全站可以共用的配置放在了这里,因为使用了 CDN 网络,所以与连接持久化有关的参数均设置得较高
client_header_buffer_size 4k;
default_type application/octet-stream;
keepalive_timeout 300s 300s;#你可以酌情降低此数值
keepalive_requests 65535;
send_timeout 10s;
sendfile on;
server_tokens off;
tcp_nopush on;
ssl_buffer_size 4k;
#支持的 TLS 协议
ssl_ciphers TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA;
#支持的 TLS 版本
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets on;
ssl_session_timeout 1h;#你可以酌情降低此数值
#OCSP Stapling 参数,与下文站点配置中的 ssl_trusted_certificate 参数相关联
ssl_stapling on;
ssl_stapling_verify on;
#这里关闭了详细的访问日志,如需要可重新开启
access_log off;
error_log /var/log/nginx/error.log;
brotli on;
brotli_comp_level 3;
brotli_static on;
brotli_types text/css text/javascript text/mathml text/plain text/x-component text/x-wiki text/xml text/vnd.wap.wml application/x-httpd-php image/svg+xml image/x-icon application/javascript application/x-javascript application/json application/xml application/atom+xml application/rss+xml application/xhtml+xml application/xspf+xml font/opentype application/x-font-ttf application/font-woff application/font-woff2 application/msword application/rtf application/x-cocoa application/x-makeself application/x-perl application/x-pilot application/x-tcl application/x-x509-ca-cert application/vnd.ms-excel application/vnd.ms-fontobject application/vnd.google-earth.kml+xml application/vnd.google-earth.kmz image/vnd.microsoft.icon;
brotli_window 2m;
gzip on;
gzip_buffers 32 4k;
gzip_comp_level 3;
gzip_disable "msie6";
gzip_http_version 1.1;
gzip_min_length 32;
gzip_proxied off;
gzip_static on;
gzip_types text/css text/javascript text/mathml text/plain text/x-component text/x-wiki text/xml text/vnd.wap.wml application/x-httpd-php image/svg+xml image/x-icon application/javascript application/x-javascript application/json application/xml application/atom+xml application/rss+xml application/xhtml+xml application/xspf+xml font/opentype application/x-font-ttf application/font-woff application/font-woff2 application/msword application/rtf application/x-cocoa application/x-makeself application/x-perl application/x-pilot application/x-tcl application/x-x509-ca-cert application/vnd.ms-excel application/vnd.ms-fontobject application/vnd.google-earth.kml+xml application/vnd.google-earth.kmz image/vnd.microsoft.icon;
gzip_vary on;
open_file_cache_errors on;
open_file_cache max=65535 inactive=30s;
open_file_cache_min_uses 2;
open_file_cache_valid 30s;
http2 on;
http3 on;
quic_gso on;
quic_retry on;
ssl_early_data on;
#这里引用外部的站点配置
include /path/to/sites/*.nginx;
}
站点配置
因我有数十个不同功能的子域名,所以为了方便及减小配置文件大小,我将 HTTP/HTTPS 的共用配置与站点的个体功能实现部分的配置进行了分离,
这里假设我有一example.com
域名及数个三级子域,它们均将长期使用 HTTPS 协议,并将www.example.com
作为目标域名,下面是配置示例。
HTTP 转发配置
#创建新文件:/path/to/sites/default.nginx
server {
listen 80;
server_name example.com *.example.com;
include /path/to/sites/http-site.conf;
return 301 https://$host$request_uri;
}
server {
listen 80 reuseport default;
listen 443 ssl reuseport default;
listen 443 quic reuseport default;
server_name _;
include /path/to/sites/https-site.conf;
if ($scheme = http) {
return 405;
}
ssl_reject_handshake on;
}
HTTP 全局配置
#创建新文件:/path/to/sites/http-site.conf
add_header X-Content-Type-Options nosniff always;
add_header X-Frame-Options sameorigin always;
add_header X-Xss-Protection "1; mode=block" always;
HTTPS 全局配置
#创建新文件:/path/to/sites/https-site.conf
ssl_certificate /path/to/ca/ssl_fullchain.crt;
ssl_certificate_key /path/to/ca/ssl.key;
ssl_trusted_certificate /path/to/ca/ssl_fullchain.crt;
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains; preload" always;#这是 HSTS 配置,不需要不加入,以免影响同域名的 HTTP 站点
add_header X-Content-Type-Options nosniff always;
add_header X-Frame-Options sameorigin always;
add_header X-Xss-Protection "1; mode=block" always;
子域配置示例
#创建新文件:/path/to/sites/example.com.nginx
server {
listen 443 ssl;
listen 443 quic;
server_name example.com;
include /path/to/sites/https-site.conf;
return 301 https://www.example.com;
}
server {
listen 443 ssl;
listen 443 quic;
server_name www.example.com;
include /path/to/sites/https-site.conf;
location / {
root /path/to/www;
index index.html;
}
}
注:为了符合 HSTS Preload 的标准,需要先将example.com
从 80 端口重定向至 443 端口后再重定向至其他子域的 443 端口。
加入 HSTS 预加载列表
HSTS 是国际互联网工程组织 IETE 正在推行一种新的 Web 安全协议,采用 HSTS 协议的网站可以确保浏览器始终连接到该网站的 HTTPS 加密版本,不需要用户手动在 URL 地址栏中输入加密地址。但单纯的 HSTS 有些许不足,它无法保证用户首次访问网站的安全性,即 HTTP 重定向至 HTTPS 的过程中可能被重定向至其他网站或 HSTS 标识头被篡改。
为了应对此情况,HSTS 预加载列表出现了。它被硬编码到浏览器中,列表中的站点将会默认使用 HTTPS 进行访问,提高了用户首次访问网站的安全性。
申请要求
- 有效的 SSL 证书
- 重定向所有 HTTP 请求到 HTTPS(HTTPS ONLY)
- 子域名均使用 HTTPS,并在相应的域名中添加 HSTS 响应头
- 响应头过期时间至少大于 18 周(10886400 秒)
- 响应头必须声明 includeSubdomains
- 响应头必须声明 preload
- 跳转的页面也需要有 HSTS 响应头
响应头示例:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
开始申请
访问 HSTS Preload List Submission,在输入框中输入你的主域名,点击提交。它会显示提交状态。如显示错误按照提示更改后重新提交即可。
域名被硬编码到浏览器需要数周或数月,需要耐心等待。
为网站进行评分
分数总会给予人鼓舞,访问 MySSL,即可得到像下图一样的评分结果。
互联网技术变化得往往非常迅猛,这意味着本文具有较高的时效性,还望参考之时多加考量。
本文由 安忆 发表,全文共计 1566 字
本站文章均采用 知识共享署名4.0 国际许可协议进行许可,转载前请务必署名
最后编辑时间为:2023 年 9 月 16 日 16 时 31 分
本文二维码
请问 Windows Server 能不能用?
应该是不行的,Windows 平台的 Nginx 是预编译好的。
文章更新的得好勤快a
每次都是 Nginx 释出没多久就更
嗯,因为最近 Nginx 1.19 加了一些新功能,正好用得上。
兄弟,你可以更新了,好久没动过了
大兄弟说谁?
兄弟,你可以更新了,好久没动过了
最近无事,好久不出门也没接触外面,实在是没有什么感触。
更新也有的,比如一直在更正Wikipedia 全域恢复访问指南,也在回评论呀(正经脸
给跪了
我目前是 Centos,用着 oneinstack,有时间折腾一下?????