Nginx 反向代理和 wordpress

Nginx 反向代理和 wordpress

一切运行良好,但是当我在扩展页面时,我遇到了 WordPress 的问题。

问题是插件图标没有显示,当我点击要安装的插件图标时,会打开一个空窗口,并一直加载。但是当我点击“安装”按钮时,插件安装没有任何问题。

你可以看看这张图片来了解发生了什么

发行 Wordpress

这里是配置:

配置

以下是 Web 服务器配置:

前端 Nginx

server {
        listen 443 ssl;

            # SSL 
            ssl on;
            ssl_certificate /etc/ssl/nginx/nginx.crt;
            ssl_certificate_key /etc/ssl/nginx/nginx.key;
            ssl_session_cache shared:SSL:40m;
            ssl_session_timeout 10m;
            ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
            ssl_prefer_server_ciphers on;

        server_name domaine.tld;

        # Proxy Pass to Varnish and  Add headers to recognize SSL
        location / {
            proxy_pass  http://127.0.0.1:80;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-Proto https;
            proxy_set_header X-Forwarded-Port 443;
            proxy_set_header X-Secure on;
        }
}

后端 Nginx

server {
        listen 8000;

        server_name domaine.tld;
        root /var/www/domaine;
        index index.php;

        # Custom Error Page
        error_page  404 403 /page_error/404.html;
        # Log
        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;

        location / {
            try_files $uri $uri/ /index.php?$args;
                    auth_basic "Restricted";
                auth_basic_user_file /etc/nginx/.htpasswd;
        }

            # PHP-FPM
            location ~ \.php$ {
                try_files $uri =404;
                    fastcgi_split_path_info ^(.+\.php)(/.+)$;
                    include fastcgi_params;
                    fastcgi_index index.php;
                    fastcgi_param SCRIPT_FILENAME         $document_root$fastcgi_script_name;
                    fastcgi_pass unix:/var/run/php5-fpm.sock;
                    fastcgi_param  HTTPS              on;
            }
}

Varnish 默认

DAEMON_OPTS="-a :80 \
             -T localhost:6082 \
             -f /etc/varnish/default.vcl \
             -S /etc/varnish/secret \
             -s malloc,256m"

清漆VCL 4.0

backend default {
    .host = "127.0.0.1";
    .port = "8000";
    .connect_timeout = 600s;
    .first_byte_timeout = 600s;
    .between_bytes_timeout = 600s;
    .max_connections = 800;
}

# Only allow purging from specific IPs
acl purge {
    "localhost";
    "127.0.0.1";
}

# This function is used when a request is send by a HTTP client (Browser) 
sub vcl_recv {

    # Redirect to https
    if ( (req.http.host ~ "^(?i)www.domaine.tld" || req.http.host ~ "^(?i)domaine.tld") && req.http.X-Forwarded-Proto !~ "(?i)https") {
                return (synth(750, ""));
        }

    # Normalize the header, remove the port (in case you're testing this on various TCP ports)
    set req.http.Host = regsub(req.http.Host, ":[0-9]+", "");

    # Allow purging from ACL
    if (req.method == "PURGE") {
        # If not allowed then a error 405 is returned
        if (!client.ip ~ purge) {
            return(synth(405, "This IP is not allowed to send PURGE requests."));
        }   
        # If allowed, do a cache_lookup -> vlc_hit() or vlc_miss()
        return (purge);
    }

    # Post requests will not be cached
    if (req.http.Authorization || req.method == "POST") {
        return (pass);
    }

    # Did not cache .ht* file
    if ( req.url ~ ".*htaccess.*" ) {
        return(pass);
    }

    if ( req.url ~ ".*htpasswd.*" ) {
        return(pass);
    }

    # Don't cache phpmyadmin
    if ( req.url ~ "/nothingtodo" ) {
        return(pass);
    }

    # --- Wordpress specific configuration

    # Did not cache the RSS feed
    if (req.url ~ "/feed") {
        return (pass);
    }

    # Don't cache 404 error 
    if (req.url ~ "^/404") {
        return (pass);
    }

    # Blitz hack
        if (req.url ~ "/mu-.*") {
                return (pass);
        }


    # Did not cache the admin and login pages
    if (req.url ~ "/wp-(login|admin)") {
        return (pass);
    }

     # Do not cache the WooCommerce pages
     ### REMOVE IT IF YOU DO NOT USE WOOCOMMERCE ###
    if (req.url ~ "/(cart|my-account|checkout|addons|/?add-to-cart=)") {
            return (pass);
        }

    # First remove the Google Analytics added parameters, useless for our backend
    if(req.url ~ "(\?|&)(utm_source|utm_medium|utm_campaign|gclid|cx|ie|cof|siteurl)=") {
        set req.url = regsuball(req.url, "&(utm_source|utm_medium|utm_campaign|gclid|cx|ie|cof|siteurl)=([A-z0-9_\-\.%25]+)", "");
        set req.url = regsuball(req.url, "\?(utm_source|utm_medium|utm_campaign|gclid|cx|ie|cof|siteurl)=([A-z0-9_\-\.%25]+)", "?");
        set req.url = regsub(req.url, "\?&", "?");
        set req.url = regsub(req.url, "\?$", "");
    }

    # Remove the "has_js" cookie
    set req.http.Cookie = regsuball(req.http.Cookie, "has_js=[^;]+(; )?", "");

    # Remove any Google Analytics based cookies
    set req.http.Cookie = regsuball(req.http.Cookie, "__utm.=[^;]+(; )?", "");

    # Remove the Quant Capital cookies (added by some plugin, all __qca)
    set req.http.Cookie = regsuball(req.http.Cookie, "__qc.=[^;]+(; )?", "");

    # Remove the wp-settings-1 cookie
    set req.http.Cookie = regsuball(req.http.Cookie, "wp-settings-1=[^;]+(; )?", "");

    # Remove the wp-settings-time-1 cookie
    set req.http.Cookie = regsuball(req.http.Cookie, "wp-settings-time-1=[^;]+(; )?", "");

    # Remove the wp test cookie
    set req.http.Cookie = regsuball(req.http.Cookie, "wordpress_test_cookie=[^;]+(; )?", "");

    # remove cookies for comments cookie to make caching better.
    set req.http.cookie = regsub(req.http.cookie, "dcd9527364a17bb2ae97db0ead3110ed=[^;]+(; )?", "");

    # remove ?ver=xxxxx strings from urls so css and js files are cached.
    set req.url = regsub(req.url, "\?ver=.*$", "");
    # Remove "replytocom" from requests to make caching better.
    set req.url = regsub(req.url, "\?replytocom=.*$", "");
    # Strip hash, server doesn't need it.
    set req.url = regsub(req.url, "\#.*$", "");
    # Strip trailing ?
    set req.url = regsub(req.url, "\?$", "");

    # Are there cookies left with only spaces or that are empty?
    if (req.http.cookie ~ "^ *$") {
            unset req.http.cookie;
    }

    # Drop any cookies sent to Wordpress.
    if (!(req.url ~ "wp-(login|admin)")) {
                       unset req.http.cookie;
        }

    # Cache the following files extensions 
    if (req.url ~ "\.(css|js|png|gif|jp(e)?g|swf|ico)") {
        unset req.http.cookie;
    }

    # Normalize Accept-Encoding header and compression
    # https://www.varnish-cache.org/docs/3.0/tutorial/vary.html
    if (req.http.Accept-Encoding) {
        # Do no compress compressed files...
        if (req.url ~ "\.(jpg|png|gif|gz|tgz|bz2|tbz|mp3|ogg)$") {
                unset req.http.Accept-Encoding;
        } elsif (req.http.Accept-Encoding ~ "gzip") {
                set req.http.Accept-Encoding = "gzip";
        } elsif (req.http.Accept-Encoding ~ "deflate") {
                set req.http.Accept-Encoding = "deflate";
        } else {
            unset req.http.Accept-Encoding;
        }
    }

    # Check the cookies for wordpress-specific items
    if (req.http.Cookie ~ "wordpress_" || req.http.Cookie ~ "comment_") {
        return (pass);
    }
    if (!req.http.cookie) {
        unset req.http.cookie;
    }

    # --- End of Wordpress specific configuration

    # No cache for big video files
    if (req.url ~ "\.(avi|mp4)") {
        return (pass);
    } 

    # Did not cache HTTP authentication and HTTP Cookie
    if (req.http.Authorization || req.http.Cookie) {
        # Not cacheable by default
        return (pass);
    }

    # Cache all others requests
    return (hash);
}

sub vcl_pipe {
    # Note that only the first request to the backend will have
    # X-Forwarded-For set. If you use X-Forwarded-For and want to
    # have it set for all requests, make sure to have:
    # set bereq.http.connection = "close";
    # here. It is not set by default as it might break some broken web
    # applications, like IIS with NTLM authentication.
    #set bereq.http.Connection = "Close";
    return (pipe);
}

sub vcl_pass {
    return (fetch);
}

sub vcl_synth {
    if (resp.status == 750) {
        set resp.status = 301;
        set resp.http.Location = "https://www.paris-vendome.com" + req.url;
        return(deliver);
    }
}


# The data on which the hashing will take place
sub vcl_hash {
    hash_data(req.url);
    if (req.http.host) {
        hash_data(req.http.host);
    } else {
        hash_data(server.ip);
    }

    # hash cookies for requests that have them
    if (req.http.Cookie) {
        hash_data(req.http.Cookie);
    }

    # If the client supports compression, keep that in a different cache
        if (req.http.Accept-Encoding) {
            hash_data(req.http.Accept-Encoding);
    }

    return (lookup);
}

# This function is used when a request is sent by our backend (Nginx server)
sub vcl_backend_response {
    # Remove some headers we never want to see
    unset beresp.http.Server;
    unset beresp.http.X-Powered-By;

    # For static content strip all backend cookies
    if (bereq.url ~ "\.(css|js|png|gif|jp(e?)g)|swf|ico") {
        unset beresp.http.cookie;
    }

    # Only allow cookies to be set if we're in admin area
    if (beresp.http.Set-Cookie && bereq.url !~ "^/wp-(login|admin)") {
            unset beresp.http.Set-Cookie;
        }

    # don't cache response to posted requests or those with basic auth
    if ( bereq.method == "POST" || bereq.http.Authorization ) {
            set beresp.uncacheable = true;
        set beresp.ttl = 120s;
        return (deliver);
        }

        # don't cache search results
    if ( bereq.url ~ "\?s=" ){
        set beresp.uncacheable = true;
                set beresp.ttl = 120s;
                return (deliver);
    }

    # only cache status ok
    if ( beresp.status != 200 ) {
        set beresp.uncacheable = true;
                set beresp.ttl = 120s;
                return (deliver);
    }

    # A TTL of 24h
    set beresp.ttl = 24h;
    # Define the default grace period to serve cached content
    set beresp.grace = 30s;

    return (deliver);
}

# The routine when we deliver the HTTP request to the user
# Last chance to modify headers that are sent to the client
sub vcl_deliver {
    if (obj.hits > 0) { 
        set resp.http.X-Cache = "cached";
    } else {
        set resp.http.x-Cache = "uncached";
    }

    # Remove some headers: PHP version
    unset resp.http.X-Powered-By;

    # Remove some headers: Apache version & OS
    unset resp.http.Server;

    # Remove some headers: Varnish
    unset resp.http.Via;
    unset resp.http.X-Varnish;

    unset resp.http.Age;
    unset resp.http.Link;

    return (deliver);
}

sub vcl_hit {
    return (deliver);
}
sub vcl_miss {
    return (fetch);
}

sub vcl_init {
    return (ok);
}

sub vcl_fini {
    return (ok);
}

我认为问题与 varnish 无关,而与后端有关,因为当我使用这个配置(无 varnish / 无后端)进行测试时,一切正常,没有任何问题:

server {
       listen         80;
       server_name    domaine.tld;
       return         301 https://www.domaine.tld$request_uri;
}


server{
    listen 443;
    ssl on;
    ssl_certificate /etc/ssl/nginx/nginx.crt;
    ssl_certificate_key /etc/ssl/nginx/nginx.key;
    ssl_session_timeout 10m;

    root /var/www/domaine;
    index index.htm index.html index.php;

    server_name domaine.tld;

    server_tokens off;
    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

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

    gzip on;
    etag off;


    location / {
        try_files $uri $uri/ =404;
        auth_basic "Restricted";
        auth_basic_user_file /etc/nginx/.htpasswd;
    }

    location ~ \.php$ {


        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        include fastcgi_params;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass unix:/var/run/php5-fpm.sock;
        fastcgi_param  HTTPS              on;
    }
}

如果我遗漏了什么,或者你想了解更多信息,请随时与我们联系。抱歉发了这么长的帖子,但我很绝望。希望有人能帮助我,提前谢谢

答案1

回答您的评论:

已解决:我不知道为什么,但这是 的问题add_header Content-Security-Policy。我刚刚将其从 http 块中删除,现在一切都正常了!瞧

proxy_pass指令(在您的 Varnishlocation块内)将请求传递给upstream(内部主机)网络中的服务器。这意味着您不再位于 Nginx 服务器上,而是位于 Varnish 服务器上,监听网络中的端口 9000。当您现在定义一个Content-Security-Policy并且不允许访问您自己的网络时,您将被锁定,因为您的服务器将成为过度保护的父母

不要盲目地相信服务器提供的一切,CSP 定义 Content-Security-Policy HTTP 标头它允许您创建受信任内容来源的白名单,并指示浏览器仅执行或呈现来自这些来源的资源。即使攻击者可以找到注入脚本的漏洞,该脚本也不会与白名单匹配,因此不会被执行。

由于我们相信apis.google.com可以提供有效的代码,并且我们相信自己也会这样做,因此让我们定义一个策略,仅允许来自以下两个来源之一的脚本执行:

Content-Security-Policy: script-src 'self' https://apis.google.com

… 您可能已经猜到了,script-src这是一条控制特定页面的一组脚本相关权限的指令。我们已指定'self'一个有效脚本源,另一个则指定为有效脚本源。浏览器将尽职尽责地通过HTTPS 下载并执行 JavaScript,以及从当前页面的来源https://apis.google.com下载并执行 JavaScript 。apis.google.com

引述来源:HTML5Rocks

相关内容