对于个人研发者来说购买高性能的阿里云等服务器价格偏高,实际利用率也不高,所以最近一直在研究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();
}
}