Lua是一个可以嵌入到Nginx配置文件中的动态脚本语言,从而可以在Nginx请求处理的任何阶段执行各种Lua代码。刚开始我们只是用Lua 把请求路由到后端服务器,但是它对我们架构的作用超出了我们的预期。下面就讲讲我们所做的工作。
强制搜索引擎只索引mixlr.com
Google把子域名当作完全独立的网站,我们不希望爬虫抓取子域名的页面,降低我们的Page rank。
location /{ header_filter_by_lua ' if ngx.var.query_string and ngx.re.match( ngx.var.query_string, "^([0-9]{10})$" ) then ngx.header["Expires"] = ngx.http_time( ngx.time() + 31536000 ); ngx.header["Cache-Control"] = "max-age=31536000"; end ';
如果对robots.txt的请求不是mixlr.com域名的话,则内部重写到robots_diallow.txt,虽然标准的重写指令也可以实现这个需求,但是 Lua的实现更容易理解和维护。
根据程序逻辑设置响应头
Lua提供了比Nginx默认配置规则更加灵活的设置方式。 在下面的例子中,我们要保证正确设置响应头,这样浏览器如果发送了指定请求头后,就可以 无限期缓存静态文件,是的用户只需下载一次即可。 这个重写规则使得任何静态文件,如果请求参数中包含时间戳值,那么就设置相应的Expires和Cache-Control响应头。
location /{ header_filter_by_lua ' if ngx.var.query_string and ngx.re.match( ngx.var.query_string, "^([0-9]{10})$" ) then ngx.header["Expires"] = ngx.http_time( ngx.time() + 31536000 ); ngx.header["Cache-Control"] = "max-age=31536000"; end '; try_files $uri @dynamic;}
删除jQuery JSONP请求的时间戳参数
很多外部客户端请求JSONP接口时,都会包含一个时间戳类似的参数,从而导致Nginx proxy缓存无法命中(因为无法忽略指定的HTTP参数)。下面的 规则删除了时间戳参数,使得Nginx可以缓存upstream server的响应内容,减轻后端服务器的负载。
location /{ rewrite_by_lua ' if ngx.var.args ~= nil then -- /some_request?_=1346491660 becomes /some_request local fixed_args, count = ngx.re.sub( ngx.var.args, "&?_=[0-9]+", "" ); if count > 0 then return ngx.exec(ngx.var.uri, fixed_args); end end ';}
把后端的慢请求日志记录到Nginx的错误日志
如果后端请求响应很慢,可以把它记录到Nginx的错误日志,以备后续追查。
location /{ log_by_lua ' if tonumber(ngx.var.upstream_response_time) >= 1 then ngx.log(ngx.WARN, "[SLOW] Ngx upstream response time: " .. ngx.var.upstream_response_time .. "s from " .. ngx.var.upstream_addr); end ';}
基于Redis的实时IP封禁
某些情况下,需要阻止流氓爬虫的抓取,这可以通过专门的封禁设备去做,但是通过Lua,也可以实现简单版本的封禁。
lua_shared_dict banned_ips 1m; location /{ access_by_lua ' local banned_ips = ngx.shared.banned_ips; local updated_at = banned_ips:get("updated_at"); -- only update banned_ips from Redis once every ten seconds: if updated_at == nil or updated_at < ( ngx.now() - 10 ) then local redis = require "resty.redis"; local red = redis:new(); red:set_timeout(200); local ok, err = red:connect("your-redis-hostname", 6379); if not ok then ngx.log(ngx.WARN, "Redis connection error retrieving banned_ips: " .. err); else local updated_banned_ips, err = red:smembers("banned_ips"); if err then ngx.log(ngx.WARN, "Redis read error retrieving banned_ips: " .. err); else -- replace the locally stored banned_ips with the updated values: banned_ips:flush_all(); for index, banned_ip in ipairs(updated_banned_ips) do banned_ips:set(banned_ip, true); end banned_ips:set("updated_at", ngx.now()); end end end if banned_ips:get(ngx.var.remote_addr) then ngx.log(ngx.WARN, "Banned IP detected and refused access: " .. ngx.var.remote_addr); return ngx.exit(ngx.HTTP_FORBIDDEN); end ';}
现在就可以阻止特定IP的访问:
ruby> $redis.sadd("banned_ips","200.1.35.4")
Nginx进程每隔10秒从Redis获取一次最新的禁止IP名单。需要注意的是,如果架构中使用了Haproxy这样类似的负载均衡服务器时, 需要把$remote_addr设置为正确的远端IP地址。
这个方法还可以用于HTTP User-Agent字段的检查,要求满足指定条件。
使用Nginx输出CSRF(form_authenticity_token)
Mixlr大量使用页面缓存,由此引入的一个问题是如何给每个页面输出会话级别的CSRF token。我们通过Nginx的子请求,从upstream web server 获取token,然后利用Nginx的SSI(server-side include)功能输出到页面中。这样既解决了CSRF攻击问题,也保证了cache能被正常利用。
location /csrf_token_endpoint {internal; include /opt/nginx/conf/proxy.conf; proxy_pass "http://upstream";} location @dynamic{ ssi on;set $csrf_token ''; rewrite_by_lua ' -- Using a subrequest, we our upstream servers for the CSRF token for this session: local csrf_capture = ngx.location.capture("/csrf_token_endpoint"); if csrf_capture.status == 200 then ngx.var.csrf_token = csrf_capture.body; -- if this is a new session, ensure it sticks by passing through the new session_id -- to both the subsequent upstream request, and the response: if not ngx.var.cookie_session then local match = ngx.re.match(csrf_capture.header["Set-Cookie"], "session=([a-zA-Z0-9_+=/+]+);"); if match then ngx.req.set_header("Cookie", "session=" .. match[1]); ngx.header["Set-Cookie"] = csrf_capture.header["Set-Cookie"]; end end else ngx.log(ngx.WARN, "No CSRF token returned from upstream, ignoring."); end '; try_files /maintenance.html /rails_cache$uri @thin;}
CSRF token生成 app/metal/csrf_token_endpoint.rb:
classCsrfTokenEndpointdefself.call(env)if env["PATH_INFO"]=~/^\/csrf_token_endpoint/ session = env["rack.session"]||{} token = session[:_csrf_token]if token.nil? token =SecureRandom.base64(32) session[:_csrf_token]= token end[200,{"Content-Type"=>"text/plain"},[ token ]]else[404,{"Content-Type"=>"text/html"},["Not Found"]]end endend
我们的模版文件示例:
<metaname=”csrf-param”value=”authenticity_token”/> <meta name=”csrf-token” value=”<!–# echo var=”csrf_token” default=”” encoding=”none” –>”/>
Again you could make use of lua_shared_dict to store in memory the CSRF token for a particular session. This minimises the number of trips made to /csrf_token_endpoint.
原文链接:http://devblog.mixlr.com/2012/09/01/nginx-lua/
相关推荐
基于lua的nginx自定义负载均衡基于lua的nginx自定义负载均衡
Nginx与Docker的Lua模块基于带有Lua模块的Alpine Nginx,并支持sass语言。 Nginx版本:1.12.2 SASS版本:3.5.4建造要构建容器,请运行: docker build -t your-name .跑步要启动容器运行: docker run --name your-...
nginx+lua+redis实现token验证。实现基本的token验证、反向代理转发内部服务,lua连接redis封装、lua域名解析封装、lua域名脚本等
基于nginx+lua+dyups实现服务自定义调度资源整理,自定义服务调度主要是指根据不同客户端请求进行判断,转发到不同的服务集群。
nginx+lua+redis通过匹配客户端ip进行灰度发布
Nginx实战:基于Lua语言的配置、开发与架构详解
nginx-lua-GraphicsMagick Nginx + Lua + GraphicsMagick,实现自定义图片尺寸功能,支持两种模式[固定高宽模式,定高或定宽模式],支持FastDFS文件存储github地址: : 说明类似淘宝图片,实现自定义图片尺寸功能,...
nginx+lua+redis 集群 连接插件和脚本,原来插件是没有密码功能 故 修改了一下 k可以自己下载使用
Lua是一种跟JavaScript很像的语言,Ngix_Lua同样使用...通过lua-nginx-module即可在nginx上启动lua脚本。 一个例子: 代码如下: location / { content_by_lua ‘ local res = ngx.location.capture(“/sub”) i
lua模块,并且将Nginx核心、LuaJIT、ngx_lua模块、许多有用的Lua库和常用的第三方Nginx模块组合在一起成为OpenResty,这样开发人员就可以安装OpenResty,使用Lua编写脚本,然后部署到Nginx Web容器中运行。...
需求大致如下:通过url传参的方式,让Nginx代理到不同的服务器 浏览器输入:http://127.0.0.1/remote?port=8081被代理到:http://192.168.108.2:8081
自己构建镜像bilxio/nginx-lua-waf ,在nginx-lua-waf文件夹执行如下命令: docker build -t bilxio/nginx-lua-waf . 或者,直接拉它, docker pull bilxio/nginx-lua-waf 要运行映像并将端口 8080 转发到...
主要介绍了Nginx中使用Lua脚本配置示例,本文以一个Lua拦截器为例讲解如何配置使用Lua脚本,需要的朋友可以参考下
nginx安装lua、jwt模块,通过lua验证jwt实现蓝绿发布样例demo,配置直接可用 luajit2-2.1-20220411.tar.gz #luajit官网存在一定的坑,下载openresty的优化版本 lua-nginx-module-0.10.22.tar.gz # 0.10.16 以后都...
OpenResty 是一个强大的 Web 应用服务器,Web 开发人员可以使用 Lua 脚本语言调动 Nginx 支持的各种 C 以及 Lua 模块,更主要的是在性能方面,OpenResty可以 快速构造出足以胜任 10K 以上并发连接响应的超高性能 Web ...
(阿里云负载均衡)或者 lvs+Tengine(nginx)+lua防护攻击(获取用户真实ip):线上正式使用,可以修改lua达到自己想要效果; 记得修改以下获取真实ip function getClientIp() IP = ngx.var....
我们选择使用OpenResty,其是由Nginx核心加很多第三方模块组成,其最大的亮点是默认集成了Lua开发环境...目前在京东如实时价格、秒杀、动态服务、单品页、列表页等都在使用Nginx+Lua架构,其他公司如淘宝、去哪儿网等。
nginx添加站点脚本
报错内容:sbin/nginx: error while loading shared libraries: libpcre.so.1: cannot open shared object file: No such file or directory 启动时如果报异常error while loading shared libraries: libpcre.so....
教你如何搭建一个图片切割和缩放的服务 1.搭建GraphicsMagick服务 2.配置nginx 3.修改Lua脚本 详情见文档