feat:ddns 动态解析

This commit is contained in:
xiang
2026-05-02 14:36:21 +08:00
parent f05e3fbd88
commit b8083381b6
11 changed files with 318 additions and 4 deletions

View File

@@ -0,0 +1,31 @@
package com.xiang.service.module.domain.schedule;
import com.xiang.common.utils.IpUtils;
import com.xiang.service.module.domain.service.IDomainService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.scheduling.annotation.Scheduled;
@Slf4j
@RequiredArgsConstructor
public class DomainDynamicAnalysisTask {
private final IDomainService IDomainService;
@Scheduled(cron = "0 0/30 * * * ? ")
public void dynamicDomainSchedule() {
String publicIp = "";
try {
publicIp = IpUtils.getPublicIp();
} catch (Exception e) {
log.error("获取公网ip失败", e);
}
if (StringUtils.isNotBlank(publicIp)) {
try {
IDomainService.dynamicDomainAnalysis(publicIp);
} catch (Exception e) {
log.error("动态解析公网ip失败, ip:{}", publicIp, e);
}
}
}
}

View File

@@ -0,0 +1,45 @@
package com.xiang.service.module.domain.server;
import com.xiang.common.utils.IpUtils;
import com.xiang.service.module.domain.service.IDomainService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/script/domain")
public class DomainController {
private final IDomainService domainService;
@GetMapping("/ddns")
public void dynamicDomainAnalysis() {
String publicIp = "";
try {
publicIp = IpUtils.getPublicIp();
} catch (Exception e) {
log.error("获取公网ip失败", e);
}
if (StringUtils.isNotBlank(publicIp)) {
try {
domainService.dynamicDomainAnalysis(publicIp);
} catch (Exception e) {
log.error("动态解析公网ip失败, ip:{}", publicIp, e);
}
}
}
@GetMapping("/ddns4ip")
public void dynamicDomainAnalysis(@RequestParam("ip") String ip, @RequestParam("rr") String rr) {
try {
domainService.dynamicDomainAnalysis(ip, rr);
} catch (Exception e) {
log.error("动态解析公网ip失败, ip:{}", ip, e);
}
}
}

View File

@@ -0,0 +1,15 @@
package com.xiang.service.module.domain.service;
/**
* @Author: xiang
* @Date: 2025-06-10 16:48
*/
public interface IDomainService {
/**
* 动态域名解析
* @param publicIp 动态ip
*/
void dynamicDomainAnalysis(String publicIp) throws Exception;
void dynamicDomainAnalysis(String publicIp, String rr) throws Exception;
}

View File

@@ -0,0 +1,111 @@
package com.xiang.service.module.domain.service;
import com.aliyun.alidns20150109.Client;
import com.aliyun.alidns20150109.models.AddDomainRecordRequest;
import com.aliyun.alidns20150109.models.DescribeSubDomainRecordsRequest;
import com.aliyun.alidns20150109.models.DescribeSubDomainRecordsResponse;
import com.aliyun.alidns20150109.models.DescribeSubDomainRecordsResponseBody;
import com.aliyun.alidns20150109.models.UpdateDomainRecordRequest;
import com.aliyun.teaopenapi.models.Config;
import com.xiang.common.config.AliyunDnsPropertyConfig;
import com.xiang.common.factory.ScriptDingTalkFactory;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @Author: xiang
* @Date: 2025-06-10 16:48
*/
@Service
@Slf4j
@RequiredArgsConstructor
public class IDomainServiceImpl implements IDomainService {
private static final String ACCESS_KEY_ID = "LTAI5tDMjaVF8Bbqcpp4dmvP";
private static final String ACCESS_KEY_SECRET = "nkmnaNjWQy5984C5kjyS0oDmdMKGQd";
/**
* 根域名
*/
@Value("${aliyun.dns.rootDomain}")
private String rootDomain;
/**
* 主机记录,例如 home.example.com
*/
private final AliyunDnsPropertyConfig aliyunDnsPropertyConfig;
private static final String TYPE = "A";
private final ScriptDingTalkFactory dingTalkService;
@Override
public void dynamicDomainAnalysis(String publicIp) throws Exception {
Client client = createClient();
for (String rr : aliyunDnsPropertyConfig.getRR()) {
record(client, publicIp, rr);
}
}
@Override
public void dynamicDomainAnalysis(String publicIp, String rr) throws Exception {
Client client = createClient();
record(client, publicIp, rr);
}
private void record(Client client, String publicIp, String rr) throws Exception{
// 查询记录
DescribeSubDomainRecordsRequest query = new DescribeSubDomainRecordsRequest()
.setSubDomain(rr + "." + rootDomain)
.setType(TYPE);
DescribeSubDomainRecordsResponse response = client.describeSubDomainRecords(query);
List<DescribeSubDomainRecordsResponseBody.DescribeSubDomainRecordsResponseBodyDomainRecordsRecord> records =
response.getBody().getDomainRecords().getRecord();
if (records.isEmpty()) {
log.info("未找到记录,添加记录..., ip:{}", publicIp);
addDnsRecord(client, publicIp, rr);
dingTalkService.sendMsg("动态解析公网ip成功域名" + rr + "." + rootDomain + ", 新ip:" + publicIp);
} else {
String recordId = records.get(0).getRecordId();
String currentValue = records.get(0).getValue();
if (!publicIp.equals(currentValue)) {
log.info("IP变更更新记录...,ip:{}", publicIp);
updateDnsRecord(client, recordId, publicIp, rr);
dingTalkService.sendMsg("动态解析公网ip成功域名" + rr + "." + rootDomain + ", 新ip:" + publicIp);
} else {
log.info("ip未变更无需修改ip:{}", publicIp);
}
}
}
private Client createClient() throws Exception {
Config config = new Config()
.setAccessKeyId(ACCESS_KEY_ID)
.setAccessKeySecret(ACCESS_KEY_SECRET)
.setEndpoint("alidns.cn-hangzhou.aliyuncs.com");
return new Client(config);
}
private void updateDnsRecord(Client client, String recordId, String newIp, String rr) throws Exception {
UpdateDomainRecordRequest request = new UpdateDomainRecordRequest()
.setRecordId(recordId)
.setRR(rr)
.setType(TYPE)
.setValue(newIp);
client.updateDomainRecord(request);
log.info("更新成功: newIP:{}", newIp);
}
private void addDnsRecord(Client client, String ip, String rr) throws Exception {
AddDomainRecordRequest request = new AddDomainRecordRequest()
.setDomainName(rootDomain)
.setRR(rr)
.setType(TYPE)
.setValue(ip);
client.addDomainRecord(request);
log.info("添加成功: ip:{}", ip);
}
}