- Web2.0时代,绝大多数网站都是以用户为中心多的,例如:bbs,blog,sns产品,这几个产品都有一个共同特色,就是不但容许用户发布内容到服务器,还容许用户发图片甚至上传附件到服务器上,因为为用户开了上传功能,所以给服务器带来了很大的安全风险。虽然不少程序在上传前会着必定的控制,例如:文件大小,类型等,可是,一不当心就会被黑客钻了控制,上传了木马程序。
- 下面将利用Nginx配置禁止访问上传资源目录下的PHP,Shell,Perl,Python程序文件,这样用户即便上传了木马文件也无法执行,从而增强了网站的安全。
范例1:配置Nginx,禁止解析指定目录下的指定程序。php
location ~ ^/images/.*\.(php|php5|sh|pl|py)$ { deny all; } location ~ ^/static/.*\.(php|php5|sh|pl|py)$ { deny all; } location ~* ^/data/(attachment|avatar)/.*\.(php|php5)$ { deny all; } #对上述目录的限制必须写在Nginx处理PHP服务配置的前面,以下: location ~ .*\.(php|php5)$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include fcgi.conf; }
范例2:Nginx下配置禁止访问.txt和.doc文件。html
#实际配置信息以下: location ~* \.(txt|doc)$ { if (-f $request_filename) { root /data/www/www; #rewrite ...能够重定向到某个URL break; } } location ~* \.(txt|doc)$ { root /data/www/www; deny all; }
范例1:配置禁止访问指定的单个或多个目录前端
#禁止访问单个目录的命令以下: location ~ ^/static { deny all; } #禁止访问多个目录的命令以下: location ~ ^/(static|js) { deny all; }
范例2:禁止访问目录并返回指定的HTTP状态码,命令以下:node
server { listen 80; server_name www.yunjisuan.com yunjisuan.com; root /data/www/www; index index.html index.htm; access_log logs/www_access.log commonlog; location /admin/ { return 404; } location /tmplates/ { return 403; } }
- 做用:禁止访问目录下的指定文件1,或者禁止访问指定目录下的全部内容。
- 最佳应用场景:对于集群的共享存储,通常是存放静态资源文件,因此,可禁止执行指定扩展名的程序,例:.php,.sh,.pl,.py
- 下面介绍如何使用ngx_http_access_module限制网站来源IP访问
- 案例环境:phpmyadmin数据库的Web客户端,内部开发人员用的。
范例1:禁止某目录让外界访问,但容许某IP访问该目录,且支持PHP解析,命令以下:ios
location ~ ^/yunjisuan/ { allow 202.111.12.211; deny all; } location ~ .*\.(php|php5)$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include fastcgi.conf; }
范例2:限制指定IP或IP段访问,命令以下:nginx
location / { deny 192.168.1.1; allow 192.168.1.0/24; allow 10.1.1.0/16; deny all; }
参考资料:http://nginx.org/en/docs/http/ngx_http_access_module.htmlweb
企业问题案例: Nginx作反向代理的时候能够限制客户端IP吗?
答:能够,具体方法以下:算法
方法一:使用if来控制,命令以下:数据库
if ($remote_addr = 10.0.0.7) { return 403; } if ($remote_addr = 218.247.17.130) { set $allow_access_root 'ture'; #我也不知道什么意思 }
方法二:利用deny和allow只容许IP访问,命令以下:浏览器
location / { root html/blog; index index.php index.html index.htm; allow 10.0.0.7; deny all; }
方法三:只拒绝某些IP访问,命令以下:
location / { root html/blog; index index.php index.html index.htm; deny 10.0.0.7; allow all; }
注意事项:
- deny必定要加一个IP,不然会直接跳转到403,再也不往下执行了,若是 403默认页是在同一域名下,会形成死循环访问。
- 对于allow的IP段,从容许访问的段位从小到大排列,如127.0.0.0/24的下面才能是10.10.0.0/16,其中:
- 24表示子网掩码:255.255.255.0
- 16表示子网掩码:255.255.0.0
- 8表示子网掩码:255.0.0.0
以deny all:结尾,表示除了上面容许的,其余的都禁止。如: deny 192.168.1.1; allow 127.0.0.0/24; allow 192.168.0.0/16; allow 10.10.0.0/16; deny all;
问题:Nginx如何防止用户IP访问网站(恶意域名解析,也至关因而直接IP访问企业网站)
方法一:让使用IP访问网站的用户,或者恶意解析域名的用过户,收到501错误,命令以下:
server { listen 80 default_server; server_name _; return 501; } #说明:直接报501错误,从用户体验上不是很好
方法二:经过301跳转到主页,命令以下:
server { listen 80 default_server; server_name _; rewrite ^(.*) http://www.yunjisuan.com/$1 permanent; }
方法三:发现某域名恶意解析到公司的服务器IP,在server标签里添加如下代码便可,如有多个server则要多处添加。
if ($host ! ~ ^www\.yunjisuan\.com$) { rewrite ^(.*) http://www.yunjisuan.com/$1 permanent; } #说明:代码含义为若是header信息的host主机名字非www.yunjisuan.com,就301跳转到www.yunjisuan.com
简单的说,就是某些不法网站未经容许,经过在其自身网站程序里非法调用其余网站的资源,而后在本身的网站上显示这些调用的资源,达到填充自身网站的效果。这一举动不只浪费了调用资源网站的网络流量,还形成其余网站的带宽及服务压力吃紧,甚至宕机。
下面经过示意图阐述资源被盗链原理,以下图所示:
若网站图片及相关资源被盗链,最直接的影响就是网络带宽占用加大了,带宽费用多了,网络流量也可能忽高忽低,Nagios/Zabbix等报警服务频繁报警,相似下图所示:
最严重的状况就是网站的资源被非法使用,使网站带宽成本加大和服务器压力加大,这有可能致使数万元的损失,且网站的正经常使用户访问也会受到影响。
某日,接到从事运维工做的朋友的紧急求助,其公司的CDN源站,源站的流量没有变更,但CDN加速那边的流量无端超了好几个GB,不知道怎么处理。
该故障的影响:因为是购买的CDN网站加速服务,所以虽然流量多了几个GB,可是业务未受影响。只是,这么大的异常流量,持续下去可直接致使公司无端损失数万元。解决这个问题可体现运维的价值。
那么,这样的问题如何及时发现,又如何处理呢?
- 第一:对IDC及CDN带宽作监控报警
- 第二:做为高级运维或运维经理,天天上班的重要任务,就是常常查看网站流量图,关注流量变化,关注异常流量。
- 第三:对访问日志作分析,迅速定位异常流量,而且和公司市场推广等保持较好的沟通,以便调度带宽和服务器资源,确保网站正常的访问体验。
- 在HTTP协议中,有一个表头字段叫referer,使用URL格式来表示是哪里的连接用了当前网页的资源。经过referer能够检测访问的来源网页,若是是资源文件,能够跟踪到显示它的网页地址,一旦检测出来源不是本站,立刻进行阻止或返回指定的页面。
- HTTP referer是header的一部分,当浏览器向Web服务器发送请求时,通常会带上referer,告诉服务器我是从哪一个页面连接过来的,服务器借此得到一些信息用于处理。Apache,Nginx,Lighttpd三者都支持根据HTTP referer实现防盗链,referer是目前网站图片,附件,html等最经常使用的防盗链手段。下图是referer防盗链的基本原理图。
- 对于一些特殊的业务数据,例如流媒体应用经过ActiveX显示的内容(例如,Flash,Windows Media视频,流媒体的RTSP协议等),由于他们不向服务器提供referer header,因此若采用上述的referer的防盗链手段,就达不到想要的效果。
- 对于Flash,Windows Media视频这种占用流量较大的业务数据,防盗链是比较困难的,此时能够采用Cookie技术,解决Flash,Windows Media视频等的防盗链问题。
例如:ActiveX插件不传递referer,但会传递Cookie,能够在显示ActiveX的页面的标签内嵌入一段JavaScript代码,设置“Cookie:Cache=av”以下:
<script>document.cookie="Cache=av;domain=domain.com;path=/";</script>
而后就能够经过各类手段来判断这个Cookie的存在,以及验证其值的操做了。
根据Cookie来防盗链的技术比较复杂,咱们不在这里涉及,同窗们若是感兴趣,或者企业确实须要,可经过网络来了解相关方法。
此种方法比较适合视频及下载类业务数据的网站。例如:Lighttpd有相似的插件mod_secdownload来实现此功能。先在服务器端配置此模块,设置一个固定用于加密的字符串,好比yunjisuan,而后设置一个url前缀,好比/mp4/,再设置一个过时时间,好比1小时,而后写一段PHP代码,利用加密字符串和系统时间等经过md5算法生成一个加密字符串。最终获取到的文件的URL连接中会带有一个时间戳和一个加密字符的MD5数值,在访问时系统会对这两个数据进行验证。若是时间不在预期的时间段内(如1小时内)则失效;若是时间戳符合条件,可是加密的字符串不符合条件也会失效,从而达到防盗链的效果。
在默认状况下,只须要进行简单的配置,便可实现防盗链处理。请看下面的实例。
#下面的代码为利用referer且针对扩展名rewrite重定向,即实现防盗链的Nginx配置。 location ~* \.(jpg|gif|png|swf|flv|wma|wmv|asf|mp3|mmf|zip|rar)$ { valid_referers none blocked *.yunjisuan.com yunjisuan.com; # if ($invalid_referer) { rewrite ^/ http://www.yunjisuan.com/img/nolink.jpg; } } #提示:要根据本身公司的实际业务(是否有外链的合做)进行域名设置。
针对目录的方法以下: location /images { root /data/www/www; valid_referers none blocked *.yunjisuan.com yunjisuan.com; if ($invalid_referer) { return403; } }
在上面这段防盗链设置中,分别针对不一样文件类型和不一样的目录进行了设置,我们能够根据本身需求进行相似设定。下面是上述代码的说明:
- 若是不怕麻烦,有条件实现的话,推荐使用NginxHttpAccessKeyModule。
- 其运行方式是:如download目录下有一个file.zip文件。对应的URI是http://www.abc.com/download/file.zip,使用ngx_http_accesskey_module 模块后就成了http://www.bac.com/download/file.zipkey=09093abeac094,只有正确地给定了key值,才能下载download目录下的file.zip,并且key值是与用户的IP相关的,这样就能够避免被盗链了。听说,如今NginxHttpAccessKeyModule连迅雷均可以防了,同窗们执行尝试一下。
产品设计时,处理盗链问题可将计就计,为网站上传的图片增长水印。例如:下图就是为网站上传的图片增长的水印。
为图片添加版权水印是颇有效的方法。网站直接转载图片通常是为了快捷,可是对于有水印的图片,不少站长是不肯意转载的。
在网站的运行过程当中,可能由于页面不存在或系统过载等缘由,致使网站没法正常响应用户的请求,此时Web服务会返回系统默认的错误码,或者很不友好的页面,以下图所示:
咱们能够将404,403等的错误信息页面重定向到网站首页或其余事先指定的页面,提高网站的用户访问体验。
范例1:对错误代码403实行本地页面跳转,命令以下:
server { listen 80; server_name www.yunjisuan.com; location / { root html/www; index index.html index.htm; } error_page 403 /403.html; #当出现403错误时,会跳转到403.html页面 } #上面的/403.html是相对于站点根目录html/www的。
范例2:对错误代码404实行本地页面优雅显示,命令以下:
server { listen 80; server_name www.yunjisuan.com; location / { root html/www; index index.html index.htm; error_page 404 /404.html; #当出现404错误时,会跳转到404.html页面 } } #代码中的/404.html是相对于站点根目录html/www的
范例3: 50x页面放到本地单独目录下,进行优雅显示
error_page 500 502 503 504 /50x.html; location = /50x.html { root /data/www/html; } #这里指定单独的站点目录存放到50x.html文件中。
范例4: 错误状态码URL重定向,命令以下:
server { listen 80; server_name www.yunjisuan.com; location / { root html/www; index index.html index.htm; error_page 404 http://bbs.yunjisuan.com; #当出现404错误时,会跳转到指定的URL http://bbs.yunjisuan.com页面显示给用户,这个URL通常是企业另外的可用地址。 access_log /usr/local/nginx/logs/bbs_access.log commonlog; } } #代码中的/404.html是相对于站点根目录html/www的。
范例5: 将错误状态码重定向到一个location,命令以下:
location / { error_page 404 = @fallback; } location @fallback { proxy_pass http://backend; }
error_page 500 501 502 503 504 http://err.tmall.com/error2.html; error_page 400 403 404 405 408 410 411 412 413 414 415 http://err.tmall.com/error1.html;
为了保证网站不遭受木马入侵,全部站点目录的用户和组都应该为root,全部的目录权限是755;全部的文件权限是644.设置以下:
[root@NginxWeb ~]# ls -l /usr/local/nginx/html/ | tail -5 -rw-r--r--. 1 root root 8048 Jan 11 2017 wp-mail.php -rw-r--r--. 1 root root 16255 Apr 6 14:23 wp-settings.php -rw-r--r--. 1 root root 29896 Oct 19 2016 wp-signup.php -rw-r--r--. 1 root root 4513 Oct 14 2016 wp-trackback.php -rw-r--r--. 1 root root 3065 Aug 31 2016 xmlrpc.php
- 以上的权限设置能够防止黑客上传木马,以及修改站点文件,可是,合理的网站用户上传的内容也会被拒之门外。那么如何让合法的用户能够上传文件,而又不至于被黑客利用攻击呢?
- 若是是单机的LNMP环境,站点目录和文件属性设置以下。
- 先把全部的目录权限设置为755,全部的文件权限设置为644,所用的目录,以及文件用户和组都是root;而后把用户上传资源的目录权限设置为755,将用户和组设置为Nginx服务的用户;最后针对上传资源的目录作资源访问限制。
- 部分公司所采用的受权方式不是很安全,常见的有以下两种:
chmod -R 777 /directory chmod -R nginx.nginx /directory
- 述两种受权方法虽然不能说错误,可是没有作到受权最小化,会给网站带来很是大的安全隐患,特别是木马入侵的时候。
- 在比较好的网站业务架构中,应把资源文件,包括用户上传的图片,附件等服务和程序服务分离,最好把上传程序服务也分离出来,这样就能够从容地按照以前所述进行安全受权了。
结合Linux权限体系及Nginx大型集群架构进行配置,严格控制针对Nginx目录的访问才能下降网站被入侵的风险。好比,可根据下图中的企业集群架构逻辑图和不一样角色提供的不一样服务来严格控制不一样服务器的Nginx目录权限。
下图为集群架构中不一样于前面Web业务的权限管理细化。
服务器角色 | 权限处理 | 安全系数 |
---|---|---|
动态Web集群 | 目录权限755,文件权限644,所用目录,以及文件用户和组都是root。环境为Nginx+PHP | 文件不能被改,目录不能被写入,安全系数10 |
static图片集群 | 目录权限755,文件权限644,所用的目录,以及文件用户和组都是root。环境为Nginx | 文件不能被改,目录不能被写入,安全系数10 |
上传upload集群 | 目录权限755,文件权限644,所用的目录,以及文件用户和组都是root。特别:用户上传的目录设置为755,用户和组使用Nginx服务配置的用户 | 文件不能被改,目录不能被写入,可是用户上传的目录容许写入文件且须要经过Nginx的其余功能来禁止读文件,安全系数8 |
作到上述的设置后,网站服务在系统层面被入侵的风险就大大下降了。
- Robots协议(也称为爬虫协议,机器人协议等)的全称是“网络爬虫排除标准”(Robots Exclusion Protocol),网站经过Robots协议告诉搜索引擎哪些页面能够抓取,哪些页面不能抓取。
- 我理解的是robots.txt是经过代码控制搜索引擎蜘蛛索引的一个手段,以便减轻网站服务器的带宽使用率,从而让网站的空间更稳定,同时也能够提升网站其余页面的索引效率,提升网站收录。
- 咱们只须要建立一个robots.txt文本文件,而后在文档内设置好代码,告诉搜索引擎我网站的哪些文件你不能访问。而后上传到网站根目录下面,由于当搜索引擎蜘蛛在索引一个网站时,会先爬行查看网站根目录下是否有robots.txt文件。
2011年10月25日,京东商城正式将一淘网的搜索爬虫屏蔽,以防止一淘网对其内容进行抓取。
京东的robots.txt设置以下: https://www.jd.com/robots.txt
2008年9月8日,淘宝网宣布封杀百度爬虫,百度忍痛遵照爬虫协议。由于一旦破坏协议,用户的隐私和利益就没法获得保障,搜索网站就谈不上人性关怀。
淘宝的robots.txt设置以下: https://www.taobao.com/robots.txt
咱们能够根据客户端的user-agents信息,轻松地阻止指定的爬虫爬取咱们的网站。下面来看几个案例。
范例1:阻止下载协议代理,命令以下:
#Block download agents## if ($http_user_agent ~* LWP:Simple | BBBike | wget) { return 403; } #说明:若是用户匹配了if后面的客户端(例如wget),就返回403.
这里根据$http_user_agent获取客户端agent,而后判断是否容许或返回指定错误码。
范例2:添加内容防止N多爬虫代理访问网站,命令以下:
#这些爬虫代理使用“|”分隔,具体要处理的爬虫能够根据需求增长或减小,添加的内容以下: if ($http_user_agent ~* "qihoobot|Baiduspider|Googlebot-Modile|Googlebot-Image|Mediapartners-Google|Adsbot-Google|Yahoo! SSlurp China|YoudaoBot|Sosospider|Sogou spider|Sogou web spider|MSNBot") { return 403; }
范例3:测试禁止不一样的浏览器软件访问
示例代码以下: if ($http_user_agent ~* "Firefox|MSIE") { rewrite ^(.*) http://www.yunjisuan.com/$1 permanent; } #若是浏览器为Firefox或IE,就会跳转到http://www.yunjisuan.com
在以前的HTTP协议原理一节中,讲解了不少HTTP方法,其中最经常使用的HTTP方法为GET,POST,咱们能够经过Nginx限制HTTP请求的方法来达到提高服务器安全的目的,例如,让HTTP只能使用GET,HEAD和POST方法的配置以下:
#Only allow these request methods if ($request_method ! ~ ^(GET|HEAD|POST)$) { return 501; }
当上传服务器上传数据到存储服务器时,用户上传写入的目录就不得不给Nginx对应的用户相关权限,这样一旦程序有漏洞,木马就有可能被上传到服务器挂载的对应存储服务器的目录里,虽然咱们也作了禁止PHP,SH,PL,PY等扩展名的解析限制,但仍是会遗漏一些想不到的可执行文件。对于这样状况,该怎么办呢?事实上,还能够经过限制上传服务器的Web服务(能够具体到文件)使用GET方法,防止用户经过上传服务器访问存储内容,让访问存储渠道只能从静态或图片服务器入口进入。例如,在上传服务器上限制HTTP的GET方法的配置以下:
#Only deny GET request methods ## if ($request_method ~* ^(GET)$) { return 501; } #提示:还能够加一层location,更具体地限制文件名
实际效果以下图所示:
- CDN的全称是Content Delivery Network,中文意思是内容分发网络。简单地讲,经过在现有的Internet中增长一层新的网络架构,将网站的内容发布到最接近用户的Cache服务器内,经过智能DNS负载均衡技术,判断用户的来源,让用户就近使用与服务器相同线路的带宽访问Cache服务器,取得所需的内容。例如:天津网通用户访问天津网通Cache服务器上的内容,北京电信访问北京电信Cache服务器上的内容。这样能够有效减小数据在网络上传输的时间,提升访问速度。
- CDN是一套全国或全球的1分布式缓存集群,其实质是经过智能DNS判断用户的来源地域及上网线路,为用户选择一个最接近用户地域,以及和用户上网线路相同的服务器节点,由于地域近,且线路相同,因此,能够大幅提高用户浏览网站的体验。
- CDN产生背景之一:BGP机房虽然能够提高用户体验,可是价格昂贵,对于用户来讲,CDN的诞生能够提供比BGP机房更好的体验(让同一地区,同一线路的用户访问和当地同一线路的网站),BGP机房和普通机房有将近5~10倍的价格差。CDN多使用单线的机房,根据用户的线路及位置,为用户选择靠近用户的位置,以及相同的运营商线路,不但提高了用户体验,价格也降下来了。
CDN的价值:
- 为架设网站的企业省钱
- 提高企业网站的用户访问体验(相同线路,相同地域,内存访问)
- 能够阻挡大部分流量攻击,例如:DDOS攻击
CDN就是一个具有根据用户区域和线路智能调度的分布式内存缓存集群。其特色以下:
- 经过服务器内存缓存网站数据,提升了企业站点(尤为含有大量图片,视频等的站点)的访问速度,并大大提升企业站点的稳定性(省钱且提高用户体验)。
- 用户根据智能DNS技术自动选择最适合的Cache服务器,下降了不一样运营商之间互联瓶颈形成的影响,实现了跨运营商的网络加速,保证不一样网络中的用户都能获得良好的访问质量。
- 加快了访问速度,减小了原站点的带宽
- 用户访问时从服务器的内存中读取数据,分担了网络流量,同时减轻了原站点负载压力等。
- 使用CDN能够分担源站的网络流量,同时能够减轻原站点的负载压力,并下降黑客入侵及各类DDOS攻击对网站的影响,保证网站有较好的服务质量。
下面是经过curl命令访问163网站的header信息,能够看到163网站的首页就使用了CDN进行加速。
[root@NginxWeb ~]# curl -I www.163.com HTTP/1.1 200 OK Date: Fri, 12 Oct 2018 08:57:46 GMT Server: nginx Content-Type: text/html; charset=GBK Vary: Accept-Encoding,User-Agent,Accept Expires: Fri, 12 Oct 2018 08:59:06 GMT Cache-Control: max-age=80 X-Via: 1.1 PSgdmmsxlt85:7 (Cdn Cache Server V2.0), 1.1 PSbjyd3bk189:12 (Cdn Cache Server V2.0) Connection: keep-alive
上面的“(CdnCacheServerV2.0)”表示163首页使用了CDN加速。
首先要说的是,不是全部的网站均可以一上来就能用CDN的。要加速的业务数据应该存在独立的域名,例如:img1-4.yunjisuan.com/video1-4.yunjisuan.com,业务内容图片,附件,JS,CSS等静态元素,这样的静态网站域名才可使用CDN。
下面来看一个DNS解析范例。DNS服务器加速前的A记录以下:
;A records img.yunjisuanl.com IN A 124.106.0.21 (企业服务器的IP) #删除上面的记录,命令以下: img.yunjisuanl.com IN A 124.106.0.21 (服务器的IP) #而后,作下面的别名解析: ;CNAME records img.yunjisuan.com IN CNAME bbs img.yunjisuan.com 3M IN CNAME img.yunjisuan.com.cachecn.com.
提示: 这个img.yunjisuan.com.cachecn.com.地址必须是事先由CDN公司配置好的CDN公司的域名。国内较大的CDN提供商为网宿,蓝讯,快网。
解耦是开发人员中流行的一个名词,简单地说就是把一堆程序代码按照业务用途分开,而后提供服务,例如:注册登陆,上传,下载,浏览列表,商品内容页面,订单支付等都应该是独立的程序服务,只不过在客户端看来是一个总体而已。若是中小公司作不到上述细致的解耦,起码也要让下面的几个程序模块独立。
- 网页页面服务。(静态,动态页面)
- 图片附件及下载服务。(upload)
- 上传图片服务。(static)
- 上述三者的功能尽可能分离。分离的最佳方式是分别使用独立的服务器(须要改动程序),若是程序实在不易更改,次选方案是在前端负载均衡器Haproxy/Nginx上,根据URI(例如目录或扩展名)过滤请求,而后抛给后面对应的服务器。
- 例如:根据扩展名分发,请求http://www.yunjisuan.com/a/b.jpg就应抛给图片服务器(独立的静态服务器最适合使用CDN);根据URL路径分发,请求http://www.yunjisuan.com/upload/index.php就应抛给上传服务器。不符合上面两个要求的,默认抛给Web服务器。
说明:能够部署3台服务器,人为分布请求服务器。固然了,这适合并发比较高,服务器较多的状况。程序架构分离了,效率,安全性都会提升不少。
默认状况下,Nginx的Master进程使用的是root用户,worker进程使用的是Nginx指定的普通用过户,使用root用户跑Nginx的Master进程有两个最大的问题:
- 管理权限必须是root,这就使得最小化分配权限原则遇到难题。
- 使用root跑Nginx服务,一旦网站出现漏洞,用户就能够很容易地得到服务器的root权限。
所以,若是能有一种不用给开发人员,甚至普通运维人员管理员权限,就能够很好地管理Nginx服务的方法,具体内容将在下节为你们讲解。
解决方案以下:
- 给Nginx服务降权,用inca用户跑Nginx服务,给开发及运维设置普通帐号,只要与inca同组便可管理Nginx,该方案解决了Nginx管理问题,防止root分配权限过大。
- 开发人员使用普通帐户便可管理Nginx服务及站点下的程序和日志。
- 采起项目负责制度,即谁负责项目维护,出了问题就是谁负责。
不少公司开发和运维为root权限争得不可开交,甚至大打出手。
参考资料:到底要不要给开发人员管理服务器的权限?(http://down.51cto.com/data/844517)
本优化属架构优化(一样适合其余软件),经过Nginx启动命令的-c参数指定不一样的Nginx配置文件,能够同时启动多个实例,并使用普通的用户运行服务。
Nginx安装后的启动命令路径为“/usr/local/nginx/sbin/nginx”,能够经过加-h参数查看相关参数的用法,命令及结果以下:
[root@NginxWeb ~]# /usr/local/nginx/sbin/nginx -h nginx version: yangwenbo/0.0.0.0 Usage: nginx [-?hvVtTq] [-s signal] [-c filename] [-p prefix] [-g directives] Options: -?,-h : this help -v : show version and exit -V : show version and configure options then exit -t : test configuration and exit -T : test configuration, dump it and exit -q : suppress non-error messages during configuration testing -s signal : send signal to a master process: stop, quit, reopen, reload -p prefix : set prefix path (default: /usr/local/nginx/) -c filename : set configuration file (default: conf/nginx.conf) #使用指定的配置文件而不是conf目录下的nginx.conf这里咱们就是经过nginx -c路径的功能来实现跑多实例nginx -g directives : set global directives out of configuration file
较经常使用的方法是使服务跑在指定用户的家目录下面,这样相对比较安全,同时有利于批量业务部署和上线。
配置普通用户启动Nginx的过程以下:
(1) 添加用户并建立相关目录和文件,操做以下:
[root@NginxWeb ~]# useradd yunjisuan [root@NginxWeb ~]# su - yunjisuan [yunjisuan@NginxWeb ~]# pwd [yunjisuan@NginxWeb ~]# mkdir conf logs www #在普通用户家目录下建立nginx配置文件目录 [yunjisuan@NginxWeb ~]# ls conf logs www [yunjisuan@NginxWeb ~]# cp /usr/local/nginx/conf/mime.types ~/conf/ #复制媒体类型配置文件 [yunjisuan@NginxWeb ~]# echo "yunjisuan" > www/index.html #建立网页首页
(2) 配置Nginx配置文件。配置后的查看命令以下:
[yunjisuan@NginxWeb conf]# pwd /usr/local/nginx/conf [yunjisuan@NginxWeb conf]# cat nginx.conf worker_processes 4; worker_cpu_affinity 0001 0010 0100 1000; worker_rlimit_nofile 65535; error_log /home/yunjisuan/logs/error.log; user yunjisuan yunjisuan; pid /home/yunjisuan/logs/nginx.pid; events { use epoll; worker_connections 10240; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; log_format main '$remote_addr-$remote_user[$time_local]"$request"' '$status $body_bytes_sent "$http_referer"' '"$http_user_agent""$http_x_forwarded_for"'; server { listen 8080; server_name www.yunjisuan.com; root /home/yunjisuan/www; location / { index index.php index.html index.htm; } access_log /home/yunjisuan/logs/web_blog_access.log main; } } [yunjisuan@NginxWeb ~]# tree . ├── conf │ ├── mime.types │ └── nginx.conf ├── logs └── www └── index.html 3 directories, 3 files
说明以下:
- 全部参数的值,带路径的都要改为/home/yunjisuan.
- 特权用户root使用的80端口,改成普通用过户使用的端口,在1024以上,这里为8080.
(3) 启动Nginx,命令以下:
[yunjisuan@NginxWeb ~]# ps -ef | grep nginx | grep -v grep [yunjisuan@NginxWeb ~]# /usr/local/nginx/sbin/nginx -c /home/yunjisuan/conf/nginx.conf &>/dev/null & [1] 2478 [yunjisuan@LNMP ~]$ ps -ef | grep nginx | grep -v grep 503 2479 1 0 14:34 ? 00:00:00 nginx: master process /usr/local/nginx/sbin/nginx -c /home/yunjisuan/conf/nginx.conf 503 2480 2479 0 14:34 ? 00:00:00 nginx: worker process 503 2481 2479 0 14:34 ? 00:00:00 nginx: worker process 503 2482 2479 0 14:34 ? 00:00:00 nginx: worker process 503 2483 2479 0 14:34 ? 00:00:00 nginx: worker process [1]+ Done /usr/local/nginx/sbin/nginx -c /home/yunjisuan/conf/nginx.conf &>/dev/null #提示503是用户yunjisuan的UID号 [yunjisuan@NginxWeb ~]# id yunjisuan uid=503(yunjisuan) gid=503(yunjisuan) groups=503(yunjisuan)
特别提示:此处启动nginx,若是不定向到空会显示一些提示,不是错误,能够经过&>/dev/null 定向到空,从而忽略不见。
[yunjisuan@NginxWeb ~]$ killall nginx [yunjisuan@NginxWeb ~]$ ps -ef | grep nginx | grep -v grep [yunjisuan@NginxWeb ~]$ /usr/local/nginx/sbin/nginx -c /home/yunjisuan/conf/nginx.conf & [1] 2495 [yunjisuan@NginxWeb ~]$ nginx: [alert] could not open error log file: open() "/usr/local/nginx/logs/error.log" failed (13: Permission denied) 2017/08/30 14:38:20 [warn] 2495#0: the "user" directive makes sense only if the master process runs with super-user privileges, ignored in /home/yunjisuan/conf/nginx.conf:5 #此处错误能够忽略,定向输出到&>/dev/null
(4) 配置好解析后,浏览器带端口访问结果以下图所示:
(5) 解决普通端口非80提供服务的问题
用负载均衡器解决Web服务非80端口的转换问题,负载均衡器可为Haproxy,Nginx,F5等。
本解决方案的优势以下:
- 给Nginx服务降权,让网站更安全。
- 按用户设置站点权限,使站点更独立(无需虚拟化隔离)
- 开发不须要用root便可完整管理服务及站点。
- 可实现责任划分,即网络问题属于运维的责任,网站打不开就是开发的责任,或者二者共同承担。
- ngx_http_limit_conn_module这个模块用于限制每一个定义的key值的链接数(Nginx默认已经被编译),特别是单IP的链接数。
- 不是全部的链接数都会被计数。一个符合计数要求的链接是整个请求头已经被读取的链接。
控制Nginx并发链接数量参数的说明以下:
(1) limit_conn_zone参数:
语法:limit_conn_zone key zone=name:size; 上下文:http #用于设置共享内存区域,key能够是字符串,Nginx自带变量或前两个组合,如$binary_remote_addr,$server_name.name为内存区域的名称,size为内存区域的大小。
(2) limit_conn参数:
语法:limit_conn zone number; 上下文:http,server,location #用于指定key设置最大链接数。当超过最大链接数时,服务器会返回503(Service Temporarily Unavailable)错误
Nginx的配置文件以下:
[root@NginxWeb conf]# pwd /usr/local/nginx/conf [root@NginxWeb conf]# cat nginx.conf worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; limit_conn_zone $binary_remote_addr zone=addr:10m; server { listen 80; server_name www.yunjisuan.com; location / { root html; index index.html index.htm; limit_conn addr 1; #限制同IP的并发为1; } } }
测试1:利用Webbench进行并发链接测试(模拟一个客户端)
[root@webbench01 ~]# webbench -c 1 -t 5 http://192.168.200.144/ Webbench - Simple Web Benchmark 1.5 Copyright (c) Radim Kolar 1997-2004, GPL Open Source Software. Benchmarking: GET http://192.168.0.225/ 1 client, running 5 sec. Speed=341472 pages/min, 4808941 bytes/sec. Requests: 28456 susceed, 0 failed. #提示:192.168.0.225为web服务器, #-c:指定客户端数量 #-t:指定持续时间
咱们查看Web服务器的access.log日志以下:
[root@webbench01 logs]# pwd /usr/local/nginx/logs [root@webbench01 log]# tail access.log 192.168.200.144 - - [30/Aug/2017:16:29:20 -0400] "GET / HTTP/1.0" 200 612 "-" "WebBench 1.5" 192.168.200.144 - - [30/Aug/2017:16:29:20 -0400] "GET / HTTP/1.0" 200 612 "-" "WebBench 1.5" 192.168.200.144 - - [30/Aug/2017:16:29:20 -0400] "GET / HTTP/1.0" 200 612 "-" "WebBench 1.5" 192.168.200.144 - - [30/Aug/2017:16:29:20 -0400] "GET / HTTP/1.0" 200 612 "-" "WebBench 1.5" 192.168.200.144 - - [30/Aug/2017:16:29:20 -0400] "GET / HTTP/1.0" 200 612 "-" "WebBench 1.5"
从上边的日志咱们能够看到,当并发数为1时(就一个客户端),nginx正常记录用户的访问状况,http返回状态码为200
测试2:利用Webbench进行多客户端并发测试(模拟2个客户端)
[root@webbench01 ~]# webbench -c 2 -t 5 http://192.168.200.144/ Webbench - Simple Web Benchmark 1.5 Copyright (c) Radim Kolar 1997-2004, GPL Open Source Software. Benchmarking: GET http://192.168.200.144/ 2 clients, running 5 sec. Speed=565608 pages/min, 5808154 bytes/sec. Requests: 47134 susceed, 0 failed.
咱们查看Web服务器的access.log日志以下:
[root@webbench01 logs]# pwd /usr/local/nginx/logs [root@webbench01 log]# tail access.log 192.168.200.144- - [30/Aug/2017:16:31:08 -0400] "GET / HTTP/1.0" 503 213 "-" "WebBench 1.5" 192.168.200.144 - - [30/Aug/2017:16:31:08 -0400] "GET / HTTP/1.0" 200 612 "-" "WebBench 1.5" 192.168.200.144 - - [30/Aug/2017:16:31:08 -0400] "GET / HTTP/1.0" 503 213 "-" "WebBench 1.5" 192.168.200.144 - - [30/Aug/2017:16:31:08 -0400] "GET / HTTP/1.0" 200 612 "-" "WebBench 1.5"
从上边的日志咱们能够看出,当咱们用单IP地址模拟两个并发客户端进行链接时,日志以1:1比例交替出现了503错误。即Nginx已经作了并发链接限制,对超过限制的请求返回503.
测试3:利用Webbench进行多客户端并发测试(模拟3个客户端)
[root@localhost ~]# webbench -c 3 -t 5 http://192.168.200.144/ Webbench - Simple Web Benchmark 1.5 Copyright (c) Radim Kolar 1997-2004, GPL Open Source Software. Benchmarking: GET http://192.168.200.144/ 3 clients, running 5 sec. Speed=653388 pages/min, 6162385 bytes/sec. Requests: 54449 susceed, 0 failed.
咱们查看Web服务器的access.log日志以下:
[root@webbench01 logs]# pwd /usr/local/nginx/logs [root@webbench01 logs]# tail access.log 192.168.200.144 - - [30/Aug/2017:16:39:20 -0400] "GET / HTTP/1.0" 503 213 "-" "WebBench 1.5" 192.168.200.144 - - [30/Aug/2017:16:39:20 -0400] "GET / HTTP/1.0" 200 612 "-" "WebBench 1.5" 192.168.200.144 - - [30/Aug/2017:16:39:20 -0400] "GET / HTTP/1.0" 503 213 "-" "WebBench 1.5" 192.168.200.144 - - [30/Aug/2017:16:39:20 -0400] "GET / HTTP/1.0" 503 213 "-" "WebBench 1.5"
通过测试,能够看得出,200与503基本出现次数为1:2,即Nginx已经作了并发链接限制,对超过限制的请求返回503.
以上功能的应用场景之一是用于服务器下载,命令以下:
location /download/ { limit_conn addr 11; }
上面的命令限制访问download下载目录的链接数,该链接数1.
不只能够限制单IP的并发链接数,还能够限制虚拟主机总链接数,甚至能够对二者同时限制。
Nginx的配置文件以下: [root@NginxWeb conf]# pwd /usr/local/nginx/conf [root@NginxWeb conf]# cat nginx.conf worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; limit_conn_zone $binary_remote_addr zone=addr:10m; limit_conn_zone $server_name zone=perserver:10m; server { listen 80; server_name www.yunjisuan.com; location / { root html; index index.html index.htm; #limit_conn addr 1; limit_conn perserver 2; #设置虚拟主机链接数为2 } } }
测试:
#重启Nginx服务后进行测试 [root@webbench01 ~]# webbench -c 5 -t 5 http://192.168.200.144/ Webbench - Simple Web Benchmark 1.5 Copyright (c) Radim Kolar 1997-2004, GPL Open Source Software. Benchmarking: GET http://192.168.200.144/ 5 clients, running 5 sec. Speed=682128 pages/min, 7674820 bytes/sec. Requests: 56844 susceed, 0 failed.
咱们查看Web服务器的access.log日志以下:
[root@webbench01 logs]# pwd /usr/local/nginx/logs [root@webbench01 logs]# tail access.log 192.168.200.144 - - [30/Aug/2017:17:11:14 -0400] "GET / HTTP/1.0" 503 213 "-" "WebBench 1.5" 192.168.200.144 - - [30/Aug/2017:17:11:14 -0400] "GET / HTTP/1.0" 200 612 "-" "WebBench 1.5" 192.168.200.144 - - [30/Aug/2017:17:11:14 -0400] "GET / HTTP/1.0" 200 612 "-" "WebBench 1.5" 192.168.200.144 - - [30/Aug/2017:17:11:14 -0400] "GET / HTTP/1.0" 503 213 "-" "WebBench 1.5" [root@webbench01 logs]# grep -c 200 logs/access.log 35850 [root@webbench01 logs]# grep -c 503 logs/access.log 20998 [root@webbench01 logs]# cat logs/access.log | wc -l 56848
结论:200和503出现的次数近似2:1
至此,Nginx限制链接数的应用实践就讲解完毕了。
ngx_http_limit_req_module模块用于限制每一个IP访问每一个定义key的请求速率。
语法:limit\_req\_zone key zone=name: size rate=rate; 上下文1:http #用于设置共享内存区域,key能够是1字符串,Nginx自带变量或前两个组合,如$binary_remote_addr。name为内存区域的名称,size为内存区域的大小,rate为速率,单位为r/s,每秒一个请求。 limit_req参数说明以下: 语法:limit_req zone=name [burst=number][nodelay]; 上下文:http,server,location
- 这里运用了令牌桶原理,burst=num,一共有num块令牌,令牌发完后,多出来的那些请求就会返回503。
- 换句话说,一个银行,只有一个营业员,银行很小,等候室只有5我的的位置。所以,营业员一个时刻只能为一我的提供服务,剩下的不超过5我的能够在银行内等待,超出的人不提供服务,直接返回503。
- nodelay默认在不超过burst值的前提下会排队等待处理,若是使用此参数,就会处理完num + 1次请求,剩余的请求都视为超时,返回503。
用于测试的Nginx配置文件以下:
[root@NginxWeb conf]# pwd /usr/local/nginx/conf [root@NginxWeb conf]# cat nginx.conf worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s; #以请求的客户端IP做为key值,内存区域命令为one,分配10m内存空间,访问速率限制为1秒1次请求(request) # limit_conn_zone $binary_remote_addr zone=addr:10m; # limit_conn_zone $server_name zone=perserver:10m; server { listen 80; server_name www.yunjisuan.com; location / { root html; index index.html index.htm; limit_req zone=one burst=5; #使用前面定义的名为one的内存空间,队列值为5,便可以有5个请求排队等待 # limit_conn addr 1; # limit_conn addr 1; } } } [root@NginxWeb conf]# /usr/local/nginx/sbin/nginx -s reload #重启服务
利用Webbench进行测试
[root@webbench01 ~]# webbench -c 100 -t 10 http://192.168.200.144/ Webbench - Simple Web Benchmark 1.5 Copyright (c) Radim Kolar 1997-2004, GPL Open Source Software. Benchmarking: GET http://192.168.200.144/ 100 clients, running 10 sec. Speed=749706 pages/min, 4811119 bytes/sec. Requests: 124951 susceed, 0 failed.
咱们查看Web服务器的access.log日志以下:
[root@webbench01 logs]# pwd /usr/local/nginx/logs [root@webbench01 logs]# >access.log [root@webbench01 logs]# grep -c 200 access.log 11 [root@webbench01 logs]# grep -c 503 access.log 124978 [root@webbench01 logs]# cat access.log | wc -l 124994 #说明:本次测试只成功响应了11个请求,近视1秒处理1个请求。多余的请求一概用503进行响应。
- 经过过滤排重日志,能够看到第一个请求返回200,为正常处理,剩余2582次+9858次超过了限制的在1秒内执行完成,可是都返回了503
- 具体过程原理为:Nginx在第1秒先处理第一个请求,同时接下来的5个请求等待排队,剩下的(2582+9858)请求返回503。接着第2秒到第6秒处理等待的5个请求。
- 更多内容可参考:http://nginx.org/en/docs/http/ngx_http_limit_req_module.html。
- 安全优化:隐藏Nginx软件名及版本号。
- 性能加安全优化:链接超时参数及FastCGI相关参数调优
- 性能优化:expires缓存功能及调试查看方法。
- 性能优化:gzip压缩功能及调试查看方法。
- 安全优化:集群中各角色服务站点目录权限控制策略。
- 安全优化:站点目录下全部的文件和目录访问控制。
- 性能加安全优化:静态资源防盗链解决方案
- 性能加安全优化:robots.txt协议及防爬虫优化解决方案
- 用户体验优化:错误页面优雅显示方法
- 安全优化:限制http请求方法
- 性能加安全优化:CDN加速知识
- 安全优化:监牢模式运行Nginx方案策略
- 性能加安全优化:Nginx并发链接数及请求速率控制