DualWAN+PHP+DNSPOD实现域名自动解析

2014-10-09 08:45:52 11 4778


去年折腾的一个小玩意, 出发点是电脑上搭了一个php程序, 需要实现外网实时访问然后路由是用的dualwan, tomato的固件, 其实固件里已经内置了解析功能, 可以直接解析3322和花生壳,
但是由于几个动态域名服务商都不太稳定的原因 (其实就是他妈闲的蛋疼瞎折腾), 所以就想用用dnspod来动态解析.
首先dnspod自己就提供了一套动态解析的服务端, (地址:https://support.dnspod.cn/Kb/showarticle/tsid/19)
但是由于是软件模式的, 你还得搞个开机启动, 还得装个服务才能用, 还是很不爽, 如果直接在路由上实现就不会有这些问题了.

好了不废话了, dnspod官方有提供域名解析相应的api (地址: https://www.dnspod.cn/docs/records.html#record-modify)
接口地址:  https://dnsapi.cn/Record.Modify
HTTP请求方式:  POST
请求参数:  
公共参数
  domain_id 域名ID,必选
  record_id 记录ID,必选
  sub_domain 主机记录,默认@,如 www,可选
  record_type 记录类型,通过API记录类型获得,大写英文,比如:A,必选
  record_line 记录线路,通过API记录线路获得,中文,比如:默认,必选
  value 记录值, 如 IP:200.200.200.200, CNAME: cname.dnspod.com.,
  MX: mail.dnspod.com.,必选
  mx {1-20} MX优先级, 当记录类型是 MX 时有效,范围1-20, mx记录必选
  ttl {1-604800} TTL,范围1-604800,不同等级域名最小值不同,可选

响应代码:  共通返回
  -15 域名已被封禁
  -7 企业账号的域名需要升级才能设置
  -8 代理名下用户的域名需要升级才能设置
  6 域名ID错误
  7 不是域名所有者或没有权限
  8 记录ID错误
  21 域名被锁定
  22 子域名不合法
  23 子域名级数超出限制
  24 泛解析子域名错误
  25 轮循记录数量超出限制
  26 记录线路错误
  27 记录类型错误
  29 TTL 值太小
  30 MX 值错误,1-20
  31 URL记录数超出限制
  32 NS 记录数超出限制
  33 AAAA 记录数超出限制
  34 记录值非法
  35 添加的IP不允许
  36 @主机的NS纪录只能添加默认线路
  82 不能添加黑名单中的IP
其实这里就已经很简单了, 一个curl就可以搞定, but蛋疼的是路由并没有预装这个curl类
也不想手动的去装他, 所以就另辟蹊径, curl不能用, 我用wget还不行嘛! 所以就有了后面结合php的想法

好了开始说正题吧, api有两个比较重要的参数需要获取, 那就是
  domain_id 域名ID,必选
  record_id 记录ID,必选
这两个参数值我发现dnspod官方并没有给出获取方法, google了一下发现可以用以下方法获取,
第一, 安装dnspod官方的动态解析软件 (https://www.dnspod.cn/client/DNSPodClientLite.zip), 登录你的帐号 如图





然后选择要解析的域名点击"动态解析", 之后选择对应的记录添加到启动动态解析:



设置好以后再看软件目录下的config.xml文件就可以找到你域名的id(domain_id)和记录id(record_id):



有了这些参数以后再用php来提交就可以了, 这里用了一个dnspod开发人员写的api类, 直接调用一下就可以了,
index.php里修改一下对应的参数即可:



classh.php(api提交类), index.php(功能) 两个文件代码文末会贴出
之后放到web目录下, 比如我本地访问地址为 http://127.0.0.1/DNSPOD/index.php
而我本机对应的内网ip为192.168.1.210

然后进入"tomato - 系统管理 - 定时任务", 开启一个脚本, 命令代码如下:
rm -rf /tmp/dnspod/
mkdir /tmp/dnspod/
wget "http://192.168.1.210/DNSPOD/?ip=$(nvram get wan_ipaddr)|^$(nvram get wan2_ipaddr)|^$(nvram get wan3_ipaddr)|^$(nvram get wan4_ipaddr)" -O /tmp/dnspod/log.txt
rm -rf /tmp/dnspod/log.txt
这里记得写你的内网地址, 别写127.0.0.1, 如图:



设置完成后保存设置就大功告成了!

最后说一下为什么我这里是提交的4个ip, 因为我是设置的4条多拨, 入过没有设置多拨就是单拨的黑客直接把wget地址修改成
http://192.168.1.210/DNSPOD/?ip=$(nvram get wan_ipaddr)
即可, 如果是两拨或者三拨设置相应的参数就行了, 以 |^ 为分隔符, 如下:
两拨:
http://192.168.1.210/DNSPOD/?ip=$(nvram get wan_ipaddr)|^$(nvram get wan2_ipaddr)
三拨
http://192.168.1.210/DNSPOD/?ip=$(nvram get wan_ipaddr)|^$(nvram get wan2_ipaddr)|^$(nvram get wan3_ipaddr)
四拨:
http://192.168.1.210/DNSPOD/?ip=$(nvram get wan_ipaddr)|^$(nvram get wan2_ipaddr)|^$(nvram get wan3_ipaddr)|^$(nvram get wan4_ipaddr)
这里不需要再设置当wan联机的脚本了, 反正这个任务也是每分钟就执行一次, 设置好以后等个一分钟可以去dnspod控制面板看ip是否已经更新成功
其实很简单, 这个问题也有很多人在各种地方问, 大部分人就卡在不能用curl那了, 各种不能安装, 其实有时候多转转脑子问题就解决了

最后贴代码 index.php:
<?php
require './class.php';
$dnspod = new dnspod();
$ip = explode("|^",$_GET['ip']);

if( count($ip) >= 1 && is_array($ip) ){
        foreach($ip as $k=>$v){
                if(ip_check($v)){
                        $value = $v;
                        break;
                }
        }
}else
{
        if(ip_check($v)){
                $value = $v;
                break;
        }else{
                exit();
        }
}

$dnspod->api_call("Record.Modify",
array('login_email'=>'DNSPOD登录名',
        'login_password'=>'DNSPOD密码',
        'format'=>'json',
        'domain_id'=>'看文中先获取',
        'record_id'=>'看文中先获取',
        'value'=>$value,
        'record_type'=>'A',
        'record_line'=>'默认')
);


function ip_check($value){        //验证ip是否非法
         preg_match_all("/[.]/i",$value,$matches);        //取点号
         if(count($matches[0])==3 && strlen($value)<=15){        //判断IP是否正确
                 if(is_numeric(substr($value, strlen($value)-1, 1)) && is_numeric(substr($value, 0, 1))){        //判断IP是否正确
                         return true;
                 }
         }else{
                 return false;
         }
}
?>
class.php:
<?php
/*
* DNSPod API PHP Web 示例
* [url=http://www.zhetenga.com/]http://www.zhetenga.com/[/url]
*
* Copyright 2011, Kexian Li
* Released under the MIT, BSD, and GPL Licenses.
*
*/

class dnspod {
        public function api_call($api, $data) {
                if ($api == '' || !is_array($data)) {
                        exit('内部错误:参数错误');
                }

                $api = 'https://dnsapi.cn/' . $api;
                //$data = array_merge($data, array('login_email' => $_SESSION['login_email'], 'login_password' => $_SESSION['login_password'], 'format' => 'json', 'lang' => 'cn', 'error_on_empty' => 'no'));

                $result = $this->post_data($api, $data);
                if (!$result) {
                        exit('内部错误:调用失败');
                }

                $results = @json_decode($result, 1);
                if (!is_array($results)) {
                        exit('内部错误:返回错误');
                }

                if ($results['status']['code'] != 1) {
                        exit($results['status']['message']);
                }

                return $results;
        }

        private function post_data($url, $data) {
                if ($url == '' || !is_array($data)) {
                        return false;
                }

                $ch = @curl_init();
                if (!$ch) {
                        exit('内部错误:服务器不支持CURL');
                }

                curl_setopt($ch, CURLOPT_URL, $url);
                curl_setopt($ch, CURLOPT_POST, 1);
                curl_setopt($ch, CURLOPT_HEADER, 0);
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
                curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
                curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
                curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
                curl_setopt($ch, CURLOPT_USERAGENT, 'DNSPod API PHP Web Client/0.1 ([url=mailto:[email protected]][email protected][/url])');
                $result = curl_exec($ch);
                curl_close($ch);

                return $result;
        }
}
?>
两个文件记住放同一目录下

关于作者

Rices154篇文章2132篇回复

评论11次

要评论?请先  登录  或  注册