动态域名解析 解决方案



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

 

版权声明:本文为freefei原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/freefei/articles/3235002.html