写在前面的话

nginx 中主要的内容在前面的章节其实已经差不多了,接下都是一些小功能的实现以及关于 nginx 的优化问题。我们一起来探讨以下,如何把我们的 nginx 打造成为企业级应用。

安全优化:隐藏版本号和服务名称

我们在使用 curl 命令请求 nginx 的时候,甚至我们在访问出现 404 的时候,都会打印出我们的服务名称/版本号,如图:

WEB 访问:

这肯定是不好的,知道了版本号意味着黑客就能通过指定版本的漏洞对我们的服务器进行攻击,甚至知道了你是啥服务也能够针对性攻击,如果是小漏洞还好,如果是大漏洞就炸穿。

解决办法如下:

修改 /data/services/nginx/conf/fastcgi.conf:

fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;

该配置就是 curl 那里显示的 nginx/1.16.0,我们只需要把这个改成想要字符:

fastcgi_param  SERVER_SOFTWARE    apache;

并且在主配置文件中加入配置:

...
http {
server_tokens off;
...
}
...

比如我们把它改成 apache 后重载配置:

WEB 访问:

此时发现版本号确实被我们隐藏,但是服务器类型并没有因为我们改为 apache 而成功。

如果像修改服务器名称,则需要修改源码包中的:

1. 修改 /data/packages/nginx/nginx-1.16.0/src/core/nginx.h

2. 修改 /data/packages/nginx/nginx-1.16.0/src/http/ngx_http_header_filter_module.c

3.修改 /data/packages/nginx/nginx-1.16.0/src/http/ngx_http_special_response.c

由于我们并不是添加插件或者编译参数,所以回到 nginx 源码根目录直接编译:

# 编译
cd /data/packages/nginx/nginx-1.16.0
make # 备份
mv /data/services/nginx/sbin/nginx /data/backup/nginx/nginx_$(date +%F) # 更新
cp /data/packages/nginx/nginx-1.16.0/objs/nginx /data/services/nginx/sbin/ # 查看
/data/services/nginx/sbin/nginx -V

此时可以看到我们查了 nginx 的信息为:

重载配置,curl 测试:

访问错误页面:

可以看到我们第三步删除了默认网页中输出的那行代码,直接隐藏了服务器信息。这才是我们想要的。

安全优化:连接限制

大流量攻击一直就是互联网中比较常见的一种攻击,最为简单的就是黑客使用同一 IP 风控的对服务器发起请求或者传输文件导致服务器带宽被耗尽,进而影响正常用户的使用。

针对这样类似的攻击,nginx 是提供了 limit 模块用于对用户请求进行约束的。

也就是模块:http_limit_conn_module(默认编译)

参数 说明
limit_conn_zone

描述会话状态存储区域,只能在 http 段

配置段:http

语法:limit_conn_zone $variable zone=name:size;

limit_zone 和 limit_conn_zone 同等意思,已被弃用
limit_conn_log_level

当达到最大限制连接数后,记录日志的等级

配置段:http, server, location

语法:limit_conn_log_level info | notice | warn | error

limit_conn

指定每个给定键值的最大同时连接数,当超过时返回 503

配置段:http, server, location

语法:limit_conn zone_name number

limit_conn_status

指定当超过限制时,返回的状态码,默认是 503

配置段:http, server, location

语法:limit_conn_status code;

limit_rate

对每个连接的速率限制。参数 rate 的单位是字节/秒,设置为 0 将关闭限速

配置段:http, server, location, if in location

语法:limit_rate rate

所谓的限制网速,其实质就是限制该 IP 每个线程的网速

另外需要补充几点:

1. 使用 limit_conn_zone 如:limit_conn_zone $binary_remote_addr zone=addr:10m;

说明:$binary_remote_addr 变量的固定长度是 4 个字节,我们定义了一个叫 addr 的空间,并给了这个空间 10M 的共享内存。如果是 32 位的平台上,1M 共享内存能够保存 3.2 万个 $binary_remote_addr 产生的存储状态,64 位则为  1.6 万。如果访问量过多导致超出了这个共享内存,新的访问则会被返回 503 错误。

2. 使用 limit_conn 来限制每个 IP 的并发,例如限制每个 IP 只能有一个活动连接:

limit_conn_zone $binary_remote_addr zone=client_addr:10m;
server {
location / {
limit_conn client_addr 1;
}
}

3. 我们也可以限制限制单个 IP 的活动连接数的同时也限制单个虚拟主机的总连接数:

limit_conn_zone $binary_remote_addr zone=client_addr:10m;
limit_conn_zone $server_name zone=server_addr:10m;
server {
location / {
limit_conn client_addr 10;
limit_conn server_addr 100;
}
}

比如这样允许每个 IP 开 10 个连接,总共支持 100 个连接。

说了这么多,我们来做做限制测试:limit-demo.conf

limit_conn_zone  $binary_remote_addr zone=client_addr:10m;
limit_conn_zone $server_name zone=server_addr:10m; server {
listen 10003;
server_name localhost; location ^~ /download {
charset utf-8;
alias /data/files/share; # 限制
limit_conn client_addr 2;
limit_conn server_addr 2;
limit_rate 200k; autoindex on;
autoindex_exact_size on;
autoindex_localtime on; if ($request_filename ~* ^.*?\.(txt|log|pdf|doc|docx|xls|xlsx|ppt|pptx|rar|zip|tar.gz|tar.xz|bz2|iso)$ ) {
add_header Content-Disposition attachment;
}
} }

我们允许每个 IP 开两个连接,且服务器只支持 2 个连接,限速每个连接下载速率 200K。

访问测试:

点击两个下载:

可以看到限速到了 200K 每秒的下载速度!

此时已经占用了两个连接,我们刷新页面:

发现无法处理第三个请求,报错 503!

我们去其它服务器上面下载:

还是报错 503,因为我们只支持 2 个连接!你要是想使用只能等着别人处理完断开。

安全优化:请求限制

上文中的限制下载,请求数能够满足我们的一部分需求,但是某些时候我们还要一些特殊的需求,比如限制服务器每秒钟只能处理多少请求,请求的处理速率问题,这就需要另外一个限制模块。

一次性限制连接池终究还是太狠了点,我们换一种更加温柔的方式来进行限制,直接让请求者每秒钟只能请求处理这么多次。

模块:http_limit_req_module(默认编译)

参数 说明
limit_req_zone

设置一块共享内存限制域用来保存键值的状态参数。

配置段:http

语法:limit_req_zone $variable zone=name:size rate=rate;

limit_req_log_level

设置日志级别。

配置段:http, server, location

语法:limit_req_log_level info | notice | warn | error;

limit_req_status

设置拒绝请求的响应状态码,默认 503。

配置段:http, server, location

语法:limit_req_status code;

limit_req

设置对应的共享内存限制域和允许被处理的最大请求数阈值。

配置段:http, server, location

语法:limit_req zone=name [burst=number] [nodelay];

配置说明:

1. limit_req_zone 和前面的配置类似,定义共享内存空间,但是相对于 limit_conn_zone 多了处理速度,比如:

limit_req_zone $binary_remote_addr zone=req_client_addr:10m rate=1r/s;

在添加 rate,但是必须是整数,所以 2 秒处理一个只能写为 30r/m。

2. limit_req 的使用我们举个例子,限制每秒处理请求不超 1 个,且排队的不超过 5 个。

limit_req_zone $binary_remote_addr zone=req_client_addr:10m rate=1r/s;
server {
location / {
limit_req zone=req_client_addr burst=5;
}
}

如果希望超过的请求不被延迟,可以在最后加 nodelay 参数:

limit_req zone=req_client_addr burst=5 nodelay;

我们做个测试验证一下:req-limit-demo.conf

limit_req_zone  $binary_remote_addr zone=req_client_addr:10m rate=6r/m;

server {
listen 10004;
server_name localhost; location ^~ /download {
charset utf-8;
alias /data/files/share; # 限制
limit_req zone=req_client_addr burst=2; fancyindex on;
fancyindex_exact_size on;
fancyindex_localtime on; if ($request_filename ~* ^.*?\.(txt|log|pdf|doc|docx|xls|xlsx|ppt|pptx|rar|zip|tar.gz|tar.xz|bz2|iso)$ ) {
add_header Content-Disposition attachment;
}
}
}

我们配置每个来源 IP 处理速率为 10 秒一个请求,访问测试:

连续刷新:

可以看到请求卡住了,需要等待几秒钟。准确其实是 10 秒。

放在 linux 上面测试:

while true; do curl -I http://192.168.100.111:10004/download/;done

请求结果:

可以看到两次请求成功的时间间隔 10 秒,这里就很准确了。

同时我们在这台机器上面再新开两个窗口允许同样的请求,再度运行这个命令会发现也会继续执行。

但是当我门总共开到第三个窗口运行这个命令的时候:

由于是死循环,所以疯狂的返回 503,这就是我们配置 burst 的作用。

我们加上 nodelay 参数,然后使用新命令访问:

while true; do curl -I http://192.168.100.111:10004/download/; sleep 1;done

我们每秒请求一次:

可以发现,请求立即返回,因为 burst 的原因,前 3 个请求都完全没问题,到第 4 个也就是第 4 秒的时候返回 503,后面几个 503 之后会重新 200,如此循环。

这就是 nodelay 的作用,直接返回,不去等待。

安全优化:访问控制

我们这里所说的访问控制其实就是来源的 IP,在 nginx 我们可以设置类似白名单这样的东西,只允许某些 IP 或者网段访问或者拒绝访问。

这其实是我们针对攻击者最狠的方式,直接禁止他的 IP 访问我们的服务。

同样,在内网中或者外网中,我们只希望某些人能够访问,也能进行 IP 限制来解决。

相对来说,这是一个非常非常实用的功能,依赖于:ngx_http_access_module 模块,默认安装

主要就两个参数:

参数 说明
allow

允许某个 ip 或者一个 ip 段访问,如果指定 unix: ,那将允许 socket 的访问。

配置段:http, server, location, limit_except

语法:allow address | CIDR | unix: | all;

deny

和 allow 相反。

配置段:http, server, location, limit_except

语法:deny address | CIDR | unix: | all;

具体格式如下:

location / {
deny 192.168.1.1;
allow 192.168.1.0/24;
allow 10.1.1.0/16;
allow 2001:0db8::/32;
deny all;
}

测试新增配置:allow-deny-demo.conf

server {
listen 10005;
server_name localhost;
default_type text/html; location / {
allow 192.168.100.112;
deny all;
root /data/www/demo-80;
index index.html index.htm;
}
}

使用 112 机器访问:

使用 113 访问:

安全优化:限制白名单

nginx 的白名单的实现依赖于:http_geo_module 和 http_map_module 模块,这两个模块都是默认安装的。

我们添加配置:whitelist-demo.conf

geo $remote_addr $grant {
default 1;
127.0.0.1 0;
192.168.100.112 0;
} server {
listen 10007;
server_name localhost;
location ^~ /download {
alias /data/files/share;
charset utf-8;
fancyindex on;
fancyindex_exact_size off;
fancyindex_localtime on; if ( $grant = 1 ){
return 403;
} if ($request_filename ~* ^.*?\.(txt|log|pdf|doc|docx|xls|xlsx|ppt|pptx|rar|zip|tar.gz|tar.xz|bz2|iso)$ ) {
add_header Content-Disposition attachment;
}
}
}

说明:

1. 我们对来源的用户 IP 进行映射,如果为 1,则返回 403,则默认不在白名单的都为 1。

2. 在 location 中对来源的映射值进行判断,返回 403。

访问测试:

不在白名单的服务器:

访问测试配置完成!

修改配置:whitelist-demo.conf 实现限速白名单

geo $whiteiplist {
default 1;
127.0.0.1 0;
192.168.100.112 0;
} map $whiteiplist $limit {
1 $binary_remote_addr;
0 "";
} limit_conn_zone $limit zone=list_client_addr:10m; server {
listen 10007;
server_name localhost;
location ^~ /download {
alias /data/files/share;
charset utf-8;
fancyindex on;
fancyindex_exact_size off;
fancyindex_localtime on; limit_conn list_client_addr 1;
if ( $limit != "" ) {
limit_rate 200k;
}
if ($request_filename ~* ^.*?\.(txt|log|pdf|doc|docx|xls|xlsx|ppt|pptx|rar|zip|tar.gz|tar.xz|bz2|iso)$ ) {
add_header Content-Disposition attachment;
}
}
}

简单的说明:

1. 使用 geo 生成了一个 list,我们给 list 中的每项赋值为 0 或者 1,且默认设置为 1。

2. 通过 map 建立 0 和 1 的对应关系,0 代表 $binary_remote_addr,1 则为 ""。所以上面的 default 其实就是 $binary_remote_addr。

3. 我们做了 limit_conn 的限制,这次给的键的名称不是单独的某个变量,而是 map 定义的映射关系。

4. 整体配置的意思是:在 geo 定义的列表中,我们默认所有限速,如果不限速,将 IP 加入 geo 列表并赋值为 0。这就是白名单。

在很多资料中我们会看到:limit_conn_zone 和 limit_req_zone 指令对于键为空值的将会被忽略

但是在我这个版本中一直没有成功,所有我在外层多了个 if 判断。

访问测试白名单中的机器:

访问不在白名单的机器:

小结

这部分内容是进行 nginx 安全优化的重点,平时可能不起作用,但是生效都是大作用。

【08】Nginx:安全优化 / 信息隐藏 / 请求限制 / 白名单的更多相关文章

  1. Nginx基础优化

    Nginx基础优化 1.隐藏nginx header版本号 1.1查看版本号 [root@Nginx ~]# curl -I http://www.yunwei.cn HTTP/1.1 200 OK ...

  2. nginx的优化和防盗链

    nginx的优化和防盗链 目录 nginx的优化和防盗链 一.nginx的优化 1. 隐藏版本号 (1)隐藏版本号的原因 (2)查看版本号的方法 (3)隐藏方法一:修改配置文件 (4)隐藏方法二:修改 ...

  3. Nginx优化之基本安全优化 (隐藏Nginx软件版本号信息,更改源码隐藏Nginx软件名及版本号,更改Nginx服务的默认用户)

    一,隐藏Nginx软件版本号信息 查看版本号 curl -I 192.168.0.220 HTTP/1.1 200 OK Server: nginx/1.6.2 #这里清晰的暴露了Web版本号(1.6 ...

  4. Nginx修改版本信息或隐藏版本号

    一,隐藏版本号.首先说明,这个是某一方面隐藏,不是彻底隐藏.未隐藏之前查看nginx信息: 隐藏方法: 修改nginx.conf配置文件,在http { } 标签里边加入字段: server_toke ...

  5. The server of Nginx(三)——Nginx企业级优化

    相信看过我之前apache文章的朋友们,对服务优化也有了一个大概的了解,相比较而言,Nginx企业中应用的更多一些,因此今天也会详细阐述Nginx的优化,有人说,服务器不需要优化,开虚拟化,分分钟成倍 ...

  6. Nginx服务优化及优化深入(配置网页缓存时间、日志切割、防盗链等等)

    原文:https://blog.51cto.com/11134648/2134389 默认的Nginx安装参数只能提供最基本的服务,还需要调整如网页缓存时间.连接超时.网页压缩等相应参数,才能发挥出服 ...

  7. [Nginx] – 性能优化 – 配置文件优化

    Nginx基本安全优化 1.调整参数隐藏Nginx版本号信息     一般来说,软件的漏洞都和版本有关,因此我们应尽量隐藏或清除Web服务队访问的用户显示各类敏感信息(例如:Web软件名称及版本号等信 ...

  8. Nginx软件优化【转】

    转自 Nginx软件优化 - 惨绿少年 - 博客园 Nginx软件优化 - 惨绿少年 - 博客园 https://www.cnblogs.com/clsn/p/8484559.html 1.1 Ngi ...

  9. Nginx软件优化

    1.1 Nginx优化分类 安全优化(提升网站安全性配置) 性能优化(提升用户访问网站效率) 1.2 Nginx安全优化 1.2.1 隐藏nginx版本信息优化 官方配置参数说明:http://ngi ...

随机推荐

  1. 2018-12-25-win10-uwp-通知列表

    原文:2018-12-25-win10-uwp-通知列表 title author date CreateTime categories win10 uwp 通知列表 lindexi 2018-12- ...

  2. ASP.NET Core框架深度学习(二) 管道对象

    4.HttpContext 第一个对象 我们的ASP.NET Core Mini由7个核心对象构建而成.第一个就是大家非常熟悉的HttpContext对象,它可以说是ASP.NET Core应用开发中 ...

  3. 20个Python代码段,你需要立刻学会,好用到哭!

    Python是一种非BS编程语言.设计简单和易读性是它广受欢迎的两大原因.正如Python的宗旨:美丽胜于丑陋,显式胜于隐式. 记住一些帮助提高编码设计的常用小诀窍是有用的.在必要时刻,这些小诀窍能够 ...

  4. 新手教程丨利用Python制作一款截图识别软件!

    进入正文前给大家推荐一个微软开发的工具:Snipaste. 这是一款截图软件,把截出的图片放置到窗口上,可以随意移动,使用非常方便,并且支持各类电脑系统. 先简单介绍一下它的用法,F1截图,Ctrl+ ...

  5. SparkStreaming整合flume

    SparkStreaming整合flume 在实际开发中push会丢数据,因为push是由flume将数据发给程序,程序出错,丢失数据.所以不会使用不做讲解,这里讲解poll,拉去flume的数据,保 ...

  6. REST API的使用

    需求描述 GET: http://localhost:8080/MyWebsite/user/ Header: Content-Type = application/json Body: 空 Resp ...

  7. Troubleshooting ORA-30013 Error (Doc ID 1578717.1)

    Troubleshooting ORA-30013 Error (Doc ID 1578717.1) APPLIES TO: Oracle Database - Enterprise Edition ...

  8. CentOS7使用docker搭建Solo博客

    一.获取最新镜像 docker pull b3log/solo 二.启动容器 使用 MySQL 先手动建库(库名 solo,字符集使用 utf8mb4,排序规则 utf8mb4_general_ci) ...

  9. day65_10_9vue循环指令与组件

    一.v-once v-once指令赋值给标签后,这个标签中的所有变量都不能被更改,只能被渲染一次.之后的改动不能改变该标签中的值: <div id="app"> < ...

  10. 日常学习python

    一.条件语句 Python条件语句是通过一条或多条语句的执行结果(True或者False)来决定执行的代码块. 可以通过下图来简单了解条件语句的执行过程: Python程序语言指定任何非0和非空(nu ...