Search code examples
wordpressnginxsslcorsreverse-proxy

MIXED CONTENT/CSP issue from (VPS) nginx reverse proxy with termination SSL and (HOME) nginx wordpress


It's been few day as I try to figure out what I'm doing wrong.

DNS points to VPS on VPS I have nginx reverse proxy with ssl termination that forward request to home server on home server I have nginx without ssl with Wordpress installation (which is mirror from same page on other domain, this is a mirror page so I redirect people to new server)

As soon as I enter URL into browser I see broken site with blocked request because of mixed content and CORS.

I'm definitely doing something wrong and nginx just doing the thing I told him, but I don't know where I'm making the error.

server {
    listen 80;
    listen [::]:80;

    server_name mypage.dns;
    # rewrite ^(.*) https://$host$1 permanent;
    return 301 https://$host$request_uri; 
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    server_name     mypage.dns;

    location / {
        add_header X-Served-By $host;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
        # proxy_set_header X-Forwarded-Ssl https;
        # proxy_set_header X-Url-Scheme https;
        proxy_set_header X-Forwarded-Port 443;
        proxy_set_header Proxy "";
        proxy_pass         http://172.16.100.100;
        proxy_redirect off;
        # proxy_redirect http://172.16.100.100/ https://$host/;
        # proxy_pass_request_headers      on;
    }
    ssl_certificate /etc/letsencrypt/live/mypage.dns/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/mypage.dns/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
}

Next I'm using config that worked before as stand alone www - and I want it to work as mirror of the original page.

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name     mypage.dns;
    keepalive_timeout 10;
    keepalive_disable msie6;
    keepalive_requests 200;

    include snippets/csp.conf;

    location / {
        #add_header X-Forwarded-Proto https;
        gzip on;
        gzip_static on;
        try_files $uri $uri/ /index.php$is_args$args;
    }

    location ~ \.php$ {
        #add_header X-Forwarded-Proto https;

        include fastcgi_params;
        fastcgi_intercept_errors on;

        gzip on;

        fastcgi_cache MYPAGE;
        fastcgi_cache_valid 200 301 302 10h;
        fastcgi_cache_valid 404 5m;
        fastcgi_cache_bypass $no_cache;
        fastcgi_no_cache $no_cache;
        fastcgi_cache_lock on;
        fastcgi_cache_lock_age 5s;
        fastcgi_cache_lock_timeout 5s;
        fastcgi_cache_use_stale error timeout updating invalid_header http_500 http_503;
        fastcgi_cache_min_uses 1;

        fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
        add_header X-Cache-Status $upstream_cache_status;

        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

        fastcgi_read_timeout 600s;
        fastcgi_pass unix:/var/www/mypage.dns/php/php-mypage.sock;
    }
    location ~* .(webp|avif|webm|ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|css|rss|atom|js|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
        sendfile           on;
        sendfile_max_chunk 1m;
        tcp_nopush on;
        expires max;
        log_not_found off;
        access_log off;

        include snippets/csp.conf;
        add_header Cache-Control public;
        open_file_cache                 max=10000 inactive=12h;
        open_file_cache_valid           5m;
        open_file_cache_min_uses        1;
        open_file_cache_errors          off;
    }
}

also the snippets/csp.conf

set $cors_origin "";
set $cors_cred   "";
set $cors_header "";
set $cors_method "";

if ($http_origin ~ '^https?://(mypage\.dns|cdn\.mypage\.dns|otherpage\.dns)$') {
    set $cors_origin $http_origin;
    set $cors_cred   true;
    set $cors_header $http_access_control_request_headers;
    set $cors_method $http_access_control_request_method;
}

add_header Access-Control-Allow-Origin      $cors_origin;
add_header Access-Control-Allow-Credentials $cors_cred;
add_header Access-Control-Allow-Headers     $cors_header;
add_header Access-Control-Allow-Methods     $cors_method;

add_header X-Frame-Options "SAMEORIGIN";

add_header X-XSS-Protection "1; mode=block";

add_header X-Content-Type-Options nosniff;
add_header Referrer-Policy "no-referrer-when-downgrade";

Also code that I added in wp-config.php from wordpress.

if (isset($_SERVER['HTTP_X_FORWARDED_HOST'])) {
    $_SERVER['HTTP_HOST'] = $_SERVER['HTTP_X_FORWARDED_HOST'];
}
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO'])) {
    if ($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') {
        $_SERVER['HTTPS'] = 'on';
    }
}

define('WP_SITEURL', 'https://' . $_SERVER['HTTP_HOST'] );
define('WP_HOME', 'https://' . $_SERVER['HTTP_HOST'] );

Looking at it make sense and every tutorial/setup guide/know how, told me to only add headers into reverse proxy, add or not some lines in wp-config and it should be done.

I'm checking with curl / browser with incognito

each time i try with curl: curl -H 'Pragma: no-cache' https://mypage.dns I see http in source code not being change to https based on PROTO/SCHEMA.

I understand that I'm: CLIENT <---- ssl/443 ---> reverse proxy <---- http/80 ----> nginx wordpress so wordpress see the http, but from what I understand it should be overwriten by $_SERVER['HTTPS'] = 'on' Even with the if logic and with only: $_SERVER['HTTPS'] = 'on' I dont see any changes in source code, and from my understand this is the main issue I'm having.

I tried adding or editing both nginx confs, wp-config with forced ssl, some "magic" or non intuitive proxy parameters...

I tried the recommended posts from stackoverflow

I'm hoping to run the page successfully without mixed content/csp errors thru reverse proxy.

The only thing that I noticed is that when I try to access https://mypage.dns/wp-admin/ it get redirected to original page url that the mirror is made of - which is other problem (probably sql replacement or url?).


Solution

  • fastcgi_cache
    

    For anyone (maybe that one guy in few years or more likely me in future) I enabled fastcgi_cache so the wordpress pages that are generated thru php are cached and fast delivered....

    So testing if something is working would be best done with any caching mechanism DISABLED.

    TL;DR: turn off cache before testing any changes.