mirror of
https://github.com/2dust/v2rayN.git
synced 2026-04-18 05:25:46 +00:00
Merge branch '2dust:master' into master
This commit is contained in:
commit
364a6b3997
5 changed files with 129 additions and 38 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
<Project>
|
<Project>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Version>7.19.1</Version>
|
<Version>7.19.2</Version>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
|
|
|
||||||
|
|
@ -1332,6 +1332,7 @@ public static class ConfigHandler
|
||||||
public static async Task<int> RemoveInvalidServerResult(Config config, string subid)
|
public static async Task<int> RemoveInvalidServerResult(Config config, string subid)
|
||||||
{
|
{
|
||||||
var lstModel = await AppManager.Instance.ProfileModels(subid, "");
|
var lstModel = await AppManager.Instance.ProfileModels(subid, "");
|
||||||
|
lstModel.RemoveAll(t => t.ConfigType.IsComplexType());
|
||||||
if (lstModel is { Count: <= 0 })
|
if (lstModel is { Count: <= 0 })
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
||||||
|
|
@ -93,7 +93,23 @@ public partial class CoreConfigSingboxService
|
||||||
|
|
||||||
foreach (var kvp in Utils.ParseHostsToDictionary(simpleDnsItem.Hosts))
|
foreach (var kvp in Utils.ParseHostsToDictionary(simpleDnsItem.Hosts))
|
||||||
{
|
{
|
||||||
hostsDns.predefined[kvp.Key] = kvp.Value.Where(Utils.IsIpAddress).ToList();
|
// only allow full match
|
||||||
|
// like example.com and full:example.com,
|
||||||
|
// but not domain:example.com, keyword:example.com or regex:example.com etc.
|
||||||
|
var testRule = new Rule4Sbox();
|
||||||
|
if (!ParseV2Domain(kvp.Key, testRule))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (testRule.domain_keyword?.Count > 0 && !kvp.Key.Contains(':'))
|
||||||
|
{
|
||||||
|
testRule.domain = testRule.domain_keyword;
|
||||||
|
testRule.domain_keyword = null;
|
||||||
|
}
|
||||||
|
if (testRule.domain?.Count == 1)
|
||||||
|
{
|
||||||
|
hostsDns.predefined[testRule.domain.First()] = kvp.Value.Where(Utils.IsIpAddress).ToList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var host in hostsDns.predefined)
|
foreach (var host in hostsDns.predefined)
|
||||||
|
|
@ -179,44 +195,66 @@ public partial class CoreConfigSingboxService
|
||||||
foreach (var kvp in Utils.ParseHostsToDictionary(simpleDnsItem.Hosts))
|
foreach (var kvp in Utils.ParseHostsToDictionary(simpleDnsItem.Hosts))
|
||||||
{
|
{
|
||||||
var predefined = kvp.Value.First();
|
var predefined = kvp.Value.First();
|
||||||
if (predefined.IsNullOrEmpty() || Utils.IsIpAddress(predefined))
|
if (predefined.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (predefined.StartsWith('#') && int.TryParse(predefined.AsSpan(1), out var rcode))
|
var rule = new Rule4Sbox()
|
||||||
{
|
{
|
||||||
// xray syntactic sugar for predefined
|
query_type = [1, 5, 28], // A, CNAME and AAAA
|
||||||
// etc. #0 -> NOERROR
|
|
||||||
_coreConfig.dns.rules.Add(new()
|
|
||||||
{
|
|
||||||
query_type = [1, 28],
|
|
||||||
domain = [kvp.Key],
|
|
||||||
action = "predefined",
|
|
||||||
rcode = rcode switch
|
|
||||||
{
|
|
||||||
0 => "NOERROR",
|
|
||||||
1 => "FORMERR",
|
|
||||||
2 => "SERVFAIL",
|
|
||||||
3 => "NXDOMAIN",
|
|
||||||
4 => "NOTIMP",
|
|
||||||
5 => "REFUSED",
|
|
||||||
_ => "NOERROR",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// CNAME record
|
|
||||||
Rule4Sbox rule = new()
|
|
||||||
{
|
|
||||||
query_type = [1, 28],
|
|
||||||
action = "predefined",
|
action = "predefined",
|
||||||
rcode = "NOERROR",
|
rcode = "NOERROR",
|
||||||
answer = [$"*. IN CNAME {predefined}."],
|
|
||||||
};
|
};
|
||||||
if (ParseV2Domain(kvp.Key, rule))
|
if (!ParseV2Domain(kvp.Key, rule))
|
||||||
{
|
{
|
||||||
_coreConfig.dns.rules.Add(rule);
|
continue;
|
||||||
}
|
}
|
||||||
|
// see: https://xtls.github.io/en/config/dns.html#dnsobject
|
||||||
|
// The matching format (domain:, full:, etc.) is the same as the domain
|
||||||
|
// in the commonly used Routing System. The difference is that without a prefix,
|
||||||
|
// it defaults to using the full: prefix (similar to the common hosts file syntax).
|
||||||
|
if (rule.domain_keyword?.Count > 0 && !kvp.Key.Contains(':'))
|
||||||
|
{
|
||||||
|
rule.domain = rule.domain_keyword;
|
||||||
|
rule.domain_keyword = null;
|
||||||
|
}
|
||||||
|
// example.com #0 -> example.com with NOERROR
|
||||||
|
if (predefined.StartsWith('#') && int.TryParse(predefined.AsSpan(1), out var rcode))
|
||||||
|
{
|
||||||
|
rule.rcode = rcode switch
|
||||||
|
{
|
||||||
|
0 => "NOERROR",
|
||||||
|
1 => "FORMERR",
|
||||||
|
2 => "SERVFAIL",
|
||||||
|
3 => "NXDOMAIN",
|
||||||
|
4 => "NOTIMP",
|
||||||
|
5 => "REFUSED",
|
||||||
|
_ => "NOERROR",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else if (Utils.IsDomain(predefined))
|
||||||
|
{
|
||||||
|
// example.com CNAME target.com -> example.com with CNAME target.com
|
||||||
|
rule.answer = new List<string> { $"*. IN CNAME {predefined}." };
|
||||||
|
}
|
||||||
|
else if (Utils.IsIpAddress(predefined) && (rule.domain?.Count ?? 0) == 0)
|
||||||
|
{
|
||||||
|
// not full match, but an IP address, treat it as predefined answer
|
||||||
|
if (Utils.IsIpv6(predefined))
|
||||||
|
{
|
||||||
|
rule.answer = new List<string> { $"*. IN AAAA {predefined}" };
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rule.answer = new List<string> { $"*. IN A {predefined}" };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
_coreConfig.dns.rules.Add(rule);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (simpleDnsItem.BlockBindingQuery == true)
|
if (simpleDnsItem.BlockBindingQuery == true)
|
||||||
|
|
|
||||||
|
|
@ -84,11 +84,58 @@ public partial class CoreConfigSingboxService
|
||||||
}
|
}
|
||||||
if (hostsDomains.Count > 0)
|
if (hostsDomains.Count > 0)
|
||||||
{
|
{
|
||||||
_coreConfig.route.rules.Add(new()
|
var hostsResolveRule = new Rule4Sbox
|
||||||
{
|
{
|
||||||
action = "resolve",
|
action = "resolve",
|
||||||
domain = hostsDomains,
|
};
|
||||||
});
|
var hostsCounter = 0;
|
||||||
|
foreach (var host in hostsDomains)
|
||||||
|
{
|
||||||
|
var domainRule = new Rule4Sbox();
|
||||||
|
if (!ParseV2Domain(host, domainRule))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (domainRule.domain_keyword?.Count > 0 && !host.Contains(':'))
|
||||||
|
{
|
||||||
|
domainRule.domain = domainRule.domain_keyword;
|
||||||
|
domainRule.domain_keyword = null;
|
||||||
|
}
|
||||||
|
if (domainRule.domain?.Count > 0)
|
||||||
|
{
|
||||||
|
hostsResolveRule.domain ??= [];
|
||||||
|
hostsResolveRule.domain.AddRange(domainRule.domain);
|
||||||
|
hostsCounter++;
|
||||||
|
}
|
||||||
|
else if (domainRule.domain_keyword?.Count > 0)
|
||||||
|
{
|
||||||
|
hostsResolveRule.domain_keyword ??= [];
|
||||||
|
hostsResolveRule.domain_keyword.AddRange(domainRule.domain_keyword);
|
||||||
|
hostsCounter++;
|
||||||
|
}
|
||||||
|
else if (domainRule.domain_suffix?.Count > 0)
|
||||||
|
{
|
||||||
|
hostsResolveRule.domain_suffix ??= [];
|
||||||
|
hostsResolveRule.domain_suffix.AddRange(domainRule.domain_suffix);
|
||||||
|
hostsCounter++;
|
||||||
|
}
|
||||||
|
else if (domainRule.domain_regex?.Count > 0)
|
||||||
|
{
|
||||||
|
hostsResolveRule.domain_regex ??= [];
|
||||||
|
hostsResolveRule.domain_regex.AddRange(domainRule.domain_regex);
|
||||||
|
hostsCounter++;
|
||||||
|
}
|
||||||
|
else if (domainRule.geosite?.Count > 0)
|
||||||
|
{
|
||||||
|
hostsResolveRule.geosite ??= [];
|
||||||
|
hostsResolveRule.geosite.AddRange(domainRule.geosite);
|
||||||
|
hostsCounter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hostsCounter > 0)
|
||||||
|
{
|
||||||
|
_coreConfig.route.rules.Add(hostsResolveRule);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_coreConfig.route.rules.Add(new()
|
_coreConfig.route.rules.Add(new()
|
||||||
|
|
@ -355,6 +402,11 @@ public partial class CoreConfigSingboxService
|
||||||
rule.domain_keyword ??= [];
|
rule.domain_keyword ??= [];
|
||||||
rule.domain_keyword?.Add(domain.Substring(8));
|
rule.domain_keyword?.Add(domain.Substring(8));
|
||||||
}
|
}
|
||||||
|
else if (domain.StartsWith("dotless:"))
|
||||||
|
{
|
||||||
|
rule.domain_keyword ??= [];
|
||||||
|
rule.domain_keyword?.Add(domain.Substring(8));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
rule.domain_keyword ??= [];
|
rule.domain_keyword ??= [];
|
||||||
|
|
|
||||||
|
|
@ -31,13 +31,13 @@ public partial class DNSSettingWindow
|
||||||
this.Bind(ViewModel, vm => vm.AddCommonHosts, v => v.togAddCommonHosts.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.AddCommonHosts, v => v.togAddCommonHosts.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.FakeIP, v => v.togFakeIP.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.FakeIP, v => v.togFakeIP.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.BlockBindingQuery, v => v.togBlockBindingQuery.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.BlockBindingQuery, v => v.togBlockBindingQuery.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.DirectDNS, v => v.cmbDirectDNS.SelectedItem).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.DirectDNS, v => v.cmbDirectDNS.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.RemoteDNS, v => v.cmbRemoteDNS.SelectedItem).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.RemoteDNS, v => v.cmbRemoteDNS.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.BootstrapDNS, v => v.cmbBootstrapDNS.SelectedItem).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.BootstrapDNS, v => v.cmbBootstrapDNS.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.Strategy4Freedom, v => v.cmbDirectDNSStrategy.SelectedItem).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.Strategy4Freedom, v => v.cmbDirectDNSStrategy.SelectedItem).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.Strategy4Proxy, v => v.cmbRemoteDNSStrategy.SelectedItem).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.Strategy4Proxy, v => v.cmbRemoteDNSStrategy.SelectedItem).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.Hosts, v => v.txtHosts.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.Hosts, v => v.txtHosts.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.DirectExpectedIPs, v => v.cmbDirectExpectedIPs.SelectedItem).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.DirectExpectedIPs, v => v.cmbDirectExpectedIPs.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.ParallelQuery, v => v.togParallelQuery.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.ParallelQuery, v => v.togParallelQuery.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.ServeStale, v => v.togServeStale.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.ServeStale, v => v.togServeStale.IsChecked).DisposeWith(disposables);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue