mirror of
https://github.com/2dust/v2rayN.git
synced 2026-03-10 02:13:05 +00:00
Compare commits
No commits in common. "d9843dc77502454b1ec48cec6244e115f1abd082" and "fdb733fa726f938827284e069e504374ac962c93" have entirely different histories.
d9843dc775
...
fdb733fa72
8 changed files with 55 additions and 89 deletions
|
|
@ -332,20 +332,22 @@ public class Utils
|
||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Dictionary<string, List<string>> ParseHostsToDictionary(string? hostsContent)
|
public static Dictionary<string, List<string>> ParseHostsToDictionary(string hostsContent)
|
||||||
{
|
{
|
||||||
if (hostsContent.IsNullOrEmpty())
|
|
||||||
{
|
|
||||||
return new();
|
|
||||||
}
|
|
||||||
var userHostsMap = hostsContent
|
var userHostsMap = hostsContent
|
||||||
.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries)
|
.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)
|
||||||
.Select(line => line.Trim())
|
.Select(line => line.Trim())
|
||||||
// skip full-line comments
|
// skip full-line comments
|
||||||
.Where(line => !string.IsNullOrWhiteSpace(line) && !line.StartsWith('#'))
|
.Where(line => !string.IsNullOrWhiteSpace(line) && !line.StartsWith("#"))
|
||||||
|
// strip inline comments (truncate at '#')
|
||||||
|
.Select(line =>
|
||||||
|
{
|
||||||
|
var index = line.IndexOf('#');
|
||||||
|
return index >= 0 ? line.Substring(0, index).Trim() : line;
|
||||||
|
})
|
||||||
// ensure line still contains valid parts
|
// ensure line still contains valid parts
|
||||||
.Where(line => !string.IsNullOrWhiteSpace(line) && line.Contains(' '))
|
.Where(line => !string.IsNullOrWhiteSpace(line) && line.Contains(' '))
|
||||||
.Select(line => line.Split([' ', '\t'], StringSplitOptions.RemoveEmptyEntries))
|
.Select(line => line.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries))
|
||||||
.Where(parts => parts.Length >= 2)
|
.Where(parts => parts.Length >= 2)
|
||||||
.GroupBy(parts => parts[0])
|
.GroupBy(parts => parts[0])
|
||||||
.ToDictionary(
|
.ToDictionary(
|
||||||
|
|
@ -1084,19 +1086,7 @@ public class Utils
|
||||||
|
|
||||||
public static string GetExeName(string name)
|
public static string GetExeName(string name)
|
||||||
{
|
{
|
||||||
if (name.IsNullOrEmpty() || IsNonWindows())
|
return IsWindows() ? $"{name}.exe" : name;
|
||||||
{
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (name.EndsWith(".exe", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return $"{name}.exe";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsAdministrator()
|
public static bool IsAdministrator()
|
||||||
|
|
|
||||||
|
|
@ -88,9 +88,14 @@ public partial class CoreConfigSingboxService
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var kvp in Utils.ParseHostsToDictionary(simpleDNSItem.Hosts))
|
if (!simpleDNSItem.Hosts.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
hostsDns.predefined[kvp.Key] = kvp.Value.Where(s => Utils.IsIpAddress(s)).ToList();
|
var userHostsMap = Utils.ParseHostsToDictionary(simpleDNSItem.Hosts);
|
||||||
|
|
||||||
|
foreach (var kvp in userHostsMap)
|
||||||
|
{
|
||||||
|
hostsDns.predefined[kvp.Key] = kvp.Value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var host in hostsDns.predefined)
|
foreach (var host in hostsDns.predefined)
|
||||||
|
|
@ -110,7 +115,7 @@ public partial class CoreConfigSingboxService
|
||||||
}
|
}
|
||||||
|
|
||||||
singboxConfig.dns ??= new Dns4Sbox();
|
singboxConfig.dns ??= new Dns4Sbox();
|
||||||
singboxConfig.dns.servers ??= [];
|
singboxConfig.dns.servers ??= new List<Server4Sbox>();
|
||||||
singboxConfig.dns.servers.Add(remoteDns);
|
singboxConfig.dns.servers.Add(remoteDns);
|
||||||
singboxConfig.dns.servers.Add(directDns);
|
singboxConfig.dns.servers.Add(directDns);
|
||||||
singboxConfig.dns.servers.Add(hostsDns);
|
singboxConfig.dns.servers.Add(hostsDns);
|
||||||
|
|
@ -186,56 +191,13 @@ public partial class CoreConfigSingboxService
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
foreach (var kvp in Utils.ParseHostsToDictionary(simpleDNSItem.Hosts))
|
|
||||||
{
|
|
||||||
var predefined = kvp.Value.First();
|
|
||||||
if (predefined.IsNullOrEmpty() || Utils.IsIpAddress(predefined))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (predefined.StartsWith('#') && int.TryParse(predefined.AsSpan(1), out var rcode))
|
|
||||||
{
|
|
||||||
// xray syntactic sugar for predefined
|
|
||||||
// etc. #0 -> NOERROR
|
|
||||||
singboxConfig.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",
|
|
||||||
rcode = "NOERROR",
|
|
||||||
answer = [$"*. IN CNAME {predefined}."],
|
|
||||||
};
|
|
||||||
if (ParseV2Domain(kvp.Key, rule))
|
|
||||||
{
|
|
||||||
singboxConfig.dns.rules.Add(rule);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var (ech, _) = ParseEchParam(node?.EchConfigList);
|
var (ech, _) = ParseEchParam(node?.EchConfigList);
|
||||||
if (ech is not null)
|
if (ech is not null)
|
||||||
{
|
{
|
||||||
var echDomain = ech.query_server_name ?? node?.Sni;
|
var echDomain = ech.query_server_name ?? node?.Sni;
|
||||||
singboxConfig.dns.rules.Add(new()
|
singboxConfig.dns.rules.Add(new()
|
||||||
{
|
{
|
||||||
query_type = [64, 65],
|
query_type = new List<int> { 64, 65 },
|
||||||
server = Global.SingboxEchDNSTag,
|
server = Global.SingboxEchDNSTag,
|
||||||
domain = echDomain is not null ? new List<string> { echDomain } : null,
|
domain = echDomain is not null ? new List<string> { echDomain } : null,
|
||||||
});
|
});
|
||||||
|
|
@ -247,7 +209,7 @@ public partial class CoreConfigSingboxService
|
||||||
{
|
{
|
||||||
singboxConfig.dns.rules.Add(new()
|
singboxConfig.dns.rules.Add(new()
|
||||||
{
|
{
|
||||||
query_type = [64, 65],
|
query_type = new List<int> { 64, 65 },
|
||||||
server = Global.SingboxEchDNSTag,
|
server = Global.SingboxEchDNSTag,
|
||||||
domain = queryServerNames,
|
domain = queryServerNames,
|
||||||
});
|
});
|
||||||
|
|
@ -258,9 +220,9 @@ public partial class CoreConfigSingboxService
|
||||||
{
|
{
|
||||||
singboxConfig.dns.rules.Add(new()
|
singboxConfig.dns.rules.Add(new()
|
||||||
{
|
{
|
||||||
query_type = [64, 65],
|
query_type = new List<int> { 64, 65 },
|
||||||
action = "predefined",
|
action = "predefined",
|
||||||
rcode = "NOERROR"
|
rcode = "NOTIMP"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -274,14 +236,13 @@ public partial class CoreConfigSingboxService
|
||||||
type = "logical",
|
type = "logical",
|
||||||
mode = "and",
|
mode = "and",
|
||||||
rewrite_ttl = 1,
|
rewrite_ttl = 1,
|
||||||
rules =
|
rules = new List<Rule4Sbox>
|
||||||
[
|
{
|
||||||
new()
|
new() {
|
||||||
{
|
query_type = new List<int> { 1, 28 }, // A and AAAA
|
||||||
query_type = [1, 28], // A and AAAA
|
|
||||||
},
|
},
|
||||||
fakeipFilterRule
|
fakeipFilterRule,
|
||||||
]
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
singboxConfig.dns.rules.Add(rule4Fake);
|
singboxConfig.dns.rules.Add(rule4Fake);
|
||||||
|
|
@ -301,7 +262,7 @@ public partial class CoreConfigSingboxService
|
||||||
if (!string.IsNullOrEmpty(simpleDNSItem?.DirectExpectedIPs))
|
if (!string.IsNullOrEmpty(simpleDNSItem?.DirectExpectedIPs))
|
||||||
{
|
{
|
||||||
var ipItems = simpleDNSItem.DirectExpectedIPs
|
var ipItems = simpleDNSItem.DirectExpectedIPs
|
||||||
.Split([',', ';'], StringSplitOptions.RemoveEmptyEntries)
|
.Split(new[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries)
|
||||||
.Select(s => s.Trim())
|
.Select(s => s.Trim())
|
||||||
.Where(s => !string.IsNullOrEmpty(s))
|
.Where(s => !string.IsNullOrEmpty(s))
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
|
||||||
|
|
@ -75,8 +75,14 @@ public partial class CoreConfigSingboxService
|
||||||
var dnsItem = await AppManager.Instance.GetDNSItem(ECoreType.sing_box);
|
var dnsItem = await AppManager.Instance.GetDNSItem(ECoreType.sing_box);
|
||||||
if (dnsItem == null || !dnsItem.Enabled)
|
if (dnsItem == null || !dnsItem.Enabled)
|
||||||
{
|
{
|
||||||
var userHostsMap = Utils.ParseHostsToDictionary(simpleDnsItem.Hosts);
|
if (!simpleDnsItem.Hosts.IsNullOrEmpty())
|
||||||
hostsDomains.AddRange(userHostsMap.Select(kvp => kvp.Key));
|
{
|
||||||
|
var userHostsMap = Utils.ParseHostsToDictionary(simpleDnsItem.Hosts);
|
||||||
|
foreach (var kvp in userHostsMap)
|
||||||
|
{
|
||||||
|
hostsDomains.Add(kvp.Key);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (simpleDnsItem.UseSystemHosts == true)
|
if (simpleDnsItem.UseSystemHosts == true)
|
||||||
{
|
{
|
||||||
var systemHostsMap = Utils.GetSystemHosts();
|
var systemHostsMap = Utils.GetSystemHosts();
|
||||||
|
|
@ -271,7 +277,7 @@ public partial class CoreConfigSingboxService
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.Process?.Count > 0)
|
if (_config.TunModeItem.EnableTun && item.Process?.Count > 0)
|
||||||
{
|
{
|
||||||
var ruleProcName = JsonUtils.DeepCopy(rule3);
|
var ruleProcName = JsonUtils.DeepCopy(rule3);
|
||||||
ruleProcName.process_name ??= [];
|
ruleProcName.process_name ??= [];
|
||||||
|
|
@ -298,7 +304,11 @@ public partial class CoreConfigSingboxService
|
||||||
}
|
}
|
||||||
|
|
||||||
// sing-box strictly matches the exe suffix on Windows
|
// sing-box strictly matches the exe suffix on Windows
|
||||||
var procName = Utils.GetExeName(process);
|
var procName = process;
|
||||||
|
if (Utils.IsWindows() && !procName.EndsWith(".exe", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
procName += ".exe";
|
||||||
|
}
|
||||||
|
|
||||||
ruleProcName.process_name.Add(procName);
|
ruleProcName.process_name.Add(procName);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -333,9 +333,14 @@ public partial class CoreConfigV2rayService
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var kvp in Utils.ParseHostsToDictionary(simpleDNSItem.Hosts))
|
if (!simpleDNSItem.Hosts.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
dnsItem.hosts[kvp.Key] = kvp.Value;
|
var userHostsMap = Utils.ParseHostsToDictionary(simpleDNSItem.Hosts);
|
||||||
|
|
||||||
|
foreach (var kvp in userHostsMap)
|
||||||
|
{
|
||||||
|
dnsItem.hosts[kvp.Key] = kvp.Value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return await Task.FromResult(0);
|
return await Task.FromResult(0);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,7 @@ public partial class CoreConfigV2rayService
|
||||||
v2rayConfig.routing.rules.Add(it);
|
v2rayConfig.routing.rules.Add(it);
|
||||||
hasDomainIp = true;
|
hasDomainIp = true;
|
||||||
}
|
}
|
||||||
if (rule.process?.Count > 0)
|
if (_config.TunModeItem.EnableTun && rule.process?.Count > 0)
|
||||||
{
|
{
|
||||||
var it = JsonUtils.DeepCopy(rule);
|
var it = JsonUtils.DeepCopy(rule);
|
||||||
it.domain = null;
|
it.domain = null;
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,7 @@ public class RoutingRuleSettingViewModel : MyReactiveObject
|
||||||
Network = item.Network,
|
Network = item.Network,
|
||||||
Protocols = Utils.List2String(item.Protocol),
|
Protocols = Utils.List2String(item.Protocol),
|
||||||
InboundTags = Utils.List2String(item.InboundTag),
|
InboundTags = Utils.List2String(item.InboundTag),
|
||||||
Domains = Utils.List2String((item.Domain ?? []).Concat(item.Ip ?? []).ToList().Concat(item.Process ?? []).ToList()),
|
Domains = Utils.List2String((item.Domain ?? []).Concat(item.Ip ?? []).ToList()),
|
||||||
Enabled = item.Enabled,
|
Enabled = item.Enabled,
|
||||||
Remarks = item.Remarks,
|
Remarks = item.Remarks,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -248,7 +248,7 @@
|
||||||
<DataGridTextColumn
|
<DataGridTextColumn
|
||||||
Width="*"
|
Width="*"
|
||||||
Binding="{Binding Domains}"
|
Binding="{Binding Domains}"
|
||||||
Header="domain / ip / process" />
|
Header="domain / ip" />
|
||||||
</DataGrid.Columns>
|
</DataGrid.Columns>
|
||||||
</DataGrid>
|
</DataGrid>
|
||||||
</TabItem>
|
</TabItem>
|
||||||
|
|
|
||||||
|
|
@ -333,7 +333,7 @@
|
||||||
<DataGridTextColumn
|
<DataGridTextColumn
|
||||||
Width="*"
|
Width="*"
|
||||||
Binding="{Binding Domains}"
|
Binding="{Binding Domains}"
|
||||||
Header="domain / ip / process" />
|
Header="domain / ip" />
|
||||||
</DataGrid.Columns>
|
</DataGrid.Columns>
|
||||||
</DataGrid>
|
</DataGrid>
|
||||||
</TabItem>
|
</TabItem>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue