mirror of
https://github.com/2dust/v2rayN.git
synced 2026-02-28 21:23:04 +00:00
Compare commits
3 commits
6143fdad90
...
cd04e170d3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cd04e170d3 | ||
|
|
780ba84393 | ||
|
|
8b47a90c07 |
6 changed files with 135 additions and 69 deletions
|
|
@ -49,6 +49,7 @@ public class Global
|
||||||
public const string DirectTag = "direct";
|
public const string DirectTag = "direct";
|
||||||
public const string BlockTag = "block";
|
public const string BlockTag = "block";
|
||||||
public const string DnsTag = "dns-module";
|
public const string DnsTag = "dns-module";
|
||||||
|
public const string DirectDnsTag = "direct-dns";
|
||||||
public const string BalancerTagSuffix = "-round";
|
public const string BalancerTagSuffix = "-round";
|
||||||
public const string StreamSecurity = "tls";
|
public const string StreamSecurity = "tls";
|
||||||
public const string StreamSecurityReality = "reality";
|
public const string StreamSecurityReality = "reality";
|
||||||
|
|
|
||||||
|
|
@ -220,12 +220,6 @@ public class DnsServer4Ray
|
||||||
public List<string>? domains { get; set; }
|
public List<string>? domains { get; set; }
|
||||||
public bool? skipFallback { get; set; }
|
public bool? skipFallback { get; set; }
|
||||||
public List<string>? expectedIPs { get; set; }
|
public List<string>? expectedIPs { get; set; }
|
||||||
public List<string>? unexpectedIPs { get; set; }
|
|
||||||
public string? clientIp { get; set; }
|
|
||||||
public string? queryStrategy { get; set; }
|
|
||||||
public int? timeoutMs { get; set; }
|
|
||||||
public bool? disableCache { get; set; }
|
|
||||||
public bool? finalQuery { get; set; }
|
|
||||||
public string? tag { get; set; }
|
public string? tag { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,11 +20,14 @@ public partial class CoreConfigSingboxService
|
||||||
{
|
{
|
||||||
proxyOutboundList.AddRange(BuildGroupProxyOutbounds(baseTagName));
|
proxyOutboundList.AddRange(BuildGroupProxyOutbounds(baseTagName));
|
||||||
}
|
}
|
||||||
|
if (withSelector)
|
||||||
|
{
|
||||||
var proxyTags = proxyOutboundList.Where(n => n.tag.StartsWith(Global.ProxyTag)).Select(n => n.tag).ToList();
|
var proxyTags = proxyOutboundList.Where(n => n.tag.StartsWith(Global.ProxyTag)).Select(n => n.tag).ToList();
|
||||||
if (proxyTags.Count > 1)
|
if (proxyTags.Count > 1)
|
||||||
{
|
{
|
||||||
proxyOutboundList.InsertRange(0, BuildSelectorOutbounds(proxyTags, baseTagName));
|
proxyOutboundList.InsertRange(0, BuildSelectorOutbounds(proxyTags, baseTagName));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return proxyOutboundList;
|
return proxyOutboundList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -239,6 +239,7 @@ public partial class CoreConfigV2rayService(CoreConfigContext context)
|
||||||
GenLog();
|
GenLog();
|
||||||
GenOutbounds();
|
GenOutbounds();
|
||||||
|
|
||||||
|
_coreConfig.routing.domainStrategy = Global.AsIs;
|
||||||
_coreConfig.routing.rules.Clear();
|
_coreConfig.routing.rules.Clear();
|
||||||
_coreConfig.inbounds.Clear();
|
_coreConfig.inbounds.Clear();
|
||||||
_coreConfig.inbounds.Add(new()
|
_coreConfig.inbounds.Add(new()
|
||||||
|
|
@ -249,6 +250,8 @@ public partial class CoreConfigV2rayService(CoreConfigContext context)
|
||||||
protocol = EInboundProtocol.mixed.ToString(),
|
protocol = EInboundProtocol.mixed.ToString(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
_coreConfig.routing.rules.Add(BuildFinalRule());
|
||||||
|
|
||||||
ret.Msg = string.Format(ResUI.SuccessfulConfiguration, "");
|
ret.Msg = string.Format(ResUI.SuccessfulConfiguration, "");
|
||||||
ret.Success = true;
|
ret.Success = true;
|
||||||
ret.Data = JsonUtils.Serialize(_coreConfig);
|
ret.Data = JsonUtils.Serialize(_coreConfig);
|
||||||
|
|
|
||||||
|
|
@ -70,18 +70,36 @@ public partial class CoreConfigV2rayService
|
||||||
dnsItem.serveStale = simpleDnsItem?.ServeStale is true ? true : null;
|
dnsItem.serveStale = simpleDnsItem?.ServeStale is true ? true : null;
|
||||||
dnsItem.enableParallelQuery = simpleDnsItem?.ParallelQuery is true ? true : null;
|
dnsItem.enableParallelQuery = simpleDnsItem?.ParallelQuery is true ? true : null;
|
||||||
|
|
||||||
if (_coreConfig.routing.domainStrategy == Global.IPIfNonMatch)
|
|
||||||
{
|
|
||||||
// DNS routing
|
// DNS routing
|
||||||
dnsItem.tag = Global.DnsTag;
|
var directDnsTags = dnsItem.servers
|
||||||
_coreConfig.routing.rules.Add(new RulesItem4Ray
|
.Select(server =>
|
||||||
|
{
|
||||||
|
var tagNode = (server as JsonObject)?["tag"];
|
||||||
|
return tagNode is JsonValue value && value.TryGetValue<string>(out var tag) ? tag : null;
|
||||||
|
})
|
||||||
|
.Where(tag => tag is not null && tag.StartsWith(Global.DirectDnsTag, StringComparison.Ordinal))
|
||||||
|
.Select(tag => tag!)
|
||||||
|
.ToList();
|
||||||
|
if (directDnsTags.Count > 0)
|
||||||
|
{
|
||||||
|
_coreConfig.routing.rules.Add(new()
|
||||||
{
|
{
|
||||||
type = "field",
|
type = "field",
|
||||||
inboundTag = new List<string> { Global.DnsTag },
|
inboundTag = directDnsTags,
|
||||||
outboundTag = Global.ProxyTag,
|
outboundTag = Global.DirectTag,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var finalRule = BuildFinalRule();
|
||||||
|
dnsItem.tag = Global.DnsTag;
|
||||||
|
_coreConfig.routing.rules.Add(new()
|
||||||
|
{
|
||||||
|
type = "field",
|
||||||
|
inboundTag = [Global.DnsTag],
|
||||||
|
outboundTag = finalRule.outboundTag,
|
||||||
|
balancerTag = finalRule.balancerTag,
|
||||||
|
});
|
||||||
|
|
||||||
_coreConfig.dns = dnsItem;
|
_coreConfig.dns = dnsItem;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|
@ -93,45 +111,6 @@ public partial class CoreConfigV2rayService
|
||||||
private void FillDnsServers(Dns4Ray dnsItem)
|
private void FillDnsServers(Dns4Ray dnsItem)
|
||||||
{
|
{
|
||||||
var simpleDNSItem = context.SimpleDnsItem;
|
var simpleDNSItem = context.SimpleDnsItem;
|
||||||
static List<string> ParseDnsAddresses(string? dnsInput, string defaultAddress)
|
|
||||||
{
|
|
||||||
var addresses = dnsInput?.Split(dnsInput.Contains(',') ? ',' : ';')
|
|
||||||
.Select(addr => addr.Trim())
|
|
||||||
.Where(addr => !string.IsNullOrEmpty(addr))
|
|
||||||
.Select(addr => addr.StartsWith("dhcp", StringComparison.OrdinalIgnoreCase) ? "localhost" : addr)
|
|
||||||
.Distinct()
|
|
||||||
.ToList() ?? new List<string> { defaultAddress };
|
|
||||||
return addresses.Count > 0 ? addresses : new List<string> { defaultAddress };
|
|
||||||
}
|
|
||||||
|
|
||||||
static object? CreateDnsServer(string dnsAddress, List<string> domains, List<string>? expectedIPs = null)
|
|
||||||
{
|
|
||||||
var (domain, scheme, port, path) = Utils.ParseUrl(dnsAddress);
|
|
||||||
var domainFinal = dnsAddress;
|
|
||||||
int? portFinal = null;
|
|
||||||
if (scheme.IsNullOrEmpty() || scheme.StartsWith("udp", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
domainFinal = domain;
|
|
||||||
portFinal = port > 0 ? port : null;
|
|
||||||
}
|
|
||||||
else if (scheme.StartsWith("tcp", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
domainFinal = scheme + "://" + domain;
|
|
||||||
portFinal = port > 0 ? port : null;
|
|
||||||
}
|
|
||||||
var dnsServer = new DnsServer4Ray
|
|
||||||
{
|
|
||||||
address = domainFinal,
|
|
||||||
port = portFinal,
|
|
||||||
skipFallback = true,
|
|
||||||
domains = domains.Count > 0 ? domains : null,
|
|
||||||
expectedIPs = expectedIPs?.Count > 0 ? expectedIPs : null
|
|
||||||
};
|
|
||||||
return JsonUtils.SerializeToNode(dnsServer, new JsonSerializerOptions
|
|
||||||
{
|
|
||||||
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
var directDNSAddress = ParseDnsAddresses(simpleDNSItem?.DirectDNS, Global.DomainDirectDNSAddress.First());
|
var directDNSAddress = ParseDnsAddresses(simpleDNSItem?.DirectDNS, Global.DomainDirectDNSAddress.First());
|
||||||
var remoteDNSAddress = ParseDnsAddresses(simpleDNSItem?.RemoteDNS, Global.DomainRemoteDNSAddress.First());
|
var remoteDNSAddress = ParseDnsAddresses(simpleDNSItem?.RemoteDNS, Global.DomainRemoteDNSAddress.First());
|
||||||
|
|
@ -252,22 +231,13 @@ public partial class CoreConfigV2rayService
|
||||||
|
|
||||||
dnsItem.servers ??= [];
|
dnsItem.servers ??= [];
|
||||||
|
|
||||||
void AddDnsServers(List<string> dnsAddresses, List<string> domains, List<string>? expectedIPs = null)
|
var directDnsTagIndex = 1;
|
||||||
{
|
|
||||||
if (domains.Count > 0)
|
|
||||||
{
|
|
||||||
foreach (var dnsAddress in dnsAddresses)
|
|
||||||
{
|
|
||||||
dnsItem.servers.Add(CreateDnsServer(dnsAddress, domains, expectedIPs));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AddDnsServers(remoteDNSAddress, proxyDomainList);
|
AddDnsServers(remoteDNSAddress, proxyDomainList);
|
||||||
AddDnsServers(directDNSAddress, directDomainList);
|
AddDnsServers(directDNSAddress, directDomainList, true);
|
||||||
AddDnsServers(remoteDNSAddress, proxyGeositeList);
|
AddDnsServers(remoteDNSAddress, proxyGeositeList);
|
||||||
AddDnsServers(directDNSAddress, directGeositeList);
|
AddDnsServers(directDNSAddress, directGeositeList, true);
|
||||||
AddDnsServers(directDNSAddress, expectedDomainList, expectedIPs);
|
AddDnsServers(directDNSAddress, expectedDomainList, true, expectedIPs);
|
||||||
if (dnsServerDomains.Count > 0)
|
if (dnsServerDomains.Count > 0)
|
||||||
{
|
{
|
||||||
AddDnsServers(bootstrapDNSAddress, dnsServerDomains);
|
AddDnsServers(bootstrapDNSAddress, dnsServerDomains);
|
||||||
|
|
@ -279,8 +249,78 @@ public partial class CoreConfigV2rayService
|
||||||
|| lastRule.Network == "tcp,udp"
|
|| lastRule.Network == "tcp,udp"
|
||||||
|| lastRule.Ip?.Contains("0.0.0.0/0") == true);
|
|| lastRule.Ip?.Contains("0.0.0.0/0") == true);
|
||||||
|
|
||||||
var defaultDnsServers = useDirectDns ? directDNSAddress : remoteDNSAddress;
|
if (!useDirectDns)
|
||||||
dnsItem.servers.AddRange(defaultDnsServers);
|
{
|
||||||
|
dnsItem.servers.AddRange(remoteDNSAddress);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (var dns in directDNSAddress)
|
||||||
|
{
|
||||||
|
var dnsServer = CreateDnsServer(dns, []);
|
||||||
|
dnsServer.tag = $"{Global.DirectDnsTag}-{directDnsTagIndex++}";
|
||||||
|
dnsServer.skipFallback = false;
|
||||||
|
dnsItem.servers.Add(JsonUtils.SerializeToNode(dnsServer,
|
||||||
|
new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
|
||||||
|
static List<string> ParseDnsAddresses(string? dnsInput, string defaultAddress)
|
||||||
|
{
|
||||||
|
var addresses = dnsInput?.Split(dnsInput.Contains(',') ? ',' : ';')
|
||||||
|
.Select(addr => addr.Trim())
|
||||||
|
.Where(addr => !string.IsNullOrEmpty(addr))
|
||||||
|
.Select(addr => addr.StartsWith("dhcp", StringComparison.OrdinalIgnoreCase) ? "localhost" : addr)
|
||||||
|
.Distinct()
|
||||||
|
.ToList() ?? [defaultAddress];
|
||||||
|
return addresses.Count > 0 ? addresses : new List<string> { defaultAddress };
|
||||||
|
}
|
||||||
|
|
||||||
|
static DnsServer4Ray CreateDnsServer(string dnsAddress, List<string> domains, List<string>? expectedIPs = null)
|
||||||
|
{
|
||||||
|
var (domain, scheme, port, path) = Utils.ParseUrl(dnsAddress);
|
||||||
|
var domainFinal = dnsAddress;
|
||||||
|
int? portFinal = null;
|
||||||
|
if (scheme.IsNullOrEmpty() || scheme.StartsWith("udp", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
domainFinal = domain;
|
||||||
|
portFinal = port > 0 ? port : null;
|
||||||
|
}
|
||||||
|
else if (scheme.StartsWith("tcp", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
domainFinal = scheme + "://" + domain;
|
||||||
|
portFinal = port > 0 ? port : null;
|
||||||
|
}
|
||||||
|
var dnsServer = new DnsServer4Ray
|
||||||
|
{
|
||||||
|
address = domainFinal,
|
||||||
|
port = portFinal,
|
||||||
|
skipFallback = true,
|
||||||
|
domains = domains.Count > 0 ? domains : null,
|
||||||
|
expectedIPs = expectedIPs?.Count > 0 ? expectedIPs : null
|
||||||
|
};
|
||||||
|
return dnsServer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddDnsServers(List<string> dnsAddresses, List<string> domains, bool isDirectDns = false, List<string>? expectedIPs = null)
|
||||||
|
{
|
||||||
|
if (domains.Count <= 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
foreach (var dnsAddress in dnsAddresses)
|
||||||
|
{
|
||||||
|
var dnsServer = CreateDnsServer(dnsAddress, domains, expectedIPs);
|
||||||
|
if (isDirectDns)
|
||||||
|
{
|
||||||
|
dnsServer.tag = $"{Global.DirectDnsTag}-{directDnsTagIndex++}";
|
||||||
|
}
|
||||||
|
var dnsServerNode = JsonUtils.SerializeToNode(dnsServer,
|
||||||
|
new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull });
|
||||||
|
dnsItem.servers.Add(dnsServerNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FillDnsHosts(Dns4Ray dnsItem)
|
private void FillDnsHosts(Dns4Ray dnsItem)
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ public partial class CoreConfigV2rayService
|
||||||
rulesItem.outboundTag = null;
|
rulesItem.outboundTag = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_coreConfig.routing.rules.Add(BuildFinalRule());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|
@ -181,4 +182,28 @@ public partial class CoreConfigV2rayService
|
||||||
|
|
||||||
return tag;
|
return tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private RulesItem4Ray BuildFinalRule()
|
||||||
|
{
|
||||||
|
var finalRule = new RulesItem4Ray()
|
||||||
|
{
|
||||||
|
type = "field",
|
||||||
|
network = "tcp,udp",
|
||||||
|
outboundTag = Global.ProxyTag,
|
||||||
|
};
|
||||||
|
var balancer =
|
||||||
|
_coreConfig?.routing?.balancers?.FirstOrDefault(b => b.tag == Global.ProxyTag + Global.BalancerTagSuffix, null);
|
||||||
|
var domainStrategy = _coreConfig.routing?.domainStrategy ?? Global.AsIs;
|
||||||
|
if (balancer is not null)
|
||||||
|
{
|
||||||
|
finalRule.outboundTag = null;
|
||||||
|
finalRule.balancerTag = balancer.tag;
|
||||||
|
}
|
||||||
|
if (domainStrategy == Global.IPIfNonMatch)
|
||||||
|
{
|
||||||
|
finalRule.network = null;
|
||||||
|
finalRule.ip = ["0.0.0.0/0", "::/0"];
|
||||||
|
}
|
||||||
|
return finalRule;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue