天天看點

利用阿裡雲解析api實作DDNS

對于個人研發者來說購買高性能的阿裡雲等伺服器價格偏高,實際使用率也不高,是以最近一直在研究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();
	}
}
           

繼續閱讀