1、获取cdn下用户的真实ip
http
{
set_real_ip_from 0.0.0.0/0;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
}
2、Nginx默认是不允许列出整个目录的,可以增加配置
http
{
autoindex off;
}
3、nginx默认是会在返回的数据包中显示版本号,隐藏ng版本号
http
{
server_tokens off;
}
4、限制访问请求参数
http {
#设置客户端请求头读取超时时间,超过这个时间还没有发送任何数据,Nginx将返回“Request time out(408)”错误
client_header_timeout 15;
#设置客户端请求主体读取超时时间,超过这个时间还没有发送任何数据,Nginx将返回“Request time out(408)”错误
client_body_timeout 15;
#上传文件大小限制
client_max_body_size 100m;
#指定响应客户端的超时时间。这个超过仅限于两个连接活动之间的时间,如果超过这个时间,客户端没有任何活动,Nginx将会关闭连接。
send_timeout 600;
#设置客户端连接保持会话的超时时间,超过这个时间,服务器会关闭该连接。
keepalive_timeout 60;
}
5、限制访问个别目录或文件后缀名。
#在访问uploads、images目录时,访问php|php5|jsp后缀的文件会返回403代码,也就是不给执行代码了。
location ~ ^/(uploads|images)/.*\.(php|php5|jsp)$ {
return 403;
}
#禁止访问所有目录下的sql|log|txt|jar|war|sh|py后缀的文件,这些是什么文件就不详细说了。
location ~.*\.(sql|log|txt|jar|war|sh|py) {
deny all;
}
#有时候,有些访问记录不想保存到日志里面,例如静态图片
location ~ .*\.(js|jpg|JPG|jpeg|JPEG|css|bmp|gif|GIF|png)$ {
access_log off;
}
6、 限制IP的访问频率
防御DDOS是一个系统工程,攻击花样多,防御的成本高瓶颈多,防御起来即被动又无奈。DDOS的特点是分布式,针对带宽和服务攻击,也就 是四层流量攻击和七层应用攻击,相应的防御瓶颈四层在带宽,七层的多在架构的吞吐量。对于七层的应用攻击,我们还是可以做一些配置来防御的,例如前端是 Nginx,主要使用nginx的http_limit_conn和http_limit_req模块来防御。 ngx_http_limit_conn_module 可以限制单个IP的连接数,ngx_http_limit_req_module 可以限制单个IP每秒请求数,通过限制连接数和请求数能相对有效的防御CC攻击。
ngx_http_limit_req_module模块通过漏桶原理来限制单位时间内的请求数,一旦单位时间内请求数超过限制,就会返回503错误。配置需要在两个地方设置:
1、nginx.conf的http段内定义触发条件,可以有多个条件;
2、在location内定义达到触发条件时nginx所要执行的动作;要先在http层定义,然后在 location, server, http上下文中作限制,他们用的是限制单ip访问的漏桶算法,超过定义的限制会报503错误,当然,有些时候可能是某个公司同一个ip有几十人一起访问网站,这是有可能被误伤的,做好503报错回调是很有必要的。
http {
limit_req_zone $binary_remote_addr zone=iplimit:10m rate=20r/s;
# zone=iplimit:10m 表示生成一个大小为10M的名字为iplimit的内存区域来存储访问频次信息,1M大约可以存16000个ip会话,看你访问量有多少就设多少
# rate=20r/s 表示允许相同标识的客户端访问频次 每秒20次,依据你的访问量来设置
server{
location ~ ^/api {
proxy_pass http:#127.0.0.1:8000;
# 对访问以/api的请求,限制每个ip每秒不超过20个请求,漏桶数burst为5,brust的意思就是,如果第1,2,3,4秒请求为19个,第5秒的请求为25个是被允许的。但是如果你第1秒就25个请求,第2秒超过20的请求返回503错误。nodelay,如果不设置该选项,第1秒25个请求时,5个请求放到第2秒执行,设置nodelay,25个请求将在第1秒执行。
limit_req zone=ipmlimit burst=5 nodelay;
limit_req_status 503;
# burst 缓冲区大小
# nodelay 超过访问频次而且缓冲区也满的时候返回503
# limit_req_status指定自定义错误码, 默认503
}
}
# 指定503错误页面:
error_page 503 /errpage/503.html;
}
7、Nginx 限制IP的并发
通过 limit_conn_zone 模块来达到限制用户的连接数的目的,即限制同一用户 IP 地址的并发连接数。
通过配置,设定/api 这个location,每个IP,同一时刻只存在一个连接。
注意:并发的概念并不是说 每秒多少连接。
http {
limit_conn_zone $binary_remote_addr zone=connlimit:10m;
# zone=iplimit:10m 表示生成一个大小为10M的名字为iplimit的内存区域来存储访问频次信息,1M大约可以存16000个ip会话,看你访问量有多少就设多少
server{
location ~ ^/api {
proxy_pass http:#127.0.0.1:8000;
# 配置的并发请求为 1, 依据你的实际情况来设置
limit_conn connlimit 1;
# limit_conn_status 指定自定义错误码, 默认503
limit_conn_status 503;
}
}
# 指定503错误页面:
error_page 503 /errpage/503.html;
}
8、Nginx 限制IP的流量
通过limit_rate模块来进行流量控制, 对于提供下载的网站,肯定是要进行流量控制的。Nginx 通过 core模块的 limit_rate 等指令可以做到限流的目的。
如果要进行限速,可以和 limit_conn_zone 模块配合进行使用
http {
server{
location ~ ^/download{
# 以最大的速度下载 size大小后,在进行 limit_rate speed 限速,例如:limit_rate_after 3m 解释为:以最大的速度下载3m后,再进行限速。
limit_rate_after 3m;
# 向客户端传输数据的速度,速度的单位是每秒传输的字节数。注意:该限制只是针对一个连接的设定,也就是说,如果同时有2个连接,那么它的速度将会是该指令设置的两倍。
limit_rate 512k;
}
}
}
9、禁止不安全的HTTP方法
默认情况下,Nginx支持多种HTTP方法,包括GET、POST、OPTIONS等。然而,某些HTTP方法可能存在安全风险,例如TRACE方法可以被用于跨站脚本(XSS)攻击。我们可以使用Nginx的"limit_except"指令来限制某些HTTP方法的访问。
示例代码:
location / {
limit_except GET POST {
deny all;
}
}
防止SQL注入、XSS攻击将下面的Nginx配置文件代码放入到对应站点的.conf配置文件[server]里,然后重启Nginx即可生效。
if ($request_method !~* GET|POST) { return 444; }
#使用444错误代码可以更加减轻服务器负载压力。
#防止SQL注入
if ($query_string ~* (\$|'|--|[+|(%20)]union[+|(%20)]|[+|(%20)]insert[+|(%20)]|[+|(%20)]drop[+|(%20)]|[+|(%20)]truncate[+|(%20)]|[+|(%20)]update[+|(%20)]|[+|(%20)]from[+|(%20)]|[+|(%20)]grant[+|(%20)]|[+|(%20)]exec[+|(%20)]|[+|(%20)]where[+|(%20)]|[+|(%20)]select[+|(%20)]|[+|(%20)]and[+|(%20)]|[+|(%20)]or[+|(%20)]|[+|(%20)]count[+|(%20)]|[+|(%20)]exec[+|(%20)]|[+|(%20)]chr[+|(%20)]|[+|(%20)]mid[+|(%20)]|[+|(%20)]like[+|(%20)]|[+|(%20)]iframe[+|(%20)]|[\<|%3c]script[\>|%3e]|javascript|alert|webscan|dbappsecurity|style|confirm\(|innerhtml|innertext)(.*)$) { return 555; }
if ($uri ~* (/~).*) { return 501; }
if ($uri ~* (\\x.)) { return 501; }
#防止SQL注入
if ($query_string ~* "[;'<>].*") { return 509; }
if ($request_uri ~ " ") { return 509; }
if ($request_uri ~ (\/\.+)) { return 509; }
if ($request_uri ~ (\.+\/)) { return 509; }
#if ($uri ~* (insert|select|delete|update|count|master|truncate|declare|exec|\*|\')(.*)$ ) { return 503; }
#防止SQL注入
if ($request_uri ~* "(cost\()|(concat\()") { return 504; }
if ($request_uri ~* "[+|(%20)]union[+|(%20)]") { return 504; }
if ($request_uri ~* "[+|(%20)]and[+|(%20)]") { return 504; }
if ($request_uri ~* "[+|(%20)]select[+|(%20)]") { return 504; }
if ($request_uri ~* "[+|(%20)]or[+|(%20)]") { return 504; }
if ($request_uri ~* "[+|(%20)]delete[+|(%20)]") { return 504; }
if ($request_uri ~* "[+|(%20)]update[+|(%20)]") { return 504; }
if ($request_uri ~* "[+|(%20)]insert[+|(%20)]") { return 504; }
if ($query_string ~ "(<|%3C).*script.*(>|%3E)") { return 505; }
if ($query_string ~ "GLOBALS(=|\[|\%[0-9A-Z]{0,2})") { return 505; }
if ($query_string ~ "_REQUEST(=|\[|\%[0-9A-Z]{0,2})") { return 505; }
if ($query_string ~ "proc/self/environ") { return 505; }
if ($query_string ~ "mosConfig_[a-zA-Z_]{1,21}(=|\%3D)") { return 505; }
if ($query_string ~ "base64_(en|de)code\(.*\)") { return 505; }
if ($query_string ~ "[a-zA-Z0-9_]=http://") { return 506; }
if ($query_string ~ "[a-zA-Z0-9_]=(\.\.//?)+") { return 506; }
if ($query_string ~ "[a-zA-Z0-9_]=/([a-z0-9_.]//?)+") { return 506; }
if ($query_string ~ "b(ultram|unicauca|valium|viagra|vicodin|xanax|ypxaieo)b") { return 507; }
if ($query_string ~ "b(erections|hoodia|huronriveracres|impotence|levitra|libido)b") {return 507; }
if ($query_string ~ "b(ambien|bluespill|cialis|cocaine|ejaculation|erectile)b") { return 507; }
if ($query_string ~ "b(lipitor|phentermin|pro[sz]ac|sandyauer|tramadol|troyhamby)b") { return 507; }
#这里大家根据自己情况添加删减上述判断参数,cURL、wget这类的屏蔽有点儿极端了,但要“宁可错杀一千,不可放过一个”。
if ($http_user_agent ~* YisouSpider|ApacheBench|WebBench|Jmeter|JoeDog|Havij|GetRight|TurnitinBot|GrabNet|masscan|mail2000|github|wget|curl|Java|python) { return 508; }
#同上,大家根据自己站点实际情况来添加删减下面的屏蔽拦截参数。
if ($http_user_agent ~* "Go-Ahead-Got-It") { return 508; }
if ($http_user_agent ~* "GetWeb!") { return 508; }
if ($http_user_agent ~* "Go!Zilla") { return 508; }
if ($http_user_agent ~* "Download Demon") { return 508; }
if ($http_user_agent ~* "Indy Library") { return 508; }
if ($http_user_agent ~* "libwww-perl") { return 508; }
if ($http_user_agent ~* "Nmap Scripting Engine") { return 508; }
if ($http_user_agent ~* "~17ce.com") { return 508; }
if ($http_user_agent ~* "WebBench*") { return 508; }
if ($http_user_agent ~* "spider") { return 508; } #这个会影响国内某些搜索引擎爬虫,比如:搜狗
#拦截各恶意请求的UA,可以通过分析站点日志文件或者waf日志作为参考配置。
if ($http_referer ~* 17ce.com) { return 509; }
#拦截17ce.com站点测速节点的请求
if ($http_referer ~* WebBench*") { return 509; }
#拦截WebBench或者类似压力测试工具,其他工具只需要更换名称即可。
10、防止恶意请求
恶意请求包括大量的请求、大文件上传、恶意脚本等等,这会导致服务器负载过高。我们可以通过设置请求限制,来防止这种情况发生。
http {
limit_req_zone $binary_remote_addr zone=req_limit:10m rate=1r/s;
server {
location / {
limit_req zone=req_limit burst=5 nodelay;
# 其他配置
}
}
}
11、拒绝User-Agent:server、location
可能有一些不法者会利用wget/curl等工具扫描我们的网站,我们可以通过禁止相应的user-agent来简单的防范
Nginx的444状态比较特殊,如果返回444那么客户端将不会收到服务端返回的信息,就像是网站无法连接一样
if ($http_user_agent ~* LWP::Simple|BBBike|wget|curl) {
return 444;
}
如果经常分析网站日志你会发现,一些奇怪的 UA 总是频繁的来访问网站,而这些 UA 对网站收录毫无意义,反而增加服务器压力,可以直接将其屏蔽。
if ($http_user_agent ~* (SemrushBot|python|MJ12bot|AhrefsBot|AhrefsBot|hubspot|opensiteexplorer|leiki|webmeup)) {
return 444;
}
12、禁止访问目录
#禁止访问多个目录
location ~ ^/(picture|move)/ {
deny all;
break;
}
#禁止访问 htaccess
location ~/\.ht {
deny all;
}
#禁止访问 /data 开头的文件
location ~ ^/data {
deny all;
}
#禁止访问单个目录
location /imxhy/images/ {
deny all;
}
13、Nginx代理安全策略
Strict-Transport-Security
(简称为 HSTS)可以告诉浏览器,在指定的 max-age 内,始终通过 HTTPS 访问我的站点。即使用户自己输入 HTTP 的地址,或者点击了 HTTP 链接,浏览器也会在本地替换为 HTTPS 再发送请求。
X-Frame-Options
用来指定此网页是否允许被 iframe 嵌套,deny 就是不允许任何嵌套发生。
X-Content-Type-Options
用来指定浏览器对未指定或错误指定 Content-Type 资源真正类型的猜测行为,nosniff 表示不允许任何猜测。
Content-Security-Policy
(简称为 CSP)用来指定页面可以加载哪些资源,主要目的是减少 XSS 的发生。我允许了来自本站、disquscdn 的外链 JS,还允许内联 JS,以及在 JS 中使用 eval;允许来自本站和 google 统计的图片,以及内联图片(Data URI 形式);允许本站外链 CSS 以及内联 CSS;允许 iframe 加载来自 disqus 的页面。对于其他未指定的资源,都会走默认规则
self
,也就是只允许加载本站的。关于 CSP 的详细介绍请看这里。
server {
listen 28443;
server_tokens off;
location /cas {
proxy_pass http://localhost:28442/cas;
proxy_redirect default;
proxy_read_timeout 600s;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 防止xss
add_header X-XSS-Protection "1; mode=block";
# 防劫持
add_header X-Frame-Options "SAMEORIGIN";
# 防劫持
add_header X-Content-Type-Options "nosniff";
# 防劫持
add_header Content-Security-Policy "frame-ancestors 'self'";
# HSTS
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
add_header Referrer-Policy origin;
add_header X-Permitted-Cross-Domain-Policies "master-only";
add_header X-Download-Options noopen;
index index.html index.htm;
}
}
14、日志快速查询
#查询访问最频繁的前100个IP
awk '{print $1}' access_temp.log | sort -n|uniq -c | sort -rn | head -n 100
#统计耗时接⼝, 列出传输时间超过 2 秒的接⼝,显示前5条
cat time_temp.log|awk '($NF > 2){print $7}'|sort -n|uniq -c|sort -nr|head -5
备注:$NF 表示最后⼀列, awk '{print $NF}'
awk 是⽂本处理⼯具,默认按照空格切分,
$N 是第切割后第N个,从1开始
sort命令⽤于将⽂本⽂件内容加以排序,-n 按照数值排,-r 按照倒序来排案例的
sort -n 是按照第⼀列的数值⼤⼩进⾏排序,从⼩到⼤,倒序就是 sort -rn
uniq 去除重复出现的⾏列, -c 在每列旁边显示该⾏重复出现的次数。
版权归原作者 大新软件技术部 所有, 如有侵权,请联系我们删除。