feat: detect an agent's public IPv4 and IPv6 addresses automatically, manual values still win [CI]
ci/woodpecker/push/main-amd64-build Pipeline was successful
ci/woodpecker/push/main-amd64-build Pipeline was successful
This commit is contained in:
1 parent
9966ea5d63
commit
f03988d68b
26 files changed
+517
-33
No files matched your search
@@ -0,0 +1,40 @@
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using MoShiro.Protocol;
|
||||
|
||||
namespace MoShiro.Backend.Application;
|
||||
|
||||
/// <summary>
|
||||
/// 自动识别 Agent 的对外地址:Agent 上报本机的公网地址,注册请求的来源地址作为补充(来源是私网或隧道出口时不用)。
|
||||
/// 管理员手填的(<c>*_manual</c>)永远优先;已经选中的自动地址还在候选里就不换,不会因为网卡顺序变化来回改。
|
||||
/// </summary>
|
||||
public static class AgentAddressPolicy
|
||||
{
|
||||
/// <summary>返回要写入的 <c>(public_host, ipv6_host)</c>;没有候选的那一项是 null(保持不变)。</summary>
|
||||
public static (string? PublicHost, string? Ipv6Host) Choose(AgentRecord current, IReadOnlyList<string> reported, string? observed)
|
||||
{
|
||||
var v4 = new List<string>();
|
||||
var v6 = new List<string>();
|
||||
foreach (string text in reported.Append(observed ?? ""))
|
||||
{
|
||||
if (!IPAddress.TryParse(text, out IPAddress? address))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (address.AddressFamily == AddressFamily.InterNetwork && PublicAddress.IsPublicIpv4(address) && !v4.Contains(address.ToString()))
|
||||
{
|
||||
v4.Add(address.ToString());
|
||||
}
|
||||
else if (address.AddressFamily == AddressFamily.InterNetworkV6 && PublicAddress.IsGlobalIpv6(address) && !v6.Contains(address.ToString()))
|
||||
{
|
||||
v6.Add(address.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
return (current.PublicHostManual ? null : Pick(v4, current.PublicHost), current.Ipv6HostManual ? null : Pick(v6, current.Ipv6Host));
|
||||
}
|
||||
|
||||
private static string? Pick(List<string> candidates, string current) =>
|
||||
candidates.Count == 0 ? null : candidates.Contains(current) ? current : candidates[0];
|
||||
}
|
||||
Reference in new issue
Block a user