阿里云域名动态解析

时间:2024-04-27 14:30:23

前景说明:

你有一个阿里云的域名,想让它解析到你家用宽带动态ip上。

解决思路:

1、定时查看宽带的ip;

2、发现变化时,通过阿里云提供的sdk修改域名解析。

一、阿里云控制台创建AccessKey

官方文档:创建阿里云AccessKey_访问控制(RAM)-阿里云帮助中心 (aliyun.com)

二、阿里云 云解析

官方文档:云解析_SDK中心-阿里云OpenAPI开发者门户 (aliyun.com)

官方接口:UpdateDomainRecord_云解析_API调试-阿里云OpenAPI开发者门户 (aliyun.com)

DescribeDomainRecordInfo_云解析_API调试-阿里云OpenAPI开发者门户

三、上代码

1、pom.xml引包
   <dependencies>
    <dependency>
      <groupId>com.aliyun</groupId>
      <artifactId>alidns20150109</artifactId>
      <version>3.1.0</version>
    </dependency>
    <dependency>
      <groupId>com.aliyun</groupId>
      <artifactId>credentials-java</artifactId>
      <version>0.3.0</version>
    </dependency>
  </dependencies>
2、获取外网ip的方法
package com.chhuang;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
import java.util.regex.Pattern;

public class ExternalIPUtil {

    /**
     * IP 地址校验的正则表达式
     */
    private static final Pattern IPV4_PATTERN = Pattern.compile("^(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])$");

    /**
     * 获取 IP 地址的服务列表
     */
    private static final String[] IPV4_SERVICES = {
            "http://checkip.amazonaws.com/",
            "https://ipv4.icanhazip.com/",
            "http://bot.whatismyipaddress.com/"
            // and so on ...
    };

//    线程池的 ExecutorService.invokeAny(callables) 方法用于并发执行多个线程,并拿到最快的执行成功的线程的返回值,
//    只要有一个执行成功,其他失败的任务都会忽略。但是如果全部失败,
//    例如本机根本就没有连外网,那么就会抛出 ExecutionException 异常。
    public static String get() throws ExecutionException, InterruptedException {
        List<Callable<String>> callables = new ArrayList<>();
        for (String ipService : IPV4_SERVICES) {
            callables.add(() -> get(ipService));
        }

        ExecutorService executorService = Executors.newCachedThreadPool();
        try {
            // 返回第一个成功获取的 IP
            return executorService.invokeAny(callables);
        } finally {
            executorService.shutdown();
        }
    }

    private static String get(String url) throws IOException {
        try (BufferedReader in = new BufferedReader(new InputStreamReader(new URL(url).openStream()))) {
            String ip = in.readLine();
            if (IPV4_PATTERN.matcher(ip).matches()) {
                return ip;
            } else {
                throw new IOException("invalid IPv4 address: " + ip);
            }
        }
    }
}
3、使用云解析
package com.chhuang;

import com.aliyun.alidns20150109.Client;
import com.aliyun.alidns20150109.models.DescribeDomainRecordInfoRequest;
import com.aliyun.alidns20150109.models.DescribeDomainRecordInfoResponse;
import com.aliyun.alidns20150109.models.UpdateDomainRecordRequest;
import com.aliyun.tea.TeaException;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.Common;
import com.aliyun.teautil.models.RuntimeOptions;

import java.util.Random;

/**
 * Hello world!
 *
 */
public class App {

    private static final String APP_ALIBABA_ID = "你自己的ALIBABA_CLOUD_ACCESS_KEY_ID";
    private static final String SECURITY_ALIBABA_KEY = "你自己的ALIBABA_CLOUD_ACCESS_KEY_SECRET";

    /**
     * 使用AK&SK初始化账号Client
     * @return Client
     * @throws Exception
     */
    public static Client createClient() throws Exception {
        // 工程代码泄露可能会导致 AccessKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考。
        // 建议使用更安全的 STS 方式,更多鉴权访问方式请参见:https://help.aliyun.com/document_detail/378657.html。
        Config config = new Config()
                .setAccessKeyId(APP_ALIBABA_ID)
                .setAccessKeySecret(SECURITY_ALIBABA_KEY);
        // Endpoint 请参考 https://api.aliyun.com/product/Alidns
        config.endpoint = "alidns.cn-hangzhou.aliyuncs.com";
        return new Client(config);
    }

    public static void main( String[] args ) throws Exception {
        while (true) {
            Random random = new Random();
            Thread.sleep((random.nextInt(600) + 600) * 1000);

            // 获取外网ip
            String ip = ExternalIPUtil.get();
            System.out.println("ip=" + ip);
            // 更新域名解析
            updateDomain(ip);
        }
    }

    private static void updateDomain(String ip) throws Exception {
        Client client = App.createClient();
        // 获取解析记录的详细信息
        DescribeDomainRecordInfoRequest describeDomainRecordInfoRequest = new DescribeDomainRecordInfoRequest()
                .setRecordId("你自己域名解析记录的recordId");

        RuntimeOptions runtime = new RuntimeOptions();
        try {
            // 复制代码运行请自行打印 API 的返回值
            DescribeDomainRecordInfoResponse response = client.describeDomainRecordInfoWithOptions(describeDomainRecordInfoRequest, runtime);
            String value = response.getBody().getValue();

            // 判断 ip 是否需要修改
            if (!ip.equals(value)) {
                UpdateDomainRecordRequest updateDomainRecordRequest = new UpdateDomainRecordRequest()
                        .setRecordId("你自己域名解析记录的recordId") // 通过阿里云后台,DescribeDomainRecords 获取解析记录
                        .setRR("www")
                        .setType("A")
                        .setValue(ip)
                        .setTTL(600L);

                // 复制代码运行请自行打印 API 的返回值
                client.updateDomainRecordWithOptions(updateDomainRecordRequest, runtime);
            }
        } catch (TeaException error) {
            // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
            // 错误 message
            error.printStackTrace();
            // 诊断地址
            System.out.println(error.getData().get("Recommend"));
            Common.assertAsString(error.message);
        } catch (Exception _error) {
            _error.printStackTrace();
            TeaException error = new TeaException(_error.getMessage(), _error);
            // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
            // 诊断地址
            System.out.println(error.getData().get("Recommend"));
            Common.assertAsString(error.message);
        }
    }
}