找回密码
 加入怎通
查看: 190|回复: 4

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

[复制链接]
我来看看 发表于 2023-03-22 06:54:06 | 显示全部楼层 |阅读模式
8 P H% ?9 e: O4 I H

基础配置经常会有针对某个版本的nginx安全漏洞出现,隐藏nginx版本号就成了主要的安全优化手段之一,当然最重要的是及时升级修复漏洞http {% r+ \1 {' S8 u" z3 \ server_tokensoff; N- e1 n( F) M" G- Y }Header头设置。

: q0 g0 y a! M

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

; E. i# O& }0 z+ ^ G8 r6 G7 U6 k

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

# Q8 N. U7 b' `3 |1 j4 Y+ y! u

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

- n) w! H1 Q! W; b9 C& z5 c$ z: z

add_header X-Frame-Options SAMEORIGIN;% X" W, U; s) k7 ]# A0 C" F # 禁止嗅探文件类型add_header X-Content-Type-Options nosniff;add_header

" W( B: j# \ ^" N6 S* u

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

3 q7 G# u+ A8 Z

;账号认证server { 4 p" ~2 x0 c8 {% n! o location / {) |/ V. M! ^9 i# P/ H" n auth_basic"please input user&passwd"; # C/ r T4 c/ u0 n* _+ K auth_basic_user_file

# o& v# p9 b4 c% S9 X; b; }

key/auth.key; 5 `( Q" p: d# F. q' Z. ~ } ! t7 w. [- M" M. `. J' e }限制请求方法$request_method能够获取到请求nginx的method这里配置只允许GET/POST方法访问,其他的method返回405if ($request_method

# ~4 H& H% t: {2 B

!~ ^(GET|POST)$ ) { : x9 }- n5 A7 A& c1 D& L/ f9 {6 B8 G return405;7 J; n }' U* T0 E* x `, g }拒绝指定User-Agent可能有一些不法者会利用wget/curl等工具扫描我们的网站,我们可以通过禁止相应的user-agent

@; [5 X3 R5 J8 h" `

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

4 D4 g$ q3 i3 e% A( B

{ % Y/ {3 o7 k( `6 H return444;7 p3 d2 Q+ `6 h5 X: @ } ( v# |+ T, A& S #禁止指定UA及UA为空的访问if ($http_user_agent~ "WinHttp|WebZIP|FetchURL|node-superagent|java/|FeedDemon|Jullo|JikeSpider|Indy

6 d- E0 B9 {- ~! g1 F- L5 J5 u

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/

2 H' i" ^# A4 ~1 a9 H6 d

0.1|YandexBot|FlightDeckReports|Linguee Bot|^$" ) { 2 Y0 r+ |- f, ?5 [% P return 444; w3 w p! b) G }图片防盗链location /images/ { 0 f7 r$ p4 j& M& [, O

4 l$ h. ]. y- c+ s N1 M

valid_referersnoneblocked www.host.com; % o* e% X, ~ {2 A9 O5 _ if ($invalid_referer) { 4 V* N5 y# m4 h' Z/ w return403; ( B$ Q' x3 \. ^' O }2 j7 n7 D8 R% P" ^4 c" u }valid_referers

S1 _ E4 _0 t! j0 [; h& j

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

& {7 X- c7 X& U7 A, k& l

当然你也可以给不符合referer规则的请求重定向到一个默认的图片,比如下边这样location /images/ {* R8 o3 j- S9 K9 t valid_referersblocked www.host.com9 i( @) S$ _* B$ {+ O( z5 K3 h if (

) d" K9 R& i! s, n- j

$invalid_referer) { ( V7 x0 k: L8 t1 j! s# L rewrite ^/images/.*.(gif|jpg|jpeg|png)$ /static/qrcode.jpg last; : A1 P& j1 W+ s9 @, B2 y } 4 @4 L5 T( [% c3 N; c" d }限制并发及请求数

+ F( D# ?" I5 A) u4 |

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

1 `' j* s6 S4 v5 a' n- N; _8 s1 Z

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

0 v. z9 O4 O/ t, ], x; }

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

) n" a \" w' v$ q

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

+ a7 p% \4 x! B6 o) l

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

9 U+ G" V* d) e# J$ P

limit_conn_zone$binary_remote_addr zone=TotalConnLimitZone:10m ;6 N# `0 F6 W* ~ limit_conn TotalConnLimitZone 50; 2 ~2 ]8 S& k2 @1 W/ ^

& s( u" J7 z/ a' \# P7 o! {5 c2 S

limit_conn_log_levelnotice; ( g6 L- h9 \/ T# D ## 用户的 IP 地址 $binary_remote_addr 作为 Key,每个 IP 地址每秒处理 10 个请求## 你想用程序每秒几百次的刷我,没戏,再快了就不处理了,直接返回 503 错误给你

/ T( [% T# b% S) G, ]; P

limit_req_zone$binary_remote_addr zone=ConnLimitZone:10m rate=10r/s;- X& L' Q" ~& c1 b3 w( v limit_req_log_levelnotice; : k9 ^2 S( m; l1 v% b7 z$ r! d ## 具体服务器配置

3 ?$ U! O' b) m0 z

server {$ {3 n0 I9 q5 K# `/ ` listen80; + D+ x+ @6 Z% l5 a4 U: c+ \3 J location~ \.php$ { ) Z! h# r' C1 U0 a _) ]% A, }1 f # 最多 5 个排队, 由于每秒处理 10 个请求 + 5个排队,你一秒最多发送 15 个请求过来,再多就直接返回 503 错误给你了

! ]) K5 w/ v9 f( t" B5 z

limit_req zone=ConnLimitZone burst=5 nodelay; $ B: S6 I' [+ V, G' h3 r% | fastcgi_pass127.0.0.1:9000;: g4 y' @0 Q7 D5 H/ E7 v! H fastcgi_index

: \3 s) b: |) h: e: p

index.php; ! Z4 H% D! a$ [" D4 R+ u# G8 R include fastcgi_params;' V7 u p% l4 e }& C/ `1 ^9 W* Z! G1 G }这样一个最简单的服务器安全限制访问就完成了,这个基本上你 Google 一搜索能搜索到 90% 的网站都是这个例子,而且还强调用“$binary_remote_addr”可以节省内存之类的废话

4 X% G, ?5 G: q$ l5 @

经过多层CDN之后取得原始用户的IP地址Nginx 配置取得用户的原始地址map $http_x_forwarded_for $clientRealIp { / e, z* n; f g5 s. c J ## 没有通过代理,直接用

: l1 T1 |* o. X E7 d; T

' T+ ?) Z& x, g9 m8 U- w remote_addr "" $remote_addr;$ i; [: E& i t/ }* R, C0 R ## 用正则匹配,从 x_forwarded_for 中取得用户的原始IP ## 例如 X-Forwarded-For: 202.123.123.11, 208.22.22.234, 192.168.2.100,...

+ k9 n# Z! `1 y0 Z

## 这里第一个 202.123.123.11 是用户的真实 IP,后面其它都是经过的 CDN 服务器! ~6 i8 ]% j- J( Y' `& e( M ~^(?P[0-9\.]+),?.*$ $firstAddr;# K5 J/ M7 F$ s) l, ^* [ }9 W2 j, K3 s, b# h1 ?

4 `+ ~5 w+ }/ _% W8 ]& z' Q/ a2 K

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

3 z3 r' K( a5 V |" B

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

; A5 j0 ^, {/ h9 l9 z# N

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

$ q* {, J7 ], W+ d1 v* ~

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

3 a, k# i; a4 M0 ~$ [+ k1 q

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

# b' A _9 D" g$ I: {

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

# V2 }1 w% W1 A# ]; f4 {) F2 O9 i' N

zone=ConnLimitZone burst=5 nodelay;}}

3 v! E! |) _& ]& R# S; r5 r/ D! h 5 p( K) F. j2 k- h: j; q2 c& g; k! v% K7 _; n & ]" ~ L" ~; K! `: p2 K4 b 1 y( v ^+ S* E% V8 ^+ v. ^

暂时无法加载帖子列表

回复

使用道具 举报

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 | 显示全部楼层
刚好遇到类似问题,看完这个帖子心里有底了
回复

使用道具 举报

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

    本版积分规则

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

    GMT+8, 2026-9-13 06:22 , Processed in 0.040164 second(s), 25 queries , Gzip On.

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

    Powered by Discuz! X3.5

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