773c230e3d
- 实现阿里/腾讯云 SSL 证书的全生命周期自动化管理。 - 重构 NewJob 为 DdnsJob,优化子域名匹配与记录自动创建逻辑。 - 更新项目配置结构,移除冗余的 AppJob 相关代码。
152 lines
6.3 KiB
C#
152 lines
6.3 KiB
C#
using System.Xml;
|
|
using AutoMapper;
|
|
using Hua.DDNS.Models;
|
|
using Microsoft.Extensions.Hosting;
|
|
using Microsoft.Extensions.Options;
|
|
using Newtonsoft.Json;
|
|
|
|
namespace Hua.DDNS.DDNSProviders.Namesilo
|
|
{
|
|
/// <summary>
|
|
/// Namesilo DDNS 解析提供者
|
|
/// </summary>
|
|
public class NamesiloDdnsProvider : IDdnsProvider
|
|
{
|
|
public readonly NamesiloOption _namesiloOption;
|
|
public readonly DdnsOption _ddnsOption;
|
|
|
|
/// <summary>
|
|
/// 构造函数
|
|
/// </summary>
|
|
/// <param name="namesiloOption">Namesilo 配置</param>
|
|
/// <param name="ddnsOption">DDNS 配置</param>
|
|
public NamesiloDdnsProvider(IOptions<NamesiloOption> namesiloOption, IOptions<DdnsOption> ddnsOption)
|
|
{
|
|
_ddnsOption = ddnsOption.Value;
|
|
_namesiloOption = namesiloOption.Value;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 异步获取 Namesilo 上的域名解析记录列表
|
|
/// </summary>
|
|
/// <returns>解析记录列表</returns>
|
|
public async Task<IEnumerable<DnsRecord>?> GetRecordListAsync()
|
|
{
|
|
var client = new HttpClient();
|
|
var response =
|
|
await client.GetAsync($"https://www.namesilo.com/api/dnsListRecords?version=1&type=xml&key={_namesiloOption.ApiKey}&domain={_ddnsOption.Domain}");
|
|
var content = response.Content.ReadAsStringAsync().Result;
|
|
|
|
var reply = new XmlDocument();
|
|
reply.LoadXml(content);
|
|
var status = reply.SelectSingleNode("/namesilo/reply/code/text()");
|
|
if (status == null)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
if (status.Value != "300")
|
|
{
|
|
throw new Exception($"Failed to retrieve value. Check API key.{status}");
|
|
}
|
|
|
|
var records = reply.SelectNodes($"/namesilo/reply/resource_record/host");
|
|
if (records == null)
|
|
{
|
|
return new List<DnsRecord>();
|
|
}
|
|
|
|
return (from record in records.Cast<XmlNode>()
|
|
let host = record.ParentNode.SelectSingleNode("host/text()").Value
|
|
let subDomain = host.Replace($".{_ddnsOption.Domain}", "").Replace(_ddnsOption.Domain, "")
|
|
where _ddnsOption.SubDomainArray.Contains(subDomain) || (subDomain == "" && _ddnsOption.SubDomainArray.Contains("@"))
|
|
select new DnsRecord
|
|
{
|
|
Id = record.ParentNode.SelectSingleNode("record_id/text()").Value,
|
|
Ip = record.ParentNode.SelectSingleNode("value/text()").Value,
|
|
Host = host,
|
|
Domain = _ddnsOption.Domain,
|
|
TTL = record.ParentNode.SelectSingleNode("ttl/text()").Value,
|
|
SubDomain = subDomain,
|
|
}).ToList();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 异步在 Namesilo 上创建新的域名解析记录
|
|
/// </summary>
|
|
/// <param name="dnsRecord">解析记录信息</param>
|
|
/// <returns>创建后的解析记录信息</returns>
|
|
public async Task<DnsRecord> CreateDnsRecordAsync(DnsRecord dnsRecord)
|
|
{
|
|
var host = dnsRecord.SubDomain == "@" ? "" : dnsRecord.SubDomain;
|
|
//https://www.namesilo.com/api/dnsAddRecord?version=1&type=xml&key=12345&domain=namesilo.com&rrtype=A&rrhost=test&rrvalue=55.55.55.55&rrttl=7207
|
|
var url = $"https://www.namesilo.com/api/dnsAddRecord?version=1&type=xml&key={_namesiloOption.ApiKey}&domain={dnsRecord.Domain}&rrtype={dnsRecord.RecordType}&rrhost={host}&rrvalue={dnsRecord.Ip}&rrttl={dnsRecord.TTL}";
|
|
|
|
using var client = new HttpClient();
|
|
{
|
|
|
|
var response = await client.GetAsync(url);
|
|
var content = await response.Content.ReadAsStringAsync();
|
|
|
|
var reply = new XmlDocument();
|
|
reply.LoadXml(content);
|
|
var status = reply.SelectSingleNode("/namesilo/reply/code/text()");
|
|
if (status == null)
|
|
{
|
|
await Console.Error.WriteLineAsync($"Failed to create record: '{JsonConvert.SerializeObject(dnsRecord)}'");
|
|
return null;
|
|
}
|
|
|
|
if (status.Value != "300")
|
|
{
|
|
await Console.Error.WriteLineAsync($"Failed to create record: '{JsonConvert.SerializeObject(dnsRecord)}', Status: {status.Value}");
|
|
return null;
|
|
}
|
|
}
|
|
return dnsRecord;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 异步批量修改 Namesilo 上的域名解析记录
|
|
/// </summary>
|
|
/// <param name="newIp">新的 IP 地址</param>
|
|
/// <param name="records">需要修改的解析记录列表</param>
|
|
/// <returns>修改后的解析记录列表</returns>
|
|
public async Task<IEnumerable<DnsRecord>> ModifyRecordListAsync(string newIp, IEnumerable<DnsRecord> records)
|
|
{
|
|
foreach (var dnsRecord in records)
|
|
{
|
|
using var client = new HttpClient();
|
|
{
|
|
var host = dnsRecord.SubDomain == "@" ? "" : dnsRecord.SubDomain;
|
|
var request =
|
|
$"https://www.namesilo.com/api/dnsUpdateRecord?version=1&type=xml&key={_namesiloOption.ApiKey}&domain={dnsRecord.Domain}&rrid={dnsRecord.Id}&rrhost={host}&rrvalue={newIp}&rrttl={dnsRecord.TTL}";
|
|
//Console.WriteLine(request);
|
|
var response = await client.GetAsync(request);
|
|
var content = await response.Content.ReadAsStringAsync();
|
|
|
|
var reply = new XmlDocument();
|
|
reply.LoadXml(content);
|
|
var status = reply.SelectSingleNode("/namesilo/reply/code/text()");
|
|
if (status == null || status.Value != "300")
|
|
{
|
|
await Console.Error.WriteLineAsync($"Failed to update record: '{dnsRecord.Id}' with Ip: '{newIp}'. Status: {status?.Value}");
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
return records;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 异步清理无效证书
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public Task CleanInvalidCertificatesAsync()
|
|
{
|
|
return Task.CompletedTask;
|
|
}
|
|
}
|
|
} |