Nginx - 集成Waf 功能

2024-05-26 13:45:37 浏览数 (2)

核心内容

代码语言:javascript复制
 if ($request_method !~ ^(GET|PUT|POST)$ ) {
         return 444;
      }
    if ($query_string ~* ($|'|--|[ |( )]union[ |( )]|[ |( )]insert[ |( )]|[ |( )]drop[ |( )]|[ |( )]truncate[ |( )]|[ |( )]update[ |( )]|[ |( )]from[ |( )]|[ |( )]grant[ |( )]|[ |( )]exec[ |( )]|[ |( )]where[ |( )]|[ |( )]select[ |( )]|[ |( )]and[ |( )]|[ |( )]or[ |( )]|[ |( )]count[ |( )]|[ |( )]exec[ |( )]|[ |( )]chr[ |( )]|[ |( )]mid[ |( )]|[ |( )]like[ |( )]|[ |( )]iframe[ |( )]|[<|<]script[>|>]|javascript|alert|webscan|dbappsecurity|style|confirm(|innerhtml|innertext)(.*)$) { return 555;   }
    if ($uri ~* (/~).*) { return 501;   }
    if ($uri ~* (\x.)) { return 501;   }
    if ($query_string ~* "[;'<>].*") { return 509;   }
    if ($request_uri ~ " ") { return 509;   }
    if ($request_uri ~ (/. )) { return 509;   }
    if ($request_uri ~ (. /)) { return 509;   }
    if ($uri ~* (insert|select|delete|update|count|master|truncate|declare|exec|*|')(.*)$ ) { return 503;   }
    if ($request_uri ~* "(cost()|(concat()") { return 504;   }
    if ($request_uri ~* "[ |( )]union[ |( )]") { return 504;   }
    if ($request_uri ~* "[ |( )]and[ |( )]") { return 504;   }
    if ($request_uri ~* "[ |( )]select[ |( )]") { return 504;   }
    if ($request_uri ~* "[ |( )]or[ |( )]") { return 504;   }
    if ($request_uri ~* "[ |( )]delete[ |( )]") { return 504;   }
    if ($request_uri ~* "[ |( )]update[ |( )]") { return 504;   }
    if ($request_uri ~* "[ |( )]insert[ |( )]") { return 504;   }
    if ($query_string ~ "(<|<).*script.*(>|>)") { return 505;   }
    if ($query_string ~ "GLOBALS(=|[|%[0-9A-Z]{0,2})") { return 505;   }
    if ($query_string ~ "_REQUEST(=|[|%[0-9A-Z]{0,2})") { return 505;   }
    if ($query_string ~ "proc/self/environ") { return 505;   }
    if ($query_string ~ "mosConfig_[a-zA-Z_]{1,21}(=|=)") { return 505;   }
    if ($query_string ~ "base64_(en|de)code(.*)") { return 505;   }
   if ($query_string ~ "[a-zA-Z0-9_]=http://") { return 506;   }
     if ($query_string ~ "[a-zA-Z0-9_]=(..//?) ") { return 506;   }
   if ($query_string ~ "[a-zA-Z0-9_]=/([a-z0-9_.]//?) ") { return 506;   }
    if ($query_string ~ "b(ultram|unicauca|valium|viagra|vicodin|xanax|ypxaieo)b") { return 507;   }
    if ($query_string ~ "b(erections|hoodia|huronriveracres|impotence|levitra|libido)b") {return 507;   }
    if ($query_string ~ "b(ambien|bluespill|cialis|cocaine|ejaculation|erectile)b") { return 507;   }
    if ($query_string ~ "b(lipitor|phentermin|pro[sz]ac|sandyauer|tramadol|troyhamby)b") { return 507;   }
   if ($http_user_agent ~* YisouSpider|ApacheBench|WebBench|Jmeter|JoeDog|Havij|GetRight|TurnitinBot|GrabNet|masscan|mail2000|github|python) { return 508;   }
   if ($http_user_agent ~* "Go-Ahead-Got-It") { return 508;   }
   if ($http_user_agent ~* "GetWeb!") { return 508;   }
    if ($http_user_agent ~* "Go!Zilla") { return 508;   }
   if ($http_user_agent ~* "Download Demon") { return 508;   }
   if ($http_user_agent ~* "Indy Library") { return 508;   }
    if ($http_user_agent ~* "libwww-perl") { return 508;   }
   if ($http_user_agent ~* "Nmap Scripting Engine") { return 508;   }
   if ($http_user_agent ~* "WebBench*") { return 508;   }
    if ($http_user_agent ~* "spider") { return 508;   }
    if ($http_referer ~* WebBench*") { return 509;   }

该代码主要用于Nginx配置文件中,目的是进行请求方法、查询字符串、URI和用户代理的过滤,防止常见的Web攻击和恶意请求。

代码语言:javascript复制
if ($request_method !~ ^(GET|PUT|POST)$ ) {
    return 444;
}

检查请求方法是否是GET、PUT或POST,如果不是,返回状态码444(连接关闭而无响应)。


代码语言:javascript复制
if ($query_string ~* ($|'|--|[ |( )]union[ |( )]|[ |( )]insert[ |( )]|[ |( )]drop[ |( )]|[ |( )]truncate[ |( )]|[ |( )]update[ |( )]|[ |( )]from[ |( )]|[ |( )]grant[ |( )]|[ |( )]exec[ |( )]|[ |( )]where[ |( )]|[ |( )]select[ |( )]|[ |( )]and[ |( )]|[ |( )]or[ |( )]|[ |( )]count[ |( )]|[ |( )]exec[ |( )]|[ |( )]chr[ |( )]|[ |( )]mid[ |( )]|[ |( )]like[ |( )]|[ |( )]iframe[ |( )]|[<|<]script[>|>]|javascript|alert|webscan|dbappsecurity|style|confirm(|innerhtml|innertext)(.*)$) { return 555; }

检查查询字符串是否包含SQL注入和XSS等攻击的常用特征字符串,如果匹配,返回状态码555。


代码语言:javascript复制
if ($uri ~* (/~).*) { return 501; }
if ($uri ~* (\x.)) { return 501; }

检查URI是否包含"/~"或十六进制转义字符,如果匹配,返回状态码501。


代码语言:javascript复制
if ($query_string ~* "[;'<>].*") { return 509; }

检查查询字符串是否包含’;‘、’<‘、’>'字符,如果匹配,返回状态码509。


代码语言:javascript复制
if ($request_uri ~ " ") { return 509; }
if ($request_uri ~ (/. )) { return 509; }
if ($request_uri ~ (. /)) { return 509; }

检查请求URI是否包含空格、“/.“或”./”,如果匹配,返回状态码509。


代码语言:javascript复制
if ($uri ~* (insert|select|delete|update|count|master|truncate|declare|exec|*|')(.*)$ ) { return 503; }

检查URI是否包含SQL命令或’*‘、’''字符,如果匹配,返回状态码503。


代码语言:javascript复制
if ($request_uri ~* "(cost()|(concat()") { return 504; }
if ($request_uri ~* "[ |( )]union[ |( )]") { return 504; }
if ($request_uri ~* "[ |( )]and[ |( )]") { return 504; }
if ($request_uri ~* "[ |( )]select[ |( )]") { return 504; }
if ($request_uri ~* "[ |( )]or[ |( )]") { return 504; }
if ($request_uri ~* "[ |( )]delete[ |( )]") { return 504; }
if ($request_uri ~* "[ |( )]update[ |( )]") { return 504; }
if ($request_uri ~* "[ |( )]insert[ |( )]") { return 504; }

检查请求URI是否包含"cost("或"concat("函数,或者URI中包含的SQL命令(如union、and、select、or、delete、update、insert)前后有空格或’ '符号,如果匹配,返回状态码504。


代码语言:javascript复制
if ($query_string ~ "(<|<).*script.*(>|>)") { return 505; }
if ($query_string ~ "GLOBALS(=|[|%[0-9A-Z]{0,2})") { return 505; }
if ($query_string ~ "_REQUEST(=|[|%[0-9A-Z]{0,2})") { return 505; }
if ($query_string ~ "proc/self/environ") { return 505; }
if ($query_string ~ "mosConfig_[a-zA-Z_]{1,21}(=|=)") { return 505; }
if ($query_string ~ "base64_(en|de)code(.*)") { return 505; }

检查查询字符串是否包含<script>标签、


代码语言:javascript复制
if ($query_string ~ "[a-zA-Z0-9_]=http://") { return 506; }
if ($query_string ~ "[a-zA-Z0-9_]=(..//?) ") { return 506; }
if ($query_string ~ "[a-zA-Z0-9_]=/([a-z0-9_.]//?) ") { return 506; }

检查查询字符串是否包含"http://“、路径遍历攻击(如”…/“)或绝对路径攻击(如”/path/to/file"),如果匹配,返回状态码506。


代码语言:javascript复制
if ($query_string ~ "b(ultram|unicauca|valium|viagra|vicodin|xanax|ypxaieo)b") { return 507; }
if ($query_string ~ "b(erections|hoodia|huronriveracres|impotence|levitra|libido)b") {return 507; }
if ($query_string ~ "b(ambien|bluespill|cialis|cocaine|ejaculation|erectile)b") { return 507; }
if ($query_string ~ "b(lipitor|phentermin|pro[sz]ac|sandyauer|tramadol|troyhamby)b") { return 507; }

检查查询字符串是否包含常见的药物和成人内容相关的关键词,如果匹配,返回状态码507。


代码语言:javascript复制
if ($http_user_agent ~* YisouSpider|ApacheBench|WebBench|Jmeter|JoeDog|Havij|GetRight|TurnitinBot|GrabNet|masscan|mail2000|github|python) { return 508; }
if ($http_user_agent ~* "Go-Ahead-Got-It") { return 508; }
if ($http_user_agent ~* "GetWeb!") { return 508; }
if ($http_user_agent ~* "Go!Zilla") { return 508; }
if ($http_user_agent ~* "Download Demon") { return 508; }
if ($http_user_agent ~* "Indy Library") { return 508; }
if ($http_user_agent ~* "libwww-perl") { return 508; }
if ($http_user_agent ~* "Nmap Scripting Engine") { return 508; }
if ($http_user_agent ~* "WebBench*") { return 508; }
if ($http_user_agent ~* "spider") { return 508; }

检查HTTP用户代理字符串是否包含常见的扫描工具、下载工具、测试工具和爬虫(如YisouSpider、ApacheBench、Jmeter、Nmap等),如果匹配,返回状态码508。


代码语言:javascript复制
if ($http_referer ~* WebBench*") { return 509; }

检查HTTP引用字符串是否包含"WebBench",如果匹配,返回状态码509。


总结,这段配置通过对请求方法、查询字符串、URI和用户代理的全面检查,能够有效防止各种Web攻击和恶意请求,保护服务器的安全。


附 Nginx.conf

代码语言:javascript复制
# 全局设置,定义Nginx运行的用户和工作进程数
user root;
worker_processes 8;

# 事件块,配置网络连接的处理
events {
    worker_connections 65535; # 每个工作进程的最大连接数
    accept_mutex on; # 启用接受互斥锁,防止惊群现象
}

# HTTP块,配置HTTP服务器相关参数
http {
    include mime.types; # 包含MIME类型映射文件
    default_type application/octet-stream; # 设置默认的MIME类型

    # 配置代理缓存路径及其相关参数
    proxy_cache_path /opt/artisan_Nginx/tmp levels=1 keys_zone=cache_one:512m inactive=60s max_size=1000m;

    # 添加HTTP头信息,用于安全防护
    add_header X-XSS-Protection "1; mode=block";
    
    # 配置子过滤器
    sub_filter_types *; # 过滤所有类型
    sub_filter_once off; # 允许多次过滤
    
    # 设置客户端请求缓冲区大小和超时
    client_body_buffer_size 1k;
    client_header_buffer_size 128k;
    client_max_body_size 1k; # 限制客户端请求体最大值为1k
    large_client_header_buffers 2 1k; # 设置大请求头缓冲区数量和大小
    client_body_timeout 10; # 设置请求体读取超时时间
    client_header_timeout 10; # 设置请求头读取超时时间
    
    # 设置请求速率限制
    limit_req_zone $binary_remote_addr zone=limit_req_zone:10m rate=5r/s;
    
    # 安全相关设置
    server_tokens off; # 关闭服务器版本号显示

    # 传输设置
    sendfile on;
    keepalive_timeout 65; # 设置长连接超时时间
    send_timeout 10; # 设置发送响应超时时间

    # 连接限制设置
    limit_conn_zone $binary_remote_addr zone=perip:10m; # 每IP连接数限制
    limit_conn_zone $server_name zone=perserver:10m; # 每服务器连接数限制

    underscores_in_headers on; # 允许HTTP头中使用下划线

    # 自定义日志格式,包含上游响应时间
    log_format upstream_time '$remote_addr - $remote_user [$time_local] '
                             '"$request" $status $body_bytes_sent '
                             '"$http_referer" "$http_user_agent" '
                             'rt=$request_time uct="$upstream_connect_time" uht="$upstream_header_time" urt="$upstream_response_time"';

    # 上游服务器配置
    upstream gateway {
        sticky; # 会话粘性
        server 127.0.0.1:8888;
    }

    # 请求白名单
    map $request_uri $is_whitelisted {
        default 0;
        ~* ^(/xxxx|/yyyy) 1; # 白名单路径
    }

    # 服务器块,定义特定端口及SSL配置
    server {
        listen 28443 ssl http2;
        ssl_certificate /opt/artisan_Nginx/conf/crt/server.crt;
        ssl_certificate_key /opt/artisan_Nginx/conf/crt/server.key;
        ssl_protocols TLSv1.2 TLSv1.3;
        proxy_intercept_errors on;
        error_page 500 502 503 504 505 /error/5xx.html; # 自定义错误页面
        error_page 400 401 402 403 404 497 /error/4xx.html; # 自定义错误页面
        gzip on; # 开启gzip压缩
        gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml rss text/javascript;
        gzip_static on;
        ssl_session_cache shared:SSL:10m;
        ssl_session_timeout 10m;
        client_max_body_size 800M; # 设置客户端请求体最大值
        ssl_prefer_server_ciphers on;
        ssl_ciphers HIGH:!aNULL:!MD5;
        add_header X-UA-Compatible 'IE=EmulateIE7'; # 兼容IE浏览器
        add_header X-XSS-Protection "1; mode=block";
        add_header X-Content-Type-Options "nosniff";
        add_header Content-Security-Policy "default-src 'self' *; script-src 'self' 'unsafe-inline' 'unsafe-eval' https:; style-src 'self' 'unsafe-inline' https:; img-src 'self' data: https:; font-src 'self' data: https:; connect-src 'self' ws: wss: https:";
        add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
        add_header X-Frame-Options "SAMEORIGIN";
        add_header backendIP $upstream_addr;
        add_header backendCode $upstream_status;
        index index.html index.htm index.jsp index.php;
        limit_rate_after 50m; # 设置限速起始点
        limit_rate 150k; # 设置传输限速
        proxy_read_timeout 600s; # 上游服务器读取超时时间

        # 按日期分割日志
        if ($time_iso8601 ~ "^(d{4})-(d{2})-(d{2})") {
            set $year $1;
            set $month $2;
            set $day $3;
        }
        access_log logs/access-$year-$month-$day.log upstream_time;

        # 跳过白名单检查
        if ($is_whitelisted) { break; }

        # 请求方法限制
        if ($request_method !~ ^(GET|PUT|POST)$ ) {
            return 444;
        }

        # 检查并拦截恶意查询字符串
        if ($query_string ~* ($|'|--|[ |( )]union[ |( )]|[ |( )]insert[ |( )]|[ |( )]drop[ |( )]|[ |( )]truncate[ |( )]|[ |( )]update[ |( )]|[ |( )]from[ |( )]|[ |( )]grant[ |( )]|[ |( )]exec[ |( )]|[ |( )]where[ |( )]|[ |( )]select[ |( )]|[ |( )]and[ |( )]|[ |( )]or[ |( )]|[ |( )]count[ |( )]|[ |( )]exec[ |( )]|[ |( )]chr[ |( )]|[ |( )]mid[ |( )]|[ |( )]like[ |( )]|[ |( )]iframe[ |( )]|[<|<]script[>|>]|javascript|alert|webscan|dbappsecurity|style|confirm(|innerhtml|innertext)(.*)$) {
            return 555;
        }

        # 拦截特定URI请求
        if ($uri ~* (/~).*) { return 501; }
        if ($uri ~* (\x.)) { return 501; }
        if ($query_string ~* "[;'<>].*") { return 509; }
        if ($request_uri ~ " ") { return 509; }
        if ($request_uri ~ (/. )) { return 509; }
        if ($request_uri ~ (. /)) { return 509; }
        if ($uri ~* (insert|select|delete|update|count|master|truncate|declare|exec|*|')(.*)$ ) { return 503; }
        if ($request_uri ~* "(cost()|(concat()") { return 504; }
        if ($request_uri ~* "[ |( )]union[ |( )]") { return 504; }
        if ($request_uri ~* "[ |( )]and[ |( )]") { return 504; }
        if ($request_uri ~* "[ |( )]select[ |( )]") { return 504; }
        if ($request_uri ~* "[ |( )]or[ |( )]") { return 504; }
        if ($request_uri ~* "[ |( )]delete[ |( )]") { return 504; }
        if ($request_uri ~* "[ |( )]update[ |( )]") { return 504; }
        if ($request_uri ~* "[ |( )]insert[ |( )]") { return 504; }
        if ($query_string ~ "(<|<).*script.*(>|>)") { return 505; }
        if ($query_string ~ "GLOBALS(=|[|%[0-9A-Z]{0,2})") { return 505; }
        if ($query_string ~ "_REQUEST(=|[|%[0-9A-Z]{0,2})") { return 505; }
        if ($query_string ~ "proc/self/environ") { return 505; }
        if ($query_string ~ "mosConfig_[a-zA-Z_]{1,21}(=|=)") { return 505; }
        if ($query_string ~ "base64_(en|de)code(.*)") { return 505; }
        if ($query_string ~ "[a-zA-Z0-9_]=http://") { return 506; }
        if ($query_string ~ "[a-zA-Z0-9_]=(..//?) ") { return 506; }
        if ($query_string ~ "[a-zA-Z0-9_]=/([a-z0-9_.]//?) ") { return 506; }
        if ($query_string ~ "b(ultram|unicauca|valium|viagra|vicodin|xanax|ypxaieo)b") { return 507; }
        if ($query_string ~ "b(erections|hoodia|huronriveracres|impotence|levitra|libido)b") {return 507; }
        if ($query_string ~ "b(ambien|bluespill|cialis|cocaine|ejaculation|erectile)b") { return 507; }
        if ($query_string ~ "b(lipitor|phentermin|pro[sz]ac|sandyauer|tramadol|troyhamby)b") { return 507; }

        # 拦截特定的User-Agent
        if ($http_user_agent ~* YisouSpider|ApacheBench|WebBench|Jmeter|JoeDog|Havij|GetRight|TurnitinBot|GrabNet|masscan|mail2000|github|python) { return 508; }
        if ($http_user_agent ~* "Go-Ahead-Got-It") { return 508; }
        if ($http_user_agent ~* "GetWeb!") { return 508; }
        if ($http_user_agent ~* "Go!Zilla") { return 508; }
        if ($http_user_agent ~* "Download Demon") { return 508; }
        if ($http_user_agent ~* "Indy Library") { return 508; }
        if ($http_user_agent ~* "libwww-perl") { return 508; }
        if ($http_user_agent ~* "Nmap Scripting Engine") { return 508; }
        if ($http_user_agent ~* "WebBench*") { return 508; }
        if ($http_user_agent ~* "spider") { return 508; }
        if ($http_referer ~* WebBench*") { return 509; }

        # 默认位置块,代理请求到上游服务器
        location / {
            proxy_pass http://gateway;
            proxy_set_header Host $host:$server_port;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Host $http_host;
            proxy_set_header X-Forwarded-Port $server_port;
            proxy_set_header X-Forwarded-Proto $scheme;
            
            # 重写规则,特定URI重定向
            if ( $uri = '/more' ) {
                rewrite / https://$host:$server_port/core/install/download;
            }
            
            proxy_redirect http:// https://;

            # 设置真实IP
            set $Real $proxy_add_x_forwarded_for;
            if ( $Real ~ (d ).(d ).(d ).(d ),(.*) ){
                set $Real $1.$2.$3.$4;
            }
            
            # 设置静态资源缓存时间
            if ( $request_filename ~ .*.(css|js|jpg|png|gif|swf|woff|woff2|eot|svg|ttf|otf|mp3|m4a|aac|txt)$ ){
                expires 1d;
            }
            proxy_set_header X-real-ip $Real;
        }
        
        # web目录下的静态文件配置
        location /web {
            root html/artisan-web/;
            index index.html index.htm;
            try_files $uri $uri/ /xxxx/index.html;
            expires 1d;
            autoindex on;
            autoindex_exact_size off;
            autoindex_localtime off;
        }
        
        # 错误页面配置
        location /error {
            alias html/;
            index html/index.html;
        }
    }
}

# Stream块,配置TCP/UDP代理
stream {
    upstream socket_proxy {
        hash $remote_addr consistent;
        server 127.0.0.1:15002;
    }

    server {
        listen 15001;
        proxy_connect_timeout 600s;
        proxy_timeout 600s;
        proxy_pass socket_proxy;
    }
}
  • 全局设置:
    • user root; 指定Nginx运行的用户。
    • worker_processes 8; 设置工作进程数。
  • 事件块:
    • 配置每个工作进程的最大连接数和接受互斥锁。
  • HTTP块:
    • 包含MIME类型映射文件,设置默认MIME类型,配置代理缓存路径及其相关参数。
    • 添加安全防护头信息,配置子过滤器、客户端请求缓冲区大小和超时、请求速率限制、安全相关设置、传输设置、连接限制设置、自定义日志格式、上游服务器配置、请求白名单、服务器块。
    • 服务器块配置了SSL证书、错误页面、gzip压缩、会话设置、客户端请求体最大值、安全头信息、后端服务器信息、日志按日期分割、请求方法限制、拦截恶意查询字符串和URI、拦截特定User-Agent、代理请求到上游服务器、静态文件配置和错误页面配置。
  • Stream块:
    • 配置TCP/UDP代理及其连接设置和上游服务器。

0 人点赞