IT 相关 · 2025 年 2 月 26 日

修改 DouPHP 代码及数据库以支持适配 IPv6 显示

在登录 DouPHP 后台时,发现管理员登录记录 IP 地址总显示 127.0.0.1,以为是使用了 WAF 导致,在修改 CDN 回源绕过 WAF 后仍然如此。通过查看代码后发现 DouPHP 对获取到的 IP 地址只要不符合 IPv4 的正则表达式就返回 127.0.0.1 。 IPv6 已经成为网络通信的主流标准,官方至今 (DouPHP 版本 v1.8 Release 20250217) 仍未进行适配,为了正确显示 IPv6,需要自行修改以适配。

在 include/common.class.php 修改 get_ip() 方法以修正正则表达式:确保正则表达式能够匹配完整的 IPv6 地址,修改后代码如下。

function get_ip() {
    static $ip;
    if (isset($_SERVER)) {
        if (isset($_SERVER["HTTP_X_FORWARDED_FOR"])) {
            // 处理 HTTP_X_FORWARDED_FOR 中可能包含的多个 IP 地址
            $ip_list = explode(',', $_SERVER["HTTP_X_FORWARDED_FOR"]);
            $ip = trim($ip_list[0]); // 取第一个 IP 地址
        } else if (isset($_SERVER["HTTP_CLIENT_IP"])) {
            $ip = $_SERVER["HTTP_CLIENT_IP"];
        } else {
            $ip = $_SERVER["REMOTE_ADDR"];
        }
    } else {
        if (getenv("HTTP_X_FORWARDED_FOR")) {
            $ip_list = explode(',', getenv("HTTP_X_FORWARDED_FOR"));
            $ip = trim($ip_list[0]); // 取第一个 IP 地址
        } else if (getenv("HTTP_CLIENT_IP")) {
            $ip = getenv("HTTP_CLIENT_IP");
        } else {
            $ip = getenv("REMOTE_ADDR");
        }
    }

    // 支持 IPv4 和 IPv6 的正则表达式
    if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6)) {
        return $ip;
    } else {
        return '127.0.0.1'; // 默认返回本地回环地址
    }
}

数据库中 IP 字段的类型为 VARCHAR(15),这是 IPv4 的长度限制,需要将其调整为支持 IPv6 的长度。 IPv6 地址最长为 39 个字符,因此将字段长度设置为 VARCHAR(39) 或更高。可手动修改或执行以下 sql 语句:

-- 管理员登录记录中的 IP
ALTER TABLE `dou_admin_log` MODIFY COLUMN `ip` VARCHAR(40);
-- 插件智能客服对话记录中的首次访问 IP 和最近访问 IP
ALTER TABLE `dou_chat_service` MODIFY COLUMN `first_ip` VARCHAR(40);
ALTER TABLE `dou_chat_service` MODIFY COLUMN `last_ip` VARCHAR(40);
-- 插件智能客服对话记录的每条对话记录 IP(虽然后台没有显示,但在数据库中有该字段)
ALTER TABLE `dou_chat_service_recorde` MODIFY COLUMN `ip` VARCHAR(40);

如果没有安装插件智能客服,只需要修改或执行第一个 sql 语句。