尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

二级域名分发系统 V3.1.2 源码拆解:部署、二次开发与避坑指南

二级域名分发系统 V3.1.2 源码拆解:部署、二次开发与避坑指南 简介迅风DNS Pro二级域名分发全新V3.1.2系统源码是一套面向域名服务商、IDC与站长的域名分发管理系统。它聚合阿里、腾讯、Cloudflare、华为、百度、火山等多家DNS服务商通过插件驱动在一个后台完成域名解析、订单管理、工单处理与日志审计解决多平台重复登录、数据割裂的运维痛点适合有PHP开发或服务器部署经验的用户做二次开发。压缩包共2000个文件约11.09MB以1256个PHP文件为业务核心配合269个JS、116个CSS实现管理界面交互另含JSON配置、SQL数据库脚本、MD说明文档、TPL模板等辅助文件便于快速安装与功能扩展。资源支持账号/第三方登录、支付与卡密、违规检测、多主题切换等完整功能并附带插件机制与API调用示例几乎覆盖域名分发平台的前后台全链路代码结构清晰注释可读性较好适合学习DNS管理系统架构设计。目前已有117人学习/下载适合需要搭建或研究域名分发系统的技术人群。1. 二级域名分发一套能撑起几百个客户域名自助管理的 V3.1.2 源码值不值得下做建站服务或者 IDC 分销的同行应该都有这种体验客户越接越多手动去 DNS 面板一条条加解析记录一天下来眼睛看花还容易把 A 记录和 CNAME 搞混。我之前带过一个团队高峰期同时维护 300 多个客户的二级域名每周光改解析就要花掉小半天更头疼的是客户总在晚上十一点打电话说“域名怎么还没生效”。后来换了域名分发系统把“客户提交申请→系统自动解析→状态自动回写”这条链路跑通才算是把这块人力彻底解放出来。迅风 DNS Pro 二级域名分发系统 V3.1.2 就是这类工具里比较完整的一套源码自带用户端和后台管理支持套餐模板、自动开解析、泛解析、API 对接适合建站公司、虚拟主机代理商、做 SaaS 多租户隔离的开发者。这篇笔记按我实际拆包和部署的顺序从核心实现、部署参数到踩坑记录完整过一遍想少走弯路的可以直接照着复现。2. 核心模块与数据流转从 DNS 配置解析到用户提交申请系统是怎么串起来的2.1 分发系统的核心概念NS 记录、泛解析与解析模板要理解这套源码得先搞清楚二级域名分发的底层逻辑。这里的“分发”不是指域名注册而是指你手里有一个主域名比如 example.com你把这个主域名的 NS 记录指向自己的 DNS 服务器然后系统自动在 DNS 服务器上为不同的客户生成不同的二级域名解析记录比如 customer1.example.com、customer2.example.com。这套系统默认走的是“泛解析 分级解析”思路。泛解析就是一条 *.example.com 的记录把所有未单独定义的二级域名统一指向一台服务器适合做批量分发而分级解析则是按域名前缀精确匹配指向不同的服务器 IP。V3.1.2 源码在后台把这两种模式做成了模板管理员配置好模板后用户在用户端提交解析申请系统自动调用底层 DNS 服务商的 API 写入记录。核心概念有三个NS 记录告诉全世界“这个域名的解析由谁来负责”泛解析让所有二级域名先落在默认 IP 上解析模板则把不同业务线的域名前缀、记录类型、目标 IP 绑定起来。理解这三个概念后面看系统的配置项就不会懵。2.2 关键数据表结构domain_pool、domain_order 与 user_level 的职责划分拿到源码后第一件事不是看界面而是先打开数据库字典把核心表之间的关系理清楚。V3.1.2 的系统主要围绕三张业务表展开我把它们整理成了一张表表名核心字段作用domain_pooldomain_id, domain_name, ns_group, status存储可被分发的域名资源池status 标记是否可分配domain_orderorder_id, user_id, domain_id, sub_domain, resolve_type, target_ip, create_time用户提交的解析申请单包含域名前缀、解析类型、目标 IPuser_levellevel_id, level_name, max_domains, expire_days, price用户套餐等级限定每个用户可申请的最大域名数和有效期domain_pool 是资源池管理员先在这里添加一批主域名domain_order 是业务核心每一行代表一次客户申请user_level 则控制权限边界。三张表通过 user_id 和 domain_id 关联起来流程是用户在用户端选择套餐 → 系统检查 user_level 中的 max_domains 是否超限 → 写入 domain_order → 系统调用 API 创建解析记录。2.3 用户提交解析的完整流程查重、配额校验、调 API、状态回写这套系统的核心流程可以用四个步骤概括查重、校验配额、调用 API、回写状态。每个环节都有对应的代码逻辑下面这个 PHP 示例是从源码里提取出的流程骨架加上了我自己的注释// 1. 检查提交的二级域名是否已存在 $exists Db::name(domain_order) -where(sub_domain, $subDomain) -where(domain_name, $domainName) -find(); if ($exists) { throw new \Exception(该二级域名已被占用请更换前缀); } // 2. 校验用户套餐剩余配额 $myLevel Db::name(user_level) -alias(ul) -join(user u, u.level_id ul.level_id) -where(u.user_id, $userId) -find(); $usedCount Db::name(domain_order) -where(user_id, $userId) -where(status, 1) -count(); if ($usedCount $myLevel[max_domains]) { throw new \Exception(当前套餐可分配的域名数量已达上限); } // 3. 调用 DNS API 创建解析记录 $dnsApi new \Dns\QcloudApi($config); $result $dnsApi-createRecord([ domain $domainName, subDomain $subDomain, recordType $resolveType, // A 或 CNAME recordLine 默认, value $targetIp, ttl 60, ]); // 4. 写入订单表并回写状态 Db::name(domain_order)-insert([ user_id $userId, domain_id $domainId, sub_domain $subDomain, resolve_type $resolveType, target_ip $targetIp, create_time time(), status $result[code] 0 ? 1 : 0, ]);这段代码的流程很典型。第二步的配额校验是关键它从 user_level 表里取出当前套餐的 max_domains再统计用户已生效的订单数量来比对防止客户无限刷域名。第三步的 TTL 参数我特意写成了 60 秒这是这类分发系统降低“开通后等待生效”投诉的重要手段后面避坑章还会讲。整体看下来这套源码的业务闭环是比较完整的从用户提交到 API 调用再到状态回写都有覆盖。2.4 后台的域名模板与 NS 分组管理不同业务线怎么隔离后台管理界面里有两个值得细看的功能域名模板和 NS 分组。域名模板允许管理员预设“解析类型 目标 IP”的组合比如模板 A 对应 A 记录指向 Web 服务器、模板 B 对应 CNAME 指向 CDN 加速域名。用户申请时直接选模板系统根据模板来自动填参数避免客户自己乱填 IP。NS 分组则是把多个主域名按用途拆开比如一批域名专门给企业官网用另一批给个人博客用。每个分组绑定各自的 NS 记录配置。在实际运营中这个设计的价值在于故障隔离——某个分组的 NS 服务器出问题时不影响其他分组的解析。如果你运营的域名量不大可以暂时忽略分组但建议先保持默认分组避免后续扩容时结构混乱。3. 部署安装实战LNMP 环境、配置三步走与首单解析验证3.1 环境要求与解释这套代码建议用 LNMP 而不是宝塔一键装V3.1.2 是基于 PHP 和 MySQL 开发的部署环境我推荐 LNMP 组合具体的版本组合见下表。不建议用宝塔的一键 LNMP 默认配置因为宝塔默认的 PHP 版本可能偏高某些旧扩展未编译容易出现兼容问题。组件推荐版本说明操作系统CentOS 7.9 或 Ubuntu 20.04生产环境建议 CentOSNginx1.18 及以上需开启 rewrite 模块PHP7.4源码基于 PHP 7.4 开发兼容性最好MySQL5.7需支持 InnoDB 引擎Redis5.0 及以上用于会话缓存和 API 限流可选项为什么推荐 LNMP 而不是 Docker因为这套源码依赖 PHP 的 fileinfo、curl、openssl 扩展Docker 化部署时这些扩展的编译参数往往和源码默认配置不一致排查起来费劲。直接装 LNMP环境变量可控出问题时也更容易定位。3.2 从解压到配置建库、导入 SQL、写 .env 文件的三步操作部署的第一步是建数据库并导入源码自带的 SQL 文件。我一般习惯用命令行操作省去 phpMyAdmin 的上传大小限制问题# 1. 解压源码到 Web 目录 unzip xunfengdns_v3.1.2.zip -d /data/wwwroot/xunfengdns # 2. 创建数据库和用户 mysql -uroot -p -e CREATE DATABASE IF NOT EXISTS xunfengdns DEFAULT CHARACTER SET utf8mb4; mysql -uroot -p -e GRANT ALL PRIVILEGES ON xunfengdns.* TO dnsuserlocalhost IDENTIFIED BY YourStrongPass123; # 3. 导入初始数据 mysql -uroot -p xunfengdns /data/wwwroot/xunfengdns/database/init.sql # 4. 复制并编辑 .env 配置文件 cp /data/wwwroot/xunfengdns/.env.example /data/wwwroot/xunfengdns/.env vim /data/wwwroot/xunfengdns/.env.env文件里主要改四项数据库连接信息、Redis 配置、后台管理员初始密码、DNS API 密钥。数据库连接信息填刚才创建的用户和密码管理员初始密码建议用强随机字符串登录后台后再改一次DNS API 密钥需要先去你的 DNS 服务商后台申请目前源码适配了腾讯云和阿里云两家的接口。3.3 Nginx 站点配置rewrite 规则和 PHP 解析参数LNMP 环境里最常翻车的点是 Nginx 配置。这套系统的前端页面需要 rewrite 支持伪静态规则如果不对访问后台会直接 404。下面是我在 Nginx 里用的配置片段server { listen 80; server_name dns.example.com; root /data/wwwroot/xunfengdns/public; index index.php index.html; location / { if (!-e $request_filename) { rewrite ^(.*)$ /index.php?s$1 last; break; } } location ~ \.php$ { fastcgi_pass unix:/run/php/php7.4-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ { expires 30d; access_log off; } }这套配置的关键在于if (!-e $request_filename)那段——当请求的文件在磁盘上不存在时把请求转发给 index.php 处理由 PHP 层来做路由分发。静态资源缓存那行可以改善页面加载速度但如果你后续要频繁调试前端可以把 expires 注释掉避免改了代码还看到旧样式。3.4 配置定时任务与队列解析状态同步靠 cron 驱动很多人装完系统发现用户提交后状态一直是“处理中”十有八九是定时任务没配置。V3.1.2 的 API 回调是异步的DNS 服务商创建记录后系统需要定时去查询结果并更新订单状态。在 crontab 里加上这样一行# 每分钟执行一次异步任务处理器 * * * * * php /data/wwwroot/xunfengdns/think cron:run /data/wwwroot/xunfengdns/runtime/cron.log 21这里用的是 ThinkPHP 框架的命令行模式cron:run会去拉取待处理的订单调用 DNS API 查询解析是否已生效然后更新状态。日志重定向到 runtime 目录排查问题时直接看这个日志文件即可。我建议你把日志按天切割防止单个文件撑爆磁盘。3.5 首单验证提交一个子域名看解析是否真的生效环境部署完后用一个真实业务跑通全流程确认系统是否真的能用。先在后台创建一个测试套餐配置好域名模板然后到用户端注册一个账号提交一个二级域名最后用 dig 命令验证解析是否生效# 等待 1-2 分钟后查询解析记录 dig subdomain.example.com short # 检查系统后台的订单状态 mysql -udnsuser -p xunfengdns -e SELECT order_id, sub_domain, status FROM domain_order ORDER BY order_id DESC LIMIT 5;如果 dig 返回了你填写的目标 IP并且数据库里这条订单的 status 字段变成了 1生效那说明从 API 调用到状态回写这条链路是通的。如果 dig 有输出但数据库状态没变去看定时任务日志多半是 cron 没执行或者 API 密钥校验失败。4. 二次开发与 API 对接把分发能力开放给下游系统的三个常见做法4.1 做法一对接发卡系统实现“付款后自动发域名”很多做虚拟主机代理的读者会有这个需求用户在你的发卡平台付款然后系统自动给他分配一个二级域名并开通解析。这个场景相当于把 V3.1.2 的 API 封装成独立接口供另外一套 PHP 或 Java 系统调用。我一般会在源码中新增一个 API 控制器使用 HMAC 签名来保证调用方身份可信。签名算法的实现代码如下// 生成签名app_id 时间戳 请求参数用 MD5 做哈希 $appId your_app_id; $secret your_app_secret; $timestamp time(); $params json_encode([ sub_domain customer_ . mt_rand(1000, 9999), domain_name example.com, resolve_type A, target_ip 1.2.3.4 ]); $sign md5($appId . $timestamp . $params . $secret); // 发起 HTTP POST 请求 $ch curl_init(https://dns.example.com/api/v1/order/create); curl_setopt_array($ch, [ CURLOPT_POST 1, CURLOPT_POSTFIELDS http_build_query([ app_id $appId, timestamp $timestamp, params $params, sign $sign ]), CURLOPT_RETURNTRANSFER 1, CURLOPT_TIMEOUT 10 ]); $response curl_exec($ch); curl_close($ch);这个做法的核心是签名校验。接收端拿到请求后用同样的算法拼一次签名比对是否一致同时检查时间戳是否在五分钟以内防止重放攻击。发卡平台只需要在用户支付成功时触发这个请求就能完成域名分发对发卡系统的改动量很小。4.2 做法二接入 CDN 服务商 CNAME 自动切换另一个高频场景是你的客户做网站需要开 CDN 加速。如果 CDN 服务商的 API 也开放你可以在 V3.1.2 的解析模板里加一个字段“是否启用 CDN”系统在创建解析记录时自动调用 CDN 服务商 API把 CNAME 值替换成 CDN 分配的加速域名。这里的实现思路是在原有的createRecord方法里增加一个分支判断。CDN API 会返回一个 CNAME 目标地址把这个地址作为value写入 DNS 记录。需要注意的点是CDN 服务商的 API 调用频率通常有限制建议在代码里做一次简单限流比如每用户每分钟只能触发一次 CDN 开通过程否则高峰期很容易触发服务商封禁。4.3 做法三读取解析日志做自动化运维报表V3.1.2 自带了解析记录的日志表但默认只保留最近 30 天。如果你要拿这些数据做运营分析建议把日志同步到独立的日志库或者 Elasticsearch。我在二次开发时写了一个简单的同步脚本把 order 日志表的数据推到本地 MySQL 的报表库中每天凌晨运行一次用 cron 控制0 2 * * * php /data/wwwroot/xunfengdns/think report:sync /data/wwwroot/xunfengdns/runtime/report.log 21这个脚本做的事情很简单从 domain_order 表里读出前一天的数据按域名分组、按解析类型统计得到“每个主域名下的二级域名数量、A 记录与 CNAME 占比、新增趋势”这些指标。放在生产环境里能帮你直观判断哪个域名的资源池快消耗完了需要提前补充域名资源。5. 投产前的避坑清单解析冲突、缓存失效与权限失控的五条记录5.1 用户提交保留字域名导致解析冲突现象用户提交mail.example.com或www.example.com这类前缀后系统的解析记录显示成功但实际访问时提示“网站无法访问”甚至影响了你的企业邮箱收发。原因源码的查重逻辑只检查 domain_order 表里是否有相同 sub_domain 记录没有过滤系统保留前缀比如www、mail、ftp、ns这些已经存在的业务域名记录。解决在提交解析的入口增加一个保留字过滤数组把这些前缀直接拦截在用户端。我在源码里加了大约 30 个保留字常见的是 www、mail、smtp、pop、imap、ns1、ns2、m、api、admin 等。5.2 泛解析和单条记录之间互相“打架”现象某个子域名解析完一会儿能被解析到正确 IP一会儿又回到默认 IP在后台看解析记录也是混乱的。原因DNS 服务商同时存在一条*.example.com泛解析和一条sub.example.com精确解析时各 DNS 节点缓存不一致导致的间歇性生效。解决这套系统建议只保留一条泛解析记录所有二级域名统一走泛解析不做精确匹配的单条记录。或者反过来关闭泛解析全部用精确记录。两种模式不要混用这是我做过最多次的救火操作。5.3 用户反馈“半小时了解析还不生效”现象提交解析申请后用户说域名一直打不开后台订单状态已经是“生效”但本地浏览器访问还是超时。原因多数情况下不是系统问题而是用户的终端设备或者路由器缓存了旧的 DNS 解析结果。旧版本的 TTL 设置过长比如默认 600 秒甚至 3600 秒导致所有节点的缓存刷新时间被拉长。解决将新解析记录的 TTL 调成 60 秒。这是这类分发系统的重要参数优化缩短了客户等待“全球生效”的时间。另外可以在用户端页面上加一行提示“解析生效中最长等待 2 分钟”降低骚扰工单数量。5.4 定时任务没开订单全部卡在“待处理”现象后台能创建套餐用户也能提交申请但订单状态永远是“待处理”没有一条变成“处理成功”。原因这部分在部署章节提到过——cron:run进程没跑异步任务处理器没有机会去调用 DNS API。源码的设计是把高频操作异步化来避免页面请求阻塞但异步化的前提是定时调度器在运行。解决执行 crontab 命令把 cron:run 挂上去。注意 PHP 的可执行路径要用which php查一下有些环境 PHP 在/usr/bin/php有些在/usr/local/php/bin/php路径写错会导致定时任务静默失败。5.5 后台登录密码明文存储在数据库中现象偶然用 phpMyAdmin 打开 user 表发现密码字段直接是明文可读的比如123456所有账号都一样。原因旧版本源码使用的哈希算法强度不够或者一些演示环境直接没有启用密码哈希安装时自带的初始账号密码落库就是明文。解决升级到 V3.1.2 之后开启强制哈希校验。如果老数据已经存在我一般会写一个一次性脚本把这些明文密码批量更新为password_hash()生成的哈希值同时强制所有用户下次登录时重置密码。这条属于安全底线建议拿到源码第一时间处理。6. 高可用部署与解析收敛验证从单机跑到多节点我的压测习惯如果这套系统要支撑到几千个客户单机部署是不够的。我的做法是把 Nginx PHP 和 MySQL 拆开PHP 节点做多个前面挂一个 Nginx 负载均衡MySQL 主从同步。DNS API 调用部分不放在 PHP 业务节点里而是单独拆一台调度机出来只跑 cron 定时任务和 API 回调逻辑。这样就算某个 PHP 节点挂了用户端仍然能提交申请调度机也可以继续处理解析。压测是我每次上线前都强制自己过一遍的环节。先准备一个测试域名用脚本循环提交 500 个二级域名申请然后分批次查看收敛时间。常用的验证命令是 dig 加循环for i in $(seq 1 20); do dig sub${i}.example.com short sleep 5 done这个命令每次间隔 5 秒查询 20 个子域名的解析结果可以粗略判断从提交到完全生效大概需要多久。如果发现某个节点返回旧 IP就需要检查 Nginx 负载均衡的会话保持配置——DNS API 的调用如果被分发到不同的 PHP 节点可能因为缓存不一致导致部分节点调用失败。还有一个小习惯每次修改解析模板或者 NS 记录后我都会手动执行一遍cron:run并立刻查看日志而不是等它每分钟自动触发一次。这样能第一时间发现 SQL 语法错误或者 API 鉴权失败。曾有次我只改了数据库里的一个字段注释结果把一张表的字符集搞乱了整个后台查询全部报错从那以后我每次改配置都会在测试域名上强制走一遍完整流程确认没问题再切到线上。希望这份拆解能帮到你尤其是想直接用这套源码做业务又怕踩坑的朋友。下载后先按第一章的流程跑通一次再考虑二次开发和上线运营省下的时间够你多睡好几个安稳觉。本文还有配套的精品资源点击获取
返回列表