nginx 의 일반 보안 설정

7512 단어 nginxlua
다 같이 토론 을 해 볼 까요?
  • 프로젝트 일반 설정, 예 를 들 어 default.conf
  • server {
        #  lua          
        include conf.d/lua_core.conf;
        #      localtion   
        include conf.d/limits.conf;
    
        #  dcoment_root
        root /var/www/html/default/public;
    
        #       localtion   
        include conf.d/rewrite/thinkphp.conf;
    
        #   
        location = /lua {
            set $loggable 0;
            default_type text/html;
            content_by_lua 'ngx.say("hello world")';
            #              ,          
            include conf.d/lua/must_be_human.conf;
        }
    
        access_log /var/log/nginx/access.default.log json_log buffer=64k flush=10s if=$loggable;
        error_log /var/log/nginx/error.default.log error;
    }
  • nginx 의 주 입구 nginx.conf
  • user  nginx;
    worker_processes  auto;
    
    pid /var/run/nginx.pid;
    error_log  /var/log/nginx/nginx_error.log warn;
    
    worker_rlimit_nofile 51200;
    
    events {
        use epoll;
        worker_connections 51200;
        multi_accept on;
    }
    
    http  {
        include /etc/nginx/mime.types;
        default_type  application/octet-stream;
        
        server_names_hash_bucket_size 128;
        client_header_buffer_size 32k;
        large_client_header_buffers 4 32k;
        client_max_body_size 50m;
        client_body_buffer_size 5m;
        client_body_temp_path /var/cache/nginx/client_body_temp 1 2;
        
        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;
        
        client_body_timeout 30;
        client_header_timeout 30;
        keepalive_timeout 30;
        send_timeout 30;
        
        fastcgi_connect_timeout 300;
        fastcgi_send_timeout 300;
        fastcgi_read_timeout 300;
        fastcgi_buffer_size 1m;
        fastcgi_buffers 8 1m;
        fastcgi_busy_buffers_size 2m;
        fastcgi_temp_file_write_size 4m;
        fastcgi_temp_path /var/cache/nginx/fastcgi_temp 1 2;
        
        proxy_http_version 1.1;
        proxy_buffer_size 1m;
        proxy_buffers 4 1m;
        proxy_busy_buffers_size 2m;
        proxy_temp_file_write_size 2m;
        proxy_cache_path /var/cache/nginx/nginx_proxy_cache levels=1:2 keys_zone=cache_one:500m inactive=1d max_size=10g;
        
        gzip on;
        gzip_min_length  1k;
        gzip_buffers 4 16k;
        gzip_http_version 1.1;
        gzip_comp_level 4;
        gzip_types text/plain application/javascript application/x-javascript text/javascript text/css application/json;
        gzip_vary on;
        gzip_proxied expired no-cache no-store private auth;
        gzip_disable "MSIE [1-6]\.";
        
        server_tokens off;
        access_log off;
        autoindex off;
        
        open_file_cache max=102400 inactive=20s;
        open_file_cache_valid 30s;
        open_file_cache_min_uses 2;
        open_file_cache_errors on;
        
        map $http_x_forwarded_for $clientRealIp {
            ""  $remote_addr;
            ~^(?P[0-9\.]+),?.*$  $firstAddr;
        }
        
        map $sent_http_content_type $expires {
            default                    1d;
            text/html                  off;
            text/css                   1d;
            application/javascript     1d;
            ~image/                    1d;
        }
        
        map $host $resp_body {
            default "";
        }
        
        map $host $loggable {
            default 1;
        }
        
        map $host $request_body_sub {
            default "";
        }
        
        #    json  ,   jq      
        log_format json_log escape=json '{"realip":"$clientRealIp","timestamp":"$time_iso8601","host":"$http_host","request":"$request","req_body":"$request_body_sub","status":"$status","resp_body":"$resp_body","size":$body_bytes_sent,"ua":"$http_user_agent","cookie":"$http_cookie","req_time":"$request_time","uri":"$uri","referer":"$http_referer","xff":"$http_x_forwarded_for","ups_status":"$upstream_status","ups_addr":"$upstream_addr","ups_time":"$upstream_response_time"}';
        
        lua_need_request_body on;
        #     ,    lua module
        lua_load_resty_core off;
        
        include /etc/nginx/conf.d/vhost/*.conf;
    }
  • lua_core.conf 중의 일부 내용
  • #        log 
    body_filter_by_lua_block {
        if ngx.var.request_method == "POST" then
            ngx.var.request_body_sub = string.sub(ngx.var.request_body or "", 1, 1000)
    
            local resp_body = string.sub(ngx.arg[1] or "", 1, 1000)
            ngx.ctx.buffered = (ngx.ctx.buffered or "") .. resp_body
            if ngx.arg[2] then
                ngx.var.resp_body = ngx.ctx.buffered
            end
        end
    }
    
    #    server     
    rewrite_by_lua_block {
        local body = nil
        if ngx.var.request_method == "POST" then
            ngx.req.read_body()
            body = ngx.unescape_uri(string.sub(ngx.var.request_body or "", 1, 1000))
        elseif ngx.var.request_method == "GET" then
            body = ngx.unescape_uri(string.sub(ngx.var.args or "", 1, 1000))
        end
        
        --              
        if body and string.len(body) >= 8 then
            local patterns = {
                "(shell_exec|phpinfo|system|passthru|preg_\\w+|execute|echo)\\s*\\(",
            }
    
            for _, pattern in pairs(patterns) do
                local match = ngx.re.match(body, pattern, "ijo")
                if match then
                    ngx.status = 200
                    ngx.say("hello world")
                    ngx.exit(200)
                end
            end
        end
    }
  • limits.conf
  • #https      
    add_header X-Frame-Options SAMEORIGIN;
    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection "1; mode=block";
    add_header strict-transport-security "max-age=31536000; includeSubDomains";
    
    fastcgi_hide_header X-Powered-By;
    
    #      METHOD
    if ($request_method !~ ^(GET|POST|HEAD|OPTION)$) {
        return 405;
    }
    
    #            
    if ($http_user_agent ~* (pytho[n]?|curl|wget)) {
        return 403;
    }
    
    #       thinkphp    
    if ($request_uri ~* ^/index\.php) {
        return 405;
    }
    
    #letsencrypt           
    location ^~ /.well-known {
        try_files $uri $uri/ =404;
        access_log off;
    }
    
    #          
    #eg: /upload/../index.php
    location ~ /\. {
        deny all;
    }
    
    #upload php     ,      
    location ~* /upload[s]?/.*\.php$ {
        return 404;
    }
    
    #              
    location ~* \.(map|gif|jpg|png|css|js|ico|swf|pdf|apk|exe|eot|otf|ttf|woff|woff2)$ {
        try_files $uri =404;
        access_log off;
    }
    
    location = /favicon.ico {
        try_files $uri =404;
        access_log off;
    }
  • lua 의 일부 응용
  • #        cookie,            
    rewrite_by_lua_block {
        local random = ngx.var.cookie_random
    
        if(random == nil) then
            random = math.random(999999)
        end
    
        local token = ngx.md5("salt" .. ngx.var.remote_addr .. random)
        if (ngx.var.cookie_token ~= token) then
            ngx.header["Set-Cookie"] = {"token=" .. token, "random=" .. random}
            return ngx.redirect(ngx.var.scheme .. "://" .. ngx.var.host .. ngx.var.request_uri)
        end
    }
  • thinkphp.conf 관련 설정
  • location / {
        try_files $uri $uri/ /index.php?s=$uri&$query_string;
    }
    
    #      php     
    location = /index.php {
        try_files $uri =404;
        fastcgi_pass   php-fpm:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root/index.php; # $fastcgi_script_name
        include        fastcgi_params;
    }

    좋은 웹페이지 즐겨찾기