• 编写 java 程序,为家用电脑 ipv6 自动更新 goddy dns 记录(ddns)


    家里放了一台旧 acer 笔记本电脑,外挂几个硬盘盒,插上几个硬盘,组成硬盘盒。

    因笔记本电脑的耗电较小,硬盘盒有自动休眠省电模式,所以长期开机。此笔记本电脑,使用家庭的移动宽带,会自动分配 IPv6 , 可远程连接。

    之前,自动分配 IPv6,很长时间不变。当然,我不可能去记这个 IPv6,所以找个 DNS 服务器,记在 AAAA 记录里。

    最近好像不停地变化,这就麻烦了。用 cn.bing.com 网上搜索一番, 找到有脚本可自动更新 goddy dns 记录(ddns)。恰好我购买了一个goddy 的域名,附送 DNS 管理,也有免费的 DDNS 编程接口。脚本语言我不太熟悉,于是就改成用 java 重写了一次。

    程序分两部分:

    a. 主控 main 类 UpdateDdns,负责反复循环,每间隔 5 秒,检查 IP 地址是否变化。

    b. 业务操作类 UpdateSrv, 负责单次循环中的业务。

    代码比较简单,直接贴上,以下是 UpdateDdns.java :

     1 package update_godaddy_ddns;
     2 
     3 import org.slf4j.Logger;
     4 import org.slf4j.LoggerFactory;
     5 
     6 public class UpdateDdns {
     7 
     8     public static void main(String[] args) {
     9         Logger log = LoggerFactory.getLogger(UpdateDdns.class);
    10         log.info("main begin...");
    11         String domain = args[0]; // "mydomain.com" # your domain
    12         String typeMulti = args[1]; // ="A" # Record type A, CNAME, MX, etc.
    13         String name = args[2]; // "sip" # name of record to update
    14         String ttl = args[3]; // "3600" # Time to Live min value 600
    15         String port = args[4]; // "1" # Required port, Min value 1
    16         String weight = args[5]; // "1" # Required weight, Min value 1
    17         String key = args[6]; // "abc" # key for godaddy developer API
    18         String secret = args[7]; // "efg" # secret for godaddy developer API
    19 
    20         String[] typeArrr = typeMulti.split("/");
    21         UpdateSrv srv = new UpdateSrv();
    22 
    23         log.info("start work loop");
    24         while (true) {
    25             try {
    26                 for (String type : typeArrr) {
    27                     srv.doUpdate(domain, type, name, ttl, port, weight, key, secret);
    28                 }
    29 
    30                 Thread.sleep(5000);
    31             } catch (Exception err) {
    32                 //err.printStackTrace();
    33                 log.error(err.getMessage(),err);
    34             }
    35         }
    36         // log.info("main end");
    37     }
    38 
    39 }

    以下是 UpdateSrv.java

      1 package update_godaddy_ddns;
      2 
      3 import java.io.BufferedReader;
      4 import java.io.IOException;
      5 import java.io.InputStream;
      6 import java.io.InputStreamReader;
      7 import java.net.Inet4Address;
      8 import java.net.Inet6Address;
      9 import java.net.InetAddress;
     10 import java.net.NetworkInterface;
     11 import java.net.SocketException;
     12 import java.util.ArrayList;
     13 import java.util.Collection;
     14 import java.util.Enumeration;
     15 
     16 import org.apache.commons.lang3.StringUtils;
     17 import org.apache.http.StatusLine;
     18 import org.apache.http.client.ClientProtocolException;
     19 import org.apache.http.client.methods.CloseableHttpResponse;
     20 import org.apache.http.client.methods.HttpGet;
     21 import org.apache.http.client.methods.HttpPut;
     22 import org.apache.http.entity.StringEntity;
     23 import org.apache.http.impl.client.CloseableHttpClient;
     24 import org.apache.http.impl.client.HttpClients;
     25 import org.slf4j.Logger;
     26 import org.slf4j.LoggerFactory;
     27 
     28 import net.sf.json.JSONArray;
     29 import net.sf.json.JSONObject;
     30 
     31 public class UpdateSrv {
     32     private String lastUpdatedIpToDnsServer;
     33 
     34     public void doUpdate(String domain, String type, String name, String ttl, String port, String weight, String key,
     35             String secret) throws ClientProtocolException, IOException {
     36         Logger log = LoggerFactory.getLogger(UpdateSrv.class);
     37         log.info("doUpdate begin...");
     38 
     39         if (this.lastUpdatedIpToDnsServer == null) {
     40             String ipFromDns = getIpFromDnsServer(domain, type, name, ttl, port, weight, key, secret);
     41             this.lastUpdatedIpToDnsServer = ipFromDns;
     42         }
     43 
     44         ArrayList<InetAddress> ipListForInternet = new ArrayList<InetAddress>();
     45 
     46         // getFromLocalMachine(ipListForInternet);
     47         getInternetIpsFromLocalMachine(ipListForInternet);
     48 
     49         if (ipListForInternet.isEmpty()) {
     50             log.warn("cannot find ipv6 for internet");
     51             return;
     52         }
     53 
     54         // check if already send ip of local machine public ip(in used) to DDNS server
     55         if (StringUtils.isNotEmpty(this.lastUpdatedIpToDnsServer)) {
     56             for (InetAddress ia : ipListForInternet) {
     57                 // String ip = ia.getHostAddress();
     58                 String ip = getIp(ia);
     59                 if (ip.equalsIgnoreCase(this.lastUpdatedIpToDnsServer)) {
     60                     log.info("local machine ip not changed,no need to update:" + ip);
     61                     return;
     62                 }
     63             }
     64         }
     65 
     66         String newIp = pickUpOneIpV6(ipListForInternet);
     67         if (StringUtils.isEmpty(newIp)) {
     68             log.warn("cannot find ipv6 for internet,2");
     69             return;
     70         }
     71 
     72         log.info("try update for newIp:" + newIp);
     73         tryUpdateIpForDns(newIp, domain, type, name, ttl, port, weight, key, secret);
     74         log.info("after update for newIp:" + newIp);
     75 
     76         // if no error
     77         this.lastUpdatedIpToDnsServer = newIp;
     78 
     79     }
     80 
     81     public void tryUpdateIpForDns(String newIp, String domain, String type, String name, String ttl, String port,
     82             String weight, String key, String secret) throws ClientProtocolException, IOException {
     83         Logger log = LoggerFactory.getLogger(UpdateSrv.class);
     84         log.info("tryUpdateIpForDns begin..." + newIp);
     85 
     86         // 1.获得一个httpclient对象
     87         try (CloseableHttpClient httpclient = HttpClients.createDefault()) {
     88 
     89             // 2.生成一个 put 请求
     90             String url = "https://api.godaddy.com/v1/domains/" + domain + "/records/" + type + "/" + name;
     91             HttpPut httpput = new HttpPut(url);
     92             httpput.setHeader("Content-Type", "application/json");
     93             httpput.setHeader("Authorization", "sso-key " + key + ":" + secret);
     94 
     95             String strJson = "[{\"data\":\"" + newIp + "\",\"ttl\":" + ttl + "}]";
     96             StringEntity stringEntity = new StringEntity(strJson, "utf-8");
     97             httpput.setEntity(stringEntity);
     98 
     99             // 3.执行 put 请求并返回结果
    100             try (CloseableHttpResponse response = httpclient.execute(httpput)) {
    101                 log.info("after httpclient.execute");
    102 
    103 //                try {
    104                 // 4.处理结果
    105                 StatusLine sl = response.getStatusLine();
    106                 log.info("getStatusLine:" + sl);
    107                 // HTTP/1.1 401 Unauthorized
    108                 if (sl.getStatusCode() == 200) {
    109                     log.info("updated success");
    110                     StringBuilder sbBuffer = new StringBuilder();
    111 
    112                     try (InputStream is = response.getEntity().getContent()) {
    113                         try (InputStreamReader isr = new InputStreamReader(is)) {
    114                             try (BufferedReader reader = new BufferedReader(isr)) {
    115                                 String line;
    116                                 while ((line = reader.readLine()) != null) {
    117                                     log.info("strResponse:" + line);
    118                                     sbBuffer.append(line);
    119                                 }
    120                             }
    121                         }
    122                     }
    123 
    124                     String strResponse = sbBuffer.toString();
    125                     // should be empty
    126                     log.info("strResponse:" + strResponse);
    127                 } else {
    128 
    129                 }
    130             }
    131         }
    132     }
    133 
    134     // private void getFromLocalMachine(ArrayList<String> ipListForInternet) throws
    135     // SocketException {
    136     private void getInternetIpsFromLocalMachine(ArrayList<InetAddress> ipListForInternet) throws SocketException {
    137         Logger log = LoggerFactory.getLogger(UpdateSrv.class);
    138         log.info("getInternetIpsFromLocalMachine begin...");
    139 
    140         // get ip-v6 only
    141         Enumeration<NetworkInterface> ints = NetworkInterface.getNetworkInterfaces();
    142         while (ints.hasMoreElements()) {
    143             // each network card
    144             NetworkInterface it = ints.nextElement();
    145 
    146             Enumeration<InetAddress> adds = it.getInetAddresses();
    147             while (adds.hasMoreElements()) {
    148                 // each ip
    149                 InetAddress ia = adds.nextElement();
    150                 // String ip = ia.getHostAddress();
    151                 String ip = getIp(ia);
    152 //                if (ia instanceof Inet4Address) {
    153 //                    continue;
    154 //                } else if (ia instanceof Inet6Address) {
    155                 if (ia.isAnyLocalAddress()) {
    156                     continue;
    157                 } else if (ia.isLoopbackAddress()) {
    158                     continue;
    159                 } else if (ia.isLinkLocalAddress()) {
    160                     continue;
    161                 } else if (ia.isSiteLocalAddress()) {
    162                     continue;
    163                 }
    164 
    165                 if (ip.startsWith("fe80:")) {
    166                     continue;
    167                 }
    168                 // ipListForInternet.add(ip);
    169                 ipListForInternet.add(ia);
    170 //                } else {
    171 //                    // should not goes here.
    172 //                }
    173 
    174             }
    175         }
    176     }
    177 
    178     private String getIpFromDnsServer(String domain, String type, String name, String ttl, String port, String weight,
    179             String key, String secret) throws ClientProtocolException, IOException {
    180         Logger log = LoggerFactory.getLogger(UpdateSrv.class);
    181         log.info("getIpFromDns begin...");
    182 
    183         // 1.获得一个httpclient对象
    184         try (CloseableHttpClient httpclient = HttpClients.createDefault()) {
    185 
    186             // 2.生成一个get请求
    187             String url = "https://api.godaddy.com/v1/domains/" + domain + "/records/" + type + "/" + name;
    188             HttpGet httpget = new HttpGet(url);
    189             httpget.addHeader("Authorization", "sso-key " + key + ":" + secret);
    190             // 3.执行get请求并返回结果
    191             try (CloseableHttpResponse response = httpclient.execute(httpget)) {
    192                 log.info("after httpclient.execute");
    193 
    194 //                try {
    195                 // 4.处理结果
    196                 StatusLine sl = response.getStatusLine();
    197                 log.info("getStatusLine:" + sl);
    198                 // HTTP/1.1 401 Unauthorized
    199                 if (sl.getStatusCode() == 200) {
    200                     StringBuilder sbBuffer = new StringBuilder();
    201 
    202                     try (InputStream is = response.getEntity().getContent()) {
    203                         try (InputStreamReader isr = new InputStreamReader(is)) {
    204                             try (BufferedReader reader = new BufferedReader(isr)) {
    205                                 String line;
    206                                 while ((line = reader.readLine()) != null) {
    207                                     log.info("strResponse:" + line);
    208                                     sbBuffer.append(line);
    209                                 }
    210                             }
    211                         }
    212                     }
    213 
    214                     String strResponse = sbBuffer.toString();
    215                     // [{"data":"2409:8a1e:90ad:a1e0:dd40:8bcd:xxx","name":"abc-ipv6","ttl":1800,"type":"AAAA"}]
    216                     log.info("strResponse:" + strResponse);
    217 
    218                     // parse
    219                     String ip = parseIpFromGodaddyResponse(strResponse);
    220                     return ip;
    221                 } else {
    222 
    223                 }
    224             }
    225         }
    226 
    227         return null;
    228     }
    229 
    230     public String parseIpFromGodaddyResponse(String strResponse) {
    231         Logger log = LoggerFactory.getLogger(UpdateSrv.class);
    232         log.info("parseIpFromGodaddyResponse begin..." + strResponse);
    233 
    234         // [{"data":"2409:8a1e:90ad:a1e0:dd40:8bcd:xxx","name":"abc-ipv6","ttl":1800,"type":"AAAA"}]
    235         // JSONObject obj = JSONObject.fromObject(strResponse);
    236         JSONArray arr = JSONArray.fromObject(strResponse);
    237 
    238         for (Object object : arr) {
    239             JSONObject obj = (JSONObject) object;
    240 
    241             // Set keys = obj.keySet();
    242             String name = (String) obj.get("name");
    243             Number ttl = (Number) obj.get("ttl");
    244             String type = (String) obj.get("type");
    245             String data = (String) obj.get("data");
    246 
    247             log.info("name:" + name + ",ttl:" + ttl + ",type:" + type + ",data:" + data);
    248 
    249             if (StringUtils.isNotEmpty(data)) {
    250                 return data;
    251             }
    252         }
    253         // log.info(arr.toString());
    254 
    255         return null;
    256     }
    257 
    258     private String pickUpOneIpV6(Collection<InetAddress> ipListForInternet) {
    259         Logger log = LoggerFactory.getLogger(UpdateSrv.class);
    260         log.info("pickUpOneIpV6 begin...");
    261 
    262         for (InetAddress ia : ipListForInternet) {
    263             if (ia instanceof Inet4Address) {
    264                 continue;
    265             } else if (ia instanceof Inet6Address) {
    266                 String ip = getIp(ia);
    267                 return ip;
    268             } else {
    269                 // should not goes here.
    270             }
    271         }
    272         return null;
    273     }
    274 
    275     private String getIp(InetAddress ia) {
    276         String ip = ia.getHostAddress();
    277         // 2409:891e:9340:xxx:xxx:xxx:f3c7:xxx%wlp4s0
    278         int pos = ip.lastIndexOf("%");
    279         if (pos > 0) {
    280             ip = ip.substring(0, pos);
    281         }
    282         return ip;
    283     }
    284 }

    编译后,在 ubuntu 下,使用命令行运行:

    export CLASSPATH=".:../bin:../lib/slf4j-api-1.7.25.jar:../lib/httpclient-4.5.2.jar:../lib/httpcore-4.4.4.jar:../lib/jcl-over-slf4j-1.7.25.jar:../lib/logback-classic-1.2.3.jar:../lib/logback-core-1.2.3.jar:../lib/json-lib-2.4-jdk15.jar:../lib/commons-lang-2.4.jar:../lib/commons-lang3-3.0.1.jar:../lib/ezmorph-1.0.6.jar:../lib/commons-collections-3.2.2.jar:../lib/commons-beanutils-1.9.3.jar"
    
    java update_godaddy_ddns.UpdateDdns some.com AAAA zg_xxx 1800 1 1 xxx yyy

    命令行参数的含义,见 UpdateDdns.java 中的 main 函数。

    ------2022/01/04, 说明,以上代码,后续有更新,以此网址为准:

    编写 java 程序,为家用电脑 ipv6 自动更新 goddy dns 记录(ddns) (zheguisoft.com)

    --------------欢迎转载,转载请注明出处: https://www.cnblogs.com/jacklondon

  • 相关阅读:
    【InnoDB】插入缓存,两次写,自适应hash索引
    【InnoDB】缓冲池
    P3371 【模板】单源最短路径(弱化版) 题解
    P1463 [POI2002][HAOI2007]反素数 题解
    CF701B Cells Not Under Attack 题解
    P1120 小木棍 [数据加强版] 题解
    P3951 小凯的疑惑 题解
    P1135 奇怪的电梯 题解
    P1748 H数 题解
    P3388 【模板】割点(割顶) 题解
  • 原文地址:https://www.cnblogs.com/jacklondon/p/auto_update_ddns_for_goddy_dns_for_home_ipv6_pc_with_java.html
Copyright © 2020-2023  润新知