本方案旨在通过 WordPress 搭建一个面向多用户的 Cloudflare DDNS 托管平台。支持自动分配二级域名、API 权限隔离、动态环境适配以及自动化邮件系统。
一、 环境适配:Rockylinux9系统,动态域名与 Cloudflare 代理感知
为了让 WordPress 能够同时在内网、外网及 Cloudflare 代理下正常加载资源,必须解决“固定 URL”和“HTTPS 无限重定向”问题。
操作: 修改网站根目录 wp-config.php,在 /* That’s all, stop editing! */ 上方加入:
PHP
/* 1. 识别 Cloudflare HTTPS 代理头,解决子目录/后台无法跳转 HTTPS 问题 */
if (isset($_SERVER[‘HTTP_X_FORWARDED_PROTO’]) && $_SERVER[‘HTTP_X_FORWARDED_PROTO’] == ‘https’) {
$_SERVER[‘HTTPS’] = ‘on’;
}
/* 2. 动态获取当前访问协议 */
$http_type = ((isset($_SERVER[‘HTTPS’]) && $_SERVER[‘HTTPS’] == ‘on’) || (isset($_SERVER[‘HTTP_X_FORWARDED_PROTO’]) && $_SERVER[‘HTTP_X_FORWARDED_PROTO’] == ‘https’)) ? ‘https://’ : ‘http://’;
/* 3. 强制 WordPress 使用当前请求的域名(适配多域名/IP/内网访问) */
$current_domain = $_SERVER[‘HTTP_HOST’];
define(‘WP_HOME’, $http_type . $current_domain);
define(‘WP_SITEURL’, $http_type . $current_domain);
/* 4. 自动修复数据库中的绝对路径链接(仅输出层替换) */
ob_start( ‘ob_replace_home_url’ );
function ob_replace_home_url( $content ) {
$home_url = get_option( ‘home’ );
return str_replace( $home_url, WP_HOME, $content );
}
二、 核心插件:Cloudflare 多类型 DDNS 服务 (v3.2)
该插件负责与 Cloudflare API 交互,为每个注册用户提供专属的 API Key 和二级域名更新权限。
插件路径: /wp-content/plugins/cf-ddns-service/cf-ddns-service.php
<?php
/*
Plugin Name: Cloudflare 多类型 DDNS 服务 (专业版)
Description: 支持 A/AAAA/CNAME 自动更新,带一键复制功能的实时管理控制台。已集成越权防护、速率限制、最小长度限制及物理查重功能。
Version: 3.2
Author: Gemini Thought Partner erthanleo
*/
if (!defined('ABSPATH')) exit;
/**
* ==========================================================
* 配置区:请确保以下信息准确
* ==========================================================
*/
define('CF_DDNS_TOKEN', 'yourCFtoken');
define('CF_DDNS_ZONE_ID', 'yourCFzoneid');
define('CF_DDNS_DOMAIN', 'yourdomain');
/**
* 1. 注册验证逻辑(加固:长度、格式、黑名单、物理查重)
*/
add_filter('registration_errors', 'cf_ddns_full_registration_check', 15, 3);
function cf_ddns_full_registration_check($errors, $sanitized_user_login, $user_email) {
// 长度检查:不得小于 4 个字符
if (strlen($sanitized_user_login) < 4) {
$errors->add('username_too_short', '<strong>错误</strong>:用户名长度不得少于 4 个字符。');
}
// 格式检查:仅小写和数字
if (!preg_match('/^[a-z0-9]+$/', $sanitized_user_login)) {
$errors->add('username_invalid', '<strong>错误</strong>:用户名只能包含小写字母和数字。');
}
// 后台设置的黑名单检查
$keywords_str = get_option('cf_ddns_reserved_keywords', 'admin,www,api,root,blog');
$reserved = array_map('trim', explode(',', strtolower($keywords_str)));
if (in_array(strtolower($sanitized_user_login), $reserved)) {
$errors->add('username_reserved', '<strong>错误</strong>:该用户名受系统保护,不可注册。');
}
// Cloudflare 物理查重
$full_domain = $sanitized_user_login . '.' . CF_DDNS_DOMAIN;
$check_url = "https://api.cloudflare.com/client/v4/zones/" . CF_DDNS_ZONE_ID . "/dns_records?name=$full_domain";
$res = wp_remote_get($check_url, ['headers' => ['Authorization' => 'Bearer ' . CF_DDNS_TOKEN], 'timeout' => 5]);
if (!is_wp_error($res)) {
$body = json_decode(wp_remote_retrieve_body($res), true);
if (!empty($body['result'])) {
$errors->add('domain_taken', '<strong>错误</strong>:该二级域名在 Cloudflare 中已被占用。');
}
}
return $errors;
}
/**
* 2. 初始化 API Key
*/
add_action('user_register', function($user_id) {
$api_key = wp_generate_password(20, false);
update_user_meta($user_id, 'cf_ddns_user_key', $api_key);
});
/**
* 3. REST API 核心处理器 (加固:越权防护 + 速率限制)
*/
add_action('rest_api_init', function () {
register_rest_route('cf-ddns/v1', '/update', [
'methods' => 'GET',
'callback' => 'cf_ddns_api_handler',
'permission_callback' => '__return_true',
]);
});
function cf_ddns_api_handler($request) {
$user_login_param = sanitize_user($request->get_param('user'));
$key_param = sanitize_text_field($request->get_param('key'));
$type = strtoupper($request->get_param('type') ?: 'A');
$ip = $request->get_param('ip') ?: $_SERVER['REMOTE_ADDR'];
if (!in_array($type, ['A', 'AAAA', 'CNAME'])) {
return new WP_REST_Response(['status' => 'error', 'message' => '不支持的记录类型'], 400);
}
$user = get_user_by('login', $user_login_param);
$stored_key = $user ? get_user_meta($user->ID, 'cf_ddns_user_key', true) : '';
if (!$user || $stored_key !== $key_param) {
return new WP_REST_Response(['status' => 'error', 'message' => '身份验证失败'], 403);
}
// 速率限制:每 5 分钟 10 次
$limit_key = 'cf_limit_' . $user->ID;
$count = get_transient($limit_key) ?: 0;
if ($count >= 10) {
return new WP_REST_Response(['status' => 'error', 'message' => '请求频繁:5分钟内限10次'], 429);
}
set_transient($limit_key, $count + 1, 300);
$full_domain = strtolower($user->user_login) . '.' . CF_DDNS_DOMAIN;
$query_url = "https://api.cloudflare.com/client/v4/zones/" . CF_DDNS_ZONE_ID . "/dns_records?name=$full_domain&type=$type";
$query_res = wp_remote_get($query_url, ['headers' => ['Authorization' => 'Bearer ' . CF_DDNS_TOKEN]]);
$query_data = json_decode(wp_remote_retrieve_body($query_res), true);
$record_id = (!empty($query_data['result'])) ? $query_data['result'][0]['id'] : null;
$api_url = "https://api.cloudflare.com/client/v4/zones/" . CF_DDNS_ZONE_ID . "/dns_records" . ($record_id ? "/$record_id" : "");
$method = $record_id ? 'PUT' : 'POST';
$response = wp_remote_request($api_url, [
'method' => $method,
'headers' => ['Authorization' => 'Bearer ' . CF_DDNS_TOKEN, 'Content-Type' => 'application/json'],
'body' => json_encode(['type' => $type, 'name' => $full_domain, 'content' => $ip, 'ttl' => 120, 'proxied' => false])
]);
$res_data = json_decode(wp_remote_retrieve_body($response), true);
if (!empty($res_data['success'])) {
return new WP_REST_Response(['status' => 'success', 'domain' => $full_domain, 'remaining' => (10 - ($count + 1))], 200);
}
return new WP_REST_Response(['status' => 'error', 'message' => 'Cloudflare 交互失败'], 500);
}
/**
* 4. 前端 UI 管理控制台 [display_ddns_info]
*/
add_shortcode('display_ddns_info', 'cf_ddns_render_ui');
function cf_ddns_render_ui() {
if (!is_user_logged_in()) return '<p>请先<a href="'.wp_login_url(get_permalink()).'">登录</a>查看解析信息。</p>';
$user = wp_get_current_user();
$key = get_user_meta($user->ID, 'cf_ddns_user_key', true);
$subdomain = $user->user_login . '.' . CF_DDNS_DOMAIN;
$res = wp_remote_get("https://api.cloudflare.com/client/v4/zones/".CF_DDNS_ZONE_ID."/dns_records?name=$subdomain", [
'headers' => ['Authorization' => 'Bearer ' . CF_DDNS_TOKEN]
]);
$records = json_decode(wp_remote_retrieve_body($res), true)['result'] ?? [];
ob_start(); ?>
<div style="border: 1px solid #e1e4e8; padding: 25px; border-radius: 12px; background: #fff; box-shadow: 0 4px 12px rgba(0,0,0,0.05); margin: 20px 0;">
<h3 style="margin-top:0; color:#24292e;">域名管理控制台</h3>
<p><strong>分配域名:</strong> <code style="color:#0366d6; font-size:16px;"><?php echo $subdomain; ?></code></p>
<p><strong>您的 API Key:</strong> <code style="background:#fff5b1; padding:2px 5px; border-radius:3px;"><?php echo $key; ?></code></p>
<table style="width:100%; border-collapse: collapse; margin-top: 20px;">
<tr style="background: #f6f8fa;">
<th style="padding:12px; border: 1px solid #d1d5da; text-align: left;">记录类型</th>
<th style="padding:12px; border: 1px solid #d1d5da; text-align: left;">当前解析值</th>
<th style="padding:12px; border: 1px solid #d1d5da; text-align: left;">快捷操作</th>
</tr>
<?php foreach(['A', 'AAAA', 'CNAME'] as $t):
$val = '<span style="color:#ccc;">未设置</span>';
foreach($records as $rec) {
if($rec['type'] === $t) {
$val = '<strong style="color:#22863a;">' . $rec['content'] . '</strong>';
break;
}
}
$link = home_url("/wp-json/cf-ddns/v1/update?user={$user->user_login}&key={$key}&type={$t}&ip=你的IP");
?>
<tr>
<td style="padding:12px; border: 1px solid #d1d5da;"><strong><?php echo $t; ?></strong></td>
<td style="padding:12px; border: 1px solid #d1d5da;"><?php echo $val; ?></td>
<td style="padding:12px; border: 1px solid #d1d5da;">
<button style="cursor:pointer; background:#2ea44f; color:#fff; border:none; padding:6px 12px; border-radius:6px;"
onclick="navigator.clipboard.writeText('<?php echo $link; ?>').then(()=>alert('接口链接已复制'))">复制链接</button>
</td>
</tr>
<?php endforeach; ?>
</table>
<div style="margin-top:25px; font-size:13px; color:#586069; border-top:1px solid #eaecef; padding-top:15px; line-height:1.6;">
<h4 style="margin-top:0; color:#24292e;">使用指南:</h4>
1. 点击<strong>“复制链接”</strong>获取更新地址。<br>
2. <strong>手动更新:</strong>将链接末尾加上 <code>&ip=你的IP</code> 访问即可。<br>
3. <strong>路由器/脚本:</strong>如果不带 <code>&ip=</code> 参数,系统将自动识别设备出口 IP。<br>
4. <strong>生效时间:</strong>Cloudflare 解析通常在 2-5 分钟内生效。<br>
5. <strong>快捷查询:</strong>您可以在本地终端使用以下命令测试是否更新成功:<br>
<code>nslookup <?php echo $subdomain; ?> 1.1.1.1</code><br>
<code>nslookup <?php echo $subdomain; ?> 2606:4700:4700::1111</code>
</div>
</div>
<?php return ob_get_clean();
}
/**
* 5. 后台管理与安全权限
*/
add_action('admin_init', function() {
if (!current_user_can('administrator') && !(defined('DOING_AJAX') && DOING_AJAX)) {
wp_safe_redirect(home_url()); exit;
}
});
add_action('after_setup_theme', function() {
if (!current_user_can('administrator')) show_admin_bar(false);
});
add_action('admin_menu', function() {
add_options_page('DDNS 拦截设置', 'DDNS 拦截设置', 'manage_options', 'cf-ddns-settings', function() {
?>
<div class="wrap"><h1>DDNS 拦截设置</h1><form method="post" action="options.php">
<?php settings_fields('cf_ddns_settings_group'); do_settings_sections('cf-ddns-settings'); submit_button(); ?>
</form></div>
<?php
});
});
add_action('admin_init', function() {
register_setting('cf_ddns_settings_group', 'cf_ddns_reserved_keywords');
add_settings_section('cf_ddns_main', '注册安全控制', null, 'cf-ddns-settings');
add_settings_field('keywords', '保留关键词(逗号分隔)', function() {
$val = get_option('cf_ddns_reserved_keywords', 'admin,www,api,root');
echo '<textarea name="cf_ddns_reserved_keywords" rows="5" class="large-text">' . esc_textarea($val) . '</textarea>';
}, 'cf-ddns-settings', 'cf_ddns_main');
});
/**
* 6. 用户删除清理
*/
add_action('delete_user', function($user_id) {
$user = get_userdata($user_id);
if (!$user) return;
$domain = $user->user_login . '.' . CF_DDNS_DOMAIN;
$res = wp_remote_get("https://api.cloudflare.com/client/v4/zones/".CF_DDNS_ZONE_ID."/dns_records?name=$domain", ['headers'=>['Authorization'=>'Bearer '.CF_DDNS_TOKEN]]);
$data = json_decode(wp_remote_retrieve_body($res), true);
if (!empty($data['result'])) {
foreach($data['result'] as $r) {
wp_remote_request("https://api.cloudflare.com/client/v4/zones/".CF_DDNS_ZONE_ID."/dns_records/".$r['id'], ['method'=>'DELETE', 'headers'=>['Authorization'=>'Bearer '.CF_DDNS_TOKEN]]);
}
}
});
三、 辅助配套设置
用户管理优化:
启用注册:设置 -> 常规 -> 成员资格(勾选“任何人都可以注册”)。
固定链接:设置 -> 固定链接(选择“文章名”),确保 REST API 路由正常工作。
安全性补丁:
禁止普通用户访问 /wp-admin(已包含在插件逻辑中)。
隐藏前台管理工具栏。
邮件系统 (Gmail API):
需求原因:解决服务器 PHP 邮件由于拦截率高无法发送激活链接的问题。
核心流程:Google Cloud Console -> 启用 Gmail API -> 创建 OAuth 2.0 凭据 -> 插件授权接入。
四、 关键检查清单
Cloudflare 层面:
SSL 模式:源站有证书建议 Full (完全),无证书选Flexible (灵活),配合 wp-config.php 的代理感知。
Always Use HTTPS:开启。
Automatic HTTPS Rewrites(自动 HTTPS 重写)
页面规则:确保没有针对根目录设置导致子目录失效的规则。
插件层面:
确保 CF_DDNS_DOMAIN 不包含协议头(如 yourdoamin.com 而非 http://...)。