安全开发运维必备的Nginx代理Web服务器性能优化与安全加固配置
部署的项目,用户想要只输入网址就能访问,但实际的情况是,网站需要属于项目名称和端口号才能访问,那么解决的办法有两种:
一、修改tomcat配置
1修改context ,配置默认的项目名称,使不用输入项目名称
修改conf文件夹下的serverxml文件
path:是指web项目的访问URL路径,设置为空
docBase:项目所在的文件
2修改端口,将端口号改为80
80 端口是HTTP开放的,是浏览网页服务默认的端口号,所以可以达到只输入网址不用输入端口号就可以访问的目的
二、用nginx代理,来修改网站域名(因为客户机器80端口,没有被占用,但是tomcat启动不起来,不知道原因)
1修改tomcat ,使其能够通过localhost加端口访问
2修改naginx 的配置
将proxy_pass 改为自己网站访问的网址
将listen监听端口改为80
ok,该方法经过验证是可行的
我用的springmvc框架,可以在controller层通过
String ipFromNginx = getHeader(request, "X-Real-IP");
来获取真正ip
Nginx的配置指令执行不是按照配置的先后顺序执行,二十分为11 个阶段post-read、server-rewrite、find-config、rewrite、post-rewrite、preaccess、access、post-access、try-files、content 以及 log , Nginx配置文件中的所有指令是按照上面11个阶段的顺讯执行。
set_real_ip_from的值可以是一个ip,也可以是一个ip段,表示当请求是某一个ip时,使用real_ip_header的值替换 realip_remote_addr 和 realip_remote_port中。
运行命令
查看日志其中的remote_addr 已经改为 192222,而 $realip_remote_addr 是127001。 当Header IP是非法的IP地址,则remote_addr 不改变。
注意 real_ip_header 的默认值为 X-Real-IP
下面我们着重看一下 real_ip_recursive(默认值为off)
1) real_ip_header 的http header中仅有一个ip时,则直接替换remote_addr。
2) real_ip_header 的http header 中有多个ip时
- real_ip_recursive 为off时, 则用第一个ip替换remote_addr
- real_ip_recursive 为on时, 则用第一个不在set_real_ip_from 的ip替换remote_addr
例如nginx配置如下:
请求命令为
remote_addr 被替换为 19216823 (注意这里的顺序是从右至左)。当real_ip_recursive为off时 remote_addr被替换为 19217822
例如nginx有以下配置
访问/first之后,日志中输出 Hello world; 这是因为 set $b "Hello"; 定义在server模块下,所以在server-rewrite阶段已经执行。所以在location块中定义的才能执行的结果才是正确的。
后面再rewrite阶段会详细讲解这几个命令。
下面我们详细看一下ngx_rewrite中的7个指令:
1) rewrite (基本语法: rewrite regex replacement [flag]; 可以配置在server,location和if配置块下)
regex是RCPE风格的,如果regex匹配URI,nameURI就会被替换成replacement,replacement就是新的URI,如果同一个配置块下有多个rewrite配置指令,匹配并不会终止,而是继续用新的URI(也就是上一次匹配到的replacement)继续进行匹配,直至返回最后一个匹配。如果在匹配到之后想要停止匹配直接返回,可是使用flag参数(将其设置为break)。
注意 : 如果匹配到replacement中有关于协议的东西,例如http://或者https://等,处理将终止,直接返回客户端302(Temporary redirect)。
如果Nginx返回给客户端30x,浏览器在接收到这个状态码时,会根据response中的Location响应头再发起一次请求;如果不是30x状态码,所有的跳转只是在nginx内部完成,有兴趣的可以将nginx的日志调为debug看一下整个跳转过程。
举一个例子
当请求 curl -I http://localhost:8080/first 时,nginx接到请求之后,匹配到/first 根据第一个rewrite指令,将URI替换为/test, 然后继续执行第二个rewrite指令,将URI替换为/indexhtml,之后继续执行第三个指令,返现regex(/test)与新的URI(/indexhtml)并不匹配,所以最终我们将会看到indexhtml的返回结果。开启debug日志,可以看到详细的跳转过程。
再举一例
当请求 curl -I http://localhost:8080/first 时,首先会执行server块下的rewrite,所有请求都返回302 (Location: https://127001:8080/first )。
下面讲一下rewrite的第三个参数flag:
11 ) last
如果有last参数,那么停止处理任何rewrite相关的指令,立即用替换后的新URI开始下一轮的location匹配。
12) break
停止处理任何rewrite的相关指令,就如同break 指令本身一样。
last的break的相同点在于,立即停止执行所有当前上下文的rewrite模块指令;不同点在于last参数接着用新的URI马上搜寻新的location,而break不会搜寻新的location,直接用这个新的URI来处理请求,这样能避免重复rewite。因此,在server上下文中使用last,而在location上下文中使用break。
13) redirect
replacement 如果不包含协议,仍然是一个新的的URI,那么就用新的URI匹配的location去处理请求,不会返回30x跳转。但是redirect参数可以让这种情况也返回30x(默认302)状态码,就像新的URI包含http://和https://等一样。这样的话,浏览器看到302,就会再发起一次请求,真正返回响应结果的就是这第二个请求
14) permanent
和redirect参数一样,只不过直接返回301永久重定向
虽说URI有了新的,但是要拼接成完整的URL还需要当前请求的scheme,以及由server_name_in_redirect和port_in_redirect指令决定的HOST和PORT
还有一个比较有意思的应用,就是如果replacement中包含请求参数,那么默认情况下旧URI中的请求参数也会拼接在replacement后面作为新的URI,如果不想这么做,可以在replacement的最后面加上。
2) break (基本语法: break; 可以配置在server,location 和if配置块下)
停止任何处理rewrite的相关指令。如果出现在location里面,name所有后面的rewrite模块都不会执行,也不发起内部重定向,而是直接用新的URI处理请求。
例如有如下配置
访问 curl -I http://localhost:8080/server/break ,将返回404;
请求 curl -I http://localhost:8080/server/last 将返回indexhtml
访问 curl -I http://localhost:8080/hello ,将返回 404;
请求 curl -I http://localhost:8080/hello1 ,将返回indexhtml。
综合以上的实验,可以肯定的是在server中配置块中如果使用break指令,下面所有的location将不会执行,而last会进行下一次内部跳转。location中的break则是直接退出,返回URI的结果; last 进入下一次内部跳转,该location内的rewrite配置指令不再执行。
3) if (基本语法:if(condition) {}) 可以配置在server和location配置块中
根据condition是true和false决定是否加载 花括号中的配置,花括号中的配置可以继承外面的配置,也可以对外面的指令进行重写。
condition 可以是自定义变量或者系统变量本身,也可以是表达式:
a condition 为变量本身时, 0: false 非0 : true
b 变量可以通过"=" 、"!=" 与字符串比较
c 匹配正则表达式 ~ !~ (大小写敏感) ~ !~ (大小写不敏感)
d -f -d -e -x !-f !-d !-e !-x 等检验文件或者目录存在或者文件属性
4) return (基本语法: return code [text]; return code URL; return URL; 可以配置在server,location和if配置块中)
停止任何的进一步处理,并且将指定状态码返回给客户端。如果状态码为444(此状态码是非标准的),那么直接关闭此TCP连接。
return的参数有四种形式:
5) set (基本语法: set $var value; 可以配置在server,location和if配置块中)
这个指令可以用来自定义变量,也可以改变系统变量的值。
6) rewrite_log (基本语法: rewrite_log on | off; 可以配置在http,server,location和if配置块中)
如果开启on,name当rewrite时,会产生一个notice基本的日志;否则不产生日志。可以在调试的时候将其设置为on。
请求 curl -I http://localhost:8080/first 时,先找到 /first location,在 /first location中rewrite URI 为/indexhtml进入post-rewrite阶段,进行一次内部跳转,回到find-config阶段,使用新的/indexhtml做为URI重新匹配location至 location / 。
这里有一个问题,为什么不在rewrite阶段执行内部跳转?答案就是为了在一个location中支持反复改写URI。试想一下如果有以下配置。
如果在rewrite阶段直接做内部跳转,那么 第二个rewrite将不能执行,我们必须再声明一个 /second location进行URI 重写。
想证实这一点很简单,我们做一个简单的例子:
请求 curl http://localhost:8080/first 之后将得到 "third content"相应值,同时可以在日志中看到如下日志。
注意一下,server配置块下的rewrite命令在server-rewrite阶段执行。
nginx限制请求是一个比较复杂的模块,后面会单独解说。
在接口/post_access 中同时配置了ngx_access 和ngx_lua两个模块,这样access阶段就由两个模块一起检查,其中deny all 会让ngx_access模块处理程序拒绝当前请求,而语句access_by_lua 'ngxexit(ngxOK)' ; 则总是允许访问。当satify指令为all时,当前的请求会被拒绝,返回403(forbidden)。
为了更好的指导部署与测试艺术升系统nginx网站服务器高性能同时下安全稳定运行,需要对nginx服务进行调优与加固;
本次进行Nginx服务调优加固主要从以下几个部分:
本文档仅供内部使用,禁止外传,帮助研发人员,运维人员对系统长期稳定的运行提供技术文档参考。
Nginx是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服务器。Nginx作为负载均衡服务器, Nginx 既可以在内部直接支持 Rails 和 PHP 程序对外进行服务,也可以支持作为 HTTP代理服务器对外进行服务。
Nginx版本选择:
项目结构:
Nginx文档帮助: http://nginxorg/en/docs/
Nginx首页地址目录: /usr/share/nginx/html
Nginx配置文件:
localtion 请求匹配的url实是一个正则表达式:
Nginx 匹配判断表达式:
例如,匹配末尾为如下后缀的静态并判断是否存在该文件, 如不存在则404。
查看可用模块编译参数:http://nginxorg/en/docs/configurehtml
http_gzip模块
开启gzip压缩输出(常常是大于1kb的静态文件),减少网络传输;
http_fastcgi_module模块
nginx可以用来请求路由到FastCGI服务器运行应用程序由各种框架和PHP编程语言等。可以开启FastCGI的缓存功能以及将静态资源进行剥离,从而提高性能。
keepalive模块
长连接对性能有很大的影响,通过减少CPU和网络开销需要开启或关闭连接;
http_ssl_module模块
Nginx开启支持Https协议的SSL模块
Linux内核参数部分默认值不适合高并发,Linux内核调优,主要涉及到网络和文件系统、内存等的优化,
下面是我常用的内核调优配置:
文件描述符
文件描述符是操作系统资源,用于表示连接、打开的文件,以及其他信息。NGINX 每个连接可以使用两个文件描述符。
例如如果NGINX充当代理时,通常一个文件描述符表示客户端连接,另一个连接到代理服务器,如果开启了HTTP 保持连接,这个比例会更低(译注:为什么更低呢)。
对于有大量连接服务的系统,下面的设置可能需要调整一下:
精简模块:Nginx由于不断添加新的功能,附带的模块也越来越多,建议一般常用的服务器软件使用源码编译安装管理;
(1) 减小Nginx编译后的文件大小
(2) 指定GCC编译参数
修改GCC编译参数提高编译优化级别稳妥起见采用 -O2 这也是大多数软件编译推荐的优化级别。
GCC编译参数优化 [可选项] 总共提供了5级编译优化级别:
常用编译参数:
缓存和压缩与限制可以提高性能
NGINX的一些额外功能可用于提高Web应用的性能,调优的时候web应用不需要关掉但值得一提,因为它们的影响可能很重要。
简单示例:
1) 永久重定向
例如,配置 http 向 https 跳转 (永久)
nginx配置文件指令优化一览表
描述:Nginx因为安全配置不合适导致的安全问题,Nginx的默认配置中存在一些安全问题,例如版本号信息泄露、未配置使用SSL协议等。
对Nginx进行安全配置可以有效的防范一些常见安全问题,按照基线标准做好安全配置能够减少安全事件的发生,保证采用Nginx服务器系统应用安全运行;
Nginx安全配置项:
温馨提示: 在修改相应的源代码文件后需重新编译。
设置成功后验证:
应配置非root低权限用户来运行nginx服务,设置如下建立Nginx用户组和用户,采用user指令指运行用户
加固方法:
我们应该为提供的站点配置Secure Sockets Layer Protocol (SSL协议),配置其是为了数据传输的安全,SSL依靠证书来验证服务器的身份,并为浏览器和服务器之间的通信加密。
不应使用不安全SSLv2、SSLv3协议即以下和存在脆弱性的加密套件(ciphers), 我们应该使用较新的TLS协议也应该优于旧的,并使用安全的加密套件。
HTTP Referrer Spam是垃圾信息发送者用来提高他们正在尝试推广的网站的互联网搜索引擎排名一种技术,如果他们的垃圾信息链接显示在访问日志中,并且这些日志被搜索引擎扫描,则会对网站排名产生不利影响
加固方法:
当恶意攻击者采用扫描器进行扫描时候利用use-agent判断是否是常用的工具扫描以及特定的版本,是则返回错误或者重定向;
Nginx支持webdav,虽然默认情况下不会编译。如果使用webdav,则应该在Nginx策略中禁用此规则。
加固方法: dav_methods 应设置为off
当访问一个特制的URL时,如"/nginxstatus",stub_status模块提供一个简短的Nginx服务器状态摘要,大多数情况下不应启用此模块。
加固方法:nginxconf文件中stub_status不应设置为:on
如果在浏览器中出现Nginx自动生成的错误消息,默认情况下会包含Nginx的版本号,这些信息可以被攻击者用来帮助他们发现服务器的潜在漏洞
加固方法: 关闭"Server"响应头中输出的Nginx版本号将server_tokens应设置为:off
client_body_timeout设置请求体(request body)的读超时时间。仅当在一次readstep中,没有得到请求体,就会设为超时。超时后Nginx返回HTTP状态码408(Request timed out)。
加固方法:nginxconf文件中client_body_timeout应设置为:10
client_header_timeout设置等待client发送一个请求头的超时时间(例如:GET / HTTP/11)。仅当在一次read中没有收到请求头,才会设为超时。超时后Nginx返回HTTP状态码408(Request timed out)。
加固方法:nginxconf文件中client_header_timeout应设置为:10
keepalive_timeout设置与client的keep-alive连接超时时间。服务器将会在这个时间后关闭连接。
加固方法:nginxconf文件中keepalive_timeout应设置为:55
send_timeout设置客户端的响应超时时间。这个设置不会用于整个转发器,而是在两次客户端读取操作之间。如果在这段时间内,客户端没有读取任何数据,Nginx就会关闭连接。
加固方法:nginxconf文件中send_timeout应设置为:10
GET和POST是Internet上最常用的方法。Web服务器方法在RFC 2616中定义禁用不需要实现的可用方法。
加固方法:
limit_zone 配置项限制来自客户端的同时连接数。通过此模块可以从一个地址限制分配会话的同时连接数量或特殊情况。
加固方法:nginxconf文件中limit_zone应设置为:slimits $binary_remote_addr 5m
该配置项控制一个会话同时连接的最大数量,即限制来自单个IP地址的连接数量。
加固方法:nginxconf 文件中 limit_conn 应设置为: slimits 5
加固方法:
加固方法:
解决办法:
描述后端获取Proxy后的真实Client的IP获取需要安装--with-http_realip_module,然后后端程序采用JAVA(requestgetAttribute("X-Real-IP"))进行获取;
描述: 如果要使用geoip地区选择,我们需要再nginx编译时加入 --with-http_geoip_module 编译参数。
描述: 为了防止外部站点引用我们的静态资源,我们需要设置那些域名可以访问我们的静态资源。
描述: 下面收集了Web服务中常规的安全响应头, 它可以保证不受到某些攻击,建议在指定的 server{} 代码块进行配置。
描述: 为了防止某些未备案的域名或者恶意镜像站域名绑定到我们服务器上, 导致服务器被警告关停,将会对业务或者SEO排名以及企业形象造成影响,我们可以通过如下方式进行防范。
执行结果:
描述: 有时你的网站可能只需要被某一IP或者IP段的地址请求访问,那么非白名单中的地址访问将被阻止访问, 我们可以如下配置;
常用nginx配置文件解释:
(1) 阿里巴巴提供的Concat或者Google的PageSpeed模块实现这个合并文件的功能。
(2) PHP-FPM的优化
如果您高负载网站使用PHP-FPM管理FastCGI对于PHP-FPM的优化非常重要
(3) 配置Resin on Linux或者Windows为我们可以打开 resin-319/bin/httpdsh 在不影响其他代码的地方加入:-Dhttpsprotocols=TLSv12, 例如
原文地址: https://blogweiyigeektop/2019/9-2-122html
用phpstudy自动配好nginx+php环境,win版和linux版都有。支持php版本一键切换。nginxconf已经配好,phpstudy菜单上有站点管理,自己添加站点即可,点点鼠标即可完成。phpstudy如图
例子:
以上一些配置为在该server下具有全局性,例如 root ,可在location中重新定义root
当我们想定义多个server监听同一个端口但访问的host不一样时,server_name就派上用场了。nginx会根据HTTP请求的header Host选择nginx配置文件里符合条件的server_name的server配置
匹配顺序如下
所以当我们监听的的端口只有一个server配置的时候,server_name 可以不填
两者作用差不多,区别在于最终映射的地址不同,例:
简单例子,匹配所有请求
一个正则匹配的例子:
一个反向代理的例子:
vue-router、react-router等路由框架要开启history模式可以选择的nginx配置的例子
location的匹配规则和顺序
还有一种特殊匹配类型 @url ,只用于nginx内部跳转,例:
例子:
有常用两种负载均衡支持调度算法,分别是 weight 和 ip_hash 。weight 模式下可以为每个 server 设置weight值,weight值越大,分配到的访问机率越高,ip_hash 为同一个ip的
分配同一个后端服务器,这样我们不用解决session共享问题。
例子:
mime type 和 文件扩展名的对应关系一般放在 mimetypes 里,然后 用 include mimetypes ;
mimetypes作用:通过文件的扩展名设置了Content-Type,Nginx如果没找到对应文件的扩展名的话,就使用默认的Type,默认Type通用 default_type 定义,比如 default_type application/octet-stream ;
完整的 mimetypes 配置: https://githubcom/h5bp/server-configs-nginx/blob/master/mimetypes
一个虚拟主机对一个文件配置,放到vhost文件夹下面,然后通过include指令包含进来,这样更便于维护和管理
配置:
参考:
http://tooloschinanet/apidocs/apidocapi=nginx-zh
https://wwwjianshucom/p/bed000e1830b
Nginx官方发布“避免10大NGINX配置错误”中,推荐nginxconf配置为:
即使没有负载平衡或在一台机器内,也要启用upstream{}块,它解锁了几个提高性能的功能:
Nginx官方推荐的nginxconf标准配置
0条评论