关于 Nginx 的一些问题及解决方法

启用 HSTS 等安全 Headers1

1
2
3
4
5
6
7
8
9
http {
    server {
        #...其他配置
        add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
        add_header X-Content-Type-Options "nosniff" always;
        add_header X-XSS-Protection "1; mode=block" always;
        #...其他配置
    }
}

同时开启 HTTP2 和 HTTP3

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
http {
    server {
        listen  443 ssl;
        listen  443 quic reuseport; # 多个 server 开启 HTTP3 时,reuseport 只需设置一次
        http2   on;
        # 开启 HTTP2 时必须开启 HTTPS
        ssl_certificate     ...;
        ssl_certificate_key ...;
        # HTTP3 需要添加的 Headers
        add_header Alt-Svc 'h3=":443"; ma=31536000';
        add_header Alt-Svc 'h3-29=":443"';
        add_header x-quic  'h3';
        #...其他配置
    }
    server {
        listen  443 ssl;
        listen  443 quic;
        http2   on;
        # 开启 HTTP2 时必须开启 HTTPS
        ssl_certificate     ...;
        ssl_certificate_key ...;
        # HTTP3 需要添加的 Headers
        add_header Alt-Svc 'h3=":443"; ma=31536000';
        add_header Alt-Svc 'h3-29=":443"';
        add_header x-quic  'h3';
        #...其他配置
    }
}

加载 GeoIP2 动态模块

编译模块

这里使用 Alpine Linux 镜像演示。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 下载 Nginx 源码
wget -q https://nginx.org/download/nginx-1.27.3.tar.gz && \
tar -zxf nginx-1.27.3.tar.gz && \
cd nginx-1.27.3

# 克隆模块仓库
git clone https://github.com/leev/ngx_http_geoip2_module

# 安装编译所需软件包
apk --update add \
autoconf \
automake \
g++ \
gcc \
git \
libc-dev \
libmaxminddb-dev \
libtool \
linux-headers \
make \
openssl-dev \
pcre-dev \
zlib-dev

# 配置并编译
./configure --with-compat --with-stream \
--add-dynamic-module=./ngx_http_geoip2_module \
&& make modules

# 编译的文件放在 objs 文件夹中
# objs/ngx_http_geoip2_module.so
# objs/ngx_stream_geoip2_module.so

配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 加载模块
load_module modules/ngx_http_geoip2_module.so;
load_module modules/ngx_stream_geoip2_module.so;
http {
    # 载入 GeoIP 库
    geoip2 dbip.mmdb {
        $geoip2_continent   default=- source=$remote_addr continent names en;
        $geoip2_country     default=- source=$remote_addr country names en;
        $geoip2_region      default=- source=$remote_addr subdivisions 0 names en;
        $geoip2_city        default=- source=$remote_addr city names en;
    }
}

开启 Brotli 压缩

编译模块

这里使用 Alpine Linux 镜像演示。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# 下载 Nginx 源码
wget -q https://nginx.org/download/nginx-1.27.3.tar.gz && \
tar -zxf nginx-1.27.3.tar.gz && \
cd nginx-1.27.3

# 克隆模块仓库
git clone https://github.com/google/ngx_brotli

# 配置并编译
./configure --with-compat \
--add-dynamic-module=./ngx_brotli \
&& make modules

# 编译的文件放在 objs 文件夹中
# objs/ngx_http_brotli_filter_module.so
# objs/ngx_http_brotli_static_module.so

配置2

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 加载模块
load_module modules/ngx_http_brotli_filter_module.so;
load_module modules/ngx_http_brotli_static_module.so;
http {
    # 开启 brotli 压缩
    brotli on;
    brotli_comp_level   10;
    brotli_buffers      16 8k;
    brotli_min_length   20;
    brotli_static       always;
    brotli_types text/plain text/javascript text/css text/xml text/x-component application/javascript application/x-javascript application/xml application/json application/xhtml+xml application/rss+xml application/atom+xml application/x-font-ttf application/vnd.ms-fontobject image/svg+xml image/x-icon image/png font/opentype;
}

开启 gzip 压缩

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
http {
    # 开启 gzip 压缩
    gzip                on;
    gzip_vary           on;
    gzip_static         on;
    gzip_comp_level     6;      # 压缩级别 1-9
    gzip_min_length     1024;   # 最小压缩文件
    gzip_buffers        16 8k;  # 压缩缓冲区
    gzip_http_version   1.1;
    gzip_proxied        expired no-cache no-store private no_last_modified no_etag auth;
    gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/wasm application/x-font-ttf application/x-javascript application/x-web-app-manifest+json application/xhtml+xml application/xml font/eot font/opentype font/otf font/ttf image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/javascript text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy text/xml;

}

一些其他优化

可自行设置的优化参数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

event {
    # 单个进程允许的客户端最大连接数
    worker_connections 4096;
    # 使用epoll模型
    use epoll;
    # 一个时刻内可以接收多个新的连接
    multi_accept on;
    # 打开负载均衡互斥锁
    accept_mutex on;
}

http {
    server_tokens       off;    # 隐藏版本号
    keepalive_timeout   65;     # 会话保持时间
    keepalive_requests  1024;   # 长连接最大请求数
    sendfile    on; # 开启 sendfile() 支持,降低文件读写开销
    tcp_nopush  on; # 减少网络报文段数量
    tcp_nodelay on; # 提高I/O性能

    client_header_buffer_size   8k;     # 客户端请求header的缓冲区大小
    client_body_buffer_size     4m;     # 客户端请求body的缓冲区大小
    client_max_body_size        16m;    # 上传文件大小限制
    
    reset_timedout_connection   on;     # 关闭不响应的客户端连接

    # 优化服务器域名的散列表大小
    server_names_hash_bucket_size   512;
    server_names_hash_max_size      1024;
    # 读取大型客户端请求头的缓冲区的最大数量和大小
    large_client_header_buffers     8 64k;
    # 客户端请求超时时间
    client_header_timeout   15s;
    client_body_timeout     15s;
    send_timeout            15s;

    ssl_early_data  on; # 开启 0-RTT的支持
    quic_retry      on; # 启用地址验证
    quic_gso        on; # 启用 GSO 特性 (数据分段),提升高负载或大量小包下的传输效率

    server {
        listen  443 ssl;
        # 拒绝错误SNI请求以防止源站被扫描
        ssl_reject_handshake    on;
    }
}

一般情况下的反代配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
http {
    # WebSocket
    map $http_upgrade $connection_upgrade {
        default upgrade;
        ''      close;
    }

    server {
        location / {
            proxy_pass          http://endpoint:3000;
            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;
            # WebSocket
            proxy_set_header    Upgrade             $http_upgrade;
            proxy_set_header    Connection          $connection_upgrade;
        }
    }
}
Licensed under CC BY-NC-SA 4.0
使用 Hugo 构建
主题 StackJimmy 设计