前言
Nginx跨域配置
server {
listen 80;
server_name xxxx;
access_log /niub/nginx_logs/analyst.ai/xxxxx;
error_log /niub/nginx_logs/analyst.ai/xxxxxx;
#下面的配置是80强制跳转443,301的意思是永久重定向
#return 301 https://$server_name$request_uri;
#公用配置一直到if结束,都属于跨域
add_header Access-Control-Allow-Origin $http_origin;
add_header Access-Control-Allow-Credentials true;
add_header Access-Control-Allow-Headers Origin,X-Requested-With,X-Request-ID,Content-Type,Accept,Authorization;
add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;
add_header Access-Control-Max-Age 1728000;
if ($request_method = 'OPTIONS') {
return 204;
}
location /api/ {
proxy_pass http://xxxxxx/;
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_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
}
server {
listen 443 ssl;
server_name xxxxx;
access_log /niub/nginx_logs/analyst.aixxxxxx;
error_log /niub/nginx_logs/analyst.ai/xxxxx;
ssl_certificate /etc/letsencrypt/live/analyst.ai.wild/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/analyst.ai.wild/privkey.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-RC4-SHA:!ECDHE-RSA-RC4-SHA:ECDH-ECDSA-RC4-SHA:ECDH-RSA-RC4-SHA:ECDHE-RSA-AES256-SHA:HIGH:!RC4-SHA:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!CBC:!EDH:!kEDH:!PSK:!SRP:!kECDH;
#公用配置
add_header Access-Control-Allow-Origin $http_origin;
add_header Access-Control-Allow-Credentials true;
add_header Access-Control-Allow-Headers Origin,X-Requested-With,X-Request-ID,Content-Type,Accept,Authorization;
add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;
add_header Access-Control-Max-Age 1728000;
if ($request_method = 'OPTIONS') {
return 204;
}
location /abc {
proxy_pass http://xxxxxx:80;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $proxy_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location / {
root /niub/www/sourcecode/online-prod-analyst-bond/build;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
try_files $uri $uri/ /index.html;
index index.html;
}
}
跨域漏洞
在Access-Control-Allow-Origin配置中限制固定受信任的域,或通过过滤器设置响应头,并且对获取到的Access-Control-Allow-Origin这个头信息进行验证,如果验证没有通过则将此头信息设置为空
我们现在的项目正常都是前后端分离的,也就是说前端是放在nginx上面,后端是通过nginx转发的
那么我们一般都是访问nginx前端的地址后,才去请求页面上的所有,包括前后端地址
比如前端地址为:https://20.0.0.21:1234 后端地址为:http://20.0.0.22:9528
server {
listen 1234 ssl;
server_name xxxxx;
access_log /niub/nginx_logs/analyst.aixxxxxx;
error_log /niub/nginx_logs/analyst.ai/xxxxx;
#公用配置
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Credentials true;
add_header Access-Control-Allow-Headers Origin,X-Requested-With,X-Request-ID,Content-Type,Accept,Authorization;
add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;
add_header Access-Control-Max-Age 1728000;
if ($request_method = 'OPTIONS') {
return 204;
}
location /abc {
proxy_pass http://20.0.0.22:9528;
}
location / {
root /niub/www/sourcecode/online-prod-analyst-bond/build;
try_files $uri $uri/ /index.html;
index index.html;
}
}
这个时候任何Origin都是可以访问进来的,这样做是不安全的,由于网站配置不当,导致任何网站都可以发出带有用户凭证的请求,并读取这些请求的响应,我们需要指定Origin头才能正常访问
跨域主要涉及4个响应头:
Access-Control-Allow-Origin 用于设置允许跨域请求源地址 (预检请求和正式请求在跨域时候都会验证)
Access-Control-Allow-Headers 跨域允许携带的特殊头信息字段 (只在预检请求验证)
Access-Control-Allow-Methods 跨域允许的请求方法或者说HTTP动词 (只在预检请求验证)
Access-Control-Allow-Credentials 是否允许跨域使用cookies,如果要跨域使用cookies,可以添加上此请求响应头,值设为true(设置或者不设置,都不会影响请求发送,只会影响在跨域时候是否要携带cookies,但是如果设置,预检请求和正式请求都需要设置)。不过不建议跨域使用(项目中用到过,不过不稳定,有些浏览器带不过去),除非必要,因为有很多方案可以代替
接下来我们进行指定
#1.表示带有tripwolf的字符的网站可以访问
#2.表示网页为https://dmp.finerice.cn的可以进行访问
#3.表示网页为http://20.0.0.22:9528的可以进行访问
http {
...
// 再白名单里边返回0,不在返回1
map $http_origin $allow_cors {
default 1;
"~^https?://.*?\.tripwolf\.com.*$" 1;
"~^(https?://(dmp.finerice.cn)?)$" 1;
"~^(http?://(20.0.0.22:9528)?)$" 1;
"~*" 0;
}
server {
location /abc {
# 指定允许其他域名访问
add_header Access-Control-Allow-Origin $http_origin;
#允许的请求类型
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
#允许的请求头字段
add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
#如果不满足上面1 2 3 的条件则返回583
if ($allow_cors = 0){
return 583;
}
proxy_pass http://20.0.0.22:9528;
}
location / {
......
}
}
另外学习的博客:
https://blog.csdn.net/huangjinjin520/article/details/133662385
解决nginx不支持Websocket的问题
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
location /abc {
proxy_pass http://xxxxxx:80;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $proxy_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
Location不保留缓存配置
server {
listen 80;
server_name xxxxx;
access_log /niub/nginx_logs/analyst.ai/xxxxxxx_access.log abcft;
error_log /niub/nginx_logs/analyst.ai/xxxxxxx_error.log info;
return 301 https://$server_name$request_uri;
location /api {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://tpa-api.analyst.ai/api;
if ($request_filename ~* .*\.(?:htm|html)$)
{
add_header Cache-Control "private, no-store, no-cache, must-revalidate, proxy-revalidate";
}
}
关于Nginx线上跳转线下的问题
线上配置
server {
listen 80;
server_name XXXXXXXXX;
access_log /niub/nginx_logs/analyst.ai/XXXXXXXXXXX_access.log abcft;
error_log /niub/nginx_logs/analyst.ai/XXXXXXXXXXXX_error.log info;
return 301 https://$server_name$request_uri;
#公用配置
add_header Access-Control-Allow-Origin $http_origin;
add_header Access-Control-Allow-Credentials true;
add_header Access-Control-Allow-Headers Origin,X-Requested-With,X-Request-ID,Content-Type,Accept,Authorization;
add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;
add_header Access-Control-Max-Age 1728000;
if ($request_method = 'OPTIONS') {
return 204;
}
location / {
root /niub/www/sourcecode/XXXXXXXXXX/build;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
try_files $uri $uri/ /index.html;
index index.html;
}
location /api/company/ {
proxy_pass http://XXXX:80/api/company/;
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_pass http://XXXX:80/api/company/
因为跳转的时候,指挥带着主机头,不会带着路径
线下配置
server {
listen 80;
server_name bond.analyst.ai;
access_log /u-data/nginx_logs/analyst.ai/bond.analyst.ai_access.log abcft;
error_log /u-data/nginx_logs/analyst.ai/bond.analyst.ai_error.log info;
# return 301 https://$server_name$request_uri;
#公用配置
add_header Access-Control-Allow-Origin $http_origin;
add_header Access-Control-Allow-Credentials true;
add_header Access-Control-Allow-Headers Origin,X-Requested-With,X-Request-ID,Content-Type,Accept,Authorization;
add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;
add_header Access-Control-Max-Age 1728000;
if ($request_method = 'OPTIONS') {
return 204;
}
location /api/company/ {
proxy_pass http://company_bond_analyst_ai/company/;
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_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
Nginx限流
每秒最多处理一个连接:
http {
limit_req_zone $binary_remote_addr zone=perip:10m rate=1r/s;
server {
limit_req zone=perip;
key :定义限流对象,binary_remote_addr 是一种key,表示基于 remote_addr(客户端IP) 来做限流,binary_ 的目的是压缩内存占用量。
zone:定义共享内存区来存储访问信息, myRateLimit:10m 表示一个大小为10M,名字为myRateLimit的内存区域。1M能存储16000 IP地址的访问信息,10M可以存储16W IP地址访问信息。
rate:用于设置最大访问速率,rate=1r/s 表示每秒最多处理1个请求。Nginx 实际上以毫秒为粒度来跟踪请求信息,因此 10r/s 实际上是限制:每100毫秒处理一个请求。这意味着,自上一个请求处理完后,若后续100毫秒内又有请求到达,将拒绝处理该请求
-----限制访问频率:-----
按上面的配置在流量突然增大时,超出的请求将被拒绝,无法处理突发流量,那么在处理突发流量的时候,该怎么处理呢?Nginx提供了 burst 参数来解决突发流量的问题,并结合 nodelay 参数一起使用。burst 译为突发、爆发,表示在超过设定的处理速率后能额外处理的请求数
http {
limit_req_zone $binary_remote_addr zone=perip:10m rate=1r/s;
server {
limit_req zone=perip burst=5 nodelay;
如何理解:上面的配置每秒只能访问一次,下面相当于当我没有连接的时候,一次性可以有5个访问进来,再访问就需要1秒处理1个了;
限制并发连接数
这个模块用来限制单个IP的请求数。并非所有的连接都被计数。只有在服务器能正常读取到请求头并解析到ip ,连接才被计数,这个取决于当前nginx的配置,具体需要到测试环境的nginx去实现一下
官方原话:并非所有连接都被计算在内。只有当服务器正在处理一个请求并且已经读取了整个请求标头时,才计算一个连接。
http {
limit_conn_zone $binary_remote_addr zone=perip:10m;
limit_conn_zone $server_name zone=perserver:10m;
server {
...
limit_conn perip 10; 每个客户端IP连接到服务器的数量
limit_conn perserver 100; 连接到虚拟服务器的总数
下载限速:
location /flv/ {
flv;
limit_rate_after 20m;
limit_rate 100k;
Https下http资源不能访问解决方案
问题如下:nginx安装了https证书 修改为https访问后,但应用内有些http的,导致一些样式或者页面访问报错,因为https下面默认访问http是会报错的。
解决方案:我们修改下nginx的转发策略,只需在代理转发添加如下配置即可:
add_header Content-Security-Policy upgrade-insecure-requests;
上传文件大小
nginx对上传文件大小有要求,默认1m,如果很大,还要适当调整上传超时时间。
1. client_max_body_size
限制请求体的大小,若超过所设定的大小,返回413错误。
2.client_header_timeout
读取请求头的超时时间,若超过所设定的大小,返回408错误。
3. client_body_timeout
读取请求实体的超时时间,若超过所设定的大小,返回413错误。
4.proxy_connect_timeout
http请求无法立即被容器(tomcat, netty等)处理,被放在nginx的待处理池中等待被处理。此参数为等待的最长时间,默认为60秒,官方推荐最长不要超过75秒。
5.proxy_read_timeout
http请求被容器(tomcat, netty等)处理后,nginx会等待处理结果,也就是容器返回的response。此参数即为服务器响应时间,默认60秒。
6.proxy_send_timeout
http请求被服务器处理完后,把数据传返回给Nginx的用时,默认60秒。