
Utilizo dos bloques de servidor para reenviar todas las solicitudes a un bloque principal que atiende todas las solicitudes con un https://www
prefijo. Cuando arroja un error 405 https://www
en la solicitud, la página de error correspondiente se muestra como se esperaba.
Sin embargo, cuando uso un prefijo http
o https
solo y uso Postman para enviar una solicitud DELETE o PATCH, la solicitud pasa por uno de los primeros 2 bloques del servidor y no se devuelve ningún error. La página se muestra normalmente como si se hubiera realizado una solicitud GET.
¿Cómo modifico mi configuración para que se muestren los errores independientemente del prefijo de la solicitud?
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;
}
}
}
Respuesta1
nginxdocumentacióndice lo siguiente:
Se evalúa la condición especificada. Si es verdadero, se ejecutan las directivas de este módulo especificadas entre llaves y a la solicitud se le asigna la configuración dentro de la directiva if. Las configuraciones dentro de las directivas if se heredan del nivel de configuración anterior.
En su configuración de ejemplo, esto significaría que la return 301
configuración se hereda del nivel de configuración principal. La documentación no dice qué sucede cuando el nivel de configuración anterior y el nivel actual contienen una return
directiva. Pero según su resultado, parece que se conserva la directiva heredada.
Ya se sugirió que la redirección se incluiría dentro de una ubicación. Estoy escribiendo una configuración exacta aquí para resaltar cómo debería verse el bloque de configuración:
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;
}
}
Otra posibilidad es utilizar limit_except
. Esta es una versión no probada:
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
permite los métodos GET y POST, todos los demás están denegados. HEAD se permite implícitamente al permitir GET.
error_page
La directiva se utiliza para traducir 403
el código de error deny all
al 405
código de retorno y para mostrar la página de error.