利用阿里云解析api实现DDNS

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();
	}
}

相关推荐