• Resolved adamlang

    (@adamlang)


    I’ve just recently moved my blog — https://dogsofsf.com — behind a reverse proxy/ssl endpoint (nginx, also proxying a half-dozen other sites, each with their own ssl certificates) and set up a redirect from http to https, thus making my site https-all-the-time. It works beautifully for the most part, although I’ve had to overcome a couple of obstacles, but I have one vexing problem left.

    First, what I’ve found so far, since I have never seen this information all in one place before. Hopefully someone can answer my question at the end, and we can make this thread a resource for people who want to do what I did.

    1) In order to not get constant warnings that you are submitting an insecure form when you log in, search, or submit any other form (I assume the form submit buttons etc are coming through as http rather than https), you need to tell the blog to use the ‘HTTP_X_FORWARDED_PROTO’ header to determine SSL-ness. Stick this in your wp-config.php file:

    if ($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')
        $_SERVER['HTTPS']='on';

    2) If you don’t want all of your comments to appear to have come from your proxy server, you have to tell wordpress that the remote server is really at the IP address from the header ‘HTTP_X_FOWARDED_FOR’. Again, in wp-config.php:

    if (isset($_SERVER["HTTP_X_FORWARDED_FOR"])) {
        $_SERVER['REMOTE_ADDR'] = $_SERVER["HTTP_X_FORWARDED_FOR"];
    }

    I’m stuck on the last problem: the site does not display as being secure. This is because a bunch of the image URLs on the front page are, for some reason, coming through as http rather than https. They get 301-ed to https but that doesn’t actually help. As an example, my front page currently has image tags like this on it:

    https://dogsofsf.com/wp-content/uploads/2015/01/IMG_3283-600×418.jpg
    https://dogsofsf.com/wp-content/uploads/2015/01/IMG_3289-600×558.jpg
    etc. Note, no https.

    Now, my original thought was that I should change the ‘WordPress Address’ and ‘Site Address’ to ‘https://dogsofsf.com’ instead of ‘https://dogsofsf.com’. But that immediately broke the entire site and made it impossible for me to even load the admin — I had to restore from a backup, things were so bad — so I guess that’s not it? Or maybe there was something else I needed to do?

    I would really appreciate any help.

    Incidentally, it kind of boggles my mind that this stuff wouldn’t be a config option at the very least.

Viewing 5 replies - 1 through 5 (of 5 total)
  • Quite a simple fix with WP-CLI:

    wp search-replace 'https://example.org' 'https://example.org'

    Add --network if running multisite. Add --dry-run if you’re unsure. Backup before running. More here: https://wp-cli.org/commands/search-replace/

    This will also update your siteurl and home settings, and thus fix all your forms with an http action too.

    Re. site breakage, if it breaks, go watch your error logs and see what exactly is broken before restoring from backup. Then at least you’ll know what to fix.

    Thread Starter adamlang

    (@adamlang)

    I did visit the error logs. They had nothing terribly diagnostic in them.

    I just tried the search-replace thing and it did the trick. Thank you very much!

    You’re welcome ??

    I want to do the same thing with my site, i.e run it on https behind nginx proxy.
    Could you please post the complete nginx config file for your blog?

    Thread Starter adamlang

    (@adamlang)

    Let’s see if I can unpick the portions that are related to my blog. It should be fairly obvious where you have to sub in your own data (‘your-ip-address-here’, etc, but not $host or things like that) but make sure you read through the whole thing or it definitely won’t work when you start it. ??

    # What username you want to run under
    user  www;
    worker_processes  1;
    
    # If you use this you'll have to create /var/log/nginx
    error_log  /var/log/nginx/error.log;
    
    events {
        worker_connections  1024;
    }
    
    http {
        include       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;
        # don't forget log rotation if you do this on an active site! Or you can just disable
        # the access log entirely.
    
        keepalive_timeout  65;
    
        ssl_protocols  TLSv1 TLSv1.1 TLSv1.2;  # don’t use SSLv3 ref: POODLE
    
        # directive for forwarding port 80 requests to ssl
        server {
            listen       your-ip-address-here:80;
            # server_name may not be necessary? Dunno, since performance is not an issue
            # for my port 80 forwarding I never bothered to find out
            server_name  ~.*;
    
            return 301 https://$host$request_uri;
        }
    
        server {
            listen your-ip-address-here:443;
            server_name yourservername.com www.yourservername.com;
            # or whatever list of servernames you like. Make sure that the ssl certificate
            # applies to all of them. If you need a separate ssl certificate you'll need a
            # separate 'server' directive, but it can be more or less identical to this one.
    
            ssl on;
            ssl_certificate /path/to/your/server/cert/file.crt;
            ssl_certificate_key /path/to/your/server/key/file.key;
    
            add_header Strict-Transport-Security max-age=15768000;
    
            location / {
                # NOTE: You probably won't need this, I just put it in to keep these guys from
                # stealing oodles of my bandwidth to scum their way to the top of google image
                # search using my photos.
                if ($http_referer ~* (becuo|m5x\.eu|galleryhip|pixshark|imgkid|imgarcade|thoughtyoumayask) ) {
                    return 403;
                }
    
                # This can be a domain name, an internal IP address, or your local IP with a
                # different port number.
                proxy_pass https://address-to-forward-requests-to:port-number;
                # If you have people uploading stuff, set this to the largest size you think
                # should be allowed. If not, you can set it much smaller than 20M, 1 or 2 maybe
                client_max_body_size 20M;
    
                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_set_header X-Forwarded-Proto https;
    
                proxy_redirect off;
    
                proxy_buffers 64 4k;
            }
        }
    
        # put any other server directives for any other server names you're running in here.
        # note that even with only a single IP address this lets you use https for all your
        # servers, using TLS SNI. Or you can just use multiple external ips to listen on.
    
    }
Viewing 5 replies - 1 through 5 (of 5 total)
  • The topic ‘WordPress behind a reverse proxy/ssl endpoint, slightly borked’ is closed to new replies.