nginx lua在重写之前无法设置标头

时间:2016-05-05 08:20:30

标签: redirect nginx lua openresty

我的redis服务器中有一组IP地址被阻止。现在,当客户提出请求时,

  1. 请求必须由nginx拦截
  2. 检查remote_addr是否属于被阻止的IP
  3. 如果ip被阻止,则添加标头
  4. 然后使用request_uri重定向到实际的ip地址。
  5. nginx.conf

    worker_processes  1;
    
    events {
        worker_connections  1024;
    }
    
    http {
        include       mime.types;
        default_type  application/octet-stream;
    
        sendfile        on;
    
        keepalive_timeout  65;
    
        lua_shared_dict ip_status 1m;
    
        server {
            listen       9080;
            server_name  localhost;
            location ~ .* {
                rewrite_by_lua_file src/ip_check.lua;
            }
        }
    }
    

    的src / ip_check.lua

    -- redis configuration
    local redis_host                = "127.0.0.1"
    local redis_port                = 6379  -- connection timeouts for redis in ms.
    local redis_max_idle_timeout    = 10000
    local redis_pool_size           = 2     --  don't set this too high!
    local redis_timeout             = 200
    
    -- check a set with this key for blacklist entries
    local redis_key         = ngx.var.remote_addr
    local ip_status         = ngx.shared.ip_status
    local status_unblocked  = "0"
    local status_blocked    = "1"
    -- cache lookups for this many seconds
    local cache_ttl         = 1800
    
    local redirect_host             = "http://192.168.12.103:8080/Spring4MVCHelloWorld1"
    local header_ip_status_key      = "Ip-Status"
    -- value of the header to be sent when the client ip address is blocked
    local header_ip_status_value    = "block"
    local add_header                = status_unblocked
    
    -- lookup the value in the cache
    local cache_result = ip_status:get(redis_key)
    if cache_result then
      if cache_result == status_blocked then
        add_header = status_blocked
      end
    else
      -- lookup against redis
      local resty = require "resty.redis"
      local redis = resty:new()
      redis:set_timeout(redis_timeout)
    
      local connected, err = redis:connect(redis_host, redis_port)
      if not connected then
        ngx.log(ngx.ERR, "ip_check: could not connect to redis @"..redis_host..":"..redis_port.." - "..err)
      else
        ngx.log(ngx.ALERT, "ip_check: found connect to redis @"..redis_host..":"..redis_port.." - successful")
    
        local result, err = redis:get(redis_key)
        if not result then
          ngx.log(ngx.ERR, "ip_check: lookup failed for "..ngx.var.remote_addr.." - "..err)
        else
          if result == status_blocked then
            add_header = status_blocked
          end
    
          -- cache the result from redis
          ip_status:set(ip, add_header, cache_ttl)
        end
    
        redis:set_keepalive(redis_max_idle_timeout, redis_pool_size)
      end
    end
    
    ngx.log(ngx.ALERT, "ip_check: "..header_ip_status_key.." of "..ngx.var.remote_addr.." is "..add_header)
    if add_header == status_blocked then
        ngx.header[header_ip_status_key] = header_ip_status_value
        ngx.req.set_header(header_ip_status_key, header_ip_status_value)
    end
    
    ngx.redirect(redirect_host..ngx.var.request_uri)
    

    出于测试目的,我在值为1的redis中添加了127.0.0.1密钥。因此,重定向uri应该使用附加标头来命中。我面临的问题是无论我使用什么ngx.header或ngx.req.set_header, Ip-Status 标头都没有发送到重定向请求,而结束api也没有收到它

    例如,如果我在浏览器中点击http://localhost:9080/hello

    请求标题

    Host:"localhost:9080"
    User-Agent:"Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:46.0) Gecko/20100101 Firefox/46.0"
    Accept:"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
    Accept-Language:"en-US,en;q=0.5"
    Accept-Encoding:"gzip, deflate"
    Connection:"keep-alive"
    

    回复标题

    Connection:"keep-alive"
    Content-Length:"166"
    Content-Type:"text/html"
    Date:"Thu, 05 May 2016 08:06:33 GMT"
    Location:"http://192.168.12.103:8080/Spring4MVCHelloWorld1/hello"
    Server:"openresty/1.9.7.2"
    ip-status:"block"
    

    重定向的uri是http://localhost:9080/hello

    请求标题

    Host:"192.168.12.103:8080"
    User-Agent:"Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:46.0) Gecko/20100101 Firefox/46.0"
    Accept:"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
    Accept-Language:"en-US,en;q=0.5"
    Accept-Encoding:"gzip, deflate"
    Cookie:"JSESSIONID=4834843FE0E76170E429028E096A66E5"
    Connection:"keep-alive"
    

    回复标题

    Content-Language:"en-US"
    Content-Length:"166"
    Content-Type:"text/html;charset=UTF-8"
    Date:"Thu, 05 May 2016 08:06:33 GMT"
    Server:"Apache-Coyote/1.1"
    

    我能够在原始请求的响应标头中看到 Ip-Status 标头,但在重定向的uri的请求标头中却看不到。有关如何将标头发送到重定向的uri的任何帮助都将非常有用。

    我是nginx和lua的新手。问,因为如果问题已经被问到,我无法找到任何相应的问题。

1 个答案:

答案 0 :(得分:0)

浏览器重定向到重定向的uri,而nginx无法控制标头。所以,我删除了

ngx.redirect(redirect_host..ngx.var.request_uri)

从src / ip_check.lua并更改了nginx.conf以进行代理调用,我能够观察到api能够接收到额外的标头。

修改后的nginx.conf

worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    keepalive_timeout  65;
    lua_shared_dict ip_status 1m;

    server {
        listen       9080;
        server_name  localhost;
        location ~ .* {
            set $backend_host   "http://192.168.12.103:8080/Spring4MVCHelloWorld1";
            access_by_lua_file src/ip_check.lua;
            proxy_pass $backend_host$request_uri;
        }
    }
}

此修改后的nginx.conf将向 $ backend_host $ request_uri 发出请求,浏览器将不知道所做的重定向。因此,在进行代理调用时,将发送由ngx.req.set_header设置的标头。所以,

ngx.header[header_ip_status_key] = header_ip_status_value

也可以从src / ip_check.lua中删除。