当前位置: 首页 > 新闻中心 > 自定义nginx系统的配置方法,数据处理方法,装置

自定义nginx系统的配置方法,数据处理方法,装置

发布时间:2024-02-24 5:06:12

  1. nginx可以给html加自定义头部吗
  2. 隐藏 HTTP 响应头中 Server 和 X-Power-By 信息
  3. 如何在nginx方向代理的响应头中添加age。

一、nginx可以给html加自定义头部吗

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 响应头中 Server 和 X-Power-By 信息

在浏览网页时,通过开发者工具可以查看一些 http 传输时的信息,比如说响应头部的信息。

一些网站的 response headersb 部分会有 server 和 x-powered-by 数据项的值,通过这些值我们可以得到部分信息。比如说使用的 nginx 1.17.3 版本,以及使用了 php 7.3.10 语言。暴露这些信息可能会对网站的安全性有影响,所以很多的网站都会隐藏这些信息。

接下来介绍一下如何隐藏或修改这些信息,很简单的几步就可以实现了!

关闭 x-powered-by:

在 php.ini 中找到 expose_php 选项,将值修改为 off 即可隐藏。

隐藏 nginx 版本号:

在 nginx 配置文件中加入即可

修改完后重启 nginx 和 php-fpm

x-powered-by 数据项未展示,server 数据项的值为 nginx。

如果想将 server 的值进行自定义,需要在编译的时候进行配置,这里就不介绍了。

文章同步发布在我的个人博客中,传送门 hesunfly blog

三、如何在nginx方向代理的响应头中添加age。

可以通过add_header x-cache "$upstream_cache_status"; 来增加响应头中缓存是否命中, 我想知道如何可以在响应头中增加age,即缓存存在的时间长度。