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