没有不值得去解决的问题,也没有不值得去学习的技术!

根据网信办相关要求下线 8 篇自建 VPN 中文文章:保留系列标题并返回 404 的处理记录

图1:收到需要处理相关链接的通知。

作者:

自建 VPN

图15:电脑VPN连接成功截图

(1) 从 LetsVPN 停用至自建 WireGuard VPN 全流程复盘(附避坑指南)

手机端优化配置(表单字段编辑专用,仅改2个字段)如图1

(2) WireGuard VPN 配置优化:国内网站直连,国外流量走VPN(实测有效)

ChatGPT(https://chatgpt.com/)、 YouTube(https://www.youtube.com/)、 V2EX(https://v2ex.com/) 始终打不开,提示无法访问。如图1

(3) WireGuard 国内直连+国外走隧道 配置踩坑与完美解决(实测可用)

客户端无「上次握手时间」,一直处于等待连接状态。客户端显示看似连接,但实际无握手、无流量转发,接收一直为 0。

(4) WireGuard 自建 VPN 偶发不可用 全程复盘:从正常使用→突然无握手→端口被封→换端口+智能分流 完整解决流程

Speedtest 出口带宽测速,打开:https://www.speedtest.net/ 。结果如图2

(5) 从 LetsVPN 停用自建 WireGuard 后:成都移动宽带+ Vultr 新加坡节点 实测网速很慢复盘+避坑干货

2. VPS 通过 iptables 做端口段转发:20000~60000 全部UDP端口,统一转发到本机 51820; 3. Vultr 防火墙只需放行 20000~60000 端口段 ,不用逐个添加单端口规则;

(6) 自建WireGuard解决端口频繁被封终极极简方案(保姆级可复现)

洛杉矶节点:Premium、Eyeball、Tier 1 三种网络类型下所有实例均处于缺货状态,包括我能勉强接受的 LAX.AN5.Pro.TINY(Premium 网络,12.98美元/月),该节点 AN5 系列已告罄(如图6);

(7) WireGuard 握手正常但打不开网?我们为什么非要 CN2 GIA,附 DMIT 部署 & 缺货替代方案

需要确保首页 - 当前节点 - ZgoCloud-VPN 是 绿色状态(如图25)。

(8) ZgoCloud + Wstunnel + WireGuard 提速 4 倍,Clash Verge Rev 自动分流与 443 端口防封实战

不可访问:`www.google.com` 提示 `ERR_CONNECTION_CLOSED`;`chatgpt.com`、`v2ex.com` 提示 `ERR_CERT_COMMON_NAME_INVALID`(HSTS 导致的证书错误)

(9) 排查实录:解决Clash Verge + Wstunnel + WireGuard下“部分网站无法访问”的DNS死锁问题

图12:开机后网站测试全部通过

(10) Ubuntu 26.04 下 ZgoCloud + Wstunnel + Clash Verge Rev 开机自启 VPN 配置

分析:第三次测试依然稳健,上传甚至回升到了 81 Mbps。这证明了 CN2 GIA + 9929 线路在下午时段(非深夜)的优异表现。 (图7:VPN 测速 #3 详细数据截图)

(11) Ubuntu 26.04 下 自建 VPN 速度实测报告:ZgoCloud + Wstunnel + WireGuard 方案体验与对比指南

【截图位置:图17 展示了启动后的仪表盘界面】

(12) Android 下 ZgoCloud + Wstunnel + FlClash VPN 配置

📷(图1:Play 商店无法更新)

(13) 自建 WireGuard + Wstunnel 在 Android 上 Google Play 更新异常的完整排查与架构优化

[截图 5:Clash 规则片段,突出显示新增的两行 DST-PORT 规则]

(14) 自建 VPN 后 Thunderbird 无法发送 Gmail 邮件:原因与解决方法

[截图 2:Play 商店更新界面,显示两个应用正常下载]

(15) 自建 VPN 后 Play 商店应用无法更新?别折腾 Wstunnel 了,问题在 Clash 分流规则里

关键信息是 code=exited, status=203/EXEC。这个退出码意味着 systemd 无法执行指定的程序。

(16) systemd 用户服务 203/EXEC 错误排查:wstunnel 自启动配置实录

Clash Verge Rev + WireGuard + Wstunnel 稳定配置实践(一):极简原则与初版构建

(17) Clash Verge Rev + WireGuard + Wstunnel 稳定配置实践(一):极简原则与初版构建

使用 Clash Verge Rev 内置的连接测试,对常用 13 个目标进行检测:

(18) Clash Verge Rev + WireGuard + Wstunnel 稳定配置实践(二):Google 污染的 DNS 最小修正

你好,我按照你博客文章按流程操作了一下服务器,服务器防火墙也开了,但是手机修改端口还是没有握手提示,也上不了网,这是哪里出问题了吗?

(19) 帮客户远程排查 Vultr WireGuard 无握手无法上网问题(完整实录)

Thunderbird 无法与 imap.gmail.com 连接,请稍后再试。如果问题依然存在,则可能是您超出了此服务器允许的最大连接数量。可在IMAP服务器设置中减少缓存的连接数量。

(20) 从 Thunderbird 连接失败到换用 Gmail API 客户端的完整排查记录

查看服务器上的 client.conf(截图8)

(21) 客户 Android 下 Wstunnel + FIClash 远程排障全记录:从脚本创建到 IP 错配的坑

在 FlClash 中查看实时请求日志,所有 Play 商店相关的请求全部走代理

(22) FlClash + WireGuard + Wstunnel 稳定配置实践(三):Google Play 下载问题解决

🚀 WireGuard + Clash Verge Rev 实现国内直连 / 国外分流(Vultr & ZgoCloud 实战演进版)

(23) 🚀 WireGuard + Clash Verge Rev 实现国内直连 / 国外分流(Vultr & ZgoCloud 实战演进版)

Clash Verge 内存占用过高

(24) 🚀 Clash Verge 从 500MB 到 200MB:Ubuntu VPN 客户端轻量化优化实战

LetsVPN 已经无法继续为中国大陆用户提供 VPN 服务

(25) 自建 VPN 与商业 VPN 怎么选:从 LetsVPN 停用到 WireGuard 自建的真实迁移复盘

【截图 2:Clash Verge Rev 日志中出现 dns resolve failed】

(26) Clash Verge Rev + WireGuard + Wstunnel 稳定配置实践(四):DNS 偶发超时的极简兜底修正

图1:收到需要处理相关链接的通知。

(27) 根据网信办相关要求下线 8 篇自建 VPN 中文文章:保留系列标题并返回 404 的处理记录

最近,我收到了一项内容整改通知,需要处理网站中 8 篇与自建 VPN、网络代理及相关配置有关的中文文章。

这些文章都属于我的“自建 VPN”系列,其中多篇已经积累了较高的浏览量。直接在 WordPress 后台删除文章并不困难,但我并不希望采用这种方式。

如果将文章删除、移入回收站或改成草稿,系列目录中的标题也会随之消失。原本连续的内容记录将出现明显缺口,读者也很难理解为什么系列中的部分文章突然不见了。

因此,我希望找到一种折中方案:

  • 严格下线清单中列出的 8 篇中文文章;
  • 不再公开提供这些文章的中文正文;
  • 原中文 URL 返回真正的 HTTP 404;
  • 页面显示明确的停止提供提示;
  • “自建 VPN”系列中继续保留文章标题;
  • WordPress 后台仍然保留完整原文;
  • 不通过 PDF、附件、跳转或其他中文页面继续提供原内容;
  • 未出现在处置清单中的英文译文继续正常访问;
  • 发布一篇公开说明文章,解释系列中为什么会出现可以看到标题、点击后却返回 404 的情况。

最终,我通过一个独立的 WordPress MU Plugin 实现了这一目标。

一、收到需要处理 8 篇中文文章的通知

这次需要处理的内容来自一份明确的 Excel 清单,其中列出了 8 个中文文章 URL。

这些地址全部属于中文主站:

Plaintext
www.shuijingwanwq.com

清单中没有列出英文站:

Plaintext
en.shuijingwanwq.com
图1:收到需要处理相关链接的通知。
图1:收到需要处理相关链接的通知。
图2:Excel 文件中列出的 8 个中文文章链接。
图2:Excel 文件中列出的 8 个中文文章链接。

最开始,我考虑过直接在 WordPress 后台删除这 8 篇文章。

但它们并不是 8 篇彼此独立的内容,而是“自建 VPN”系列的一部分。如果直接删除,系列页面中的文章标题和原有顺序都会发生变化。

对于一个长期维护的博客来说,文章标题、发布时间和系列顺序本身也是网站历史的一部分。

因此,我希望保留这些文章曾经存在过的记录,但不再继续公开提供中文正文。

二、为什么没有把原文改成 PDF 下载

我曾考虑过另一种处理方式:

  1. 清空原文章正文;
  2. 在页面中显示停止提供的说明;
  3. 新建一篇汇总文章;
  4. 将 8 篇原文导出为 PDF;
  5. 在汇总文章中提供下载。

但仔细考虑后,我放弃了这个方案。

如果处置要求是将相关中文内容下线,那么把网页内容转换为 PDF 下载,本质上只是更换了公开传播方式。

即使原 URL 返回 404,只要用户仍然可以通过网站中的其他入口下载相同内容,就很难认为相关中文内容已经真正停止提供。

因此,最终方案中没有:

  • PDF 下载;
  • 公开附件;
  • 中文原文汇总页;
  • 301 或 302 跳转;
  • 指向其他中文镜像的入口。

完整中文原文只保留在 WordPress 后台,不再通过公开页面继续提供。

三、我希望最终达到的效果

这 8 篇中文文章继续保持 WordPress 的“已发布”状态。

这样,现有的系列文章列表仍然可以查询到这些文章,标题、发布日期和原链接也能够继续保留。

但是,当用户点击标题进入文章页面时,服务器不再返回原正文,而是返回:

Plaintext
HTTP 404

同时显示:

该页面已停止提供
根据网信部门相关要求,该页面已停止提供。

这里存在一个很重要的区别。

如果只是把正文替换为提示文字,但页面仍然返回:

Plaintext
HTTP 200

那么从浏览器、搜索引擎和服务器的角度来看,这仍然是一个正常存在的网页,只是正文内容发生了变化。

而我希望明确表达:

清单中的这 8 个中文 URL 已经不再提供原来的内容。

所以,页面必须返回真正的 HTTP 404,而不是只在一个 HTTP 200 页面中显示“内容已删除”。

四、为什么没有使用 HTTP 401

最开始,我也考虑过让这些文章返回 HTTP 401。

但 401 的标准含义通常是:

当前资源需要身份验证。

它更像是在告诉用户,登录或提供凭证后,仍然有机会访问相应资源。

这并不适合表达“该公开内容已经停止提供”。

相比之下,404 的语义更加直接:

当前 URL 不再提供对应资源。

因此,最终选择的是 HTTP 404,而不是 HTTP 401。

五、为什么不能把文章改成草稿

如果将文章改成草稿,普通访客确实无法继续访问正文。

但 WordPress 的公开查询默认只返回已发布文章。

一旦文章改成草稿:

  • 系列文章列表不再显示标题;
  • 分类和标签归档不再显示文章;
  • 主题中的相关文章查询可能忽略文章;
  • 原来的系列结构会出现缺口。

所以,实现这项需求的关键是:

文章在数据库中继续保持 publish 状态,但在中文单篇文章请求阶段进行拦截。

换句话说,不能依靠修改文章状态解决,而要在 WordPress 页面加载过程中加入自定义逻辑。

六、通过 MU Plugin 拦截指定中文文章

为了避免直接修改主题文件,也避免普通插件被误关闭,我最终选择使用 MU Plugin。

MU Plugin 放在:

Plaintext
wp-content/mu-plugins/

只要 PHP 文件存在于这个目录中,WordPress 就会自动加载,不需要在后台手动启用。

插件中维护处置清单明确列出的 8 个中文文章 ID:

PHP
function swq_blocked_posts_404_ids() {
	return array(
		19005,
		17374,
		18815,
		9675,
		9665,
		9651,
		9647,
		9601,
	);
}

然后判断当前文章是否在清单中:

PHP
function swq_blocked_posts_404_is_blocked( $post_id ) {
	return in_array(
		(int) $post_id,
		swq_blocked_posts_404_ids(),
		true
	);
}

最终版本只使用这 8 个明确的中文文章 ID。

插件不会再通过 Polylang 自动把对应英文译文加入下架清单。

七、在 template_redirect 阶段返回真正的 404

真正的页面拦截发生在 WordPress 的 template_redirect 阶段。

核心逻辑如下:

PHP
function swq_blocked_posts_404_render_notice() {
	if ( ! is_singular( 'post' ) ) {
		return;
	}

	$post_id = get_queried_object_id();

	if ( ! swq_blocked_posts_404_is_blocked( $post_id ) ) {
		return;
	}

	global $wp_query;

	if ( $wp_query instanceof WP_Query ) {
		$wp_query->set_404();
	}

	status_header( 404 );
	nocache_headers();

	header(
		'Cache-Control: no-store, no-cache, must-revalidate, max-age=0, private',
		true
	);

	header(
		'X-Robots-Tag: noindex, nofollow, noarchive, nosnippet',
		true
	);

	header(
		'Content-Type: text/html; charset=' . get_option( 'blog_charset' ),
		true
	);

	echo '<!doctype html>';
	echo '<html lang="zh-CN">';
	echo '<head>';
	echo '<meta charset="' . esc_attr( get_option( 'blog_charset' ) ) . '">';
	echo '<meta name="viewport" content="width=device-width, initial-scale=1">';
	echo '<meta name="robots" content="noindex,nofollow,noarchive,nosnippet">';
	echo '<title>页面已停止提供</title>';
	echo '</head>';

	echo '<body>';
	echo '<main>';
	echo '<h1>该页面已停止提供</h1>';
	echo '<p>根据网信部门相关要求,该页面已停止提供。</p>';
	echo '<p>HTTP 状态码:404</p>';
	echo '<a href="' . esc_url( home_url( '/' ) ) . '">返回网站首页</a>';
	echo '</main>';
	echo '</body>';
	echo '</html>';

	exit;
}

add_action(
	'template_redirect',
	'swq_blocked_posts_404_render_notice',
	-1000
);

当普通用户访问这 8 篇中文文章时,WordPress 会在加载主题正文模板之前停止后续处理,并返回自定义的 404 页面。

文章本身仍然存在,发布状态也没有改变,因此“自建 VPN”系列仍然能够显示这些文章的标题。

图3:“自建 VPN”系列中继续保留相关中文文章标题。
图3:“自建 VPN”系列中继续保留相关中文文章标题。

图4:点击中文文章标题后,页面返回 HTTP 404,并显示停止提供提示。

八、为什么最终没有强行套用原文章布局

第一次看到自定义 404 页面时,我觉得它与网站原来的文章页面差别比较大。

我原本希望提示可以直接出现在原文章的正文区域,同时保留:

  • 网站页眉;
  • 导航菜单;
  • 文章标题;
  • 系列信息;
  • 语言切换;
  • 页脚;
  • 原文章页面布局。

技术上可以实现。

例如,可以继续加载主题模板,再通过 the_content 过滤器把正文替换为停止提供提示。

但这样会引入更多需要处理的环节:

  • WordPress 查询对象;
  • 主题对 404 状态的判断;
  • 页面标题;
  • Canonical;
  • SEO 插件输出;
  • 相关文章;
  • 摘要;
  • 语言切换组件;
  • 页面缓存;
  • CDN 缓存。

页面组件越多,也越容易在其他区域继续暴露原正文、摘要或相关入口。

考虑到这次处理的首要目标是可靠地下线清单中的中文内容,我最终接受了一个独立、简洁的 404 提示页面。

它虽然没有完整套用原来的文章布局,但结果更加明确:

  • 不加载中文文章正文;
  • 不输出中文文章摘要;
  • 不提供 PDF 或附件;
  • 不跳转到其他中文页面;
  • 明确返回 HTTP 404;
  • 用户仍然可以返回网站首页。

九、通过一篇系列说明文章解释 404

仅仅保留系列标题还存在一个用户体验问题。

读者在“自建 VPN”系列中看到文章标题后,点击进入却只得到一个 404 页面,很容易产生疑问:

  • 是不是网站程序出错了?
  • 是不是链接地址写错了?
  • 为什么标题还在,正文却打不开?
  • 这些文章是不是被误删了?

因此,我决定将本文也加入“自建 VPN”系列,并放在比较显眼的位置。

它不是一篇新的 VPN 教程,而是一篇系列说明文章,用来解释:

  • 为什么有 8 篇中文文章停止提供;
  • 为什么没有直接删除文章;
  • 为什么系列中仍然保留标题;
  • 为什么点击后返回 HTTP 404;
  • 为什么英文译文仍然可以正常访问;
  • 整个 WordPress 和缓存处理过程是如何完成的。

理想的系列标题顺序类似:

Plaintext
系列说明:根据网信办相关要求下线 8 篇自建 VPN 中文文章
原文章标题一
原文章标题二
原文章标题三
……

这样,读者在浏览系列列表时,可以先看到说明,再决定是否继续查看后续标题。

本文发布后,我还可以进一步调整自定义 404 页面,在“返回网站首页”之外增加一个说明入口:

查看此次内容调整的完整说明

该链接只用于解释内容调整原因,不提供原中文正文,也不指向任何 PDF、附件或中文镜像。

由于说明文章必须先发布并取得正式 URL,这个入口需要在本文发布后再添加到 MU Plugin 中。

十、公共 REST API、RSS 和 Sitemap 也需要处理

只拦截浏览器中的中文文章页面还不够。

WordPress 还有多个可能返回文章内容的公开入口,例如:

Plaintext
/wp-json/wp/v2/posts/19005

以及:

  • REST API 文章列表;
  • RSS 和 Atom 订阅源;
  • WordPress 核心 Sitemap;
  • Yoast SEO XML Sitemap;
  • 主题生成的摘要列表;
  • 第三方客户端接口。

因此,MU Plugin 中还加入了相应限制。

这些限制同样只针对清单中的 8 篇中文文章。

1. 公共 REST API 返回 404

未登录用户访问对应中文文章的 REST API 时,返回:

PHP
return new WP_Error(
	'swq_content_unavailable',
	'该内容已停止提供。',
	array(
		'status' => 404,
	)
);

已经登录并拥有编辑权限的管理员,仍然可以通过 Gutenberg 后台正常读取和编辑文章。

2. 从公共 REST API 文章列表中排除

对于公开的文章集合查询,将这 8 个中文文章 ID 加入:

PHP
post__not_in

避免用户通过批量 REST API 重新获取正文。

3. 从 RSS 中排除

插件在 RSS 主查询中排除这 8 篇中文文章,避免旧正文继续通过订阅源提供。

4. 从 Sitemap 中排除

插件同时处理:

  • WordPress 核心 XML Sitemap;
  • Yoast SEO XML Sitemap。

文章标题仍然可以在“自建 VPN”系列目录中显示,但这 8 个中文 URL 不再作为正常文章继续提交给搜索引擎。

十一、英文译文是否应该同步下线

这是整个处理过程中,我反复思考的一点。

最初的插件版本会调用 Polylang:

PHP
pll_get_post_translations()

根据 8 个中文文章 ID,自动找到对应的英文译文,并将所有语言版本一起加入下架清单。

这种方式处理得更加彻底,也不容易遗漏对应的英文文章。

但后来我重新检查了处置 Excel。

文件中明确列出的只有 8 个中文 URL:

Plaintext
https://www.shuijingwanwq.com/...

并没有列出对应的英文 URL:

Plaintext
https://en.shuijingwanwq.com/...

因此,我最终采用的策略是:

只下线 Excel 中明确列出的 8 个中文 URL,不主动扩大到未被列出的英文文章。

最终版本删除了自动扩展 Polylang 译文 ID 的逻辑。

这意味着:

  • 中文文章返回 HTTP 404;
  • 英文文章继续返回 HTTP 200;
  • 英文正文仍然可以通过搜索引擎进入;
  • 英文文章继续保留在英文 Sitemap 中;
  • 英文 REST API 和 RSS 不受本次中文清单影响。

需要特别说明的是,本文不会列出对应英文文章的完整 URL,也不会成为通往这些英文版本的导航页。

对应英文译文继续正常存在,是因为它们未出现在目前收到的处置清单中,而不是为了通过英文页面替代已经停止提供的中文正文。

如果后续收到新的明确通知,需要处理相同内容、关联页面或多语言版本,再单独扩大下架清单。

十二、部署第一个 MU Plugin 版本

我先将插件压缩包上传到服务器:

Bash
scp -O \
  ~/下载/swq-blocked-posts-404.zip \
  aliyun:/root/swq-blocked-posts-404.zip

然后在服务器中解压并部署:

Bash
cd /root

rm -rf /root/swq-blocked-posts-404
mkdir -p /root/swq-blocked-posts-404

unzip -o \
  /root/swq-blocked-posts-404.zip \
  -d /root/swq-blocked-posts-404

php -l \
  /root/swq-blocked-posts-404/swq-blocked-posts-404.php

install -m 0644 \
  /root/swq-blocked-posts-404/swq-blocked-posts-404.php \
  /data/wwwroot/www.shuijingwanwq.com/wp-content/mu-plugins/swq-blocked-posts-404.php

php -l \
  /data/wwwroot/www.shuijingwanwq.com/wp-content/mu-plugins/swq-blocked-posts-404.php

语法检查结果为:

Plaintext
No syntax errors detected

这里还出现了一个小插曲。

我最开始误把服务器命令粘贴到了本地电脑终端中,结果出现:

Plaintext
bash: cd: /root: 权限不够

以及:

Plaintext
No such file or directory

这些错误并不是插件或服务器目录出现了问题,而是命令执行环境不对。

切换到阿里云服务器的 root 终端后,部署便正常完成。

十三、第一次验证时,部分中文文章仍然返回 200

插件部署完成后,我通过 curl 绕过 EdgeOne,直接请求源站:

Bash
curl \
  --resolve www.shuijingwanwq.com:443:127.0.0.1 \
  https://www.shuijingwanwq.com/文章路径/

第一次验证时,并不是 8 篇中文文章全部返回 404。

其中部分页面仍然显示:

Plaintext
200 | 未找到提示

只有少量页面返回:

Plaintext
404 | 提示正常

这时很容易怀疑:

  • 文章 ID 是否写错;
  • MU Plugin 是否只处理了部分页面;
  • template_redirect 是否没有执行;
  • WordPress 查询判断是否存在问题。

但加入随机查询参数后再次测试:

Bash
test_url="${url}?swq_block_test=$(date +%s%N)"

8 个页面全部返回:

Plaintext
404 | 提示正常

这说明插件逻辑本身没有问题。

真正的问题是 W3 Total Cache 中仍然保存着部署插件之前生成的静态 HTML 页面。

普通 URL 请求命中旧缓存时,Nginx 和 W3TC 会直接返回旧正文,WordPress PHP 代码根本没有机会执行。

十四、只清理指定中文文章的 W3TC 缓存

为了避免清理整个网站的页面缓存,我只删除了这 8 篇中文文章对应的 W3TC 缓存目录:

Bash
cache_root="wp-content/cache/page_enhanced/www.shuijingwanwq.com"

paths=(
  "2026/07/06/19005"
  "2026/06/19/17374"
  "2026/07/04/18815"
  "2026/05/03/9675"
  "2026/05/02/9665"
  "2026/05/01/9651"
  "2026/05/01/9647"
  "2026/04/28/9601"
)

for path in "${paths[@]}"
do
	rm -rf "$cache_root/$path"
	echo "已清理:$path"
done

清理后,再次使用不带随机参数的普通 URL 请求源站,结果全部变为:

Plaintext
404 | 提示正常

这一步确认了此前的 HTTP 200 完全来自旧页面缓存,而不是插件拦截失败。

十五、清除 EdgeOne 缓存并验证中文公网结果

中文主站使用 EdgeOne。

源站验证成功后,我又清除了 EdgeOne 中对应的 8 个中文 URL 缓存。

随后通过公网普通请求进行验证,不再使用:

Plaintext
--resolve

最终 8 篇中文文章全部返回:

Plaintext
404 | 提示正常 | eo-cache-status: MISS

这说明:

  • EdgeOne 节点中的旧正文缓存已经清除;
  • 请求重新回到源站;
  • 源站返回自定义的 404 页面;
  • CDN 没有继续向用户发送旧的中文文章正文。

十六、调整页面中的说明文字

最初的提示文字是:

因内容调整,此页面当前无法访问。

后来,我希望页面能够体现此次调整与网信相关要求有关。

如果直接写:

网信办要求我删除这篇文章。

可能会显得过于绝对,也容易让人理解为我直接收到了一份针对单篇文章的正式行政文书。

最终页面采用了相对克制的表述:

根据网信部门相关要求,该页面已停止提供。

文章标题中则使用了更容易被读者理解的“网信办相关要求”,用来说明整件事情的背景。

我通过 sed 修改插件:

Bash
plugin="wp-content/mu-plugins/swq-blocked-posts-404.php"

backup="${plugin}.bak-$(date +%Y%m%d-%H%M%S)"

cp -a "$plugin" "$backup"

sed -i \
  's/因内容调整,此页面当前无法访问。/根据网信部门相关要求,该页面已停止提供。/' \
  "$plugin"

php -l "$plugin"

修改后,普通公网请求暂时仍然显示旧提示。

但加入随机参数并绕过 CDN 后,源站已经显示新文字:

Plaintext
源站新提示:验证成功

这说明 PHP 文件修改已经生效。

由于无论新旧提示,页面都已经真实返回 404,原中文正文也无法访问,因此我没有为了让文字立即更新而再次反复清理缓存,而是允许旧提示随着缓存自然过期。

十七、恢复英文文章时遇到旧的 404 缓存

最初版本自动拦截了 Polylang 英文译文,因此对应英文文章也曾经返回 404。

删除自动扩展英文译文的逻辑后,我第一次进行英文公网验证时,相关英文 URL 仍然全部返回:

Plaintext
404

但加入随机参数、绕过 Cloudflare 和 W3TC 后,英文源站全部返回:

Plaintext
200 | 英文正文已恢复

这说明新版插件已经正常工作,公网看到的 404 只是之前留下的缓存。

十八、清理英文站 W3TC 缓存

英文站的 W3TC 页面缓存目录为:

Plaintext
wp-content/cache/page_enhanced/en.shuijingwanwq.com

我只删除了相关英文文章的旧 404 缓存目录,没有清空整个英文站缓存。

清理后,不带随机参数直接请求英文源站,所有相关英文文章均返回:

Plaintext
200 | 英文正文正常

十九、清理 Cloudflare 中的英文 404 缓存

英文站使用 Cloudflare。

W3TC 源站缓存处理完成后,我又在 Cloudflare 中按 URL 清除了相关英文文章的旧 404 缓存。

最后通过公网请求进行验证:

Plaintext
200 | 英文正文正常 | cf-cache-status: MISS

所有相关英文页面均恢复正常。

这说明:

  • Cloudflare 中原来的 404 缓存已经删除;
  • 请求重新回源;
  • 源站返回正常的英文文章;
  • 英文正文恢复公开访问;
  • 搜索引擎可以继续进入英文版本。

后续 Cloudflare 缓存状态从 MISS 变成 HIT 也属于正常现象,因为此时缓存的是恢复后的 HTTP 200 页面。

二十、最终实现效果

经过两次插件调整和缓存处理,最终状态如下。

清单中的 8 篇中文文章

  • WordPress 后台仍然保留完整原文;
  • 文章状态继续保持“已发布”;
  • “自建 VPN”系列中继续显示文章标题;
  • 标题仍然链接到原中文 URL;
  • 用户点击后返回真正的 HTTP 404;
  • 页面显示“该页面已停止提供”;
  • 中文正文不再公开输出;
  • 公共 REST API 无法获取正文;
  • RSS 不再包含这些文章;
  • Sitemap 不再提交这些中文 URL;
  • EdgeOne 不再返回旧的中文正文缓存;
  • 不通过跳转、PDF或附件继续提供中文原文。

对应的英文文章

  • 未出现在当前 Excel 处置清单中;
  • 不再被 MU Plugin 自动加入下架列表;
  • 英文页面正常返回 HTTP 200;
  • 英文正文可以正常访问;
  • 英文文章继续允许搜索引擎访问;
  • 英文 Sitemap、REST API 和 RSS 保持正常;
  • W3TC 和 Cloudflare 中的旧 404 缓存已经清除。

“自建 VPN”系列说明

  • 本文加入“自建 VPN”系列;
  • 在系列标题列表中安排在较显眼的位置;
  • 向读者解释为什么部分标题仍然存在,但点击后返回 404;
  • 本文只提供处理说明,不重新提供被下线的中文正文;
  • 本文不列出对应英文文章地址,也不作为英文版本的导航页;
  • 本文发布后,可考虑在自定义 404 页面中增加“查看完整说明”的链接。

最终策略可以概括为:

严格按照处置 Excel 中明确列出的 8 个中文 URL 执行下线,同时保留系列结构和历史记录;未出现在清单中的英文译文继续正常访问。

二十一、这次处理带来的思考

对于普通博客来说,“删除文章”通常被认为只是点击一次“移至回收站”。

但当一个网站已经运行多年,文章之间存在系列、分类、多语言映射、CDN 缓存、搜索引擎索引和历史访问数据时,下线一篇文章并不只是删除一条数据库记录。

一个看似简单的内容处理需求,实际涉及:

  • WordPress 文章状态;
  • 系列标题列表;
  • HTTP 状态码;
  • 自定义提示页面;
  • W3 Total Cache;
  • EdgeOne;
  • Cloudflare;
  • REST API;
  • RSS;
  • Sitemap;
  • Polylang 多语言映射;
  • 后台原文留存;
  • 中文与英文 URL 的处置范围;
  • 如何向系列读者解释标题仍在、正文却已停止提供。

这次我最终没有选择直接删除文章,也没有通过其他形式继续公开提供中文正文,而是通过 MU Plugin 将“后台保留”和“中文前台下线”分开处理。

同时,我也没有把处置范围无限扩大。

在重新核对 Excel 后,最终只处理清单中明确列出的 8 个中文 URL,对应英文译文继续正常访问。

为了避免读者误以为系列页面出现了故障,我又将本文作为“自建 VPN”系列中的说明文章,用来公开记录此次内容调整和技术处理过程。

从技术上看,这种方案比直接删除复杂很多。

但它最终同时保留了:

  • 博客系列结构;
  • 中文文章历史记录;
  • WordPress 后台原文;
  • 英文文章搜索流量;
  • 清单内中文 URL 的明确下线状态;
  • 面向读者的公开解释入口。

对于需要在内容合规、历史记录、多语言网站结构、搜索流量和读者体验之间寻找平衡的 WordPress 网站来说,这是一套值得记录的处理流程。

Clash Verge Rev + WireGuard + Wstunnel 稳定配置实践(四):DNS 偶发超时的极简兜底修正

🚀 推荐 VPS(WireGuard / Clash / 自建 VPN 专用)

本系列方案推荐使用 Vultr VPS 作为基础服务器环境:

✔ 支持 WireGuard / Clash / VPS 架构部署
✔ 全球多机房节点可选
✔ 稳定适合长期运行的网络服务

👉 点击访问 Vultr(推荐注册入口)



💡 新用户优惠说明

Vultr 官方可能会针对新用户提供一定的试用额度或促销活动,例如:

– 最高可能获得 $300 新用户测试额度
– 用于 VPS 部署与测试用途
– 是否生效取决于 Vultr 官方活动规则及账户条件

⚠️ 不同地区、时间或账户类型可能存在差异。


⚠️ 重要说明

本站提供的链接为 Vultr 官方联盟推广链接,用于推荐 VPS 服务。

所有优惠活动均由 Vultr 官方提供与解释,本网站不保证所有用户均可获得相同促销权益。



拒绝反复折腾|专属 WireGuard VPN 远程部署与优化服务

本系列长期记录 WireGuard、Clash、VPS、DNS、Linux 网络环境和 AI 工具访问优化等实践。如果你不想反复踩坑、折腾服务器与协议配置,可以联系我做一次远程排查或专属方案部署。

适合以下用户:
✅ ChatGPT、Claude、Gemini 等 AI 工具使用者
✅ 海外远程办公用户
✅ 技术学习与开发环境访问需求
✅ 不想长期折腾 VPS 与代理配置的用户
✅ 希望拥有专属节点而非公共机场的用户

服务内容:
远程代搭建:在你自己的服务器上部署专属 WireGuard VPN,数据完全掌控。
免费试用:可申请免费试用我的自建节点,再决定是否继续。
分流优化:针对 AI 工具、开发环境及日常使用进行优化。
问题排查:协助排查连接失败、速度慢、DNS 异常、规则配置等常见问题。

如需了解方案或申请试用,请直接联系我,并注明:VPN 咨询

联系方式:
Telegram:@shuijingwan
微信:13980074657
邮箱:shuijingwanwq@gmail.com

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理