nginx 获取真实 IP 的疑问,以及 nginx lua redis 防 CC 针对部分 IP 不起作用的问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
ladyv2
V2EX    NGINX

nginx 获取真实 IP 的疑问,以及 nginx lua redis 防 CC 针对部分 IP 不起作用的问题

  •  
  •   ladyv2 2017-06-14 21:31:24 +08:00 6812 次点击
    这是一个创建于 3111 天前的主题,其中的信息可能已经有所发展或是发生改变。

    服务器是公网 IP,单机所以没有用反向代理 是不是这种情况下,$remote_addr 就会始终是真实 IP 呢?

    我额外设置了

    fastcgi_param HTTP_X_FORWARDED_FOR $remote_addr; 

    这样就能保证$remote_addr 始终是用户的真实 IP 呢?

    我在这样的配置下,参考下面的文章 配置了 redis 和 lua https://blog.linuxeye.cn/453.html

    然后修改了其中的 IP 部分为

    function getClientIp() IP = ngx.var.remote_addr return IP end 

    然后检测 redis,发现可以正确生成黑白名单数据。但是,检查 php 的 log。发现依然会出现部分 Ip 的高频访问,这些 IP 没有被加入黑名单。比如下面这个 ip,几个小时内访问了 60W 次,基本上每秒 100 次请求。而没有被加入黑名单

    61.151.186.217 - - [14/Jun/2017:03:27:49 +0800] "GET /index.php HTTP/1.1" 302 154 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.81 Safari/537.36" "-" 61.151.186.217 - - [14/Jun/2017:03:27:49 +0800] "GET /index.php HTTP/1.1" 302 154 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.81 Safari/537.36" "-" 61.151.186.217 - - [14/Jun/2017:03:27:49 +0800] "GET /index.php HTTP/1.1" 302 154 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.81 Safari/537.36" "-" 61.151.186.217 - - [14/Jun/2017:03:27:49 +0800] "GET /index.php HTTP/1.1" 302 154 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.81 Safari/537.36" "-" 61.151.186.217 - - [14/Jun/2017:03:27:49 +0800] "GET /index.php HTTP/1.1" 302 154 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.81 Safari/537.36" "-" 

    有没有大神帮忙分析下是哪里配置有错误呢

    16 条回复    2018-01-04 13:29:40 +08:00
    Phant0m
        1
    Phant0m  
       2017-06-14 22:00:11 +08:00
    ```
    local function getClientIp()
    local headers = ngx.req.get_headers()
    if not headers['x-forwarded-for'] then
    realIp = ngx.var.remote_addr or '127.0.0.1'
    return realIp
    end
    if type(headers['x-forwarded-for']) == "table" then
    realIp = headers['x-forwarded-for'][1]
    else
    realIp = headers['x-forwarded-for']
    end
    return realIp
    end
    ```
    blackjar
        2
    blackjar  
       2017-06-14 23:40:46 +08:00
    服务器设置 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    之后取 X-Forwarded-For 的第一个段值 可以拿到真实 ip
    ladyv2
        3
    ladyv2  
    OP
       2017-06-15 06:56:51 +08:00
    @Phant0m @blackjar 感谢回复
    但是不起作用的 IP,从 log 上看并没有出现 x_forwarded_for。所以我不是很明白为什么 lua 没有起作用呢
    ladyv2
        4
    ladyv2  
    OP
       2017-06-15 09:44:49 +08:00
    今天看 log,又出现了

    61.151.186.154 - - [15/Jun/2017:01:30:00 +0800] "GET / HTTP/1.1" 302 154 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.81 Safari/537.36" "-"
    61.151.186.154 - - [15/Jun/2017:01:30:00 +0800] "GET / HTTP/1.1" 302 154 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.81 Safari/537.36" "-"

    访问次数 61.151.186.154 次
    但是看 redis,完全没有记录。。

    redis /tmp/redis.sock> keys 61.151.186
    (empty list or set)

    非常奇怪
    Phant0m
        5
    Phant0m  
       2017-06-15 11:57:02 +08:00 via iPhone
    @ladyv2 那你完整的代码贴出来看看
    ladyv2
        6
    ladyv2  
    OP
       2017-07-12 14:43:59 +08:00
    @Phant0m 代码如下

    local get_headers = ngx.req.get_headers
    local ua = ngx.var.http_user_agent
    local uri = ngx.var.request_uri
    local url = ngx.var.host .. uri
    local redis = require 'redis'
    local red = redis.new()
    local CCcount = 100
    local CCsecOnds= 30
    local blacksecOnds= 7200

    if ua == nil then
    ua = "unknown"
    end

    local redis = require "resty.redis"
    local red = redis:new()
    red:set_timeout(1000) -- 1 sec

    local ok, err = red:connect("localhost")
    if not ok then
    ngx.say("failed to connect: ", err)
    return
    end
    local res, err = red:auth("password1")
    if not res then
    ngx.say("failed to authenticate: ", err)
    return
    end

    if ok then
    function getClientIp()
    IP = ngx.var.remote_addr
    --[[
    IP = ngx.req.get_headers()["X-Real-IP"]
    if IP == nil then
    IP = ngx.req.get_headers()["x_forwarded_for"]
    end
    if IP == nil then
    IP = ngx.var.remote_addr
    end
    if IP == nil then
    IP = "unknown"
    end
    --]]
    return IP
    end
    local token = getClientIp() .. "." .. ngx.md5(url .. ua)
    local req = red:exists(token)
    if req == 0 then
    red:incr(token)
    red:expire(token,CCseconds)
    else
    local times = tonumber(red:get(token))
    if times >= CCcount then
    local blackReq = red:exists("black." .. token)
    if (blackReq == 0) then
    red:set("black." .. token,1)
    red:expire("black." .. token,blackseconds)
    red:expire(token,blackseconds)
    ngx.exit(503)
    else
    ngx.exit(503)
    end
    return
    else
    red:incr(token)
    end
    end
    return
    end
    -- put it into the connection pool of size 100,
    -- with 10 seconds max idle time
    local ok, err = red:set_keepalive(10000, 1000)
    if not ok then
    return
    end
    Phant0m
        7
    Phant0m  
       2017-07-12 15:35:58 +08:00
    @ladyv2 你代码里 存入 redis 的 key 不是 IP 啊,key 是 token = getClientIp() .. "." .. ngx.md5(url .. ua) ,直接取 IP 当然是空
    Phant0m
        8
    Phant0m  
       2017-07-12 15:42:22 +08:00
    还有最好把 IP 作为 key,如果按照你代码写的用 token,那么攻击者可以不停的更换 url 来达到攻击的目的
    ladyv2
        9
    ladyv2  
    OP
       2017-07-12 22:47:19 +08:00
    @Phant0m 不是啊。查看是不是屏蔽也是查看的这个 token 啊。查看 redis 也是有被屏蔽的

    1) "black.202.141.176.9.7c879b2da20d1694c748b1a70b8d9281"
    2) "black.1.180.215.60.9a394cf0c48fba4606c9757d3d8527c5"

    采用这个 token 也是经过考虑的。如果单纯用 IP,很容易把一些通过代理或者共用 IP 的地址封掉。所以只能采用 IP+URL+浏览器来计算
    Phant0m
        10
    Phant0m  
       2017-07-13 00:13:22 +08:00
    @ladyv2 你 27 天前的那个回复取的是 IP。。。 计数器可以用 ngx_lua 的内存字典,然后再放入 redis
    ladyv2
        11
    ladyv2  
    OP
       2017-07-13 08:15:01 +08:00
    @Phant0m 其实是一样的啊,利用 token 来屏蔽 IP
    现在的问题就是像我主楼发的一样,有的 IP 大量访问同样的 URL (几十万次),居然没被屏蔽。这就是我没搞明白的问题。。。
    Phant0m
        12
    Phant0m  
       2017-07-13 18:51:25 +08:00
    @ladyv2 日能说能说一切
    Phant0m
        13
    Phant0m  
       2017-07-13 18:52:05 +08:00
    @ladyv2 日志能说明一切
    chinaglwo
        14
    chinaglwo  
       2017-12-01 21:53:58 +08:00
    @ladyv2 解决了没有? nginx 的其他配置里面,有没有 if 判断,if 很容易导致各种各样的问题。
    chinaglwo
        15
    chinaglwo  
       2017-12-01 21:55:29 +08:00
    fastcgi_param HTTP_X_FORWARDED_FOR $remote_addr;
    这个配置是不是很多余?
    ladyv2
        16
    ladyv2  
    OP
       2018-01-04 13:29:40 +08:00
    @chinaglwo 不多于的,防止伪造 IP 啊
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2466 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 10:54 PVG 18:54 LAX 02:54 JFK 05:54
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86