
我使用兩個伺服器區塊將所有請求轉發到一個主區塊,該主區塊為所有帶有https://www
前綴的請求提供服務。當我https://www
在請求中拋出 405 錯誤時,相應的錯誤頁面會如預期顯示。
但是,當我使用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_except
允許 GET 和 POST 方法,所有其他方法均被拒絕。透過允許 GET 隱式允許 HEAD。
error_page
指令用於將403
錯誤代碼轉換為deny all
返回405
代碼並顯示錯誤頁面。