动态域名解析 解决方案
动态域名解析 解决方案
2013-05-30 17:30
freefei
阅读(1440)
评论(0)
编辑
收藏
举报
参考方案
1 dnspod 动态域名解析 详细:dnspod开放了api 接口 可以修改ip ,于是 我们可以在本地服务器上 做一个程序 脚本检查 本地的公网ip 是否和dnspod的绑定ip 是否一致,如果不一致 则本地脚本 根据API修改 dnspod的ip ,本地检查更新dnspod的脚本
2 有两个问题:1:电信封闭80 端口 需要解决方案 2:路由器需要配置开放80端口 默认关闭状态, 如果菜鸟用户 麻烦。 如此思路的 脚本 县城的有很多 针对window 和服务 linux ssh 等等的
1 <?php 2 /** 3 * @category ${NAME} 4 * @author gouki <gouki.xiao@gmail.com>, xin.qin@qinx.cn 5 * @created 13-4-7 下午9:17 6 * @updated 13-5-18 22:25 7 * @since 8 */ 9 error_reporting(7); 10 date_default_timezone_set(\'Asia/Chongqing\'); 11 /** 12 * 13 * 14 */ 15 define(\'DNSPOD_APIURL\', \'https://dnsapi.cn/Record.Modify\'); 16 //define(\'DNSPOD_APIURL\', \'https://dnsapi.cn/Record.Ddns\'); 17 define(\'LAST_IP_TMP_FILE\', \'dnspod_ip\'); 18 class Dnspod 19 { 20 protected $username = \'admin@ff-gzs.cn\'; //dnspod username 21 protected $password = \'fdsdssi\'; //dnspod user password 22 /* 23 protected $domainId = \'对应的domainId\'; 24 protected $updated = array( 25 \'subDomain对应的ID\' => \'域名\', 26 ); 27 */ 28 29 protected $domains = array( 30 //format: domain_id, record_id, sub_domain 31 array(domain_id,record_id,\'sub_domain\'), //这个id可以通过dnspod的官方客户端查看 32 array(domain_id,record_id,\'sub_domain\') 33 ); 34 35 public function getLastIp() 36 { 37 if (!file_exists(LAST_IP_TMP_FILE)) { 38 touch(LAST_IP_TMP_FILE); 39 } 40 return file_get_contents(LAST_IP_TMP_FILE); 41 } 42 43 public function getCurrentIp() 44 { 45 $ip138 = \'http://iframe.ip138.com/ic.asp\'; 46 $ip138Content = @file_get_contents($ip138); 47 preg_match(\'/\[(.*?)\]/\', $ip138Content, $output); 48 if (isset($output[1])) { 49 return trim($output[1]); 50 } 51 return \'\'; 52 } 53 54 public function saveCurrentIp($ip) 55 { 56 file_put_contents(LAST_IP_TMP_FILE, trim($ip)); 57 } 58 59 public function run() 60 { 61 $currentIp = $this->getCurrentIp(); 62 $lastIp = $this->getLastIp(); 63 if ($currentIp == $lastIp || !$currentIp) { 64 $data = \'the ip address is same as before, or cannot get ip this time.\'; 65 $this->log($data); 66 return; 67 } 68 69 /* 70 foreach ($this->updated as $recordId => $subDomain) { 71 $result = $this->saveRecord($recordId, $subDomain, $currentIp); 72 echo $result; 73 } 74 */ 75 foreach($this->domains as $value){ 76 $result = $this->saveRecord($value[0], $value[1], $value[2], $currentIp); 77 $this->log($result); 78 } 79 80 $this->saveCurrentIp($currentIp); 81 } 82 83 protected function saveRecord($domainId, $recordId, $subDomain, $ip = \'\') 84 { 85 //"format=json&login_email=$email&login_password=$password&domain_id=$domain_id&record_id=$record_id&sub_domain=$sub_domain&record_line=默认" 86 $recordData = array( 87 \'format\' => \'json\', 88 \'login_email\' => $this->username, 89 \'login_password\' => $this->password, 90 \'domain_id\' => $domainId, 91 \'record_id\' => $recordId, 92 \'sub_domain\' => $subDomain, 93 \'record_line\' => \'默认\' , 94 /** 95 * if you use Record.Ddns interface, no need to specify following 4 paramters. 96 */ 97 98 \'record_type\' => \'A\', 99 \'value\' => $ip, 100 \'mx\' => 1, 101 \'ttl\' => 10 102 103 ); 104 return $this->postData(DNSPOD_APIURL, $recordData); 105 } 106 107 protected function postData($url, $post = null) 108 { 109 $context = array(); 110 if (is_array($post)) { 111 ksort($post); 112 $context[\'http\'] = array( 113 \'method\' => \'POST\', 114 \'content\' => http_build_query($post, \'\', \'&\'), 115 ); 116 } 117 return file_get_contents($url, false, stream_context_create($context)); 118 } 119 120 protected function log($data){ 121 file_put_contents(date(\'Y-m-d\').\'\', date(\'Y-m-d H:m:s\').\': \'.$data."\r\n", FILE_APPEND); 122 } 123 } 124 125 $ddns = new Dnspod(); 126 $ddns->run();
bash解决方案 感谢 参考:http://zengrong.net/post/1524.htm
域名配置
domainList[0]=\'domain1.com \* @\' domainList[1]=\'domain2.com www subdomain1 subdomain2\'
守护进程启动
在 etc/rc.local中添加
/usr/bin/dnspodsh dnspod_name dnspod_passwaord &>/dev/null #参数 分别为 你懂得
1 #!/bin/bash 2 3 ############################## 4 # dnspodsh v0.3 5 # 基于dnspod api构架的bash ddns客户端 6 # 作者:zrong(zengrong.net) 7 # 详细介绍:http://zengrong.net/post/1524.htm 8 # 创建日期:2012-02-13 9 # 更新日期:2012-03-11 10 ############################## 11 12 login_email=${1:?\'必须提供登录名\'} 13 login_password=${2:?\'必须提供密码\'} 14 format="json" 15 lang="en" 16 userAgent="dnspodsh/0.3(zrongzrong@gmail.com)" 17 commonPost="login_email=$login_email&login_password=$login_password&format=$format&lang=$lang" 18 19 apiUrl=\'https://dnsapi.cn/\' 20 ipUrl=\'http://members.3322.org/dyndns/getip\' 21 22 # 要处理的域名数组,每个元素代表一个域名的一组记录 23 # 在数组的一个元素中,以空格分隔域名和子域名 24 # 第一个空格前为主域名,后面用空格分离多个子域名 25 # 如果使用泛域名,必须用\*转义 26 domainList[0]=\'domain1.com \* @ www\' 27 domainList[1]=\'domain2.com subdomain subdomain2\' 28 29 # 多长时间比较一次ip地址 30 delay=300 31 32 # logfile 33 logDir=\'/var/log\' 34 logFile=$logDir\'/dnspodsh.log\' 35 traceFile=$logDir\'/dnspodshtrace.log\' 36 37 # 检测ip地址是否符合要求 38 checkip() 39 { 40 # ipv4地址 41 if [[ "$1" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]];then 42 return 0 43 # ipv6地址 44 elif [[ "$1" =~ ^([\da-fA-F]{1,4}:){7}[\da-fA-F]{1,4}$|^:((:[\da-fA-F]{1,4}){1,6}|:)$|^[\da-fA-F]{1,4}:((:[\da-fA-F]{1,4}){1,5}|:)$|^([\da-fA-F]{1,4}:){2}((:[\da-fA-F]{1,4}){1,4}|:)$|^([\da-fA-F]{1,4}:){3}((:[\da-fA-F]{1,4}){1,3}|:)$|^([\da-fA-F]{1,4}:){4}((:[\da-fA-F]{1,4}){1,2}|:)$|^([\da-fA-F]{1,4}:){5}:([\da-fA-F]{1,4})?$|^([\da-fA-F]{1,4}:){6}:$ ]];then 45 return 0 46 fi 47 return 1 48 } 49 50 getUrl() 51 { 52 #curl -s -A $userAgent -d $commonPost$2 --trace $traceFile $apiUrl$1 53 curl -s -A $userAgent -d $commonPost$2 $apiUrl$1 54 } 55 56 getVersion() 57 { 58 getUrl "Info.Version" 59 } 60 61 getUserDetail() 62 { 63 getUrl "User.Detail" 64 } 65 66 writeLog() 67 { 68 if [ -w $logDir ];then 69 local pre=`date` 70 for arg in $@;do 71 pre=$pre\'\t\'$arg 72 done 73 echo -e $pre>>$logFile 74 fi 75 echo -e $1 76 } 77 78 getDomainList() 79 { 80 getUrl "Domain.List" "&type=all&offset=0&length=10" 81 } 82 83 # 根据域名id获取记录列表 84 # $1 域名id 85 getRecordList() 86 { 87 getUrl "Record.List" "&domain_id=$1&offset=0&length=20" 88 } 89 90 # 设置记录 91 setRecord() 92 { 93 writeLog "set domain $3.$8 to new ip:$7" 94 local subDomain=$3 95 # 由于*会被扩展,在最后一步将转义的\*替换成* 96 if [ "$subDomain" = \'\*\' ];then 97 subDomain=\'*\' 98 fi 99 local request="&domain_id=$1&record_id=$2&sub_domain=$subDomain&record_type=$4&record_line=$5&ttl=$6&value=$7" 100 #echo $request 101 local saveResult=$(getUrl \'Record.Modify\' "$request") 102 # 检测返回是否正常,但即使不正常也不退出程序 103 if checkStatusCode "$saveResult" 0;then 104 writeLog "set record $3.$8 success." 105 fi 106 #getUrl \'Record.Modify\' "&domain_id=$domainid&record_id=$recordid&sub_domain=$recordName&record_type=$recordtype&record_line=$recordline&ttl=$recordttl&value=$newip" 107 } 108 109 # 设置一批记录 110 setRecords() 111 { 112 numRecord=${#changedRecords[@]} 113 for (( i=0; i < $numRecord; i++ ));do 114 setRecord ${changedRecords[$i]} 115 done 116 # 删除待处理的变量 117 unset changeRecords 118 } 119 120 # 通过key得到找到一个JSON对象字符串中的值 121 getDataByKey() 122 { 123 local s=\'s/{[^}]*"\'$2\'":["]*\(\'$(getRegexp $2)\'\)["]*[^}]*}/\1/\' 124 #echo \'拼合成的regexp:\'$s 125 echo $1|sed $s 126 } 127 128 # 根据key返回要获取的正则表达式 129 getRegexp() 130 { 131 case $1 in 132 \'value\') echo \'[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\';; 133 \'type\') echo \'[A-Z]\+\';; 134 \'name\') echo \'[-_.A-Za-z*]\+\';; 135 \'ttl\'|\'id\') echo \'[0-9]\+\';; 136 \'line\') echo \'[^"]\+\';; 137 esac 138 } 139 140 # 通过一个JSON key名称,获取一个{}包围的JSON对象字符串 141 # $1 要搜索的key名称 142 # $2 要搜索的对应值 143 getJSONObjByKey() 144 { 145 grep -o \'{[^}{]*"\'$1\'":"\'$2\'"[^}]*}\' 146 } 147 148 # 获取A记录类型的域名信息 149 # 对于其它记录,同样的名称可以对应多条记录,因此使用getJSONObjByKey可能获取不到需要的数据 150 getJSONObjByARecord() 151 { 152 grep -o \'{[^}{]*"name":"\'$1\'"[^}]*"type":"A"[^}]*}\' 153 } 154 155 # 获取返回代码是否正确 156 # $1 要检测的字符串,该字符串包含{status:{code:1}}形式,代表DNSPodAPI返回正确 157 # $2 是否要停止程序,因为dnspod在代码错误过多的情况下会封禁账号 158 checkStatusCode() 159 { 160 if [[ "$1" =~ \{\"status\":\{[^}{]*\"code\":\"1\"[^}]*\} ]];then 161 return 0 162 fi 163 writeLog "DNSPOD return error:$1" 164 # 根据参数需求退出程序 165 if [ -n "$2" ] && [ "$2" -eq 1 ];then 166 writeLog \'exit dnspodsh\' 167 exit 1 168 fi 169 } 170 171 # 获取与当前ip不同的,要更新的记录的数组 172 getChangedRecords() 173 { 174 # 从DNSPod获取最新的域名列表 175 local domainListInfo=$(getDomainList) 176 if [ -z "$domainListInfo" ];then 177 writeLog \'DNSPOD tell me domain list is null,waiting...\' 178 return 1 179 fi 180 checkStatusCode "$domainListInfo" 1 181 182 # 主域名的id 183 local domainid 184 local domainName 185 # 主域名的JSON信息 186 local domainInfo 187 # 主域名的所有记录列表 188 local recordList 189 # 一条记录的JSON信息 190 local recordInfo 191 # 记录的id 192 local recordid 193 local recordName 194 # 记录的TTL 195 local recordTtl 196 # 记录的类型 197 local recordType 198 # 记录的线路 199 local recordLine 200 local j 201 202 # 用于记录被改变的记录 203 unset changedRecords 204 205 local numDomain=${#domainList[@]} 206 local domainGroup 207 208 for ((i=0;i<$numDomain;i++));do 209 domainGroup=${domainList[$i]} 210 j=0 211 for domain in ${domainGroup[@]};do 212 # 列表的第一个项目,是主域名 213 if ((j==0));then 214 domainName=$domain 215 domainInfo=$(echo $domainListInfo|getJSONObjByKey \'name\' $domainName) 216 domainid=$(getDataByKey "$domainInfo" \'id\') 217 recordList=$(getRecordList $domainid) 218 if [ -z "$recordList" ];then 219 writeLog \'DNSPOD tell me record list null,waiting...\' 220 return 1 221 fi 222 checkStatusCode "$recordList" 1 223 else 224 # 从dnspod获取要设置的子域名记录的信息 225 recordInfo=$(echo $recordList|getJSONObjByARecord $domain) 226 # 如果取不到记录,则不处理 227 if [ -z "$recordInfo" ];then 228 continue 229 fi 230 231 # 从dnspod获取要设置的子域名的ip 232 oldip=$(getDataByKey "$recordInfo" \'value\') 233 234 # 检测获取到的旧ip地址是否符合ip规则 235 if ! checkip "$oldip";then 236 writeLog \'get old ip error!it is "$oldid".waiting...\' 237 continue 238 fi 239 240 if [ "$newip" != "$oldip" ];then 241 recordid=$(getDataByKey "$recordInfo" \'id\') 242 recordName=$(getDataByKey "$recordInfo" \'name\') 243 recordTtl=$(getDataByKey "$recordInfo" \'ttl\') 244 recordType=$(getDataByKey "$recordInfo" \'type\') 245 # 由于从服务器获取的线路是utf编码,目前无法知道如何转换成中文,因此在这里写死。dnspod中免费用户的默认线路的名称就是“默认” 246 #recordLine=$(getDataByKey "$recordInfo" \'line\') 247 recordLine=\'默认\' 248 # 判断取值是否正常,如果值为空就不处理 249 if [ -n "$recordid" ] && [ -n "$recordTtl" ] && [ -n "$recordType" ]; then 250 # 使用数组记录需要修改的子域名的所有值 251 # 这里一共有8个参数,与setRecord中的参数对应 252 changedRecords[${#changedRecords[@]}]="$domainid $recordid $domain $recordType $recordLine $recordTtl $newip $domainName" 253 fi 254 fi 255 fi 256 j=$((j+1)) 257 done 258 done 259 } 260 261 # 执行检测工作 262 go() 263 { 264 # 由于获取到的数据多了一些多余的字符,所以提取ip地址的部分 265 # 从api中获取当前的外网ip 266 newip=$(curl -s $ipUrl|grep -o $(getRegexp \'value\')) 267 # 如果获取最新ip错误,就继续等待下一次取值 268 if ! checkip "$newip";then 269 writeLog \'can not get new ip,waiting...\' 270 sleep $delay 271 continue 272 fi 273 # 获取需要修改的记录 274 getChangedRecords 275 if (( ${#changedRecords[@]} > 0 ));then 276 writeLog "ip is changed,new ip is:$newip" 277 setRecords 278 fi 279 } 280 281 while [ 1 ];do 282 go 283 sleep $delay 284 done