安全配置
SSL
去掉早期的TLS版本,去掉不安全的加密方式
1 2 3 4 5 6 7 8 9 10
| ssl_certificate /etc/nginx/cert/psvmc.cn.pem; ssl_certificate_key /etc/nginx/cert/psvmc.cn.key;
ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!RC4:!3DES:!DES'; ssl_prefer_server_ciphers on;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
安全头
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| server_tokens off;
add_header X-Content-Type-Options "nosniff" always; add_header X-XSS-Protection "1; mode=block" always; add_header X-Download-Options "noopen" always; add_header X-Permitted-Cross-Domain-Policies "none" always; add_header Referrer-Policy "strict-origin-when-cross-origin" always; add_header Permission-Policy "camera=(), microphone=(), geolocation=()" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Cross-Origin-Opener-Policy "same-origin" always;
add_header Cross-Origin-Embedder-Policy "require-corp" always; add_header Cross-Origin-Resource-Policy "same-origin" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self';" always;
|
防止资源访问
1 2 3 4 5 6
| location ~ /\. { deny all; access_log off; log_not_found off; }
|
404页面
WEB容器 使用404页面,纯 API 可改用 JSON 错误体
1 2 3 4 5
| error_page 404 /404.html; location = /404.html { root /etc/nginx/html; internal; }
|
阻拦IP访问
default_server_blockip.conf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| server { listen 80 default_server; server_name _; return 444; }
server { listen 443 ssl default_server; server_name _; ssl_certificate /etc/nginx/cert/zmeduyun.cn.pem; ssl_certificate_key /etc/nginx/cert/zmeduyun.cn.key; return 444; }
|
跨域设置
允许跨域访问
可以配置 server 下,当前 server 的所i有地址生效。
也可以配置在 location 中,只对当前配置的地址生效。
核心配置
1 2 3 4 5
| add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS'; add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization'; add_header 'Access-Control-Max-Age' 36000; if ($request_method = OPTIONS ) { return 204; }
|
注意OPTIONS返回200也是可以的,但是返回204会更符合规范。
1 2 3 4 5
| add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS'; add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization'; add_header 'Access-Control-Max-Age' 36000; if ($request_method = OPTIONS ) { return 200; }
|
注意
如果Android使用webview加载pdf.js来预览PDF的时候,也要设置允许跨域访问,否则无法访问。
iframe跨域设置
禁止iframe跨域访问
1 2 3 4 5 6
|
add_header X-Frame-Options SAMEORIGIN always; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; add_header X-Content-Type-Options nosniff always; add_header X-XSS-Protection "1; mode=block" always;
|
允许自身 + 两个指定域名嵌入 iframe
1 2 3 4 5
| add_header Content-Security-Policy "frame-ancestors 'self' https://partner.example.com https://app.yourcompany.com;" always; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; add_header X-Content-Type-Options nosniff always; add_header X-XSS-Protection "1; mode=block" always;
|
注意
一旦设置了有效的 Content-Security-Policy 且包含 frame-ancestors,现代浏览器会优先使用 CSP,忽略 X-Frame-Options 。所以只需在 CSP 中正确配置即可。
WEB容器
HTTP重定向HTTPS
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
| server { server_name www.psvmc.cn; listen 80; listen 443 ssl; ssl_certificate /etc/nginx/cert/psvmc.pem; ssl_certificate_key /etc/nginx/cert/psvmc.key; ssl_session_timeout 5m; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; root /data/web_front/myblog/; index index.html; if ($scheme = http) { return 301 https://$host$request_uri; }
keepalive_timeout 60; client_max_body_size 200m;
location ~ .*\.(html)$ { add_header Cache-Control no-store; } }
|
或者
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
| server { listen 80; server_name www.psvmc.cn; return 301 https://$server_name$request_uri; }
server { server_name www.psvmc.cn;
root /data/web_front/myblog/; index index.html;
listen 443 ssl; ssl_certificate /etc/nginx/cert/psvmc.pem; ssl_certificate_key /etc/nginx/cert/psvmc.key; ssl_session_timeout 5m; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on;
client_max_body_size 200m;
error_log /etc/nginx/logs/error_www.psvmc.cn.log error;
keepalive_timeout 60;
location ~ .*\.(html)$ { add_header Cache-Control no-store; } }
|
静态页面+SSL
文件_school.psvmc.cn.conf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| server { listen 80; server_name school.psvmc.cn; listen 443 ssl; ssl_certificate /etc/nginx/cert/psvmc.cn.pem; ssl_certificate_key /etc/nginx/cert/psvmc.cn.key; ssl_session_timeout 5m; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; location / { root /data/web_front/school/; index index.html; try_files $uri $uri/ /index.html; client_max_body_size 200m; client_body_buffer_size 128k; send_timeout 60; } }
|
服务器上测试
1 2
| curl -H "Host: school.psvmc.cn" http://127.0.0.1 curl -k -H "Host: school.psvmc.cn" https://127.0.0.1
|
其中:
-k 参数用于忽略自签名证书的验证警告。
SSL核心配置
1 2 3 4 5 6 7
| listen 443 ssl; ssl_certificate /etc/nginx/cert/psvmc.cn.pem; ssl_certificate_key /etc/nginx/cert/psvmc.cn.key; ssl_session_timeout 5m; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on;
|
文件下载
Linux
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| server { listen 80; server_name localhost; index index.html;
location /download/ { alias /data/wwwjarapi/schoolfile/static/; default_type application/octet-stream; add_header 'Content-Type' 'application/octet-stream' always; add_header Content-Disposition 'attachment;' always; }
location /static/ { alias /data/wwwjarapi/schoolfile/static/; } }
|
有两种方式
方式1
最简单的方式是直接添加
1 2 3
| default_type application/octet-stream; add_header 'Content-Type' 'application/octet-stream' always; add_header Content-Disposition 'attachment;' always;
|
attachment;后没有跟文件名也能正常下载
方式2
如果要实现包含文件名的才下载可以这样
1 2 3 4 5
| location ~ ^/download/(.*\.(?:pdf|docx?|xlsx?))$ { alias /data/wwwjarapi/schoolfile/static/$1; default_type application/octet-stream; add_header Content-Disposition 'attachment; filename="$1"'; }
|
注意
root 是 在 root 路径后追加整个 URI
alias 是 去掉 location 匹配部分,把剩下的 URI 拼接到 alias 路径后
关键语句
add_header ‘Content-Type’ ‘application/octet-stream’ always;
add_header Content-Disposition ‘attachment;’ always;
注意
现代浏览器(如 Edge、Chrome)对 Office 文档的内置预览行为导致的,仅靠 Content-Type 通常不足以强制下载。
要强制浏览器下载文件而非预览,最关键的是设置响应头:
1
| add_header Content-Disposition 'attachment; filename="$1"' always;
|
Win下
Windows下路径这样写
1 2 3 4 5
| location ~ ^/download/(.*\.(?:pdf|docx?|xlsx?))$ { alias D:/data/wwwjarapi/zxsFileApi/static/$1; default_type application/octet-stream; add_header Content-Disposition 'attachment; filename="$1"'; }
|
完整配置
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
| server { listen 80; server_name zxsstatictest.psvmc.com; listen 443 ssl;
ssl_certificate 'D:/Tools/nginx-1.12.2/cert/psvmc.pem'; ssl_certificate_key 'D:/Tools/nginx-1.12.2/cert/psvmc.key'; ssl_session_timeout 5m; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHD:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; charset utf-8;
location /static/ { if ($request_method = OPTIONS ) { return 204; } add_header 'Access-Control-Allow-Origin' '*'; alias 'D:/data/wwwjarapi/zxsFileApi/static/'; }
location /download/ { if ($request_method = OPTIONS ) { return 204; } alias 'D:/data/wwwjarapi/zxsFileApi/static/'; add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS'; add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization'; add_header 'Access-Control-Max-Age' 36000; add_header 'Content-Type' 'application/octet-stream' always; add_header Content-Disposition 'attachment;' always; } }
|
Vue history模式
在使用 Vue 的 history 模式时,由于前端路由是通过修改 URL 来实现的,所以在部署到服务器上时,需要进行一些特殊的配置才能确保正常访问。
以下是一个常见的配置流程:
Nginx添加配置:
在 Nginx 的配置文件中,添加一个用于处理前端路由的 location 配置,
如下所示:
1 2 3
| location / { try_files $uri $uri/ /index.html; }
|
这个配置将会重定向所有请求到 index.html,这样访问任何一个路由都会返回同一个首页。
然后 Vue Router 会根据 URL 来动态加载相应的组件。
保存并重新启动 Nginx 服务,使配置生效。
禁用缓存
前端项目使用VUE开发的都是单页,也就是只有一个html文件,但是每次更新可能因为用户缓存,而无法正常访问,所以建议html不进行缓存。
如果HTML文件较小建议直接禁用缓存
1 2 3 4
| location ~ .*\.(html)$ { add_header Cache-Control no-store; }
|
如果HTML文件较大建议使用协商方式
1 2 3 4 5
| location ~ .*\.(html)$ { add_header Pragma no-cache; }
|
对比:
Pragma: no-cache:和Cache-Control: no-cache区别
Pragma: no-cache跟Cache-Control: no-cache作用相同
Pragma: no-cache可以应用到http 1.0 和http 1.1
Cache-Control: no-cache只能应用于http 1.1.
Cache-Control: no-cache和Cache-Control: no-store区别
看字面意思容易误解,no-cache就是不缓存,但是no-cache并不是不缓存,而是使用协商缓存,所以并不能禁止缓存,no-store才是真正的禁止缓存。
从节省带宽角度讲,使用no-cache更优一点,文件未发生改变时只传输很小的报文大小,只有在文件改变时才会传输整个文件大小。而不是no-store不管什么情况都传输整个文件大小。
GZIP压缩
server下添加
1 2 3 4 5 6 7 8
| gzip on; gzip_buffers 32 4K; gzip_comp_level 6; gzip_min_length 100; gzip_types application/javascript text/css text/xml; gzip_disable "MSIE [1-6]\."; gzip_vary on;
|
添加日志
1 2 3 4 5
| server { listen 80; server_name mapi.psvmc.cn; error_log /etc/nginx/logs/error_mapi.psvmc.cn.log error; }
|
反向代理
反代接口+SSL
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
| server { listen 80; server_name mapi.psvmc.cn; listen 443 ssl; ssl_certificate /etc/nginx/cert/psvmc.pem; ssl_certificate_key /etc/nginx/cert/psvmc.key; ssl_session_timeout 5m; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; error_log /etc/nginx/logs/error_mapi.psvmc.cn.log error;
location / { client_max_body_size 1000m; client_body_buffer_size 128k; client_body_timeout 5m; send_timeout 20s;
proxy_pass http://127.0.0.1:8080/; proxy_cookie_path / /; proxy_redirect / /; 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_connect_timeout 300s; proxy_send_timeout 300s; proxy_read_timeout 300s; } }
|
允许跨域
注意:
如果接口本身已经允许跨域了,那么不要配置Nginx,配置后反而会报跨域错误。
示例
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
| server { listen 80; server_name aitest.psvmc.cn;
location / { add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS'; add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization'; add_header 'Access-Control-Expose-Headers' 'Authorization'; add_header 'Access-Control-Max-Age' 36000; if ($request_method = OPTIONS ) { return 204; } client_max_body_size 1000m; client_body_buffer_size 128k; client_body_timeout 5m; send_timeout 20s; proxy_pass http://127.0.0.1:11434/; proxy_cookie_path / /; proxy_redirect / /; 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_connect_timeout 300s; proxy_send_timeout 300s; proxy_read_timeout 300s; } }
|
核心配置
1 2 3 4 5 6 7 8
| add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
add_header 'Access-Control-Expose-Headers' 'Authorization'; add_header 'Access-Control-Max-Age' 36000; if ($request_method = OPTIONS ) { return 204; }
|
注意OPTIONS返回200也是可以的,但是返回204会更符合规范。
1 2 3 4 5
| add_header 'Access-Control-Allow-Origin' '*'; add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS'; add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization'; add_header 'Access-Control-Max-Age' 36000; if ($request_method = OPTIONS ) { return 200; }
|
也可以这样写
1 2 3 4 5 6 7 8 9 10
| location / { add_header 'Access-Control-Allow-Origin' $http_origin always; add_header 'Access-Control-Allow-Methods' 'GET,OPTIONS,POST' always; add_header 'Access-Control-Allow-Headers' '*'; add_header 'Access-Control-Allow-Credentials' 'true' always; add_header 'Access-Control-Expose-Headers' 'Authorization'; add_header 'Access-Control-Max-Age' 36000; if ($request_method = OPTIONS ) { return 200; } }
|
允许指定域
1 2 3 4 5 6 7 8 9 10
| location / { add_header 'Access-Control-Allow-Origin' 'api.psvmc.cn' always; add_header 'Access-Control-Allow-Methods' 'GET,OPTIONS,POST' always; add_header 'Access-Control-Allow-Headers' '*'; add_header 'Access-Control-Allow-Credentials' 'true' always; add_header 'Access-Control-Expose-Headers' 'Authorization'; add_header 'Access-Control-Max-Age' 36000; if ($request_method = OPTIONS ) { return 200; } }
|
响应头无法获取
1 2
| add_header 'Access-Control-Expose-Headers' 'Authorization';
|
对比
| 响应头 |
作用 |
适用场景 |
Access-Control-Allow-Headers |
允许客户端在请求中使用哪些自定义头 |
当客户端发送的请求包含非简单头(如 Authorization、X-Custom-Header)时,用于告知浏览器服务器接受这些头 |
Access-Control-Expose-Headers |
允许客户端访问响应中的哪些自定义头 |
当服务器返回的响应包含自定义头(如 X-Total-Count、X-Pagination)时,用于告知浏览器客户端可以通过 JavaScript 读取这些头 |
负载均衡
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| upstream a_psvmc { server 192.168.1.2:8080; server 192.168.1.3:8080; ip_hash; }
server { listen 80; server_name a.psvmc.cn; location / { proxy_pass http://a_psvmc; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; client_max_body_size 10m; client_body_buffer_size 128k; proxy_connect_timeout 90; proxy_send_timeout 90; proxy_read_timeout 90; } }
|
反代WS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| upstream wsexam { server 172.26.69.12:8920; }
server { listen 80; server_name wsexam.psvmc.cn; client_max_body_size 200m; location / { proxy_pass http://wsexam; proxy_cookie_path / /; proxy_redirect / /; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }
|
相比之前配置的HTTP代理 主要增加了以下配置
1 2 3 4 5 6
| proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
反代流式接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| server { listen 80; server_name aitest.psvmc.com;
location / { proxy_pass http://127.0.0.1:11434/; proxy_buffering off; 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_connect_timeout 300s; proxy_send_timeout 300s; proxy_read_timeout 300s; } }
|
主要配置
proxy_buffering off:对于流式接口,必须将代理缓冲关闭,这样 Nginx 会立即将接收到的数据转发给客户端,而不是先缓存起来,从而保证数据的实时性。
无法获取IP
1 2 3 4 5 6 7 8 9
| location /ws/ { proxy_pass http://127.0.0.1:3000/; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "Upgrade"; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }
|
注意
只有建立连接的时候才能获取到IP。
获取IP
1 2 3
| ws.on('connection', function connection(ws, req) { const ip = req.connection.remoteAddress; });
|
Java
1 2 3 4
| String address = session.remoteAddress().toString(); String host = headers.get("Host"); String xrealip = headers.get("X-Real-IP"); String xforwardedfor = headers.get("X-Forwarded-For");
|
分别取到的地址为
address: 127.0.0.1:48630
host: sockettest2.psvmc.com
xrealip: 123.14.108.207
xforwardedfor: 123.14.108.207
其中X-Real-IP和X-Forwarded-For获取到的是用户的IP。
大文件上传
添加在server节点下
如果主要处理小文件上传(几十兆以内)
可以参考以下设置:
1 2 3 4 5 6 7
| client_max_body_size 50m; client_header_timeout 10s; client_body_timeout 30s; proxy_connect_timeout 10s; proxy_read_timeout 30s; proxy_send_timeout 30s; send_timeout 20s;
|
如果需要支持大文件上传(几百兆甚至上 GB)
可以参考以下设置:
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
| http { client_max_body_size 10G; client_body_timeout 1800s; client_body_buffer_size 100M; client_body_temp_path /data/nginx/client_temp 1 2;
keepalive_timeout 60s; keepalive_requests 100; client_connect_timeout 10s; client_header_timeout 10s; send_timeout 60s;
server { listen 80; listen 443 ssl; server_name your-domain.com;
ssl_certificate /path/to/cert.pem; ssl_certificate_key /path/to/key.pem; ssl_protocols TLSv1.2 TLSv1.3;
location /api/upload { proxy_http_version 1.1; proxy_set_header Connection ""; proxy_connect_timeout 60s; proxy_send_timeout 1800s; proxy_read_timeout 1800s; proxy_pass http://backend-ip:port; }
} }
|
每个参数的意思:
client开始的参数是客户端到Nginx的配置。
proxy开始的参数是Nginx到反代服务的配置。
client_max_body_size
限制请求体的大小,若超过所设定的大小,返回413错误。
client_header_timeout
Nginx 从客户端接收请求头(header)的最大时间。请求头包含了诸如请求方法、请求的 URL、客户端信息等内容。若超时返回408错误。
client_body_timeout
设置读取客户端请求体的超时时间,包括连接建立后读取第一个请求体数据包的超时时间以及两次连续读取请求体数据包之间的超时时间。
在接收到完整的请求头后,Nginx 开始接收请求体。若超时返回413错误。
proxy_connect_timeout
Nginx与上游服务器(被代理的服务器)建立连接所允许的最长时间。默认为60秒,官方推荐最长不要超过75秒。
proxy_read_timeout
Nginx 从上游服务器读取响应数据的最长时间间隔。默认60秒。
proxy_send_timeout
Nginx 向上游服务器发送请求数据的最长时间。默认60秒。
send_timeout
Nginx 向客户端发送响应数据的最长时间间隔。计时起始点是 Nginx 向客户端发送响应数据的第一个字节之后。
注意:
大文件上传费时的是文件到代理服务器(Nginx)的时间,所以proxy_xxx相关的时间不用配置的过长
代理Mysql/远程连接/SSH
详细文章查看:https://www.psvmc.cn/article/2020-12-31-nginx-tcp.html
配置:
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
| stream { upstream ssh { server 192.168.0.143:22; }
server { listen 3333; proxy_connect_timeout 1h; proxy_timeout 1h; proxy_pass ssh; }
upstream mstsc { server 192.168.0.19:3389; }
server { listen 13389; proxy_connect_timeout 1h; proxy_timeout 1h; proxy_pass mstsc; }
upstream mysql { server 192.168.0.143:3306; }
server { listen 13306; proxy_connect_timeout 1h; proxy_timeout 1h; proxy_pass mysql; } }
|
注意该配置要和http同级
静态+反代
如果前端开发的时候接口使用的是Vite proxy,部署的时候我们可以使用Nginx做反代。
示例1
Nginx配置
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 47 48 49 50 51 52
| server { listen 80; server_name quesaitest.psvmc.com; return 301 https://$host$request_uri; }
server { server_name quesaitest.psvmc.com; client_max_body_size 200m; listen 443 ssl; ssl_certificate /etc/nginx/cert/psvmc.pem; ssl_certificate_key /etc/nginx/cert/psvmc.key; ssl_session_timeout 5m; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; root /data/web_front/quesaitest/; index index.html;
location / { try_files $uri $uri/ /index.html; }
location /api/ { proxy_pass https://scapitest.psvmc.com/; proxy_set_header Host scapitest.psvmc.com; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 5s; proxy_read_timeout 30s; }
location /llm { rewrite ^/llm(.*)$ /v1/chat/completions$1 break;
proxy_pass https://public-xxx-iaab.zzai2.scnet.cn:58043; proxy_set_header Host public-xxx-iaab.zzai2.scnet.cn; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 5s; proxy_read_timeout 60s;
proxy_buffering off; } }
|
注意
location /llm不要写成location /llm/
前端的配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| { server: { port: 5174, strictPort: true, proxy: { "/api": { target: "https://scapitest.psvmc.com", changeOrigin: true, rewrite: (path) => path.replace(/^\/api/, "") }, "/llm": { target: "https://public-xxx-iaab.zzai2.scnet.cn:58043", changeOrigin: true, rewrite: (path) => path.replace(/^\/llm/, "/v1/chat/completions") } } } }
|
示例2(推荐)
Nginx配置
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 47 48 49 50
| server { listen 80; server_name quesaitest.psvmc.com; return 301 https://$host$request_uri; }
server { server_name quesaitest.psvmc.com; client_max_body_size 200m; listen 443 ssl; ssl_certificate /etc/nginx/cert/psvmc.pem; ssl_certificate_key /etc/nginx/cert/psvmc.key; ssl_session_timeout 5m; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; root /data/web_front/quesaitest/; index index.html;
location / { try_files $uri $uri/ /index.html; }
location /api/ { proxy_pass https://scapitest.psvmc.com/; proxy_set_header Host scapitest.psvmc.com; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 5s; proxy_read_timeout 30s; }
location /llm/ { proxy_pass https://public-xxx-iaab.zzai2.scnet.cn:58043/; proxy_set_header Host public-xxx-iaab.zzai2.scnet.cn; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 5s; proxy_read_timeout 60s;
proxy_buffering off; } }
|
一定要注意
location /llm/和proxy_pass地址两者要一致,如果后缀有/,就要两个地方都有,或者两个地方都没有,否则会导致反代报错。
前端的配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| { server: { port: 5174, strictPort: true, proxy: { "/api": { target: "https://scapitest.psvmc.com", changeOrigin: true, rewrite: (path) => path.replace(/^\/api/, "") }, "/llm": { target: "https://public-xxx-iaab.zzai2.scnet.cn:58043", changeOrigin: true, rewrite: (path) => path.replace(/^\/llm/, "") } } } }
|
动静分离
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
| upstream filetest_psvmc { server 127.0.0.1:8905; }
server { listen 80; server_name filetest.psvmc.cn; listen 443; ssl on; ssl_certificate /etc/nginx/cert/psvmc.pem; ssl_certificate_key /etc/nginx/cert/psvmc.key; ssl_session_timeout 5m; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on;
location ^~ /static/ { index index.html; root /data/wwwjarapi/8905xhkjfileapitest/; }
location / { client_max_body_size 1000m; client_body_buffer_size 128k; client_body_timeout 5m;
proxy_pass http://filetest_psvmc/; proxy_cookie_path / /; proxy_redirect / /; 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_connect_timeout 300s; proxy_send_timeout 300s; proxy_read_timeout 300s; send_timeout 20s; } }
|
注意
20行的代码root的路径不要配置为/data/wwwjarapi/8905xhkjfileapitest/static/
否则会在static文件夹下再查找static文件夹
正向代理
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
| server { resolver 114.114.114.114; listen 1080; location / { proxy_pass http://$host$request_uri; proxy_set_header HOST $host; proxy_buffers 256 4k; proxy_max_temp_file_size 0k; proxy_connect_timeout 30; proxy_send_timeout 60; proxy_read_timeout 60; proxy_next_upstream error timeout invalid_header http_502; } }
server { resolver 114.114.114.114; listen 1443; location / { proxy_pass https://$host$request_uri; proxy_buffers 256 4k; proxy_max_temp_file_size 0k; proxy_connect_timeout 30; proxy_send_timeout 60; proxy_read_timeout 60; proxy_next_upstream error timeout invalid_header http_502; } }
|
测试
1 2
| curl -I --proxy 192.168.10.10:1080 www.baidu.com curl -I --proxy 192.168.10.10:1443 www.baidu.com
|
重定向
GET请求
301重定向
比如用OSS加速文件下载
1 2 3
| location = /static/应用.apk { return 301 https://psvmc.oss-cn-huhehaote.aliyuncs.com/client/123.apk; }
|
规则路径是可以支持中文的。
重写
主要用于地址迁移 重定向到新的地址
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| server { server_name zujuan.psvmc.com; client_max_body_size 200m; listen 443; ssl on; ssl_certificate /etc/nginx/cert/psvmc.pem; ssl_certificate_key /etc/nginx/cert/psvmc.key; ssl_session_timeout 5m; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; index index.html; root /data/web_front/zujuan;
location /userapi/login { rewrite ^/userapi/login$ https://zujuan.psvmc.com/userapi/tip.json; } }
|
主要配置是
1 2 3
| location /userapi/login { rewrite ^/userapi/login$ https://zujuan.psvmc.com/userapi/tip.json; }
|
注意
rewrite是302重定向,会把post请求重定向为get请求。
POST请求
307重定向
- 301 永久重定向,告诉客户端以后应从新地址访问.
- 302 作为HTTP1.0的标准,以前叫做Moved Temporarily ,现在叫Found. 现在使用只是为了兼容性的处理,包括PHP的默认Location重定向用的也是302.
但是HTTP 1.1 有303 和307作为详细的补充,其实是对302的细化
- 303:对于POST请求,它表示请求已经被处理,客户端可以接着使用GET方法去请求Location里的URI。
- 307:对于POST请求,表示请求还没有被处理,客户端应该向Location里的URI重新发起POST请求。
大部分浏览器 302 会将 POST 请求转为 GET,所以使用307重新发起请求。
1 2 3
| location ~ ^/userapi/login { return 307 https://www.psvmc.cn/sapi/userapi/login; }
|
反代
1 2 3
| location ~ ^/userapi/login { proxy_pass https://www.psvmc.cn/sapi/userapi/login; }
|
禁止IP访问
我们需要利用 Nginx 的 default_server 指令。
default_server_blockip.conf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| server { listen 80 default_server; server_name _; return 444; }
server { listen 443 ssl default_server; server_name _; ssl_certificate /etc/nginx/cert/zmeduyun.cn.pem; ssl_certificate_key /etc/nginx/cert/zmeduyun.cn.key; return 444; }
|
其中
444 是 Nginx 特有状态码,表示直接关闭连接,不返回任何内容,既安全又节省资源
重启Nginx
Windows
结束
1
| taskkill /f /t /im nginx_basic.exe
|
重启在服务中
Linux
查看配置是否没问题
重启