使用Lua或Perl保护Nginx远离CC攻击

Published: Tags: LINUX NGINX

简单,以下方法不需要额外安装模块:

location ~ \.php$ {
    if ($cookie_reCAPTCHA != "$remote_addr"){
        add_header Set-Cookie "reCAPTCHA=$remote_addr; PATH=/";
        rewrite .* "$scheme://$host$uri" redirect;
        #rewrite .* "$scheme://localhost:$remote_port" redirect;
    }
    
    ... ...
}

进阶,返回JS跳转代码过滤模拟访问:

location ~ \.php$ {
    default_type text/html;
    if ($cookie_reCAPTCHA != "$remote_addr"){
        add_header Set-Cookie "reCAPTCHA=$remote_addr; PATH=/";
        return 200 "<script>location.reload()</script>\n";
    }
    
    ... ...
}

PERL,返回JS设置COOKIE并自动刷新:

http {
    perl_set $reCAPTCHA 'sub{use Digest::MD5 qw(md5_base64); md5_base64("SALT",shift->variable("remote_addr"))}';
    ... ...
    server {
        ... ...
        location ~ \.php$ {
            default_type text/html;
            if ($cookie_reCAPTCHA != $reCAPTCHA){ #访问非text/html会异常,换用add_header设置Cookie避免js无法执行
                return 200 '<script>\ndocument.cookie="reCAPTCHA=$reCAPTCHA";\nlocation.reload();\n</script>\n';
            }
            ... ...
        }
    }
}

综合以上方法,笔者当前使用的配置:

http {
    perl_set $reCAPTCHA 'sub{use Digest::MD5 qw(md5_base64); my $r = shift;
    md5_base64($r->variable("remote_addr")."|SALT:RANDOM|".$r->variable("http_user_agent"))}';
    ... ...
    server {
        ... ...
        location / {
            default_type text/html;
            if ($cookie_reCAPTCHA != $reCAPTCHA){
                add_header Set-Cookie "reCAPTCHA=$reCAPTCHA; PATH=/";
                return 200 '<script>location.reload()</script>';
            }
            proxy_pass http://www.baidu.com;
        }
    }
}

LUA,大同小异,可能需要安装扩展:apt-get install nginx-extras

location ~ \.php$ {
    rewrite_by_lua '
        local md5token = ngx.md5(ngx.var.remote_addr .. "|SALT:RANDOM|" .. ngx.var.http_user_agent)
        if (ngx.var.cookie_reCAPTCHA ~= md5token) then
            ngx.header.content_type = "text/html"
            ngx.header["Set-Cookie"] = "reCAPTCHA=" .. md5token .. "; PATH=/"
            ngx.say("<script>location.reload()</script>")
            return ngx.exit(ngx.OK)
        end
    ';

    ... ...
}

参考: https://jiji262.github.io/wooyun_articles/drops/通过nginx配置文件抵御攻击.html