找回密码
 加入怎通
查看: 207|回复: 5

Nginx 防攻击安全配置方案(nginx防dos)

[复制链接]
我来看看 发表于 2023-03-22 06:54:06 | 显示全部楼层 |阅读模式
) ~) r% g5 M& o# a; ]( @- U6 v- r

基础配置经常会有针对某个版本的nginx安全漏洞出现,隐藏nginx版本号就成了主要的安全优化手段之一,当然最重要的是及时升级修复漏洞http {0 `+ w! V9 q: t8 Y8 T" V server_tokensoff; & r. Q( n' l0 q; L7 K3 o0 t6 r: I }Header头设置。

% `$ \% R3 A$ C* }) V( ~3 U/ X

在通常的请求响应中,浏览器会根据Content-Type来分辨响应的类型,但当响应类型未指定或错误指定时,浏览会尝试启用MIME-sniffing来猜测资源的响应类型,这是非常危险的X-Frame-Options。

3 ~% X$ E" E) E1 U) M

:响应头表示是否允许浏览器加载frame等属性,有三个配置DENY禁止任何网页被嵌入,SAMEORIGIN只允许本网站的嵌套,ALLOW-FROM允许指定地址的嵌套X-XSS-Protection:表示启用XSS过滤(禁用过滤为X-XSS-Protection: 0),mode=block表示若检查到XSS攻击则停止渲染页面

: s; t- S8 S7 d1 N K

X-Content-Type-Options:响应头用来指定浏览器对未指定或错误指定Content-Type资源真正类型的猜测行为,nosniff 表示不允许任何猜测例如一个.jpg的图片文件被恶意嵌入了可执行的js代码,在开启资源类型猜测的情况下,浏览器将执行嵌入的js代码,可能会有意想不到的后果

/ ?" l# h* N2 I9 H

add_header X-Frame-Options SAMEORIGIN; * ?+ B2 [! h/ T9 O2 E% V0 {" P # 禁止嗅探文件类型add_header X-Content-Type-Options nosniff;add_header

' @& ~2 Y1 M$ e. p, Z

X-XSS-Protection "1; mode=block"; 开启HSTS统一https访问add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload"

% o" W3 `# _ V e

;账号认证server { 7 X. R: G2 E& u, y- i" Y/ S location / {: w3 H9 t4 e8 j1 Z3 j auth_basic"please input user&passwd";) |: O1 m3 p, M& S0 J$ v8 V auth_basic_user_file

Q/ ?- ?6 q. R

key/auth.key;% ?' y$ A5 t+ V9 s# ]' X } 7 L7 H" C$ J& p$ F! U }限制请求方法$request_method能够获取到请求nginx的method这里配置只允许GET/POST方法访问,其他的method返回405if ($request_method

1 S! @* {6 n% l! t4 s0 D# H

!~ ^(GET|POST)$ ) {4 h, B: m/ J" X4 O( U6 D t return405; 1 R0 P/ L' H P }拒绝指定User-Agent可能有一些不法者会利用wget/curl等工具扫描我们的网站,我们可以通过禁止相应的user-agent

0 }0 c: E) K2 \

来简单的防范Nginx的444状态比较特殊,如果返回444那么客户端将不会收到服务端返回的信息,就像是网站无法连接一样#禁止Scrapy等工具的抓取if ($http_user_agent~* (Scrapy|Curl|HttpClient))

. u* }( D9 D% r- I

{3 ~8 s8 t- [1 Z( W( v$ P5 r$ F5 a, p return444; / U: E% o4 g( ]$ J, _! c8 A }, h1 U7 c2 A4 z2 L. c1 _ #禁止指定UA及UA为空的访问if ($http_user_agent~ "WinHttp|WebZIP|FetchURL|node-superagent|java/|FeedDemon|Jullo|JikeSpider|Indy

# m# j* S* i, c

Library|Alexa Toolbar|AskTbFXTV|AhrefsBot|CrawlDaddy|Java|Feedly|Apache-HttpAsyncClient|UniversalFeedParser|ApacheBench|Microsoft URL Control|Swiftbot|ZmEu|oBot|jaunty|Python-urllib|lightDeckReports Bot|YYSpider|DigExt|HttpClient|MJ12bot|heritrix|EasouSpider|Ezooms|BOT/

7 ~+ D7 T6 j9 d: g4 v0 [+ y

0.1|YandexBot|FlightDeckReports|Linguee Bot|^$" ) { - [6 ~& X" z; P9 o) }2 S return 444; # [7 F4 ? A, k6 p& q4 b7 c }图片防盗链location /images/ {; s6 r/ I& W0 u \9 j% c

# F9 g9 r) w j1 g

valid_referersnoneblocked www.host.com;' `6 O7 I, W6 D- C3 U4 h if ($invalid_referer) {, o: k$ U, L; l5 n. c return403; # l H' m' e/ M [ } # M2 q- s3 G* C1 J& W2 c }valid_referers

9 Y& _2 V. N3 S6 S9 @( E6 q& K

: 验证referer,其中none允许referer为空,blocked允许不带协议的请求,除了以上两类外仅允许referer为 www.host.com 时访问images下的图片资源,否则返回403

" m+ F( V0 T; _3 i

当然你也可以给不符合referer规则的请求重定向到一个默认的图片,比如下边这样location /images/ {9 c2 p# ~, \% [( p" _ valid_referersblocked www.host.com/ s% U$ g1 t# }! O4 x% n1 Q if (

1 `* T6 T, P- {* ]6 r! D

$invalid_referer) { ; M( G, q' g: Q u' g rewrite ^/images/.*.(gif|jpg|jpeg|png)$ /static/qrcode.jpg last;, X: `" `. o4 Z m }8 _7 M. L, W$ ]1 f, @5 l }限制并发及请求数

- C$ a! U' \$ _5 _$ R

网站安全配置(Nginx)防止网站被CC攻击(包括使用了CDN加速之后的配置方法)Nginx 有 2 个模块用于控制访问“数量”和“速度”简单的说,控制你最多同时有 多少个访问,并且控制你每秒钟最多访问多少次, 你的同时并发访问不能太多,也不能太快,不然就“杀无赦”。

8 @' a' v1 ~# I) h% I: V

HttpLimitZoneModule 限制同时并发访问的数量HttpLimitReqModule 限制访问数据,每秒内最多几个请求现在我们面对的最直接的问题就是, 经过这么多层加速,我怎么得到“最前面普通用户的 IP 地址”呢?

& g9 R) J% Z$ J C7 U% d

当一个 CDN 或者透明代理服务器把用户的请求转到后面服务器的时候,这个 CDN 服务器会在 Http 的头中加入 一个记录X-Forwarded-For : 用户IP, 代理服务器IPX-Forwarded-For : 用户IP, 代理服务器1-IP, 代理服务器2-IP, 代理服务器3-IP, ….

+ W; L( f$ O; @. L4 i/ S" F1 ]9 O

可以看到经过好多层代理之后, 用户的真实IP 在第一个位置, 后面会跟一串 中间代理服务器的IP地址,从这里取到用户真实的IP地址,针对这个 IP 地址做限制就可以了,标准配置Nginx 里面设置一个限制,配置如下:

. G& C P! V% p0 J1 `

## 用户的 IP 地址 $binary_remote_addr 作为 Key,每个 IP 地址最多有 50 个并发连接## 你想开 几千个连接 刷死我? 超过 50 个连接,直接返回 503 错误给你,根本不处理你的请求了

" C2 e& r6 C" N; B/ d

limit_conn_zone$binary_remote_addr zone=TotalConnLimitZone:10m ; , }. h" Y* _" @1 A M- x! y limit_conn TotalConnLimitZone 50; 9 C( {! `" `( p5 C- b6 o; a

* J. K# Y, D$ v8 M- V+ n

limit_conn_log_levelnotice; + O+ k8 e' F: b: `- C1 S' { ## 用户的 IP 地址 $binary_remote_addr 作为 Key,每个 IP 地址每秒处理 10 个请求## 你想用程序每秒几百次的刷我,没戏,再快了就不处理了,直接返回 503 错误给你

& o$ G1 b" K+ _) B/ P3 r7 R6 A2 w

limit_req_zone$binary_remote_addr zone=ConnLimitZone:10m rate=10r/s; 4 ~$ w* d+ }5 i' |3 [- l4 n) @ limit_req_log_levelnotice; ; e* [; a2 V0 T! o2 M ## 具体服务器配置

) D) H& ? @. K# y7 \7 r( ~( O

server { ! F# C& i4 q# o( g6 m2 \ listen80; " B! X4 s9 ?9 g& J% Z- j& H$ _ location~ \.php$ { ( A0 x2 B' ]* n) N1 K3 e # 最多 5 个排队, 由于每秒处理 10 个请求 + 5个排队,你一秒最多发送 15 个请求过来,再多就直接返回 503 错误给你了

8 N, P6 M9 L. T6 T

limit_req zone=ConnLimitZone burst=5 nodelay;" t9 b- r! y9 B$ ~ fastcgi_pass127.0.0.1:9000; * x& A% e: q, U6 _5 w* U, p' t fastcgi_index

9 ]- H+ t6 P2 a2 y! P

index.php; 4 c) @' r# e# D0 v$ j3 _ include fastcgi_params;9 O8 v( c w% B7 D; q } * L ~) j' c: @ }这样一个最简单的服务器安全限制访问就完成了,这个基本上你 Google 一搜索能搜索到 90% 的网站都是这个例子,而且还强调用“$binary_remote_addr”可以节省内存之类的废话

) x% ]/ K0 w* \

经过多层CDN之后取得原始用户的IP地址Nginx 配置取得用户的原始地址map $http_x_forwarded_for $clientRealIp { 2 {# d% q! G5 Z3 o; i8 x ## 没有通过代理,直接用

* ]/ Q1 a; i- M, C5 ]9 M

3 V7 U$ Z7 Q. a5 S8 e remote_addr "" $remote_addr;) f) a& W# s" q4 e3 x ## 用正则匹配,从 x_forwarded_for 中取得用户的原始IP ## 例如 X-Forwarded-For: 202.123.123.11, 208.22.22.234, 192.168.2.100,...

" e$ R" Z5 z) F) D: G

## 这里第一个 202.123.123.11 是用户的真实 IP,后面其它都是经过的 CDN 服务器0 D; H. Y6 f3 A ~^(?P[0-9\.]+),?.*$ $firstAddr; 4 [, F6 {8 T4 V } 7 A. m( ^ @3 p5 v! A, i6 ^

+ Y8 ^. O3 C s5 C' R

## 通过 map 指令,我们为 nginx 创建了一个变量 $clientRealIp ,这个就是 原始用户的真实 IP 地址,## 不论用户是直接访问,还是通过一串 CDN 之后的访问,我们都能取得正确的原始IP地址

2 a& T: Y: h+ o, t! o G3 W# ^

根据用户的真实 IP 做连接限制下面是修改之后的 Nginx 配置:CDN环境下 Nginx 的安全配置Shell## 这里取得原始用户的IP地址map$http_x_forwarded_for $clientRealIp {

7 P5 X8 c n. o, [' M0 x. U5 x

""$remote_addr; ~^(?P[0-9\.]+),?.*$ $firstAddr;}## 针对原始用户 IP 地址做限制limit_conn_zone$clientRealIp zone=TotalConnLimitZone:20m ;

' z7 U7 M. J2 F5 \: x

limit_connTotalConnLimitZone 50;limit_conn_log_levelnotice;## 针对原始用户 IP 地址做限制limit_req_zone$clientRealIp zone=ConnLimitZone:20m rate=10r/s;

4 I, P- {; H% j# k! t" \( E4 l1 u! l

#limit_req zone=ConnLimitZone burst=10 nodelay;limit_req_log_levelnotice;## 具体服务器配置server{ listen80;

( v! a6 q3 Z0 Q

location~ \.php$ { ## 最多 5 个排队, 由于每秒处理 10 个请求 + 5个排队,你一秒最多发送 15 个请求过来,再多就直接返回 503 错误给你了 limit_req

~0 ?+ C+ x4 T7 B4 V% d

zone=ConnLimitZone burst=5 nodelay;}}

$ ]' o( U( ]5 J7 o7 N 3 l6 j( N6 P5 f4 ^. L+ d ; l( O2 \% c6 l2 J( Z2 o8 m" s8 [0 ?5 L& K# N' K4 q+ I - x' Z7 j8 h: b% o; r, ?, M5 q

暂时无法加载帖子列表

回复

使用道具 举报

coffee 发表于 2026-03-16 03:54:43 | 显示全部楼层
说得很实在,没有夸大其词,这种真实分享太难得了
回复

使用道具 举报

chen131029 发表于 2026-07-26 09:44:32 | 显示全部楼层
蹲了这么久,终于看到有价值的讨论,支持一下!
回复

使用道具 举报

za131717945 发表于 2026-08-30 12:25:49 | 显示全部楼层
这个思路很新颖,打开了新世界的大门,谢谢分享
回复

使用道具 举报

秒收录.卡母 发表于 2026-09-06 08:19:24 | 显示全部楼层
刚好遇到类似问题,看完这个帖子心里有底了
回复

使用道具 举报

安贞桥北 发表于 2026-11-02 07:45:02 | 显示全部楼层
完全赞同,我也是这么认为的,英雄所见略同~
回复

使用道具 举报

    您需要登录后才可以回帖 登录 | 加入怎通

    本版积分规则

    QQ|手机版|小黑屋|网站地图|真牛社区 ( 苏ICP备2023040716号-2 )

    GMT+8, 2026-11-2 09:21 , Processed in 0.036263 second(s), 25 queries , Gzip On.

    免责声明:本站信息来自互联网,本站不对其内容真实性负责,如有侵权等情况请联系420897364#qq.com(把#换成@)删除。

    Powered by Discuz! X3.5

    快速回复 返回顶部 返回列表