
Ich verwende zwei Serverblöcke, um alle Anfragen an einen Hauptblock weiterzuleiten, der alle Anfragen mit einem https://www
Präfix bedient. Wenn ich https://www
innerhalb der Anfrage einen 405-Fehler auslöse, wird die entsprechende Fehlerseite wie erwartet angezeigt.
Wenn ich jedoch nur das Präfix http
oder verwende https
und Postman zum Senden einer DELETE- oder PATCH-Anforderung verwende, durchläuft die Anforderung einen der ersten beiden Serverblöcke und es wird kein Fehler zurückgegeben. Die Seite wird normal angezeigt, als ob eine GET-Anforderung gestellt worden wäre.
Wie ändere ich meine Konfiguration, sodass Fehler unabhängig vom Präfix der Anfrage angezeigt werden?
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;
}
}
}
Antwort1
nginxDokumentationsagt folgendes:
Die angegebene Bedingung wird ausgewertet. Wenn sie zutrifft, werden die in Klammern angegebenen Modulanweisungen ausgeführt und der Anfrage wird die Konfiguration innerhalb der if-Anweisung zugewiesen. Konfigurationen innerhalb der if-Anweisungen werden von der vorherigen Konfigurationsebene übernommen.
In Ihrer Beispielkonfiguration würde dies bedeuten, dass die return 301
Konfiguration von der übergeordneten Konfigurationsebene übernommen wird. Aus der Dokumentation geht nicht hervor, was passiert, wenn sowohl die vorherige als auch die aktuelle Konfigurationsebene eine return
Anweisung enthalten. Aus Ihrem Ergebnis scheint jedoch hervorzugehen, dass die übernommene Anweisung erhalten bleibt.
Es wurde bereits vorgeschlagen, dass die Umleitung in einen Standort aufgenommen wird. Ich schreibe hier eine genaue Konfiguration, um hervorzuheben, wie der Konfigurationsblock aussehen sollte:
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;
}
}
Eine andere Möglichkeit ist die Verwendung von limit_except
. Dies ist eine ungetestete Version:
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
erlaubt GET- und POST-Methoden, alle anderen werden verweigert. HEAD wird implizit durch die Erlaubnis von GET zugelassen.
error_page
Die Direktive wird verwendet, um 403
den Fehlercode in deny all
einen 405
Rückgabecode zu übersetzen und die Fehlerseite anzuzeigen.