Nginx服务器怎么nginx动态添加服务器自定义网站

中国领先的IT技术网站
51CTO旗下网站
Nginx自定义模块编写:根据post参数路由到不同服务器
Nginx可以轻松实现根据不同的url 或者 get参数来转发到不同的服务器,然而当我们需要根据http包体来进行请求路由时,Nginx默认的配置规则就捉襟见肘了,但是没关系,Nginx提供了强大的自定义模块功能,我们只要进行需要的扩展就行了。
作者:blogread来源:| 15:27
Nginx可以轻松实现根据不同的url 或者 get参数来转发到不同的服务器,然而当我们需要根据http包体来进行请求路由时,Nginx默认的配置规则就捉襟见肘了,但是没关系,Nginx提供了强大的自定义模块功能,我们只要进行需要的扩展就行了。
我们来理一下思路,我们的需求是:
Nginx根据http包体的参数,来选择合适的路由
在这之前,我们先来考虑另一个问题:
在Nginx默认配置的支持下,能否实现服务器间的跳转呢?即类似于状态机,从一个服务器执行OK后,跳转到另一台服务器,按照规则依次传递下去。
答案是可以的,这也是我之前写之后,在nginx上特意尝试的功能。
一个示例的配置如下:
server&{&&&&&listen&&&&&&&8080;&&&&&server_name&&&&&&&location&/&{&&&&&&&&&proxy_pass&http://localhost:8888;&&&&&&&&&error_page&433&=&@433;&&&&&&&&&error_page&434&=&@434;&&&&&}&&&&&location&@433&{&&&&&&&&&proxy_pass&http://localhost:6788;&&&&&}&&&&&location&@434&{&&&&&&&&&proxy_pass&http://localhost:6789;&&&&&}&&&&&error_page&&&500&502&503&504&&/50x.&&&&&location&=&/50x.html&{&&&&&&&&&root&&&&&&&&}&}&
看明白了吧?我们使用了 433和434 这两个非标准http协议的返回码,所有请求进入时都默认进入 http://localhost:8888;,然后再根据返回码是 433 还是 434 来选择进入 http://localhost:6788 还是 http://localhost:6789。
OK,也许你已经猜到我将这个例子的用意了,是的,我们只要在我们的自定义模块中,根据http的包体返回不同的返回码,进而 proxy_pass 到不同的后端服务器即可。
好吧,接下来,我们正式进入nginx自定义模块的编写中来。
一. nginx 自定义模块编写 由于这也是我第一次写nginx模块,所以也是参考了非常多文档,我一一列在这里,所以详细的入门就不说了,只说比较不太一样的地方。 参考链接:
而我们这个模块一个最大的特点就是,需要等包体整个接收完才能进行处理,所以有如下代码:
void&ngx_http_foo_post_handler(ngx_http_request_t&*r){&&&&&//&请求全部读完后从这里入口,&可以产生响应&&&&&ngx_http_request_body_t*&rrb&=&r-request_&&&&&&&char*&body&=&NULL;&&&&&int&body_size&=&0;&&&&&&&if&(rb&&&&rb-buf)&&&&&{&&&&&&&&&body&=&(char*)rb-buf-&&&&&&&&&body_size&=&rb-buf-last&-&rb-buf-&&&&&}&&&&&&&int&result&=&get_route_id(r-connection-log,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&(int)r-method,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&(char*)r-uri.data,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&(char*)r-args.data,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&body,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&body_size&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&);&&&&&if&(result&&)&&&&&{&&&&&&&&&ngx_log_error(NGX_LOG_ERR,&r-connection-log,&0,&&get_route_id&fail,&result:%d&,&result);&&&&&&&&&result&=&DFT_ROUTE_ID;&&&&&}&&&&&ngx_http_finalize_request(r,&result);&&&}&static&ngx_int_t&ngx_http_req_route_handler(ngx_http_request_t&*r)&{&&&&&ngx_http_read_client_request_body(r,&ngx_http_foo_post_handler);&&&&&return&NGX_DONE;&//&主handler结束&}&
我们注册了一个回调函数 ngx_http_foo_post_handler,当包体全部接受完成时就会调用。之后我们调用了get_route_id来获取返回码,然后通过 ngx_http_finalize_request(r, result); 来告诉nginx处理的结果。
这里有个小插曲,即get_route_id。我们来看一下它定义的原型:
extern&int&get_route_id(ngx_log_t&*log,&int&method,&char*&uri,&char*&args,&char*&body,&int&body_size)&
第一个参数是 ngx_log_t *log,是为了方便在报错的时候打印日志。然而在最开始的时候,get_route_id 的原型是这样:
extern&int&get_route_id(ngx_http_request_t&*r,&int&method,&char*&uri,&char*&args,&char*&body,&int&body_size);&
结果在 get_route_id 函数内部,调用:
r-connection-log&
的结果总是null,至今也不知道为什么。
OK,接下来我们只要在get_route_id中增加逻辑代码,读几行配置,判断一下就可以了~ 但是,我想要的远不止如此。
二、lua解析器的加入
老博友应该都看过我之前写的一篇博客:&,而这一次的需求也非常符合使用脚本的原则:
只需要告诉我返回nginx哪个返回码,具体怎么算出来的,再复杂,再多变,都放到脚本里面去。
所以接下来我又写了c调用lua的代码:
int&get_route_id(ngx_log_t&*log,&int&method,&char*&uri,&char*&args,&char*&body,&int&body_size)&{&&&&&const&char&lua_funcname[]&=&&get_route_id&;&&&&&lua_State&*L&=&luaL_newstate();&&&&&luaL_openlibs(L);&&&&&if&(luaL_loadfile(L,&LUA_FILENAME)&||&lua_pcall(L,&0,&0,&0))&&&&&{&&&&&&&&&ngx_log_error(NGX_LOG_ERR,&log,&0,&&cannot&run&configuration&file:&%s&,&lua_tostring(L,&-1));&&&&&&&&&lua_close(L);&&&&&&&&&return&-1;&&&&&}&&&&&&lua_getglobal(L,&lua_funcname);&/*&function&to&be&called&*/&&&&&lua_pushnumber(L,&method);&&&&&lua_pushstring(L,&uri);&&&&&lua_pushstring(L,&args);&&&&&lua_pushlstring(L,&body,&body_size);&&&&&/*&do&the&call&(1&arguments,&1&result)&*/&&&&&if&(lua_pcall(L,&4,&1,&0)&!=&0)&&&&&{&&&&&&&&&ngx_log_error(NGX_LOG_ERR,&log,&0,&&error&running&function&%s:&%s&,&lua_funcname,&lua_tostring(L,&-1));&&&&&&&&&lua_close(L);&&&&&&&&&return&-2;&&&&&}&&&&&/*&retrieve&result&*/&&&&&if&(!lua_isnumber(L,&-1))&&&&&{&&&&&&&&&ngx_log_error(NGX_LOG_ERR,&log,&0,&&function&%s&must&return&a&number&,&lua_funcname);&&&&&&&&&lua_close(L);&&&&&&&&&return&-3;&&&&&}&&&&&int&result&=&(int)lua_tonumber(L,&-1);&&&&&&&lua_pop(L,&1);&/*&pop&returned&value&*/&&&&&&&lua_close(L);&&&&&return&&}&
比较郁闷的是,lua 5.2的很多函数都变了,比如lua_open废弃,变成luaL_newstate等,不过总体来说还算没浪费太多时间。
接下来是req_route.lua的内容,我只截取入口函数如下:
function&get_route_id(method,&uri,&args,&body)&&&&&loc,&pf&,appid&=&get_need_vals(method,&uri,&args,&body)&&&&&if&loc&==&nil&or&pf&==&nil&or&appid&==&nil&then&&&&&&&&&return&OUT_CODE&&&&&end&&&&&--到这里位置,就把所有的数据都拿到了&&&&&--print&(loc,&pf,&appid)&&&&&--&找是否在对应的url,&loc中&&&&&if&not&is_match_pf_and_loc(pf,&loc)&then&&&&&&&&&return&OUT_CODE&&&&&end&&&&&--&找是否在对应的appid中&&&&&if&not&is_match_appid(appid)&then&&&&&&&&&return&OUT_CODE&&&&&end&&&&&return&IN_CODE&end&
OK,结合了lua解析器之后,无论多复杂的调整,我们都基本可以做到只修改lua脚本而不需要重新修改、编译nginx模块代码了。
接下来,就该是体验我们的成果了。
三、Nginx配置
server&{&&&&&listen&&&&&&&8080;&&&&&server_name&&&&&&&&&location&/req_route&{&&&&&&&&&req_&&&&&&&&&error_page&433&=&@433;&&&&&&&&&error_page&434&=&@434;&&&&&}&&&&&location&@433&{&&&&&&&&&proxy_pass&http://localhost:6788;&&&&&}&&&&&location&@434&{&&&&&&&&&proxy_pass&http://localhost:6789;&&&&&}&&&&&error_page&&&500&502&503&504&&/50x.&&&&&location&=&/50x.html&{&&&&&&&&&root&&&&&&&&}&}&
OK,enjoy it!
最后,放出代码如下:
【编辑推荐】【责任编辑: TEL:(010)】
大家都在看猜你喜欢
头条头条外电头条外电
24H热文一周话题本月最赞
讲师:0人学习过
讲师:0人学习过
讲师:5人学习过
精选博文论坛热帖下载排行
本书着重介绍标准C++语言,即1998年由ISO正式推出的关于C++的国际性标准版本。
本书从最基础的编程语言概念讲起,共分6篇24章。前4篇完整...
订阅51CTO邮刊  nginx服务器绑定域名以及设置根目录非常方便,首先进入nginx安装目录,然后执行&vim conf/nginx.conf&打开nginx的配置文件,找到
  server {
    .....
    .....
  这个代码段,这段代码就是用来配置对应站点的,首先我们应该在域名控制面板将域名解析到我们服务器的IP地址,然后绑定才可以生效
  首先在我们的代码段中找到server_name这一项然后把后面的域名改成我们要绑定的域名即可
  root这一项就是指定的根目录,设置成我们指定的目录即可
  如果我们想绑定多个域名怎么办,或者是各种二级域名,比如hao.、tools.这样的二级域名;首先还是将域名解析到服务器,然后整体复制上面server{}代码段重复粘贴到下面即可,这样构造出多个server就是多站点配置了,注意要复制全,大括号要对称,并且shell脚本中大括号和前面的语句之间必须有空格或者换行,这个很重要比如server { 或者if () {等一定要注意,其他的都很容易理解;当然很多集成包中会在和配置文件nginx.conf同目录下设置一个vhost这样的代码虚拟主机的目录,对于绑定多个域名设置多个配置文件,比如aa.conf、bb.conf这些文件,然后在nginx.conf使用include vhost/*.全部引入,引入相当于所有代码写在nginx.conf中一样,并且不用考虑其他目录的关系,都以nginx.conf为准,这样方便管理,比如aa.conf;
  其他规则配置也可以像上面一样建立多个文件的方式统一管理,全部配置完毕保存退出,然后重新启动服务器即可生效了
  另外listen指定的就是站点端口,可以在不冲突的前提下自定义配置,server_name指定域名、index 指定默认首页、root指定根目录就够了,这样基本的这些配置就能够掌握了
阅读(...) 评论()当前位置:&>&&>&
Nginx服务器防CC攻击设置
时间: 16:35:48    来源:服务器之家    投稿:root
Nginx是一款轻量级的Web服务器,由俄罗斯的程序设计师Igor
Sysoev所开发,最初供俄国大型的入口网站及搜寻引Rambler使用。 其特点是占有内存少,并发能力强,事实上Nginx的并发能力确实在同类型的网站服务器中表现较好。
Nginx虽然可以比Apache处理更大的连接数,但是HTTP
FLOOD针对的不仅仅是WEB服务器,还有数据库服务器。大量HTTP请求产生了大量的数据库查询,可以在几秒之内使数据库停止响应,系统负载升高,最终导致服务器当机。
1.主动抑制
为了让Nginx支持更多的并发连接数,根据实际情况对工作线程数和每个工作线程支持的最大连接数进行调整。例如设置“worker_processes
10”和“worker_connections 1024”,那这台服务器支持的最大连接数就是10×。
worker_processes 10;
& & worker_connections 10240;
0.7开始提供了2个限制用户连接的模块:NginxHttpLimitZoneModule和NginxHttpLimitReqModule。
NginxHttpLimitZoneModule可以根据条件进行并发连接数控制。
例如可以定义以下代码:
& & limit_zone & my_zone &$binary_remote_addr &10m;
& & server {
& & & & location /somedir/ {
& & & & & & limit_conn & my_zone &1;
其中“limit_zone my_zone $binary_remote_addr
10m”的意思是定义一个名称为my_zone的存储区域、my_zone中的内容为远程IP地址、my_zone的大小为10M;“location
/somedir/”的意思是针对somedir目录应用规则;“limit_conn my_zone
1”的意思是针对上面定义的my_zone记录区记录的IP地址在指定的目录中只能建立一个连接。
NginxHttpLimitReqModule可以根据条件进行请求频率的控制。
例如可以定义以下代码:
& & limit_req_zone &$binary_remote_addr &zone=my_req_zone:10m & rate=1r/s;
& & server {
& & & & ...
& & & & location /somedir/ {
& & & & & & limit_req_zone & zone= my_req_zone &burst=2;
其中“limit_req_zone $binary_remote_addr zone=my_req_zone:10m
rate=1r/s”的意思是定义一个名称为my_req_zone的存储区域,my_req_zone内容为远程IP地址,my_req_zone大小为10M,my_req_zone中的平均请求速率只能为1个每秒;“location
/somedir/”的意思是针对somedir目录应用规则;“limit_req_zone zone= my_req_zone
burst=2”的意思是针对上面定义的my_req_zone记录区记录的IP地址在请求指定的目录中的内容时最高2个每秒的突发请求速率。
当有连接触发上诉规则时,Nginx会报“503 Service Temporarily
Unavailable”的错误,停止用户请求。返回一个503,对服务器来说影响不大,只占用一个nginx的线程而已,相对来说还是很划算的。
为了测试效果,我将以上代码放入Nginx的配置文件,并编写了一个php文件显示phpinfo;另外还写了一个html文件,其中嵌入了多个iframe调用php文件。当我打开这个html文件了,可以看到只有一个iframe中的php文件正常显示了,其他的iframe都显示503错误。
应用举例(Discuz!)
Discuz!是使用比较多的一个php论坛程序。以Discuz!7.0为例,程序目录下有比较多的可以直接访问的php文件,但其中最容易受到攻击的一般有index.php(首页)、forumdisplay.php(板块显示)、viewthread.php(帖子显示)。攻击者一般会对这些页面发起大量的请求,导致HTTP服务器连接数耗尽、mysql数据库停止响应,最终导致服务器崩溃。
为了防止上述页面被攻击,我们可以设定以下的规则进行防御:
& & limit_zone & myzone_bbs &$binary_remote_addr &10m;
& & limit_req_zone $binary_remote_addr zone=bbs:10m rate=1r/s;
& & server {
& & & & ...
& & & & location ~ ^/bbs/(index|forumdisplay|viewthread).php$ {
& & & & & & limit_conn & myzone_bbs &3;
& & & & & & limit_req zone=bbs burst=2
& & & & & & root & & & & &
& & & & & & fastcgi_pass & unix:/dev/shm/php-cgi.
& & & & & & fastcgi_index &index.
& & & & & & fastcgi_param &SCRIPT_FILENAME &/usr/share/nginx/html$fastcgi_script_
& & & & & & include & & & &fastcgi_
应用这条规则后,bbs目录下的index.php、forumdisplay.php和viewthread.php这些页面同一个IP只许建立3个连接,并且每秒只能有1个请求(突发请求可以达到2个)。
虽然这样的规则一般来说对正常的用户不会产生影响(极少有人在1秒内打开3个页面),但是为了防止影响那些手快的用户访问,可以在nginx中自定义503页面,503页面对用户进行提示,然后自动刷新。
在Nginx中自定义503页面:
error_page& &503& &/errpage/503.
503页面的源代码:
&title&页面即将载入....&/title&
&meta http-equiv=content-type c&
&META NAME="ROBOTS" C&
&body bgcolor="#FFFFFF"&
&table cellpadding="0" cellspacing="0" border="0" width="700" align="center" height="85%"&
&tr align="center" valign="middle"&
&table cellpadding="10" cellspacing="0" border="0" width="80%" align="center" style="font-family:
Verdana, T color: #666666; font-size: 11px"&
&td valign="middle" align="center" bgcolor="#EBEBEB"&
&br /&&b style="font-size: 16px"&页面即将载入&/b&
&br /&&br /&你刷新页面的速度过快。请少安毋躁,页面即将载入...
&br /&&br /&[&a href="javascript:window.location.reload();"&&font color=#666666&立即重新载入&/font&&/a&]
&br /&&br /&
&SCRIPT language=javascript&
function update()
window.location.reload();
setTimeout("update()",2000);
2.被动防御
虽然主动防御已经抵挡了大多数HTTP GET
FLOOD攻击,但是道高一尺魔高一丈,攻击者会总会找到你薄弱的环节进行攻击。所以我们在这里也要介绍一下被动防御的一些方法。
1)封IP地址
访问者通过浏览器正常访问网站,与服务器建立的连接一般不会超过20个,我们可以通过脚本禁止连接数过大的IP访问。
以下脚本通过netstat命令列举所有连接,将连接数最高的一个IP如果连接数超过150,则通过 iptables阻止访问:
status=`netstat -na|awk '$5 ~ /[0-9]+:[0-9]+/ {print $5}' |awk -F ":" -- '{print $1}' |sort -n|uniq -c |sort -n|tail -n 1`
NUM=`echo $status|awk '{print $1}'`
IP=`echo $status|awk '{print $2}'`
result=`echo "$NUM & 150" | bc`
if [ $result = 1 ]
echo IP:$IP is over $NUM, BAN IT!
/sbin/iptables -I INPUT -s $IP -j DROP
运行crontab -e,将上述脚本添加到crontab每分钟自动运行:
通过apache自带的ab工具进行服务器压力测试:
ab -n 1000 -c 100 /bbs/index.php
测试完成后,我们就可以看到系统中有IP被封的提示:
[ ~]#tail /var/spool/mail/root
Content-Type: text/ charset=ANSI_X3.4-1968
Auto-Submitted: auto-generated
X-Cron-Env: &SHELL=/bin/sh&
X-Cron-Env: &HOME=/root&
X-Cron-Env: &;PATH=/usr/bin:/bin&
X-Cron-Env: &LOGNAME=root&
X-Cron-Env: &USER=root&
IP:58.246.xx.xx is over 1047, BAN IT!
至此,又一次HTTP GET FLOOD防御成功。
2)根据特征码屏蔽请求(对CC攻击效果较好)
一般同一种CC攻击工具发起的攻击请求包总是相同的,而且和正常请求有所差异。
当服务器遭遇CC攻击时,我们可以快速查看日志,分析其请求的特征,比如User-agent。下面的是某一次CC攻击时的User-agent
Mozilla/4.0 ( MSIE 5.01; Windows NT 5.0; MyIE 3.01)Cache-Control: no-store, must-revalidate
几乎没有正常的浏览器会在User-agent中带上“must-revalidate”这样的关键字。所以我们可以以这个为特征进行过滤,将User-agent中带有“must-revalidate”的请求全部拒绝访问:
if ($http_user_agent ~ must-revalidate) {
return 403;
本文主要介绍了nginx下的HTTP GET
FLOOD防御,如果有不对的地方,希望大家可以向我提出。同时,也希望大家能够举一反三,把这种思路应用到apache、lighttpd等常见的web服务器中。
转载请注明原文地址:nginx如何设置自定义404页面 - Nginx教程 - SJY之家
404错误是WWW网站访问容易出现的错误。最常见的出错提示:404 NOT FOUND。404错误页的设置对网站SEO有很大的影响,而设置不当,比如直接转跳主页等,会被搜索引擎降权拔毛。404页面的目的应该是告诉用户:你所请求的页面是不存在的,同时引导用户浏览网站其他页面而不是关掉窗口离去。搜索引擎通过HTTP状态码来识别网页的状态。当搜索引擎获得了一个错误链接时,网站应该返回404状态码,告诉搜索引擎放弃对该链接的索引。而如果返回200或302状态码,搜索引擎就会为该链接建立索引,这导致大量不同的链接指向了相同的网页内容。结果是,搜索引擎对网站的信任度大幅降低。
下面是LNMP设置Nginx 404错误页教程:
1、vi /usr/local/nginx/conf/nginx.conf 编辑Nginx配置文件,在http 区段添加下面代码:
fastcgi_intercept_
2、编辑网站配置文件,比如本站:vi /usr/local/nginx/conf/.conf ,在server 区段添加下面代码:
error_page 404 = /404.&
注意:有网友测试上行代码需要去掉等号才会返回正确的404状态,所以请同学们自行测试是否要去掉等号。
3、测试配置文件是否正确:/usr/local/nginx/sbin/nginx -t ,返回下面代码通过:
the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
configuration file /usr/local/nginx/conf/nginx.conf test is successful
4、重启LNMP生效:/root/lnmp restart 。
5、404错误页面制作的注意事项:
不要将404错误转向到网站主页,否则可能会导致主页在搜索引擎中被降权或消失   
不要使用绝对URL,如果使用绝对URL返回的状态码是302+200,这样会产生大量的重复网页。
404页面设置完成,一定要检查是否正确。http头信息返回的一定要是404状态。这个可以通过服务器头部信息检查工具进行检查。
404页面不要自动跳转,让用户来决定去向。
自定义的404页面必须大于512字节,否则可能会出现IE默认的404页面。
欢迎转载,但请保留原文地址
最多浏览的文档The page is temporarily unavailable
nginx error!
The page you are looking for is temporarily unavailable.
Please try again later.
Website Administrator
Something has triggered an error on your
This is the default error page for
nginx that is distributed with
It is located
/usr/share/nginx/html/50x.html
You should customize this error page for your own
site or edit the error_page directive in
the nginx configuration file
/etc/nginx/nginx.conf.

我要回帖

更多关于 阿里云服务器添加网站 的文章

 

随机推荐