Nginx als Reverse-Proxy ohne Zwischenspeicherung

Nginx als Reverse-Proxy ohne Zwischenspeicherung

Ich versuche, Nginx als Caching-Reverse-Proxy zu konfigurieren. Der Ursprungsserver ist Apache und hostet eine WordPress-Instanz, falls das wichtig ist.

Die Reverse-Proxy-Funktionalität funktioniert wie erwartet, aber der Cache scheint nicht zu funktionieren. Wenn ich die gleiche statische Ressource zweimal hintereinander erhalte, erhalte ich sie x-proxy-cache: MISSzweimal.

assodigitale.it ist die Domäne, 138.201.87.123 die IP-Adresse des Ursprungsservers und 138.201.87.124 die IP-Adresse des Nginx-Proxys.

Der Ursprungsserver scheint zu antworten und dem Proxy zu erlauben, die Ressource zwischenzuspeichern:

$ curl --connect-to ::138.201.87.123:443 --http2 -I https://assodigitale.it/wp-content/uploads/2018/03/aereo.jpg
HTTP/2 200 
date: Sun, 11 Mar 2018 20:59:39 GMT
server: Apache/2.4.25 (Debian)
content-length: 32989
strict-transport-security: max-age=31536000; includeSubdomains; preload
last-modified: Wed, 07 Mar 2018 09:34:41 GMT
etag: "80dd-566cf44ca2952"
accept-ranges: bytes
vary: Accept-Encoding
cache-control: max-age=1209600, public
x-content-type-options: nosniff
content-type: image/jpeg

Die erste Anfrage an den Proxyserver führt wie erwartet zu einem MISS:

$ curl --connect-to ::138.201.87.124:443 --http2 -I https://assodigitale.it/wp-content/uploads/2018/03/aereo.jpg
HTTP/2 200 
server: nginx/1.13.9
date: Sun, 11 Mar 2018 21:04:00 GMT
content-type: image/jpeg
content-length: 32989
strict-transport-security: max-age=31536000; includeSubdomains; preload
last-modified: Wed, 07 Mar 2018 09:34:41 GMT
etag: "80dd-566cf44ca2952"
vary: Accept-Encoding
cache-control: max-age=1209600, public
x-content-type-options: nosniff
x-proxy-cache: MISS
strict-transport-security: max-age=4838400; includeSubDomains; preload
accept-ranges: bytes

Die zweite Anfrage an den Nginx-Proxy sollte zu einem HIT führen, führt aber zu einem weiteren MISS:

$ curl --connect-to ::138.201.87.124:443 --http2 -I https://assodigitale.it/wp-content/uploads/2018/03/aereo.jpg
HTTP/2 200 
server: nginx/1.13.9
date: Sun, 11 Mar 2018 21:05:52 GMT
content-type: image/jpeg
content-length: 32989
strict-transport-security: max-age=31536000; includeSubdomains; preload
last-modified: Wed, 07 Mar 2018 09:34:41 GMT
etag: "80dd-566cf44ca2952"
vary: Accept-Encoding
cache-control: max-age=1209600, public
x-content-type-options: nosniff
x-proxy-cache: MISS
strict-transport-security: max-age=4838400; includeSubDomains; preload
accept-ranges: bytes

Hier ist der relevante Teil meiner Nginx-Konfiguration:

proxy_cache_path /srv/cache/nginx levels=1:2 keys_zone=revproxy:2000m inactive=2880m use_temp_path=off;
proxy_cache_key "$scheme$request_method$host$request_uri";
proxy_cache_methods GET HEAD;
proxy_cache_valid any 1m;
proxy_cache_valid 200 1440m;

server {
    listen 443 ssl http2;
    ssl on;
    server_name assodigitale.it;

    ssl_certificate /etc/letsencrypt/live/assodigitale.it/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/assodigitale.it/privkey.pem;

    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:50m;
    ssl_session_tickets off;

    ssl_protocols TLSv1.2;
    ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
    ssl_prefer_server_ciphers on;

    location / {
        proxy_cache revproxy;
        add_header X-Proxy-Cache $upstream_cache_status;
        add_header Strict-Transport-Security "max-age=4838400; includeSubDomains; preload";

        proxy_pass  https://138.201.87.123;
        proxy_cache_use_stale updating error timeout http_500 http_502 http_503 http_504;
        proxy_cache_bypass $http_x_forceflushcacheurl;
        proxy_cache_lock on;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_hide_header Upgrade;
        proxy_buffering off;
        proxy_connect_timeout       600;
        proxy_send_timeout          600;
        proxy_read_timeout          600;
        send_timeout                600;
        proxy_ignore_headers Set-Cookie;

        http2_push_preload on;
        client_max_body_size 64M;
    }
}

Das /srv/cache/nginxVerzeichnis hat 755 Berechtigungen und www-dataeinen Besitzer, und Nginx läuft als www-data. Tatsächlich schreibt Nginx seine Ordner dort hinein, nämlich 0 1 2 3 4 5 6 7 8 9 a b c d e f, aber der insgesamt belegte Speicherplatz beträgt jetzt 344 KB für eine Site, die ziemlich groß ist und weit mehr als nur gelegentlichen Datenverkehr hat.

Wenn Sie die gleichen curlBefehle wie oben, aber mit Seiten statt Bildern, ausprobieren, erhalten Sie immer das gleiche Ergebnis: ein Fehlschlag.

Warum lehnt Nginx das Zwischenspeichern von Ressourcen ab?

Antwort1

Sie sollten Proxy_Buffering festlegen on, sonst speichert Nginx die Antwort nicht!

das offizielledokumentierensagte:

Wenn die Pufferung deaktiviert ist, wird die Antwort sofort nach dem Empfang synchron an einen Client übergeben. nginx will not try to read the whole response from the proxied server.Die maximale Größe der Daten, die nginx gleichzeitig vom Server empfangen kann, wird durch die Direktive proxy_buffer_size festgelegt.

Antwort2

Ich habe die Konfiguration von einem anderen ähnlichen Nginx-Proxy, den ich betreibe, kopiert, sie an die Website angepasst und jetzt funktioniert sie.

Dies ist die Konfiguration, die ich derzeit verwende:

proxy_cache_path /srv/cache/nginx levels=1:2 keys_zone=revproxy:2000m inactive=2880m use_temp_path=off;
proxy_cache_key "$scheme$request_method$host$request_uri";
proxy_cache_methods GET HEAD;
proxy_cache_valid any 1m;
proxy_cache_valid 200 1440m;    
server {
    listen 443 ssl http2;
    ssl on;
    server_name assodigitale.it;

    ssl_certificate /etc/letsencrypt/live/assodigitale.it/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/assodigitale.it/privkey.pem;

        ssl_protocols        SSLv3 TLSv1 TLSv1.1 TLSv1.2;    
        ssl_ciphers RC4:HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers on;
        keepalive_timeout    60;
        ssl_session_timeout  10m;

    location / {
            proxy_cache revproxy;
            add_header X-Proxy-Cache $upstream_cache_status;

            proxy_pass  https://138.201.87.123;
            proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
            proxy_cache_use_stale updating error timeout http_500 http_502 http_503 http_504;
            proxy_cache_lock on;
            proxy_set_header        Host            $host;
            proxy_set_header        X-Real-IP       $remote_addr;
            proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_hide_header      Upgrade;
            proxy_buffering on;
            proxy_connect_timeout       600;
            proxy_send_timeout          600;
            proxy_read_timeout          600;
            send_timeout                600;
            client_max_body_size 64M;
    }
}

Obwohl dies eine Antwort sein kann, weil es das Problem löst, verstehe ich nicht, warum es funktioniert (oder genauer gesagt, warum die vorherige Konfiguration nicht funktioniert hat). Daher werde ich meine eigene Antwort nicht akzeptieren.

Vielleicht kann jemand den besonderen Unterschied zwischen den beiden Konfigurationen erkennen, der den Cache zum Funktionieren bringt: Das wäre eine akzeptable Antwort.

Antwort3

Wir hatten ein ähnliches Problem. Wir verwendeten nginx als Proxy-Cache für einen S3-Bucket (damit wir IP-Whitelisting unterstützen konnten). Wir bemerkten, dass wir nicht von einem HTTPS-Endpunkt bezogen, obwohl unser Proxy auf HTTPS lief. Das schien nginx nicht zu gefallen. Nachdem wir von httpauf umgestiegen waren https, gab es keine Probleme.

verwandte Informationen