Nginx에서 405 오류 페이지가 기본 서버 블록에는 제대로 표시되지만 기본 블록으로 리디렉션되는 서버 블록에는 표시되지 않는 이유는 무엇입니까?

Nginx에서 405 오류 페이지가 기본 서버 블록에는 제대로 표시되지만 기본 블록으로 리디렉션되는 서버 블록에는 표시되지 않는 이유는 무엇입니까?

두 개의 서버 블록을 사용하여 모든 요청을 접두사가 있는 모든 요청을 처리하는 기본 블록으로 전달합니다 https://www. 요청 시 405 오류가 발생하면 https://www해당 오류 페이지가 예상대로 표시됩니다.

http그러나 접두사 만 사용 https하고 Postman을 사용하여 DELETE 또는 PATCH 요청을 보내면 요청은 처음 2개의 서버 블록 중 하나를 통과하고 오류가 반환되지 않습니다. 페이지는 GET 요청이 이루어진 것처럼 정상적으로 표시됩니다.

요청의 접두사에 관계없이 오류가 표시되도록 구성을 어떻게 변경합니까?

user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {

    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    # access_log  /var/log/nginx/access.log  main;
    access_log off;

    limit_req_zone $binary_remote_addr zone=mylimit:1m rate=50r/s;
    limit_req zone=mylimit burst=20 nodelay;

    sendfile      on;
    tcp_nopush    on;
    sendfile_max_chunk 1m;

    gzip on;
    gzip_comp_level 3;
    gzip_types text/css application/javascript application/x-javascript text/javascript;
    gzip_vary on;

    server_tokens off;
    resolver 8.8.8.8 8.8.4.4 [2001:4860:4860::8888] [2001:4860:4860::8844];

    error_page 400 /html/400.html;
    error_page 403 /html/403.html;
    error_page 404 /html/404.html;
    error_page 405 /html/405.html;
    error_page 500 502 503 504 /html/50x.html;

    server {

        listen 80;
        listen [::]:80;

        server_name example.com www.example.com;

        if ($request_method !~ ^(GET|HEAD|POST)$) {
            return 405;
        }

        return 301 https://www.example.com$request_uri;

    }

    server {

        listen 443 ssl http2;
        listen [::]:443 ssl http2;

        server_name example.com;

        ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
        ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
        include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
        ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

        if ($request_method !~ ^(GET|HEAD|POST)$) {
            return 405;
        }

        return 301 https://www.example.com$request_uri;

    }


    server {

        listen 443 ssl http2;
        listen [::]:443 ssl http2;

        server_name www.example.com;

        ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
        ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
        include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
        ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

        if ($request_method !~ ^(GET|HEAD|POST)$) {
            return 405;
        }

        ssl_stapling on;
        ssl_stapling_verify on;
        ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;

        root /srv/example/views/public;

        location ~* \.(jpg|png|svg|webp|ico)$ {
            valid_referers none blocked server_names ~\.bing\. ~\.duckduckgo\. ~\.facebook\. ~\.google\. ~\.instagram\. ~\.twitter\. ~\.yahoo\.;
            if ($invalid_referer) {
                return 403;
            }
            add_header content-security-policy "default-src 'self';";
            add_header cache-control "public, max-age=31536000";
            add_header x-content-type-options nosniff;
        }

        location ~* \.(css)$ {
            add_header content-security-policy "default-src 'self'; font-src 'self' https://fonts.gstatic.com fonts.googleapis.com; style-src 'self' fonts.googleapis.com;";
            add_header cache-control "public, max-age=2629746";
            add_header x-content-type-options nosniff;
        }

        location ~* \.(htm|html)$ {
            add_header content-security-policy "default-src 'self'; font-src 'self' https://fonts.gstatic.com fonts.googleapis.com; img-src 'self' https://www.youtube.com; media-src 'self' https://www.youtube.com; object-src 'none'; script-src 'self' https://www.google-analytics.com https://apis.google.com https://js.stripe.com; style-src 'self' fonts.googleapis.com;";
            add_header cache-control "public, max-age=2629746";
            add_header feature-policy "autoplay 'none'; legacy-image-formats 'none'; oversized-images 'none'; unsized-media 'none';";
            add_header permissions-policy "autoplay=(); legacy-image-formats=(); oversized-images=(); unsized-media=();";
            add_header referrer-policy strict-origin;
            add_header strict-transport-security "max-age=31557600; includesubdomains";
            add_header x-content-type-options nosniff;
            add_header x-frame-options sameorigin;
        }

        location ~* \.(js)$ {
            add_header content-security-policy "default-src 'self';";
            add_header cache-control "public, max-age=2629746";
            add_header x-content-type-options nosniff;
        }

        location / {
            add_header content-security-policy "default-src 'self'; font-src 'self' https://fonts.gstatic.com fonts.googleapis.com; img-src 'self' https://www.youtube.com; media-src 'self' https://www.youtube.com; object-src 'none'; script-src 'self' https://www.google-analytics.com https://apis.google.com https://js.stripe.com; style-src 'self' fonts.googleapis.com;";
            add_header cache-control "public, max-age=2629746";
            add_header feature-policy "autoplay 'none'; legacy-image-formats 'none'; oversized-images 'none'; unsized-media 'none';";
            add_header permissions-policy "autoplay=(); legacy-image-formats=(); oversized-images=(); unsized-media=();";
            add_header referrer-policy strict-origin;
            add_header strict-transport-security "max-age=31557600; includesubdomains";
            add_header x-content-type-options nosniff;
            add_header x-frame-options sameorigin;
            proxy_hide_header x-powered-by;
            proxy_pass http://127.0.0.1:8080;
        }

    }

    server {

        listen 80;
        listen [::]:80;

        server_name testbed.example.com;

        if ($request_method !~ ^(GET|HEAD|POST)$) {
            return 405;
        }

        return 301 https://testbed.example.com$request_uri;

    }

    server {

        listen 443 ssl http2;
        listen [::]:443 ssl http2;

        server_name testbed.example.com;

        ssl_certificate /etc/letsencrypt/live/testbed.example.com/fullchain.pem; # managed by Certbot
        ssl_certificate_key /etc/letsencrypt/live/testbed.example.com/privkey.pem; # managed by Certbot
        include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
        ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

        if ($request_method !~ ^(GET|HEAD|POST)$) {
            return 405;
        }

        ssl_stapling on;
        ssl_stapling_verify on;
        ssl_trusted_certificate /etc/letsencrypt/live/testbed.example.com/chain.pem;

        root /srv/testbed/views/public;

        location ~* \.(jpg|png|svg|webp|ico)$ {
            valid_referers none blocked server_names ~\.bing\. ~\.duckduckgo\. ~\.facebook\. ~\.google\. ~\.instagram\. ~\.twitter\. ~\.yahoo\.;
            if ($invalid_referer) {
                return 403;
            }
            add_header content-security-policy "default-src 'self';";
            add_header cache-control "public, max-age=31536000";
            add_header x-content-type-options nosniff;
        }

        location ~* \.(css)$ {
            add_header content-security-policy "default-src 'self'; font-src 'self' https://fonts.gstatic.com fonts.googleapis.com; style-src 'self' fonts.googleapis.com;";
            add_header cache-control "public, max-age=2629746";
            add_header x-content-type-options nosniff;
        }

        location ~* \.(htm|html)$ {
            add_header content-security-policy "default-src 'self'; font-src 'self' https://fonts.gstatic.com fonts.googleapis.com; img-src 'self' https://www.youtube.com; media-src 'self' https://www.youtube.com; object-src 'none'; script-src 'self' https://www.google-analytics.com https://apis.google.com https://js.stripe.com; style-src 'self' fonts.googleapis.com;";
            add_header cache-control "public, max-age=2629746";
            add_header feature-policy "autoplay 'none'; legacy-image-formats 'none'; oversized-images 'none'; unsized-media 'none';";
            add_header permissions-policy "autoplay=(); legacy-image-formats=(); oversized-images=(); unsized-media=();";
            add_header referrer-policy strict-origin;
            add_header strict-transport-security "max-age=31557600; includesubdomains";
            add_header x-content-type-options nosniff;
            add_header x-frame-options sameorigin;
        }

        location ~* \.(js)$ {
            add_header content-security-policy "default-src 'self';";
            add_header cache-control "public, max-age=2629746";
            add_header x-content-type-options nosniff;
        }

        location / {
            add_header content-security-policy "default-src 'self'; font-src 'self' https://fonts.gstatic.com fonts.googleapis.com; img-src 'self' https://www.youtube.com; media-src 'self' https://www.youtube.com; object-src 'none'; script-src 'self' https://www.google-analytics.com https://apis.google.com https://js.stripe.com; style-src 'self' fonts.googleapis.com;";
            add_header cache-control "public, max-age=2629746";
            add_header feature-policy "autoplay 'none'; legacy-image-formats 'none'; oversized-images 'none'; unsized-media 'none';";
            add_header permissions-policy "autoplay=(); legacy-image-formats=(); oversized-images=(); unsized-media=();";
            add_header referrer-policy strict-origin;
            add_header strict-transport-security "max-age=31557600; includesubdomains";
            add_header x-content-type-options nosniff;
            add_header x-frame-options sameorigin;
            proxy_hide_header x-powered-by;
            proxy_pass http://127.0.0.1:10001;
        }

    }

}

답변1

nginx선적 서류 비치다음을 알려줍니다.

지정된 조건이 평가됩니다. true인 경우 중괄호 안에 지정된 이 모듈 지시문이 실행되고 요청에는 if 지시문 내부의 구성이 할당됩니다. if 지시어 내부의 구성은 이전 구성 수준에서 상속됩니다.

예제 구성에서는 return 301구성이 상위 구성 수준에서 상속됨을 의미합니다. 문서에는 이전 구성 수준과 현재 수준 모두에 지시어가 포함되어 있을 때 어떤 일이 발생하는지 알려주지 않습니다 return. 그러나 결과에 따르면 상속된 지시어가 보존된 것 같습니다.

리디렉션이 위치 내에 포함될 것이라고 이미 제안되었습니다. 구성 블록이 어떻게 보이는지 강조하기 위해 여기에 정확한 구성을 작성하고 있습니다.

server {
    listen 80;
    listen [::]:80;

    server_name example.com www.example.com;

    if ($request_method !~ ^(GET|HEAD|POST)$) {
        return 405;
    }

    location / {
        return 301 https://www.example.com$request_uri;
    }
}

또 다른 가능성은 을 사용하는 것입니다 limit_except. 이것은 테스트되지 않은 버전입니다:

server {
    listen 80;
    listen [::]:80;

    server_name example.com www.example.com;

    location /
        error_page 403 =405 /html/405.html;
        limit_except GET POST {
            deny all;
        }

        return 301 https://www.example.com$request_uri;
    }
}

limit_exceptGET 및 POST 메소드를 허용하고 다른 모든 메소드는 거부됩니다. GET을 허용하면 HEAD가 암시적으로 허용됩니다.

error_page403지시문은 오류 코드를 반환 코드 deny all로 변환 405하고 오류 페이지를 표시하는 데 사용됩니다.

관련 정보