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

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

[复制链接]
我来看看 发表于 2023-03-22 06:54:06 | 显示全部楼层 |阅读模式
. F2 h- M7 o1 [, b& Y# U- Z; m

基础配置经常会有针对某个版本的nginx安全漏洞出现,隐藏nginx版本号就成了主要的安全优化手段之一,当然最重要的是及时升级修复漏洞http {* L7 V5 M5 x! T, e server_tokensoff; 7 b7 @! [+ n, S' H' t }Header头设置。

' e* U' x" F: m0 T' u9 j4 b

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

u7 E2 t) T; h8 j

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

" U) v7 z q. R

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

4 f: \/ `# I0 j- _+ `8 |

add_header X-Frame-Options SAMEORIGIN; 3 A4 _$ B$ c0 s4 r! b) Y9 y( ~: B # 禁止嗅探文件类型add_header X-Content-Type-Options nosniff;add_header

: _0 I V% X! D; e

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

3 l" X5 Q3 Q- L; [+ i3 \

;账号认证server { $ T) u v- B# w( c location / { # g0 o6 e9 G G3 v' b( v! d9 J6 [ auth_basic"please input user&passwd";+ k7 {/ V) @- V L* J auth_basic_user_file

$ [ F5 v& j9 b4 e9 t7 l

key/auth.key;' a! U- n4 G0 A, Y Z6 A0 L6 n! | }! S% h+ j" h! _ }限制请求方法$request_method能够获取到请求nginx的method这里配置只允许GET/POST方法访问,其他的method返回405if ($request_method

& H; n" Q9 \4 ?! y" w

!~ ^(GET|POST)$ ) { . `. @$ m& M! H P; E7 m& m return405;4 a3 {8 E- Z: S }拒绝指定User-Agent可能有一些不法者会利用wget/curl等工具扫描我们的网站,我们可以通过禁止相应的user-agent

4 c' w r1 T0 b

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

; I9 J- U2 P# w+ S) b0 c) G0 l; I

{ 7 H* x; [" [" Y return444;) s/ H8 L, D/ B( \* A) ], P } ! z7 T& r2 B6 N+ \5 l; Y #禁止指定UA及UA为空的访问if ($http_user_agent~ "WinHttp|WebZIP|FetchURL|node-superagent|java/|FeedDemon|Jullo|JikeSpider|Indy

2 J( Y; [7 K' I! n$ N8 t

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/

5 U$ b) s. u4 K' X" X8 t4 U y! C6 D, |

0.1|YandexBot|FlightDeckReports|Linguee Bot|^$" ) {, D# Q6 Z9 ?7 C) K9 X3 O2 p3 l return 444; 8 e* Z8 ?" Q1 G' r }图片防盗链location /images/ {" E! O5 J6 w$ u

# w6 M& H3 H- W6 F9 \; P

valid_referersnoneblocked www.host.com; - k' E7 T2 u7 l: w if ($invalid_referer) { - q8 l* s" `1 s. E, a return403;5 e9 B/ a( @' G2 C9 ?3 k } * Q" X) n) T* t }valid_referers

: f! t* ]$ ?2 a

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

! C* l ]$ \. |& p! r

当然你也可以给不符合referer规则的请求重定向到一个默认的图片,比如下边这样location /images/ {. ]& e) I0 Y# @% n valid_referersblocked www.host.com 8 r! Z+ i1 O- t$ K* s6 d" ^7 s if (

7 ?' }( p/ K! X( ?, k* [

$invalid_referer) {$ c. S5 d0 P' A/ | rewrite ^/images/.*.(gif|jpg|jpeg|png)$ /static/qrcode.jpg last; ) O1 K( c% L. K) q1 I9 m } / O; B: b9 m7 b" A: L, } }限制并发及请求数

Y L1 c; z k* j/ T6 H( y! Q0 H! [

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

3 r) r0 v$ }2 m6 J8 E; V& D

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

$ w2 g5 j3 V' d8 f. f" @' c

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

$ R5 F7 l. L$ F6 W3 ^9 |$ |0 j9 y* s

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

0 U# b! i+ z8 n. Z. }1 l

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

. _5 | t6 @1 f* g5 z0 D' ]) x

limit_conn_zone$binary_remote_addr zone=TotalConnLimitZone:10m ;6 j3 K+ q |4 Q6 [. \# Y6 P; w limit_conn TotalConnLimitZone 50;6 |! |; {) }1 p8 |- Z1 O

/ f# Q4 l# ^# m; h: T4 v" m3 T9 X

limit_conn_log_levelnotice; ' u: C# c$ ~6 d ## 用户的 IP 地址 $binary_remote_addr 作为 Key,每个 IP 地址每秒处理 10 个请求## 你想用程序每秒几百次的刷我,没戏,再快了就不处理了,直接返回 503 错误给你

! k* G4 V- N: }3 @3 W$ t; p

limit_req_zone$binary_remote_addr zone=ConnLimitZone:10m rate=10r/s;3 p/ e: r, h/ \- J# ?2 J- }2 A4 r limit_req_log_levelnotice; 9 }& k% d c/ X j ## 具体服务器配置

: M# K1 {+ B6 ~

server {' S, l, g ]- |/ |2 N6 A5 z, @ listen80;2 ?0 s. Q$ I+ P4 X9 n+ r location~ \.php$ { 2 k4 y F' P1 ]6 d$ B+ A0 ?9 ^ # 最多 5 个排队, 由于每秒处理 10 个请求 + 5个排队,你一秒最多发送 15 个请求过来,再多就直接返回 503 错误给你了

; G6 m% r) z) ?0 Y' ~9 p

limit_req zone=ConnLimitZone burst=5 nodelay; ( B" {' d8 L$ F, a3 Z% f6 y2 P! @ fastcgi_pass127.0.0.1:9000;1 W" y5 Q4 C' |2 g* o$ J+ | fastcgi_index

9 [+ e; m* m7 I- z% f8 ^( ~

index.php;& }* y. f/ y$ S# u) {! P8 @" n5 e include fastcgi_params;# ~4 k4 {3 x" U+ U. r5 j }1 o( a$ _1 _0 A8 Y4 A$ N }这样一个最简单的服务器安全限制访问就完成了,这个基本上你 Google 一搜索能搜索到 90% 的网站都是这个例子,而且还强调用“$binary_remote_addr”可以节省内存之类的废话

% e) G; B/ [6 o c3 w! Q

经过多层CDN之后取得原始用户的IP地址Nginx 配置取得用户的原始地址map $http_x_forwarded_for $clientRealIp { & c9 S% ^' {; c+ ^% c1 }8 p3 ] ## 没有通过代理,直接用

, G" j7 H% V6 B# ^4 _) Q. s+ t

" d: W) G+ b; N) z, ? remote_addr "" $remote_addr;+ B- M' P! B) a! G5 } ## 用正则匹配,从 x_forwarded_for 中取得用户的原始IP ## 例如 X-Forwarded-For: 202.123.123.11, 208.22.22.234, 192.168.2.100,...

5 T2 m& B! H9 z5 P C; C' m: s0 M' q

## 这里第一个 202.123.123.11 是用户的真实 IP,后面其它都是经过的 CDN 服务器2 W2 ~! U$ ?$ Z1 s ~^(?P[0-9\.]+),?.*$ $firstAddr; " d9 g/ E: T; e7 }' n' z; x5 O } ! u+ ^" N2 p) x8 ], |; S. b

% B6 e7 @, z0 j- X5 W9 |2 t

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

3 h, m) b! K5 r9 ~

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

. e: ^$ e9 j4 c9 S g0 }

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

& T" L& R8 |9 c. H6 q

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

; V/ L( r6 f. A m* y+ s

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

7 p7 ?' D" N8 m

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

+ _" m- u, I# r) ]$ ^3 I* f; \

zone=ConnLimitZone burst=5 nodelay;}}

2 b \( M" z7 O) Y; z$ S% g 9 y, U- ~9 ]' R7 L+ o) [ 2 ?. } o) S- e2 W' U" z- r% J6 w+ j3 S' z ( ^+ b1 L3 }! V ]# \' y4 F

暂时无法加载帖子列表

回复

使用道具 举报

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:15 , Processed in 0.052548 second(s), 24 queries , Gzip On.

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

    Powered by Discuz! X3.5

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