Java实现阿里云的动态域名解析(利用阿里云api,需要有公网ip)

现在都是动态IP,每次IP变了就得从新在阿里云后台改。用阿里云解析提供的接口,可以自动修改解析的IP。需要公网IP,一般联通,电信宽带是有公网ip的,只不过路由器重启会更改公网ip,这样就很麻烦,每次重启路由器或者光猫公网ip都会发生变化。

解决方案

使用java代码公网ip动态解析域名,你ip无论怎么变化,域名总不会发生变化吧

于是就想到了通过域名+端口号的方式去访问java/vue项目,再通过java程序去定时更新域名解析的记录值

申请域名

这个自己百度吧,我这里就不详细说明了。

一、DDNS是什么?

DDNS(Dynamic Domain Name Server,动态域名服务)是将用户的动态IP地址映射到一个固定的域名解析服务上,用户每次连接网络的时候客户端程序就会通过信息传递把该主机的动态IP地址传送给位于服务商主机上的服务器程序,服务器程序负责提供DNS服务并实现动态域名解析。

二、实现步骤

1. 阿里云添加解析记录

打开阿里云控制台>云解析DNS>选中使用的域名>解析设置>添加一条解析记录

1687335752114.jpg

2.创建AccessKey

打开AccessKey管理界面,创建自己的AccessKey并保存AccessKeyIdAccessKeySecretId

1687335937160.jpg3. 创建SpringBoot项目并引入依赖

		<dependency>
			<groupId>com.aliyun</groupId>
			<artifactId>aliyun-java-sdk-alidns</artifactId>
			<version>2.0.1</version>
		</dependency>
		<dependency>
			<groupId>com.aliyun</groupId>
			<artifactId>aliyun-java-sdk-core</artifactId>
			<version>2.3.8</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
		</dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>RELEASE</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>

4. 相关功能开发

封装获取当前公网IP工具类WebToolUtils

package org.feasy.www.util;

import org.springframework.util.StringUtils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.URL;
import java.util.Enumeration;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @Classname WebToolUtils
 * @Description TODO 获取Ipv4、Ipv6的工具
 * @Version 1.0.0
 * @Date
 * @Created liangzhuo
 */
public class WebToolUtils {
    // 方法1
    private static String getNowIP1() throws IOException {
        String ip = null;
        String chinaz = "http://ip.chinaz.com";
        StringBuilder inputLine = new StringBuilder();
        String read = "";
        URL url = null;
        HttpURLConnection urlConnection = null;
        BufferedReader in = null;
        try {
            url = new URL(chinaz);
            urlConnection = (HttpURLConnection) url.openConnection();
            in = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), "UTF-8"));
            while ((read = in.readLine()) != null) {
                inputLine.append(read + "\r\n");
            }
            Pattern p = Pattern.compile("\\<dd class\\=\"fz24\">(.*?)\\<\\/dd>");
            Matcher m = p.matcher(inputLine.toString());
            if (m.find()) {
                String ipstr = m.group(1);
                ip = ipstr;
            }
        } finally {
            if (in != null) {
                in.close();
            }
        }
        if (StringUtils.isEmpty(ip)) {
            throw new RuntimeException();
        }
        return ip;
    }
    // 方法2
    private static String getNowIP2() throws IOException {
        String ip = null;
        BufferedReader br = null;
        try {
            URL url = new URL("https://v6r.ipip.net/?format=callback");
            br = new BufferedReader(new InputStreamReader(url.openStream()));
            String s = "";
            StringBuffer sb = new StringBuffer("");
            String webContent = "";
            while ((s = br.readLine()) != null) {
                sb.append(s + "\r\n");
            }
            webContent = sb.toString();
            int start = webContent.indexOf("(") + 2;
            int end = webContent.indexOf(")") - 1;
            webContent = webContent.substring(start, end);
            ip = webContent;
        } finally {
            if (br != null)
                br.close();
        }
        if (StringUtils.isEmpty(ip)) {
            throw new RuntimeException();
        }
        return ip;
    }
    // 方法3
    private static String getNowIP3() throws IOException {
        String ip = null;
        String objWebURL = "https://ip.900cha.com/";
        BufferedReader br = null;
        try {
            URL url = new URL(objWebURL);
            br = new BufferedReader(new InputStreamReader(url.openStream()));
            String s = "";
            String webContent = "";
            while ((s = br.readLine()) != null) {
                if (s.indexOf("我的IP:") != -1) {
                    ip = s.substring(s.indexOf(":") + 1);
                    break;
                }
            }
        } finally {
            if (br != null)
                br.close();
        }
        if (StringUtils.isEmpty(ip)) {
            throw new RuntimeException();
        }
        return ip;
    }
    // 方法4
    private static String getNowIP4() throws IOException {
        String ip = null;
        String objWebURL = "https://bajiu.cn/ip/";
        BufferedReader br = null;
        try {
            URL url = new URL(objWebURL);
            br = new BufferedReader(new InputStreamReader(url.openStream()));
            String s = "";
            String webContent = "";
            while ((s = br.readLine()) != null) {
                if (s.indexOf("互联网IP") != -1) {
                    ip = s.substring(s.indexOf("'") + 1, s.lastIndexOf("'"));
                    break;
                }
            }
        } finally {
            if (br != null)
                br.close();
        }
        if (StringUtils.isEmpty(ip)) {
            throw new RuntimeException();
        }
        return ip;
    }

    public static String getPublicIP() {
        String ip = null;
        // 第一种方式
        try {
            ip = getNowIP1();
            ip.trim();
        } catch (Exception e) {
            System.out.println("getPublicIP - getNowIP1 failed ~ ");
        }
        if (!StringUtils.isEmpty(ip))
            return ip;
        // 第二种方式
        try {
            ip = getNowIP2();
            ip.trim();
        } catch (Exception e) {
            System.out.println("getPublicIP - getNowIP2 failed ~ ");
        }
        if (!StringUtils.isEmpty(ip))
            return ip;
        // 第三种方式
        try {
            ip = getNowIP3();
            ip.trim();
        } catch (Exception e) {
            System.out.println("getPublicIP - getNowIP3 failed ~ ");
        }
        if (!StringUtils.isEmpty(ip))
            return ip;
        // 第四种方式
        try {
            ip = getNowIP4();
            ip.trim();
        } catch (Exception e) {
            System.out.println("getPublicIP - getNowIP4 failed ~ ");
        }
        if (!StringUtils.isEmpty(ip))
            return ip;
        return ip;
    }

}

封装阿里云DNS-SDK操作,刷新逻辑

@Service
public class UpdateDomainServiceImpl implements UpdateDomainService {

	@Value("${aliyun.update.domains}")
	private String domains;

	@Autowired
	private IAcsClient iAcsClient;

	@Override
	public String updateDomain(List<String> newDomainList) {
		Map<String, List<String>> domainMap = getDomainMap(mergreList(newDomainList));
		//String ip = IpUtil.getIp();
		String ip = WebToolUtils.getPublicIPv4();
		for (String domainName : domainMap.keySet()) {
			List<String> domainList = domainMap.get(domainName);
			try {
				this.updateDomain(domainName, domainList, ip);
			} catch (ServerException e) {
				e.printStackTrace();
				return "ServerException:" + e.getMessage();
			} catch (ClientException e) {
				e.printStackTrace();
				return "ClientException:" + e.getMessage();
			} catch (Exception e) {
				e.printStackTrace();
				return "Exception:" + e.getMessage();
			}
		}
		return "ok";
	}
private List<String> mergreList(List<String> newDomainList) {
		if (StringUtils.isEmpty(domains) && CollectionUtils.isEmpty(newDomainList)) {
			return Collections.emptyList();
		}
		List<String> domainList = Arrays.asList(domains.split(","));
		if (CollectionUtils.isEmpty(newDomainList)) {
			return domainList;
		}
		newDomainList.forEach(d -> {
			if (!domainList.contains(d)) {
				domainList.add(d);
			}
		});
		return domainList;
	}
private Map<String, List<String>> getDomainMap(List<String> domains) {
		Map<String, List<String>> domainMap = new HashMap<>();
		if (CollectionUtils.isEmpty(domains)) {
			return domainMap;
		}
		for (String domain : domains) {
			if (StringUtils.isEmpty(domains)) {
				continue;
			}
			String rr = domain.substring(0, domain.indexOf("."));
			if (StringUtils.isEmpty(rr)) {
				continue;
			}
			String domainName = domain.substring(domain.indexOf(".") + 1);
			if (StringUtils.isEmpty(rr)) {
				continue;
			}
			if (!domainMap.containsKey(domainName)) {
				domainMap.put(domainName, new ArrayList<>());
			}
			rr = rr.trim();
			domainName.trim();
			domainMap.get(domainName).add(rr);
		}
		return domainMap;
	}
private void updateDomain(String domainName, List<String> rrList, String ip)
			throws ServerException, ClientException, Exception {
		DescribeDomainRecordsRequest request = new DescribeDomainRecordsRequest();
		request.setDomainName(domainName);
		DescribeDomainRecordsResponse response = iAcsClient.getAcsResponse(request);
		List<DescribeDomainRecordsResponse.Record> list = response.getDomainRecords();
		for (DescribeDomainRecordsResponse.Record record : list) {
			for (String rr : rrList) {
				if (record.getRR() != null && record.getRR().equals(rr) && !record.getValue().equals(ip)) {
					this.updateOne(record, ip);
				}
			}
		}
	}
private void updateOne(DescribeDomainRecordsResponse.Record record, String ip) throws Exception {
		UpdateDomainRecordRequest request = new UpdateDomainRecordRequest();
		request.setRecordId(record.getRecordId());
		request.setRR(record.getRR());
		request.setType(record.getType());
		request.setValue(ip);
		request.setTTL(record.getTTL());
		request.setPriority(record.getPriority());
		request.setLine(record.getLine());

		UpdateDomainRecordResponse response = iAcsClient.getAcsResponse(request);
		System.out.println(response.getRequestId());
	}
}

设置定时任务

/**
 * @author liangzhuo
 *
 */
@Component
public class ScheduledList {

	@Autowired
	private UpdateDomainService updateDomainService;

	@PostConstruct
	public void post() {
		updateDomain();
	}

	@Scheduled(cron = "0 0/10 * * * ?") // 每隔10分钟执行一次定时任务
	public void updateDomain() {
		System.out.println("开始更新域名-" + new Date());
		try {
			updateDomainService.updateDomain(null);
			System.out.println("结束更新域名[成功]-" + new Date());
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("结束更新域名[失败]-" + new Date());
		}
	}

}

项目配置application.properties

server.port=9998
server.tomcat.max-threads=4
spring.application.name=aliyun.domain

logging.file.path=/opt/spring-boot-project/log/${spring.application.name}-${server.port}
logging.level.root=INFO
logging.levelorg.springframework=INFO

aliyun.regionId=cn-hangzhou
aliyun.accessKeyId=AccessKeyId
aliyun.accessKeySecret=AccessKeySecretId
aliyun.update.domains=域名

总结

当前设置是启动项目会执行一次刷新DNS记录,执行频率默认10分钟执行一次

文章作者: 丁丁丁
本文链接:
版权声明: 本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 陕西双曲线软件科技有限公司
java
喜欢就支持一下吧