位于两地的两个服务器(群晖)通过pptp建立了虚拟网络,但是pptp客户端获取到的ip地址是动态的,因为使用的是群晖DSM内部提供的服务,无法配置固定IP,所以考虑使用自己的域名来解析DDNS地址。

首先配置A映射阿里云的域名:myDDNS.nzcong.cn,指向随意,后续指向会动态变化。

使用阿里云提供的SDK编写自定义接口,java语言使用jsp比较简便:

<%@ page import="com.aliyuncs.profile.IClientProfile" %>
<%@ page import="com.aliyuncs.profile.DefaultProfile" %>
<%@ page import="com.aliyuncs.DefaultAcsClient" %>
<%@ page import="com.aliyuncs.IAcsClient" %>
<%@ page import="com.aliyuncs.alidns.model.v20150109.*" %>
<%@ page import="java.util.List" %>
<%@ page import="java.util.Map" %>
<%@ page import="java.util.UUID" %>
<%@ page import="java.util.HashMap" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
    try {
        Map<String, String> keySet = new HashMap<>();
        keySet.put("myDDNS.nzcong.cn", "token1");
        keySet.put("otherDDNS.nzcong.cn", "token2");
        String domain = request.getParameter("domain");
        String recordKey = request.getParameter("recordKey");
        String currentIp = request.getParameter("currentIp");
        String key = request.getParameter("key");
        if (!keySet.getOrDefault(String.format("%s.%s", recordKey, domain), UUID.randomUUID().toString()).equals(key)) {
            response.sendError(401);
            return;
        }
        String regionId = "xxxxx";
        String accessKeyId = "xxxxx";
        String accessKeySecret = "xxxxx";
        IClientProfile profile = DefaultProfile.getProfile(regionId, accessKeyId, accessKeySecret);
        IAcsClient client = new DefaultAcsClient(profile);
        DescribeDomainRecordsRequest describeDomainRecordsRequest = new DescribeDomainRecordsRequest();
        describeDomainRecordsRequest.setDomainName(domain);
        describeDomainRecordsRequest.setRRKeyWord(recordKey);
        describeDomainRecordsRequest.setType("A");
        DescribeDomainRecordsResponse describeDomainRecordsResponse = client.getAcsResponse(describeDomainRecordsRequest);
        List<DescribeDomainRecordsResponse.Record> domainRecords = describeDomainRecordsResponse.getDomainRecords();
        if(domainRecords.size() != 0 ){
            DescribeDomainRecordsResponse.Record record = domainRecords.get(0);
            String recordId = record.getRecordId();
            String recordsValue = record.getValue();
            if(!currentIp.equals(recordsValue)){
                UpdateDomainRecordRequest updateDomainRecordRequest = new UpdateDomainRecordRequest();
                updateDomainRecordRequest.setRR(describeDomainRecordsRequest.getRRKeyWord());
                updateDomainRecordRequest.setRecordId(recordId);
                updateDomainRecordRequest.setValue(currentIp);
                updateDomainRecordRequest.setType("A");
                UpdateDomainRecordResponse updateDomainRecordResponse = client.getAcsResponse(updateDomainRecordRequest);
                response.getWriter().println("DONE!!");
            } else {
                response.getWriter().println("OK");
            }
        } else {
            response.getWriter().println("FAIL!!");
        }
    } catch (Exception e){
        response.getWriter().println(e.getMessage());
    }
%>
# 调用接口,即可将myDDNS.nzcong.cn的指向修改为10.0.0.2
curl http://myserver/path/jspName.jsp?domain=nzcong.cn&recordKey=myDDNS&key=token1&currentIp=10.0.0.2

有了ddns接口修改的地址,我们需要获取客户端的ip地址,并调用接口修改即可

我们在群晖建立一个定时任务,每分钟执行(或者其他linux使用corntab)修改脚本。

编写shell脚本,在脚本中配置域名、token、要筛选的关键字(可以用网卡或者网段)

# ddns.js
#!/bin/sh
domain=nzcong.cn
recordKey=myDDNS
key=token1
VAR="10.0.0"
HOST_IP=$(ifconfig | grep $VAR | grep "inet"| grep -v "inet6"| awk '{ print $2}' | awk -F: '{print $2}')
url="http://myserver/path/jspName.jsp?domain=$domain&recordKey=$recordKey&key=$key&currentIp=$HOST_IP"
echo $url
resp=$(curl "http://myserver/path/jspName.jsp?domain=$domain&recordKey=$recordKey&key=$key&currentIp=$HOST_IP")
echo $resp