这里是记录如何使用PHP来实现阿里云动态解析DDNS功能,因为家里ip每次断电或路由器重启后会更换,所以这个功能是个必须的。
首先,是需要到阿里云申请AccessKey,然后给它设置管理DNS的权限,之后获取它的id和secret,这个将用于获取域名的相关记录及更新。
然后就是上代码:
<?php
date_default_timezone_set("GMT");
$ipnow = (json_decode(file_get_contents("http://httpbin.org/ip"),true))['origin']; //从网上接口获取到服务器公网ip
if($ipnow == null || $ipnow == ''){
//如果没有获取到IP
echo 'IP获取失败,稍后再试';
}else{
//获取到IP的话,判断是否有变化,然后更新
//首次运行时或者服务器上iPfile文件被删除后
if(!file_exists(("ipfile.txt")) || filesize("ipfile.txt") ==0){
$ipfile = fopen("ipfile.txt", "w") or die("Unable to open file!");
fwrite($ipfile, $ipnow); //将ip写入文件用于下次判断
fclose($ipfile);
//绑定 ip 到域名
Ali::Obj()->UpdateDomainRecord($ipnow);
}else{
//如果已经存在ipfile.txt文件
$ipfile = fopen("ipfile.txt", "r") or die("Unable to open file!");
$iprecord = fread($ipfile,filesize("ipfile.txt"));
if($iprecord == $ipnow){
//如果判断出当前ip和原来的没变化
echo '现在服务器IP为:'.$iprecord.',没有改变,无需更新!';
fclose($ipfile);
}else{
//如果ip发生变化
$ipfile = fopen("ipfile.txt", "w") or die("Unable to open file!");
//绑定 ip 到域名
Ali::Obj()->UpdateDomainRecord($ipnow);
fwrite($ipfile, $ipnow);
fclose($ipfile);
}
}
}
$Ali = new Ali(); //阿里云动态解析函数
Ali::Obj()->UpdateDomainRecord($ip);
//封装阿里云动态解析DDNS
class Ali
{
/**以下4条记得修改**/
private $accessKeyId = "accessKeyId"; //阿里云的accesskeyid
private $accessSecret = "accessSecret"; //阿里云的accesssecrec
private $domainname = 'xxx.com'; //你需要更新的域名,不要带任何前缀
private $rrlist = ['@','www']; //你需要更新的域名前缀数组,前提是这几个在你已经解析的清单中已经生效过了
/**以上4条记得修改**/
private static $obj = null;
public static function Obj ()
{
if(is_null(self::$obj))
{
self::$obj = new self();
}
return self::$obj;
}
public function DescribeDomainRecords()
{
$requestParams = array(
"Action" => "DescribeDomainRecords",
"DomainName" => $this->domainname
);
//通过阿里云接口获取域名对应的主机(子域名)清单,并把获取到的数据转换成需要的数组
$val = $this->requestAli($requestParams);
$recordslist = json_decode($val,true);
$records = $recordslist['DomainRecords']['Record'];
for($i=0;$i<count($records);$i++){
$rr = $records[$i]['RR'];
//判断是否在你设置的前缀清单中
if (in_array($rr, ($this->rrlist))){
$record[$rr] = $records[$i]; //获取你要更新的对应前缀的域名清单
}
}
return $record;
}
/**更新 ip**/
public function UpdateDomainRecord($ip)
{
//通过获取到的域名清单,循环更新数据
$recordslist = $this -> DescribeDomainRecords();
foreach($recordslist as $lists){
$requestParams = array(
"Action" => "UpdateDomainRecord",
"RecordId" => $lists['RecordId'],
"RR" => $lists['RR'],
"Type" => $lists['Type'],
"Value" => $ip,
);
$val = $this->requestAli($requestParams);
$this->outPut($val." ".$ip);
}
}
//阿里云官方获取dns数据的接口
private function requestAli($requestParams)
{
$publicParams = array(
"Format" => "JSON",
"Version" => "2015-01-09",
"AccessKeyId" => $this->accessKeyId,
"Timestamp" => date("Y-m-d\TH:i:s\Z"),
"SignatureMethod" => "HMAC-SHA1",
"SignatureVersion" => "1.0",
"SignatureNonce" => substr(md5(rand(1,99999999)),rand(1,9),14),
);
$params = array_merge($publicParams, $requestParams);
$params['Signature'] = $this->sign($params, $this->accessSecrec);
$uri = http_build_query($params);
$url = 'http://alidns.aliyuncs.com/?'.$uri;
return $this->curl($url);
}
private function sign($params, $accessSecret, $method="GET")
{
ksort($params);
$stringToSign = strtoupper($method).'&'.$this->percentEncode('/').'&';
$tmp = "";
foreach($params as $key=>$val){
$tmp .= '&'.$this->percentEncode($key).'='.$this->percentEncode($val);
}
$tmp = trim($tmp, '&');
$stringToSign = $stringToSign.$this->percentEncode($tmp);
$key = $accessSecret.'&';
$hmac = hash_hmac("sha1", $stringToSign, $key, true);
return base64_encode($hmac);
}
private function percentEncode($value=null)
{
$en = urlencode($value);
$en = str_replace("+", "%20", $en);
$en = str_replace("*", "%2A", $en);
$en = str_replace("%7E", "~", $en);
return $en;
}
private function curl($url)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url );
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1 );
$result=curl_exec ($ch);
return $result;
}
private function outPut($msg)
{
echo date("Y-m-d H:i:s")." ".$msg.PHP_EOL;
}
}
?>
然后,通过定时器或者比如宝塔面板的计划任务,来个每几秒访问执行这个php文件一次,就能实时更新解析记录啦。
因为加了ip判断,也不用担心过多的访问阿里云接口可能被禁掉或限制啥的,也不会增加多少服务器负担,完美
public function UpdateDomainRecord($ip)这里会报错
报的什么错