xiaouncle 2016-02-18
对于个人研发者来说购买高性能的阿里云等服务器价格偏高,实际利用率也不高,所以最近一直在研究intel nuc。功耗低省电,还能客串家用客厅系统,一举多得。
但是问题来了,我的域名是在万网(被阿里云收购了)购买,家里宽带是联通光线无固定ip。
如何实现动态解析就成了首要问题,本来打算通过dnspod或花生壳这种东西做中转凑副一下,
但这不是我的性格,偶然得知阿里云开通了云解析API并提供了SDK环境,所以说干就干,根据联通宽带的路由方式自己写DDNS算法。
硬件配置如下:
1,联通的光纤虽然是动态分配ip,但是是独享公网ip。这点很重要,有线电视宽带不是独享公网ip,所以本方法不适用。
2,tp-link路由器
3,intel nuc通过路由实现器上网
DDNS程序大体思想如下:
1,轮询当前路由器公网ip是否变更
2,如变更则更新阿域名绑定的 ip 地址
3,如无变更则不做任何操作
4,进入路由器管理页面,选择端口映射,将需要的端口映射到指定ip的指定端口。
具体操作如下:
1.首先你得有个阿里云的域名
2.到阿里云管理控制台申请Access Key
3.下载java sdk,SDK 主要帮我们封装好了一些数据格式转换和对接的方法,能够方便我们快速接入,当然如果你足够牛逼的话,你也完全可以全部自己写。
4.进行接入操作。我的主要思路是运行该程序的时候先去阿里云获取域名绑定的 ip 地址,再跟
当前路由器公网 ip 地址做对比,如果 ip 相同则说明没改变,不需要操作。如果 ip 不同则修改域名绑定的 ip 地址。
5.服务器部署。通过windows的计划任务,每隔一分钟执行一次DDNS程序,修正域名绑定的 ip 地址。
6.进入路由器管理页面,选择端口映射,将需要的端口映射到指定ip的指定端口。
注意:
1.阿里云通过 RecordId 来区分每条域名解析记录,但是他们之前文档上对于这个参数的描述只写了“解析记录的 ID ”,没有写如何获取这条解析记录 ID ,我去我的阿里云控制台上找了好久都没找到,到后来我突然想到 sdk 上有获取域名信息的 api ,我试着用这个果然返回的信息里有这个字段。
下面上代码:
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.InetAddress; import java.net.URL; import java.net.URLConnection; import java.util.Date; import java.util.List; import com.aliyun.api.AliyunClient; import com.aliyun.api.AliyunConstants; import com.aliyun.api.DefaultAliyunClient; import com.aliyun.api.dns.dns20150109.request.DescribeSubDomainRecordsRequest; import com.aliyun.api.dns.dns20150109.request.UpdateDomainRecordRequest; import com.aliyun.api.dns.dns20150109.response.DescribeSubDomainRecordsResponse; import com.aliyun.api.dns.dns20150109.response.UpdateDomainRecordResponse; import com.aliyun.api.domain.Record; public class DemoListDomains { private static AliyunClient client; static { String serverUrl = "http://dns.aliyuncs.com/"; String accessKeyId = ""; String accessKeySecret = ""; client = new DefaultAliyunClient(serverUrl, accessKeyId, accessKeySecret, AliyunConstants.FORMAT_JSON); } public static void main(String[] args) { try { // 获取域名信息 DescribeSubDomainRecordsRequest ddi_req = new DescribeSubDomainRecordsRequest(); ddi_req.setTimestamp(new Date().getTime()); DescribeSubDomainRecordsResponse ddi_resp = new DescribeSubDomainRecordsResponse(); ddi_req.setSubDomain("www.xxxxx.com"); ddi_resp = client.execute(ddi_req); List<Record> list = ddi_resp.getDomainRecords(); for (Record record : list) { String ip = getMyIPOutter();// 获得本机公网IP if (!ip.equals(record.getValue())) { // 根据传入参数修改解析记录 UpdateDomainRecordRequest udr_req = new UpdateDomainRecordRequest(); udr_req.setTimestamp(new Date().getTime()); udr_req.setRecordId(record.getRecordId()); udr_req.setrR(record.getrR()); udr_req.setValue(ip); udr_req.setType(record.getType()); udr_req.settTL(record.gettTL()); udr_req.setPriority(record.getPriority()); udr_req.setLine(record.getLine()); UpdateDomainRecordResponse udr_resp = new UpdateDomainRecordResponse(); udr_resp = client.execute(udr_req); if (udr_resp.getErrorCode() == null) { System.out.println("success"); } else { System.out.println("error"); } } } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); System.out.println("error"); } } private static String getMyIPOutter() throws IOException { InputStream ins = null; try { URL url = new URL("http://1212.ip138.com/ic.asp"); URLConnection con = url.openConnection(); ins = con.getInputStream(); InputStreamReader isReader = new InputStreamReader(ins, "GB2312"); BufferedReader bReader = new BufferedReader(isReader); StringBuffer webContent = new StringBuffer(); String str = null; while ((str = bReader.readLine()) != null) { if (str.contains("您的IP是:[")) { webContent.append(str); break; } } int start = webContent.indexOf("[") + 1; int end = webContent.indexOf("]"); return webContent.substring(start, end); } finally { if (ins != null) { ins.close(); } } } @SuppressWarnings("unused") private static String getMyIPLocal() throws IOException { InetAddress ia = InetAddress.getLocalHost(); return ia.getHostAddress(); } }