前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Nginx - 集成Waf 功能

Nginx - 集成Waf 功能

作者头像
小小工匠
发布2024-05-26 13:45:37
1030
发布2024-05-26 13:45:37
举报
文章被收录于专栏:小工匠聊架构小工匠聊架构

核心内容

代码语言:javascript
复制
 if ($request_method !~ ^(GET|PUT|POST)$ ) {
         return 444;
      }
    if ($query_string ~* (\$|'|--|[+|(%20)]union[+|(%20)]|[+|(%20)]insert[+|(%20)]|[+|(%20)]drop[+|(%20)]|[+|(%20)]truncate[+|(%20)]|[+|(%20)]update[+|(%20)]|[+|(%20)]from[+|(%20)]|[+|(%20)]grant[+|(%20)]|[+|(%20)]exec[+|(%20)]|[+|(%20)]where[+|(%20)]|[+|(%20)]select[+|(%20)]|[+|(%20)]and[+|(%20)]|[+|(%20)]or[+|(%20)]|[+|(%20)]count[+|(%20)]|[+|(%20)]exec[+|(%20)]|[+|(%20)]chr[+|(%20)]|[+|(%20)]mid[+|(%20)]|[+|(%20)]like[+|(%20)]|[+|(%20)]iframe[+|(%20)]|[\<|%3c]script[\>|%3e]|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 ~* "[+|(%20)]union[+|(%20)]") { return 504;   }
    if ($request_uri ~* "[+|(%20)]and[+|(%20)]") { return 504;   }
    if ($request_uri ~* "[+|(%20)]select[+|(%20)]") { return 504;   }
    if ($request_uri ~* "[+|(%20)]or[+|(%20)]") { return 504;   }
    if ($request_uri ~* "[+|(%20)]delete[+|(%20)]") { return 504;   }
    if ($request_uri ~* "[+|(%20)]update[+|(%20)]") { return 504;   }
    if ($request_uri ~* "[+|(%20)]insert[+|(%20)]") { return 504;   }
    if ($query_string ~ "(<|%3C).*script.*(>|%3E)") { 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}(=|\%3D)") { 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 ~* (\$|'|--|[+|(%20)]union[+|(%20)]|[+|(%20)]insert[+|(%20)]|[+|(%20)]drop[+|(%20)]|[+|(%20)]truncate[+|(%20)]|[+|(%20)]update[+|(%20)]|[+|(%20)]from[+|(%20)]|[+|(%20)]grant[+|(%20)]|[+|(%20)]exec[+|(%20)]|[+|(%20)]where[+|(%20)]|[+|(%20)]select[+|(%20)]|[+|(%20)]and[+|(%20)]|[+|(%20)]or[+|(%20)]|[+|(%20)]count[+|(%20)]|[+|(%20)]exec[+|(%20)]|[+|(%20)]chr[+|(%20)]|[+|(%20)]mid[+|(%20)]|[+|(%20)]like[+|(%20)]|[+|(%20)]iframe[+|(%20)]|[\<|%3c]script[\>|%3e]|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 ~* "[+|(%20)]union[+|(%20)]") { return 504; }
if ($request_uri ~* "[+|(%20)]and[+|(%20)]") { return 504; }
if ($request_uri ~* "[+|(%20)]select[+|(%20)]") { return 504; }
if ($request_uri ~* "[+|(%20)]or[+|(%20)]") { return 504; }
if ($request_uri ~* "[+|(%20)]delete[+|(%20)]") { return 504; }
if ($request_uri ~* "[+|(%20)]update[+|(%20)]") { return 504; }
if ($request_uri ~* "[+|(%20)]insert[+|(%20)]") { return 504; }

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


代码语言:javascript
复制
if ($query_string ~ "(<|%3C).*script.*(>|%3E)") { 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}(=|\%3D)") { 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 ~* (\$|'|--|[+|(%20)]union[+|(%20)]|[+|(%20)]insert[+|(%20)]|[+|(%20)]drop[+|(%20)]|[+|(%20)]truncate[+|(%20)]|[+|(%20)]update[+|(%20)]|[+|(%20)]from[+|(%20)]|[+|(%20)]grant[+|(%20)]|[+|(%20)]exec[+|(%20)]|[+|(%20)]where[+|(%20)]|[+|(%20)]select[+|(%20)]|[+|(%20)]and[+|(%20)]|[+|(%20)]or[+|(%20)]|[+|(%20)]count[+|(%20)]|[+|(%20)]exec[+|(%20)]|[+|(%20)]chr[+|(%20)]|[+|(%20)]mid[+|(%20)]|[+|(%20)]like[+|(%20)]|[+|(%20)]iframe[+|(%20)]|[\<|%3c]script[\>|%3e]|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 ~* "[+|(%20)]union[+|(%20)]") { return 504; }
        if ($request_uri ~* "[+|(%20)]and[+|(%20)]") { return 504; }
        if ($request_uri ~* "[+|(%20)]select[+|(%20)]") { return 504; }
        if ($request_uri ~* "[+|(%20)]or[+|(%20)]") { return 504; }
        if ($request_uri ~* "[+|(%20)]delete[+|(%20)]") { return 504; }
        if ($request_uri ~* "[+|(%20)]update[+|(%20)]") { return 504; }
        if ($request_uri ~* "[+|(%20)]insert[+|(%20)]") { return 504; }
        if ($query_string ~ "(<|%3C).*script.*(>|%3E)") { 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}(=|\%3D)") { 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代理及其连接设置和上游服务器。
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-05-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 核心内容
  • 附 Nginx.conf
相关产品与服务
SSL 证书
腾讯云 SSL 证书(SSL Certificates)为您提供 SSL 证书的申请、管理、部署等服务,为您提供一站式 HTTPS 解决方案。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档