51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

Nginx 防攻击安全配置

基础配置

隐藏版本号

经常会有针对某个版本的nginx安全漏洞出现,隐藏nginx版本号就成了主要的安全优化手段之一,当然最重要的是及时升级修复漏洞。

http {
    server_tokens off;
}
Header头设置

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

  • X-Frame-Options:响应头表示是否允许浏览器加载frame等属性,有三个配置DENY禁止任何网页被嵌入,SAMEORIGIN只允许本网站的嵌套,ALLOW-FROM允许指定地址的嵌套
  • X-XSS-Protection:表示启用XSS过滤(禁用过滤为X-XSS-Protection: 0),mode=block表示若检查到XSS攻击则停止渲染页面
  • X-Content-Type-Options:响应头用来指定浏览器对未指定或错误指定Content-Type资源真正类型的猜测行为,nosniff 表示不允许任何猜测

例如一个.jpg的图片文件被恶意嵌入了可执行的js代码,在开启资源类型猜测的情况下,浏览器将执行嵌入的js代码,可能会有意想不到的后果

add_header X-Frame-Options SAMEORIGIN; 
# 禁止嗅探文件类型
add_header X-Content-Type-Options nosniff; 
add_header X-XSS-Protection "1; mode=block";
开启HSTS统一https访问
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
账号认证
server {
    location / {
    auth_basic "please input user&passwd";
    auth_basic_user_file key/auth.key;
    }
}
限制请求方法

$request_method能够获取到请求nginxmethod。这里配置只允许GET/POST方法访问,其他的method返回405

if ($request_method !~ ^(GET|POST)$ ) {
    return 405;
}
拒绝指定User-Agent

可能有一些不法者会利用wget/curl等工具扫描我们的网站,我们可以通过禁止相应的user-agent来简单的防范
Nginx的444状态比较特殊,如果返回444那么客户端将不会收到服务端返回的信息,就像是网站无法连接一样

#禁止Scrapy等工具的抓取
if ($http_user_agent ~* (Scrapy|Curl|HttpClient)) {
     return 444;
}
#禁止指定UA及UA为空的访问
if ($http_user_agent ~ "WinHttp|WebZIP|FetchURL|node-superagent|java/|FeedDemon|Jullo|JikeSpider|Indy 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/0.1|YandexBot|FlightDeckReports|Linguee Bot|^$" ) {
     return 444;             
}
图片防盗链
location /images/ {
    valid_referers none blocked www.lolicp.com lolicp.com;
    if ($invalid_referer) {
    return 403;
    }
}

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

当然你也可以给不符合referer规则的请求重定向到一个默认的图片,比如下边这样

location /images/ {
    valid_referers blocked www.lolicp.com lolicp.com
    if ($invalid_referer) {
    rewrite ^/images/.*.(gif|jpg|jpeg|png)$ /static/qrcode.jpg last;
    }
}

限制并发及请求数

网站安全配置(Nginx)防止网站被CC攻击(包括使用了CDN加速之后的配置方法)

Nginx 有 2 个模块用于控制访问"数量"和"速度"。

简单的说,控制你最多同时有 多少个访问,并且控制你每秒钟最多访问多少次, 你的同时并发访问不能太多,也不能太快,不然就"杀无赦"。

  • HttpLimitZoneModule 限制同时并发访问的数量
  • HttpLimitReqModule 限制访问数据,每秒内最多几个请求

现在我们面对的最直接的问题就是, 经过这么多层加速,我怎么得到"最前面普通用户的 IP 地址"呢?

当一个 CDN 或者透明代理服务器把用户的请求转到后面服务器的时候,这个 CDN 服务器会在 Http 的头中加入 一个记录

X-Forwarded-For : 用户IP, 代理服务器IP

X-Forwarded-For : 用户IP, 代理服务器1-IP, 代理服务器2-IP, 代理服务器3-IP, ....

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

标准配置

Nginx 里面设置一个限制,配置如下:

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

用户的 IP 地址 $binary_remote_addr 作为 Key,每个 IP 地址每秒处理 10 个请求
--------------------------------------------------------



你想用程序每秒几百次的刷我,没戏,再快了就不处理了,直接返回 503 错误给你
---------------------------------------



limit_req_zone $binary_remote_addr zone=ConnLimitZone:10m  rate=10r/s;
limit_req_log_level notice;


具体服务器配置
-------


`server {
listen   80;
location ~ .php$ {
# 最多 5 个排队, 由于每秒处理 10 个请求 + 5个排队,你一秒最多发送 15 个请求过来,再多就直接返回 503 错误给你了
limit_req zone=ConnLimitZone burst=5 nodelay;
fastcgi_pass   127.0.0.1:9000;
fastcgi_index  index.php;
include fastcgi_params;
}`
`
}`

这样一个最简单的服务器安全限制访问就完成了,这个基本上你 Google 一搜索能搜索到 90% 的网站都是这个例子,而且还强调用"$binary_remote_addr"可以节省内存之类的废话

经过多层CDN之后取得原始用户的IP地址Nginx 配置

取得用户的原始地址

map $http_x_forwarded_for  $clientRealIp {
        ## 没有通过代理,直接用 remote_addr
    ""  $remote_addr;  
        ## 用正则匹配,从 x_forwarded_for 中取得用户的原始IP
        ## 例如   X-Forwarded-For: 202.123.123.11, 208.22.22.234, 192.168.2.100,...
        ## 这里第一个 202.123.123.11 是用户的真实 IP,后面其它都是经过的 CDN 服务器
    ~^(?P<firstAddr>[0-9\.]+),?.*$  $firstAddr;
}

通过 map 指令,我们为 nginx 创建了一个变量 $clientRealIp ,这个就是 原始用户的真实 IP 地址,
--------------------------------------------------------------


`不论用户是直接访问,还是通过一串 CDN 之后的访问,我们都能取得正确的原始IP地址`
根据用户的真实 IP 做连接限制

下面是修改之后的 Nginx 配置:

CDN环境下 Nginx 的安全配置Shell

## 这里取得原始用户的IP地址
map $http_x_forwarded_for  $clientRealIp {
    ""  $remote_addr;
    ~^(?P<firstAddr>[0-9\.]+),?.*$  $firstAddr;
}

针对原始用户 IP 地址做限制
---------------



limit_conn_zone $clientRealIp zone=TotalConnLimitZone:20m ;
limit_conn  TotalConnLimitZone  50;
limit_conn_log_level notice;


针对原始用户 IP 地址做限制
---------------



limit_req_zone $clientRealIp zone=ConnLimitZone:20m  rate=10r/s;
#limit_req zone=ConnLimitZone burst=10 nodelay;
limit_req_log_level notice;


具体服务器配置
-------



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


        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        include fastcgi_params;
    }   



`}`

防止SSL证书泄露源IP

由于开启https默认需要证书文件,但如使用域名的证书文件没有对外来IP进行限制则可能导致源站IP泄露。

修改配置文件

在nginx配置文件http或server中添加如下配置:

目测不支持泛域名证书!

# 禁止指定域名外证书访问
ssl_reject_handshake on;
指定默认空证书

crt内容:

-----BEGIN CERTIFICATE-----
MIIDCDCCAfACCQDOSkjmus+IgTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJD
TjEVMBMGA1UEBwwMRGVmYXVsdCBDaXR5MQ0wCwYDVQQKDAR5bWNjMRAwDgYDVQQD
DAcwLjAuMC4wMCAXDTIxMDgyNjA2MjUxNVoYDzQ3NTkwNzIzMDYyNTE1WjBFMQsw
CQYDVQQGEwJDTjEVMBMGA1UEBwwMRGVmYXVsdCBDaXR5MQ0wCwYDVQQKDAR5bWNj
MRAwDgYDVQQDDAcwLjAuMC4wMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
AQEAswXEeBnamJKUKXWY20OJQNww1Pqo8U8z7Q3ywnygS0ClL6SyjPaaOpQDieIk
x+UJhq5BsLb9eu0RLJvaXnk6OSsaFwleJ1jxsTNebhwTfZ6QULMCllIHFHkUOtWm
M6QWKmrQSS4CSToPQp2sy/b9tq8CwdlzUAmJ1o8wPKrmOZbwK5h8pnR5yZ/YZyj2
6Z6QO3syce7l2zxMJsBL1RWYWPVvEygJqJRlVLJ6ARmWrysbx1yvFtpr4co/4+Kp
k8gqRGuQzSe7P9dTtvqPdulPPzRrQiaBHbKMhvgLrwbZVoHJ2Y2Zjv3T1muvDlm8
oXMJGIy28i/TY2OvsbdI6A6OxwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQApIn7T
0KF2vIdE2sDZ1aVGyczVK4EZ4uOqthEr34jFBwX3nq8vpFnEcTiHl5F29nRGrfS2
o+CMiluleynUdKdnMSKt5gjIc1YZWon5amUSgyasjvMCmTgQa3NHRBuKlxjCmh/W
Yn77P+id5RkQe+yMD3e0lhABEMfs6F+/Xqbc6Jipdz3Bbs+wzjO75bInVRDtcQM8
pgAUDLQQ23UNR3XCmAc6vmN2QxtNtftuANDKm5ms4Ld0q0z+v1Ss2yVO5xiSteOV
IHmv5EfhjrErbo9JFOF5EAsM6pgsoQ5S7YoDRvvrcEs8FBmUJkf46dkVvfsp/r3H
aIjET7vAsEudiJUc
-----END CERTIFICATE-----

key内容:

-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAswXEeBnamJKUKXWY20OJQNww1Pqo8U8z7Q3ywnygS0ClL6Sy
jPaaOpQDieIkx+UJhq5BsLb9eu0RLJvaXnk6OSsaFwleJ1jxsTNebhwTfZ6QULMC
llIHFHkUOtWmM6QWKmrQSS4CSToPQp2sy/b9tq8CwdlzUAmJ1o8wPKrmOZbwK5h8
pnR5yZ/YZyj26Z6QO3syce7l2zxMJsBL1RWYWPVvEygJqJRlVLJ6ARmWrysbx1yv
Ftpr4co/4+Kpk8gqRGuQzSe7P9dTtvqPdulPPzRrQiaBHbKMhvgLrwbZVoHJ2Y2Z
jv3T1muvDlm8oXMJGIy28i/TY2OvsbdI6A6OxwIDAQABAoIBAEqLykYgre/+iYfC
GkajltHVXtgxEIx7aKn7tuzZrH3pi1+Ne3RLc+mUnOybqKk8bH0SrvQBHwhDE3W5
6HKSlHYdxp11HynPVcVuGJJNSqhykLGp+RfTTHNv/8aIFM9IMpqzI8x1Ripr7NLW
iY/dZ8Tcl49VFzlq32Ti9zksCPZNerjYEb6AOzYooV2j3GNR/M4/KbckRZALN/AF
vy8BPxTEl9tyIjvCfmG7mtWJX6z6fAS0TwuF9J4Aw7ZfznITKz1hzNOpuogca1tj
bhKlc2Jage9U/sGCWxX+CHMiEOuiLi42qKPsqLihsJc4a1DLgF3J6z826EVPAcFn
3vjHEcECgYEA7RTsgZ2JTU8Hoi9DTB1Fqm/3fnu6/jFk6jZDKRNpj/STp8Lu65j9
Mt1+dXCtdKrkJBH/3nhOWbwo+/D5g9rwFNT+ysZEhG+FAwHjHnBi7hBedp1MBZ98
sXXbi7aBLEX/APypp7QBZ95ghA87uvPOhM0TRsX3iKQXsMCRMQa3HpECgYEAwU7R
QQwW7ZsI3CktORyMhyj3LhiOGndsB5wyUpKKCUYV04ukBe9GzZB+ZtNvtHcdU5wR
rXsPUx5IAEjOH4gpZvxx6YdSv8YbPJQB+8QFIbb9Ft3JJV+LMixJQrQmjhLKGUCB
ftLQBq64Ux5m3vobTasK4tA2WHqGLxR66QbdM9cCgYA9xsb920PsvhwaGcCqc7I0
gCp4bdtC4zINiYgkiudl2HAlNbk18M6BU4/hIDRCg0khUQNgP+8CmPIA/EC4J/OJ
KhseUV2HONvq9bHtu5E7wU4sED6/9Ff0keZcWHj+RVr2MeAvT8tR+nMh1ipVQ7Rb
jGhqd6lRlJiLuRHcOYi70QKBgHmMDZdQ+rm8Wf3VBlJ62QHDiGi7l96caJkAZcP1
0EW0g9TYYPI6WdK3oEMXf42BuDbyU0s5rZEd4TgMj07UVvQil523MRjUgBu/FOAx
iOiCHvFZ0zhksymBHy+KBxQeTGVEYihUdek9wzjATP63VKOpgNbNBN7ta6H+xqnv
XvdRAoGBAJVe7OJM2xwdcS1PvHJI6hECrogO4IiXeU9ZkuEUw2R1RRAs4tSJRBKI
n3RjPUueoEOIvcpMUFnCY17x64AZwcyYljep6WX4Ow6Z7UczEkVi0+KIg0oV+3kq
t020yVaJMbEqAYa4J95ifEyqFHVstqsJK8OauQ1BdT41W/kJojDb
-----END RSA PRIVATE KEY-----
赞(0)
未经允许不得转载:工具盒子 » Nginx 防攻击安全配置