You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

VPS Nginx反向代理SSL终止对接WordPress的混合内容/CSP问题

问题描述

DNS指向VPS,VPS部署带SSL终止的Nginx反向代理,将请求转发至家庭服务器;家庭服务器为无SSL的WordPress镜像站点,用于引导用户访问新服务器。访问时页面破碎,请求因**混合内容(MIXED CONTENT)**和CORS问题被拦截,无法定位配置错误。

按教程配置后,使用curl -H 'Pragma: no-cache' https://mypage.dns查看源码,发现http未替换为https;强制设置$_SERVER['HTTPS'] = 'on'也无效。此外,访问https://mypage.dns/wp-admin/会跳转到原站点URL,需解决反向代理下的混合内容/CSP错误,使站点正常运行。


VPS反向代理Nginx配置

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
}

家庭服务器WordPress站点Nginx配置

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;
    }
}

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";

WordPress的wp-config.php添加代码

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'] );

解决方案

1. 修复WordPress的HTTPS识别问题

家庭服务器的Nginx未将X-Forwarded-Proto传递给PHP,导致WordPress无法正确识别外部HTTPS请求。修改家庭服务器Nginx的location ~ \.php$块,添加以下参数:

fastcgi_param HTTP_X_FORWARDED_PROTO $http_x_forwarded_proto;
fastcgi_param HTTPS $http_x_forwarded_proto = 'https' ? 'on' : '';

同时取消该块中#add_header X-Forwarded-Proto https;的注释,确保头信息正确传递。

替换wp-config.php中的现有代码为:

define('WP_SITEURL', 'https://mypage.dns');
define('WP_HOME', 'https://mypage.dns');
define('FORCE_SSL_ADMIN', true);
define('FORCE_SSL_LOGIN', true);

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

硬编码域名避免动态变量异常,FORCE_SSL_ADMIN确保后台跳转正确。

2. 修复混合内容问题

若仍存在http资源,需在WordPress数据库中批量替换旧链接:
执行以下SQL命令(替换对应域名):

UPDATE wp_options SET option_value = REPLACE(option_value, 'http://mypage.dns', 'https://mypage.dns') WHERE option_name IN ('siteurl', 'home');
UPDATE wp_posts SET post_content = REPLACE(post_content, 'http://mypage.dns', 'https://mypage.dns');
UPDATE wp_postmeta SET meta_value = REPLACE(meta_value, 'http://mypage.dns', 'https://mypage.dns');

也可使用WordPress插件(如Better Search Replace)完成替换,确保所有静态资源链接为https。

3. 修复CORS和反向代理头问题

VPS端Nginx调整

启用proxy_redirect,替换家庭服务器返回的http链接为https:

proxy_redirect http://mypage.dns/ https://mypage.dns/;

确保proxy_set_header X-Forwarded-Proto https;已启用。

家庭服务器CSP调整

当前配置在非OPTIONS请求时可能返回空CORS头,导致错误。修改snippets/csp.conf:

# 处理OPTIONS预检请求
if ($request_method = OPTIONS) {
    return 204;
}

# 仅当$cors_origin非空时添加CORS头
if ($cors_origin != "") {
    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;
}

4. 清除缓存

修改配置后执行以下操作:

  • 重启VPS和家庭服务器的Nginx:sudo systemctl restart nginx
  • 清除WordPress缓存(若使用缓存插件)
  • 清除浏览器缓存或用curl -H 'Cache-Control: no-cache' https://mypage.dns测试

内容的提问来源于stack exchange,提问作者Va_ni_tas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 09:29:52