diff --git a/v2rayN/v2rayN/App.xaml b/v2rayN/v2rayN/App.xaml
index a5bafb0d..ddb2a4ba 100644
--- a/v2rayN/v2rayN/App.xaml
+++ b/v2rayN/v2rayN/App.xaml
@@ -11,7 +11,7 @@
diff --git a/v2rayN/v2rayN/Global.cs b/v2rayN/v2rayN/Global.cs
index c689e6d2..19ad0168 100644
--- a/v2rayN/v2rayN/Global.cs
+++ b/v2rayN/v2rayN/Global.cs
@@ -37,7 +37,6 @@
public const string v2raySampleInbound = "v2rayN.Sample.SampleInbound";
public const string CustomRoutingFileName = "v2rayN.Sample.custom_routing_";
- public const string TunSingboxFileName = "v2rayN.Sample.tun_singbox";
public const string TunSingboxDNSFileName = "v2rayN.Sample.tun_singbox_dns";
public const string TunSingboxInboundFileName = "v2rayN.Sample.tun_singbox_inbound";
public const string TunSingboxRulesFileName = "v2rayN.Sample.tun_singbox_rules";
@@ -158,6 +157,7 @@
public static readonly List TunMtus = new() { "9000", "1500" };
public static readonly List TunStacks = new() { "gvisor", "system" };
public static readonly List PresetMsgFilters = new() { "proxy", "direct", "block", "" };
+ public static readonly List SingboxMuxs = new() { "h2mux", "smux", "yamux", "" };
#endregion const
diff --git a/v2rayN/v2rayN/Handler/ConfigHandler.cs b/v2rayN/v2rayN/Handler/ConfigHandler.cs
index 1f7e6598..9584d799 100644
--- a/v2rayN/v2rayN/Handler/ConfigHandler.cs
+++ b/v2rayN/v2rayN/Handler/ConfigHandler.cs
@@ -132,7 +132,6 @@ namespace v2rayN.Handler
config.tunModeItem = new TunModeItem
{
enableTun = false,
- showWindow = true,
mtu = 9000,
};
}
@@ -191,6 +190,18 @@ namespace v2rayN.Handler
config.guiItem.statisticsFreshRate = 1;
}
+ if (config.mux4Sbox == null)
+ {
+ config.mux4Sbox = new()
+ {
+ protocol = Global.SingboxMuxs[0],
+ max_connections = 4,
+ min_streams = 4,
+ max_streams = 0,
+ padding = true
+ };
+ }
+
LazyConfig.Instance.SetConfig(config);
return 0;
}
diff --git a/v2rayN/v2rayN/Handler/CoreConfigHandler.cs b/v2rayN/v2rayN/Handler/CoreConfigHandler.cs
index 7e3aca47..c0dc712e 100644
--- a/v2rayN/v2rayN/Handler/CoreConfigHandler.cs
+++ b/v2rayN/v2rayN/Handler/CoreConfigHandler.cs
@@ -19,15 +19,16 @@ namespace v2rayN.Handler
msg = ResUI.CheckServerSettings;
return -1;
}
+ var config = LazyConfig.Instance.GetConfig();
msg = ResUI.InitialConfiguration;
if (node.configType == EConfigType.Custom)
{
return GenerateClientCustomConfig(node, fileName, out msg);
}
- else if (LazyConfig.Instance.GetCoreType(node, node.configType) == ECoreType.sing_box)
+ else if (config.tunModeItem.enableTun || LazyConfig.Instance.GetCoreType(node, node.configType) == ECoreType.sing_box)
{
- var configGenSingbox = new CoreConfigSingbox(LazyConfig.Instance.GetConfig());
+ var configGenSingbox = new CoreConfigSingbox(config);
if (configGenSingbox.GenerateClientConfigContent(node, out SingboxConfig? singboxConfig, out msg) != 0)
{
return -1;
@@ -43,7 +44,7 @@ namespace v2rayN.Handler
}
else
{
- var coreConfigV2ray = new CoreConfigV2ray(LazyConfig.Instance.GetConfig());
+ var coreConfigV2ray = new CoreConfigV2ray(config);
if (coreConfigV2ray.GenerateClientConfigContent(node, out V2rayConfig? v2rayConfig, out msg) != 0)
{
return -1;
diff --git a/v2rayN/v2rayN/Handler/CoreConfigSingbox.cs b/v2rayN/v2rayN/Handler/CoreConfigSingbox.cs
index 0916cd7b..9c5d2ede 100644
--- a/v2rayN/v2rayN/Handler/CoreConfigSingbox.cs
+++ b/v2rayN/v2rayN/Handler/CoreConfigSingbox.cs
@@ -52,7 +52,7 @@ namespace v2rayN.Handler
dns(node, singboxConfig);
- //statistic(singboxConfig);
+ statistic(singboxConfig);
msg = string.Format(ResUI.SuccessfulConfiguration, "");
}
@@ -258,6 +258,11 @@ namespace v2rayN.Handler
outbound.flow = node.flow;
outbound.packet_encoding = "xudp";
+
+ if (Utils.IsNullOrEmpty(node.flow))
+ {
+ outboundMux(node, outbound);
+ }
}
else if (node.configType == EConfigType.Trojan)
{
@@ -288,10 +293,11 @@ namespace v2rayN.Handler
var mux = new Multiplex4Sbox()
{
enabled = true,
- protocol = "smux",
- max_connections = 4,
- min_streams = 4,
- max_streams = 0,
+ protocol = _config.mux4Sbox.protocol,
+ max_connections = _config.mux4Sbox.max_connections,
+ min_streams = _config.mux4Sbox.min_streams,
+ max_streams = _config.mux4Sbox.max_streams,
+ padding = _config.mux4Sbox.padding
};
outbound.multiplex = mux;
}
@@ -361,6 +367,13 @@ namespace v2rayN.Handler
case "ws":
transport.type = "ws";
transport.path = Utils.IsNullOrEmpty(node.path) ? null : node.path;
+ if (!Utils.IsNullOrEmpty(node.requestHost))
+ {
+ transport.headers = new()
+ {
+ Host = node.requestHost
+ };
+ }
break;
case "quic":
@@ -446,38 +459,6 @@ namespace v2rayN.Handler
}
}
}
-
- if (_config.tunModeItem.enableTun)
- {
- if (_config.tunModeItem.bypassMode)
- {
- //direct ips
- if (_config.tunModeItem.directIP != null && _config.tunModeItem.directIP.Count > 0)
- {
- singboxConfig.route.rules.Add(new() { outbound = "direct", ip_cidr = _config.tunModeItem.directIP });
- }
- //direct process
- if (_config.tunModeItem.directProcess != null && _config.tunModeItem.directProcess.Count > 0)
- {
- singboxConfig.route.rules.Add(new() { outbound = "direct", process_name = _config.tunModeItem.directProcess });
- }
- }
- else
- {
- //proxy ips
- if (_config.tunModeItem.proxyIP != null && _config.tunModeItem.proxyIP.Count > 0)
- {
- singboxConfig.route.rules.Add(new() { outbound = "proxy", ip_cidr = _config.tunModeItem.proxyIP });
- }
- //proxy process
- if (_config.tunModeItem.proxyProcess != null && _config.tunModeItem.proxyProcess.Count > 0)
- {
- singboxConfig.route.rules.Add(new() { outbound = "proxy", process_name = _config.tunModeItem.proxyProcess });
- }
-
- singboxConfig.route.rules.Add(new() { outbound = "direct", inbound = new() { "tun-in" } });
- }
- }
}
catch (Exception ex)
{
@@ -546,6 +527,7 @@ namespace v2rayN.Handler
rule.inbound = item.inboundTag;
}
var rule2 = Utils.DeepCopy(rule);
+ var rule3 = Utils.DeepCopy(rule);
var hasDomainIp = false;
if (item.domain?.Count > 0)
@@ -568,6 +550,13 @@ namespace v2rayN.Handler
hasDomainIp = true;
}
+ if (_config.tunModeItem.enableTun && item.process?.Count > 0)
+ {
+ rule3.process_name = item.process;
+ rules.Add(rule3);
+ hasDomainIp = true;
+ }
+
if (!hasDomainIp)
{
rules.Add(rule);
@@ -653,16 +642,9 @@ namespace v2rayN.Handler
Dns4Sbox? dns4Sbox;
if (_config.tunModeItem.enableTun)
{
- string tunDNS = String.Empty;
- if (_config.tunModeItem.bypassMode)
- {
- tunDNS = _config.tunModeItem.directDNS;
- }
- else
- {
- tunDNS = _config.tunModeItem.proxyDNS;
- }
- if (tunDNS.IsNullOrEmpty() || Utils.FromJson(tunDNS) is null)
+ var item = LazyConfig.Instance.GetDNSItem(ECoreType.sing_box);
+ var tunDNS = item?.tunDNS;
+ if (string.IsNullOrWhiteSpace(tunDNS))
{
tunDNS = Utils.GetEmbedText(Global.TunSingboxDNSFileName);
}
@@ -720,13 +702,18 @@ namespace v2rayN.Handler
{
singboxConfig.experimental = new Experimental4Sbox()
{
- v2ray_api = new V2ray_Api4Sbox()
+ //v2ray_api = new V2ray_Api4Sbox()
+ //{
+ // listen = $"{Global.Loopback}:{Global.statePort}",
+ // stats = new Stats4Sbox()
+ // {
+ // enabled = true,
+ // }
+ //}
+ clash_api = new Clash_Api4Sbox()
{
- listen = $"{Global.Loopback}:{Global.statePort}",
- stats = new Stats4Sbox()
- {
- enabled = true,
- }
+ external_controller = $"{Global.Loopback}:{Global.statePort}",
+ store_selected = true
}
};
}
diff --git a/v2rayN/v2rayN/Handler/CoreConfigV2ray.cs b/v2rayN/v2rayN/Handler/CoreConfigV2ray.cs
index ea836079..b4ef45f8 100644
--- a/v2rayN/v2rayN/Handler/CoreConfigV2ray.cs
+++ b/v2rayN/v2rayN/Handler/CoreConfigV2ray.cs
@@ -96,24 +96,24 @@ namespace v2rayN.Handler
{
try
{
- v2rayConfig.inbounds = new List();
+ v2rayConfig.inbounds = new List();
- Inbounds? inbound = GetInbound(_config.inbound[0], Global.InboundSocks, 0, true);
+ Inbounds4Ray? inbound = GetInbound(_config.inbound[0], Global.InboundSocks, 0, true);
v2rayConfig.inbounds.Add(inbound);
//http
- Inbounds? inbound2 = GetInbound(_config.inbound[0], Global.InboundHttp, 1, false);
+ Inbounds4Ray? inbound2 = GetInbound(_config.inbound[0], Global.InboundHttp, 1, false);
v2rayConfig.inbounds.Add(inbound2);
if (_config.inbound[0].allowLANConn)
{
if (_config.inbound[0].newPort4LAN)
{
- Inbounds inbound3 = GetInbound(_config.inbound[0], Global.InboundSocks2, 2, true);
+ Inbounds4Ray inbound3 = GetInbound(_config.inbound[0], Global.InboundSocks2, 2, true);
inbound3.listen = "0.0.0.0";
v2rayConfig.inbounds.Add(inbound3);
- Inbounds inbound4 = GetInbound(_config.inbound[0], Global.InboundHttp2, 3, false);
+ Inbounds4Ray inbound4 = GetInbound(_config.inbound[0], Global.InboundHttp2, 3, false);
inbound4.listen = "0.0.0.0";
v2rayConfig.inbounds.Add(inbound4);
@@ -121,10 +121,10 @@ namespace v2rayN.Handler
if (!Utils.IsNullOrEmpty(_config.inbound[0].user) && !Utils.IsNullOrEmpty(_config.inbound[0].pass))
{
inbound3.settings.auth = "password";
- inbound3.settings.accounts = new List { new AccountsItem() { user = _config.inbound[0].user, pass = _config.inbound[0].pass } };
+ inbound3.settings.accounts = new List { new AccountsItem4Ray() { user = _config.inbound[0].user, pass = _config.inbound[0].pass } };
inbound4.settings.auth = "password";
- inbound4.settings.accounts = new List { new AccountsItem() { user = _config.inbound[0].user, pass = _config.inbound[0].pass } };
+ inbound4.settings.accounts = new List { new AccountsItem4Ray() { user = _config.inbound[0].user, pass = _config.inbound[0].pass } };
}
}
else
@@ -141,7 +141,7 @@ namespace v2rayN.Handler
return 0;
}
- private Inbounds? GetInbound(InItem inItem, string tag, int offset, bool bSocks)
+ private Inbounds4Ray? GetInbound(InItem inItem, string tag, int offset, bool bSocks)
{
string result = Utils.GetEmbedText(Global.v2raySampleInbound);
if (Utils.IsNullOrEmpty(result))
@@ -149,7 +149,7 @@ namespace v2rayN.Handler
return null;
}
- var inbound = Utils.FromJson(result);
+ var inbound = Utils.FromJson(result);
if (inbound == null)
{
return null;
@@ -187,7 +187,8 @@ namespace v2rayN.Handler
{
if (item.enabled)
{
- routingUserRule(item, v2rayConfig);
+ var item2 = Utils.FromJson(Utils.ToJson(item));
+ routingUserRule(item2, v2rayConfig);
}
}
}
@@ -200,7 +201,8 @@ namespace v2rayN.Handler
var rules = Utils.FromJson>(lockedItem.ruleSet);
foreach (var item in rules)
{
- routingUserRule(item, v2rayConfig);
+ var item2 = Utils.FromJson(Utils.ToJson(item));
+ routingUserRule(item2, v2rayConfig);
}
}
}
@@ -213,7 +215,7 @@ namespace v2rayN.Handler
return 0;
}
- private int routingUserRule(RulesItem rules, V2rayConfig v2rayConfig)
+ private int routingUserRule(RulesItem4Ray rules, V2rayConfig v2rayConfig)
{
try
{
@@ -291,13 +293,13 @@ namespace v2rayN.Handler
{
try
{
- Outbounds outbound = v2rayConfig.outbounds[0];
+ Outbounds4Ray outbound = v2rayConfig.outbounds[0];
if (node.configType == EConfigType.VMess)
{
- VnextItem vnextItem;
+ VnextItem4Ray vnextItem;
if (outbound.settings.vnext.Count <= 0)
{
- vnextItem = new VnextItem();
+ vnextItem = new VnextItem4Ray();
outbound.settings.vnext.Add(vnextItem);
}
else
@@ -307,10 +309,10 @@ namespace v2rayN.Handler
vnextItem.address = node.address;
vnextItem.port = node.port;
- UsersItem usersItem;
+ UsersItem4Ray usersItem;
if (vnextItem.users.Count <= 0)
{
- usersItem = new UsersItem();
+ usersItem = new UsersItem4Ray();
vnextItem.users.Add(usersItem);
}
else
@@ -330,19 +332,17 @@ namespace v2rayN.Handler
usersItem.security = Global.DefaultSecurity;
}
- //Mux
- outbound.mux.enabled = _config.coreBasicItem.muxEnabled;
- outbound.mux.concurrency = _config.coreBasicItem.muxEnabled ? 8 : -1;
+ outboundMux(node, outbound, _config.coreBasicItem.muxEnabled);
outbound.protocol = Global.vmessProtocolLite;
outbound.settings.servers = null;
}
else if (node.configType == EConfigType.Shadowsocks)
{
- ServersItem serversItem;
+ ServersItem4Ray serversItem;
if (outbound.settings.servers.Count <= 0)
{
- serversItem = new ServersItem();
+ serversItem = new ServersItem4Ray();
outbound.settings.servers.Add(serversItem);
}
else
@@ -357,18 +357,17 @@ namespace v2rayN.Handler
serversItem.ota = false;
serversItem.level = 1;
- outbound.mux.enabled = false;
- outbound.mux.concurrency = -1;
+ outboundMux(node, outbound, false);
outbound.protocol = Global.ssProtocolLite;
outbound.settings.vnext = null;
}
else if (node.configType == EConfigType.Socks)
{
- ServersItem serversItem;
+ ServersItem4Ray serversItem;
if (outbound.settings.servers.Count <= 0)
{
- serversItem = new ServersItem();
+ serversItem = new ServersItem4Ray();
outbound.settings.servers.Add(serversItem);
}
else
@@ -383,28 +382,27 @@ namespace v2rayN.Handler
if (!Utils.IsNullOrEmpty(node.security)
&& !Utils.IsNullOrEmpty(node.id))
{
- SocksUsersItem socksUsersItem = new()
+ SocksUsersItem4Ray socksUsersItem = new()
{
user = node.security,
pass = node.id,
level = 1
};
- serversItem.users = new List() { socksUsersItem };
+ serversItem.users = new List() { socksUsersItem };
}
- outbound.mux.enabled = false;
- outbound.mux.concurrency = -1;
+ outboundMux(node, outbound, false);
outbound.protocol = Global.socksProtocolLite;
outbound.settings.vnext = null;
}
else if (node.configType == EConfigType.VLESS)
{
- VnextItem vnextItem;
+ VnextItem4Ray vnextItem;
if (outbound.settings.vnext.Count <= 0)
{
- vnextItem = new VnextItem();
+ vnextItem = new VnextItem4Ray();
outbound.settings.vnext.Add(vnextItem);
}
else
@@ -414,10 +412,10 @@ namespace v2rayN.Handler
vnextItem.address = node.address;
vnextItem.port = node.port;
- UsersItem usersItem;
+ UsersItem4Ray usersItem;
if (vnextItem.users.Count <= 0)
{
- usersItem = new UsersItem();
+ usersItem = new UsersItem4Ray();
vnextItem.users.Add(usersItem);
}
else
@@ -429,9 +427,7 @@ namespace v2rayN.Handler
usersItem.email = Global.userEMail;
usersItem.encryption = node.security;
- //Mux
- outbound.mux.enabled = _config.coreBasicItem.muxEnabled;
- outbound.mux.concurrency = _config.coreBasicItem.muxEnabled ? 8 : -1;
+ outboundMux(node, outbound, _config.coreBasicItem.muxEnabled);
if (node.streamSecurity == Global.StreamSecurityReality
|| node.streamSecurity == Global.StreamSecurity)
@@ -440,20 +436,23 @@ namespace v2rayN.Handler
{
usersItem.flow = node.flow;
- outbound.mux.enabled = false;
- outbound.mux.concurrency = -1;
+ outboundMux(node, outbound, false);
}
}
+ if (node.streamSecurity == Global.StreamSecurityReality && Utils.IsNullOrEmpty(node.flow))
+ {
+ outboundMux(node, outbound, _config.coreBasicItem.muxEnabled);
+ }
outbound.protocol = Global.vlessProtocolLite;
outbound.settings.servers = null;
}
else if (node.configType == EConfigType.Trojan)
{
- ServersItem serversItem;
+ ServersItem4Ray serversItem;
if (outbound.settings.servers.Count <= 0)
{
- serversItem = new ServersItem();
+ serversItem = new ServersItem4Ray();
outbound.settings.servers.Add(serversItem);
}
else
@@ -468,8 +467,7 @@ namespace v2rayN.Handler
serversItem.ota = false;
serversItem.level = 1;
- outbound.mux.enabled = false;
- outbound.mux.concurrency = -1;
+ outboundMux(node, outbound, false);
outbound.protocol = Global.trojanProtocolLite;
outbound.settings.vnext = null;
@@ -483,7 +481,29 @@ namespace v2rayN.Handler
return 0;
}
- private int boundStreamSettings(ProfileItem node, StreamSettings streamSettings)
+ private int outboundMux(ProfileItem node, Outbounds4Ray outbound, bool enabled)
+ {
+ try
+ {
+ if (enabled)
+ {
+ outbound.mux.enabled = true;
+ outbound.mux.concurrency = 8;
+ }
+ else
+ {
+ outbound.mux.enabled = false;
+ outbound.mux.concurrency = -1;
+ }
+ }
+ catch (Exception ex)
+ {
+ Utils.SaveLog(ex.Message, ex);
+ }
+ return 0;
+ }
+
+ private int boundStreamSettings(ProfileItem node, StreamSettings4Ray streamSettings)
{
try
{
@@ -508,7 +528,7 @@ namespace v2rayN.Handler
{
streamSettings.security = node.streamSecurity;
- TlsSettings tlsSettings = new()
+ TlsSettings4Ray tlsSettings = new()
{
allowInsecure = Utils.ToBool(node.allowInsecure.IsNullOrEmpty() ? _config.coreBasicItem.defAllowInsecure.ToString().ToLower() : node.allowInsecure),
alpn = node.GetAlpn(),
@@ -530,7 +550,7 @@ namespace v2rayN.Handler
{
streamSettings.security = node.streamSecurity;
- TlsSettings realitySettings = new()
+ TlsSettings4Ray realitySettings = new()
{
fingerprint = node.fingerprint.IsNullOrEmpty() ? _config.coreBasicItem.defFingerprint : node.fingerprint,
serverName = sni,
@@ -546,7 +566,7 @@ namespace v2rayN.Handler
switch (node.GetNetwork())
{
case "kcp":
- KcpSettings kcpSettings = new()
+ KcpSettings4Ray kcpSettings = new()
{
mtu = _config.kcpItem.mtu,
tti = _config.kcpItem.tti
@@ -558,7 +578,7 @@ namespace v2rayN.Handler
kcpSettings.congestion = _config.kcpItem.congestion;
kcpSettings.readBufferSize = _config.kcpItem.readBufferSize;
kcpSettings.writeBufferSize = _config.kcpItem.writeBufferSize;
- kcpSettings.header = new Header
+ kcpSettings.header = new Header4Ray
{
type = node.headerType
};
@@ -570,8 +590,8 @@ namespace v2rayN.Handler
break;
//ws
case "ws":
- WsSettings wsSettings = new();
- wsSettings.headers = new Headers();
+ WsSettings4Ray wsSettings = new();
+ wsSettings.headers = new Headers4Ray();
string path = node.path;
if (!string.IsNullOrWhiteSpace(host))
{
@@ -590,7 +610,7 @@ namespace v2rayN.Handler
break;
//h2
case "h2":
- HttpSettings httpSettings = new();
+ HttpSettings4Ray httpSettings = new();
if (!string.IsNullOrWhiteSpace(host))
{
@@ -603,11 +623,11 @@ namespace v2rayN.Handler
break;
//quic
case "quic":
- QuicSettings quicsettings = new()
+ QuicSettings4Ray quicsettings = new()
{
security = host,
key = node.path,
- header = new Header
+ header = new Header4Ray
{
type = node.headerType
}
@@ -627,7 +647,7 @@ namespace v2rayN.Handler
break;
case "grpc":
- GrpcSettings grpcSettings = new()
+ GrpcSettings4Ray grpcSettings = new()
{
serviceName = node.path,
multiMode = (node.headerType == Global.GrpcmultiMode),
@@ -643,9 +663,9 @@ namespace v2rayN.Handler
//tcp
if (node.headerType == Global.TcpHeaderHttp)
{
- TcpSettings tcpSettings = new()
+ TcpSettings4Ray tcpSettings = new()
{
- header = new Header
+ header = new Header4Ray
{
type = node.headerType
}
@@ -718,7 +738,7 @@ namespace v2rayN.Handler
//}
}
//servers.Add("localhost");
- v2rayConfig.dns = new Mode.Dns
+ v2rayConfig.dns = new Mode.Dns4Ray
{
servers = servers
};
@@ -736,13 +756,13 @@ namespace v2rayN.Handler
if (_config.guiItem.enableStatistics)
{
string tag = Global.InboundAPITagName;
- API apiObj = new();
- Policy policyObj = new();
- SystemPolicy policySystemSetting = new();
+ API4Ray apiObj = new();
+ Policy4Ray policyObj = new();
+ SystemPolicy4Ray policySystemSetting = new();
string[] services = { "StatsService" };
- v2rayConfig.stats = new Stats();
+ v2rayConfig.stats = new Stats4Ray();
apiObj.tag = tag;
apiObj.services = services.ToList();
@@ -755,8 +775,8 @@ namespace v2rayN.Handler
if (!v2rayConfig.inbounds.Exists(item => item.tag == tag))
{
- Inbounds apiInbound = new();
- Inboundsettings apiInboundSettings = new();
+ Inbounds4Ray apiInbound = new();
+ Inboundsettings4Ray apiInboundSettings = new();
apiInbound.tag = tag;
apiInbound.listen = Global.Loopback;
apiInbound.port = Global.statePort;
@@ -768,12 +788,13 @@ namespace v2rayN.Handler
if (!v2rayConfig.routing.rules.Exists(item => item.outboundTag == tag))
{
- RulesItem apiRoutingRule = new()
+ RulesItem4Ray apiRoutingRule = new()
{
inboundTag = new List { tag },
outboundTag = tag,
type = "field"
};
+
v2rayConfig.routing.rules.Add(apiRoutingRule);
}
}
@@ -873,7 +894,7 @@ namespace v2rayN.Handler
it.allowTest = true;
//inbound
- Inbounds inbound = new()
+ Inbounds4Ray inbound = new()
{
listen = Global.Loopback,
port = port,
@@ -905,7 +926,7 @@ namespace v2rayN.Handler
v2rayConfig.outbounds.Add(v2rayConfigCopy.outbounds[0]);
//rule
- RulesItem rule = new()
+ RulesItem4Ray rule = new()
{
inboundTag = new List { inbound.tag },
outboundTag = v2rayConfigCopy.outbounds[0].tag,
diff --git a/v2rayN/v2rayN/Handler/CoreHandler.cs b/v2rayN/v2rayN/Handler/CoreHandler.cs
index 24cf5255..5960980e 100644
--- a/v2rayN/v2rayN/Handler/CoreHandler.cs
+++ b/v2rayN/v2rayN/Handler/CoreHandler.cs
@@ -12,7 +12,6 @@ namespace v2rayN.Handler
internal class CoreHandler
{
private Config _config;
- private CoreInfo? _coreInfo;
private Process? _process;
private Process? _processPre;
private Action _updateFunc;
@@ -35,11 +34,6 @@ namespace v2rayN.Handler
return;
}
- if (SetCore(node) != 0)
- {
- ShowMsg(false, ResUI.CheckServerSettings);
- return;
- }
string fileName = Utils.GetConfigPath(Global.coreConfigFileName);
if (CoreConfigHandler.GenerateClientConfig(node, fileName, out string msg, out string content) != 0)
{
@@ -74,30 +68,13 @@ namespace v2rayN.Handler
{
try
{
+ bool hasProc = false;
if (_process != null)
{
KillProcess(_process);
_process.Dispose();
_process = null;
- }
- else
- {
- if (_coreInfo == null || _coreInfo.coreExes == null)
- {
- return;
- }
- foreach (string vName in _coreInfo.coreExes)
- {
- Process[] existing = Process.GetProcessesByName(vName);
- foreach (Process p in existing)
- {
- string? path = p.MainModule?.FileName;
- if (path == $"{Utils.GetBinPath(vName, _coreInfo.coreType)}.exe")
- {
- KillProcess(p);
- }
- }
- }
+ hasProc = true;
}
if (_processPre != null)
@@ -105,6 +82,31 @@ namespace v2rayN.Handler
KillProcess(_processPre);
_processPre.Dispose();
_processPre = null;
+ hasProc = true;
+ }
+
+ if (!hasProc)
+ {
+ var coreInfos = LazyConfig.Instance.GetCoreInfos();
+ foreach (var it in coreInfos)
+ {
+ if (it.coreType == ECoreType.v2rayN)
+ {
+ continue;
+ }
+ foreach (string vName in it.coreExes)
+ {
+ Process[] existing = Process.GetProcessesByName(vName);
+ foreach (Process p in existing)
+ {
+ string? path = p.MainModule?.FileName;
+ if (path == $"{Utils.GetBinPath(vName, it.coreType)}.exe")
+ {
+ KillProcess(p);
+ }
+ }
+ }
+ }
}
}
catch (Exception ex)
@@ -152,7 +154,19 @@ namespace v2rayN.Handler
{
ShowMsg(false, string.Format(ResUI.StartService, DateTime.Now.ToString()));
- var proc = RunProcess(node, _coreInfo, "", ShowMsg);
+ ECoreType coreType;
+ if (node.configType != EConfigType.Custom && _config.tunModeItem.enableTun)
+ {
+ coreType = ECoreType.sing_box;
+ }
+ else
+ {
+ coreType = LazyConfig.Instance.GetCoreType(node, node.configType);
+ }
+ var coreInfo = LazyConfig.Instance.GetCoreInfo(coreType);
+
+ var displayLog = node.configType != EConfigType.Custom || node.displayLog;
+ var proc = RunProcess(node, coreInfo, "", displayLog, ShowMsg);
if (proc is null)
{
return;
@@ -162,21 +176,20 @@ namespace v2rayN.Handler
//start a socks service
if (_process != null && !_process.HasExited)
{
- if ((node.configType == EConfigType.Custom && node.preSocksPort > 0)
- || (node.configType != EConfigType.Custom && _coreInfo.coreType != ECoreType.sing_box && _config.tunModeItem.enableTun))
+ if ((node.configType == EConfigType.Custom && node.preSocksPort > 0))
{
var itemSocks = new ProfileItem()
{
coreType = ECoreType.sing_box,
configType = EConfigType.Socks,
address = Global.Loopback,
- port = node.preSocksPort > 0 ? node.preSocksPort : LazyConfig.Instance.GetLocalPort(Global.InboundSocks)
+ port = node.preSocksPort
};
string fileName2 = Utils.GetConfigPath(Global.corePreConfigFileName);
if (CoreConfigHandler.GenerateClientConfig(itemSocks, fileName2, out string msg2, out string configStr) == 0)
{
- var coreInfo = LazyConfig.Instance.GetCoreInfo(ECoreType.sing_box);
- var proc2 = RunProcess(node, coreInfo, $" -c {Global.corePreConfigFileName}", ShowMsg);
+ var coreInfo2 = LazyConfig.Instance.GetCoreInfo(ECoreType.sing_box);
+ var proc2 = RunProcess(node, coreInfo2, $" -c {Global.corePreConfigFileName}", true, ShowMsg);
if (proc2 is not null)
{
_processPre = proc2;
@@ -257,26 +270,9 @@ namespace v2rayN.Handler
_updateFunc(updateToTrayTooltip, msg);
}
- private int SetCore(ProfileItem node)
- {
- if (node == null)
- {
- return -1;
- }
- var coreType = LazyConfig.Instance.GetCoreType(node, node.configType);
-
- _coreInfo = LazyConfig.Instance.GetCoreInfo(coreType);
-
- if (_coreInfo == null)
- {
- return -1;
- }
- return 0;
- }
-
#region Process
- private Process? RunProcess(ProfileItem node, CoreInfo coreInfo, string configPath, Action update)
+ private Process? RunProcess(ProfileItem node, CoreInfo coreInfo, string configPath, bool displayLog, Action update)
{
try
{
@@ -285,7 +281,6 @@ namespace v2rayN.Handler
{
return null;
}
- var displayLog = node.configType != EConfigType.Custom || node.displayLog;
Process proc = new()
{
StartInfo = new ProcessStartInfo
diff --git a/v2rayN/v2rayN/Handler/MainFormHandler.cs b/v2rayN/v2rayN/Handler/MainFormHandler.cs
index bae28515..4390a6a9 100644
--- a/v2rayN/v2rayN/Handler/MainFormHandler.cs
+++ b/v2rayN/v2rayN/Handler/MainFormHandler.cs
@@ -208,8 +208,8 @@ namespace v2rayN.Handler
{
updateHandle.UpdateGeoFileAll(config, (bool success, string msg) =>
{
- update(false, msg);
- });
+ update(false, msg);
+ });
autoUpdateGeoTime = dtNow;
}
}
diff --git a/v2rayN/v2rayN/Handler/StatisticsHandler.cs b/v2rayN/v2rayN/Handler/StatisticsHandler.cs
index 23f18ba1..4ca0ae02 100644
--- a/v2rayN/v2rayN/Handler/StatisticsHandler.cs
+++ b/v2rayN/v2rayN/Handler/StatisticsHandler.cs
@@ -1,7 +1,4 @@
-using Grpc.Core;
-using Grpc.Net.Client;
-using ProtosLib.Statistics;
-using System.Net;
+using System.Net;
using System.Net.Sockets;
using v2rayN.Base;
using v2rayN.Mode;
@@ -10,51 +7,40 @@ namespace v2rayN.Handler
{
internal class StatisticsHandler
{
- private Mode.Config config_;
- private GrpcChannel _channel;
- private StatsService.StatsServiceClient _client;
- private bool _exitFlag;
+ private Config _config;
private ServerStatItem? _serverStatItem;
private List _lstServerStat;
- public List ServerStat => _lstServerStat;
-
private Action _updateFunc;
+ private StatisticsV2ray? _statisticsV2Ray;
+ private StatisticsSingbox? _statisticsSingbox;
- public bool Enable
- {
- get; set;
- }
+ public List ServerStat => _lstServerStat;
+ public bool Enable { get; set; }
- public StatisticsHandler(Mode.Config config, Action update)
+ public StatisticsHandler(Config config, Action update)
{
- config_ = config;
+ _config = config;
Enable = config.guiItem.enableStatistics;
+ if (!Enable)
+ {
+ return;
+ }
+
_updateFunc = update;
- _exitFlag = false;
Init();
- GrpcInit();
+ Global.statePort = GetFreePort();
- Task.Run(Run);
- }
-
- private void GrpcInit()
- {
- if (_channel == null)
- {
- Global.statePort = GetFreePort();
-
- _channel = GrpcChannel.ForAddress($"{Global.httpProtocol}{Global.Loopback}:{Global.statePort}");
- _client = new StatsService.StatsServiceClient(_channel);
- }
+ _statisticsV2Ray = new StatisticsV2ray(config, UpdateServerStat);
+ _statisticsSingbox = new StatisticsSingbox(config, UpdateServerStat);
}
public void Close()
{
try
{
- _exitFlag = true;
- //channel_.ShutdownAsync();
+ _statisticsV2Ray?.Close();
+ _statisticsSingbox?.Close();
}
catch (Exception ex)
{
@@ -62,57 +48,6 @@ namespace v2rayN.Handler
}
}
- public async void Run()
- {
- while (!_exitFlag)
- {
- try
- {
- if (Enable && _channel.State == ConnectivityState.Ready)
- {
- QueryStatsResponse? res = null;
- try
- {
- res = await _client.QueryStatsAsync(new QueryStatsRequest() { Pattern = "", Reset = true });
- }
- catch (Exception ex)
- {
- //Utils.SaveLog(ex.Message, ex);
- }
-
- if (res != null)
- {
- GetServerStatItem(config_.indexId);
- ParseOutput(res.Stat, out ServerSpeedItem server);
-
- if (server.proxyUp != 0 || server.proxyDown != 0)
- {
- _serverStatItem.todayUp += server.proxyUp;
- _serverStatItem.todayDown += server.proxyDown;
- _serverStatItem.totalUp += server.proxyUp;
- _serverStatItem.totalDown += server.proxyDown;
- }
- if (Global.ShowInTaskbar)
- {
- server.indexId = config_.indexId;
- server.todayUp = _serverStatItem.todayUp;
- server.todayDown = _serverStatItem.todayDown;
- server.totalUp = _serverStatItem.totalUp;
- server.totalDown = _serverStatItem.totalDown;
- _updateFunc(server);
- }
- }
- }
- var sleep = config_.guiItem.statisticsFreshRate < 1 ? 1 : config_.guiItem.statisticsFreshRate;
- Thread.Sleep(1000 * sleep);
- await _channel.ConnectAsync();
- }
- catch
- {
- }
- }
- }
-
public void ClearAllServerStatistics()
{
SqliteHelper.Instance.Execute($"delete from ServerStatItem ");
@@ -142,6 +77,28 @@ namespace v2rayN.Handler
_lstServerStat = SqliteHelper.Instance.Table().ToList();
}
+ private void UpdateServerStat(ServerSpeedItem server)
+ {
+ GetServerStatItem(_config.indexId);
+
+ if (server.proxyUp != 0 || server.proxyDown != 0)
+ {
+ _serverStatItem.todayUp += server.proxyUp;
+ _serverStatItem.todayDown += server.proxyDown;
+ _serverStatItem.totalUp += server.proxyUp;
+ _serverStatItem.totalDown += server.proxyDown;
+ }
+ if (Global.ShowInTaskbar)
+ {
+ server.indexId = _config.indexId;
+ server.todayUp = _serverStatItem.todayUp;
+ server.todayDown = _serverStatItem.todayDown;
+ server.totalUp = _serverStatItem.totalUp;
+ server.totalDown = _serverStatItem.totalDown;
+ _updateFunc(server);
+ }
+ }
+
private void GetServerStatItem(string indexId)
{
long ticks = DateTime.Now.Date.Ticks;
@@ -177,71 +134,28 @@ namespace v2rayN.Handler
}
}
- private void ParseOutput(Google.Protobuf.Collections.RepeatedField source, out ServerSpeedItem server)
- {
- server = new();
- try
- {
- foreach (Stat stat in source)
- {
- string name = stat.Name;
- long value = stat.Value / 1024; //KByte
- string[] nStr = name.Split(">>>".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
- string type = "";
-
- name = name.Trim();
-
- name = nStr[1];
- type = nStr[3];
-
- if (name == Global.agentTag)
- {
- if (type == "uplink")
- {
- server.proxyUp = value;
- }
- else if (type == "downlink")
- {
- server.proxyDown = value;
- }
- }
- else if (name == Global.directTag)
- {
- if (type == "uplink")
- {
- server.directUp = value;
- }
- else if (type == "downlink")
- {
- server.directDown = value;
- }
- }
- }
- }
- catch (Exception ex)
- {
- //Utils.SaveLog(ex.Message, ex);
- }
- }
-
private int GetFreePort()
{
- int defaultPort = 28123;
try
{
- // TCP stack please do me a favor
- TcpListener l = new(IPAddress.Loopback, 0);
- l.Start();
- int port = ((IPEndPoint)l.LocalEndpoint).Port;
- l.Stop();
- return port;
+ int defaultPort = 9090;
+ if (!Utils.PortInUse(defaultPort))
+ {
+ return defaultPort;
+ }
+ for (int i = 0; i < 3; i++)
+ {
+ TcpListener l = new(IPAddress.Loopback, 0);
+ l.Start();
+ int port = ((IPEndPoint)l.LocalEndpoint).Port;
+ l.Stop();
+ return port;
+ }
}
- catch (Exception ex)
+ catch
{
- // in case access denied
- Utils.SaveLog(ex.Message, ex);
- return defaultPort;
}
+ return 69090;
}
}
}
\ No newline at end of file
diff --git a/v2rayN/v2rayN/Handler/StatisticsSingbox.cs b/v2rayN/v2rayN/Handler/StatisticsSingbox.cs
new file mode 100644
index 00000000..15fea2d9
--- /dev/null
+++ b/v2rayN/v2rayN/Handler/StatisticsSingbox.cs
@@ -0,0 +1,127 @@
+using System.Net.WebSockets;
+using System.Text;
+using v2rayN.Mode;
+
+namespace v2rayN.Handler
+{
+ internal class StatisticsSingbox
+ {
+ private Config _config;
+ private bool _exitFlag;
+ private ClientWebSocket? webSocket;
+ private string url = string.Empty;
+ private Action _updateFunc;
+
+ public StatisticsSingbox(Config config, Action update)
+ {
+ _config = config;
+ _updateFunc = update;
+ _exitFlag = false;
+
+ Task.Run(() => Run());
+ }
+
+ private async void Init()
+ {
+ Thread.Sleep(5000);
+
+ try
+ {
+ url = $"ws://{Global.Loopback}:{Global.statePort}/traffic";
+
+ if (webSocket == null)
+ {
+ webSocket = new ClientWebSocket();
+ await webSocket.ConnectAsync(new Uri(url), CancellationToken.None);
+ }
+ }
+ catch { }
+ }
+
+ public void Close()
+ {
+ try
+ {
+ _exitFlag = true;
+ if (webSocket != null)
+ {
+ webSocket.Abort();
+ webSocket = null;
+ }
+ }
+ catch (Exception ex)
+ {
+ Utils.SaveLog(ex.Message, ex);
+ }
+ }
+
+ private async void Run()
+ {
+ Init();
+
+ while (!_exitFlag)
+ {
+ try
+ {
+ if (webSocket != null)
+ {
+ if (webSocket.State == WebSocketState.Aborted
+ || webSocket.State == WebSocketState.Closed)
+ {
+ webSocket.Abort();
+ webSocket = null;
+ Init();
+ }
+
+ if (webSocket.State != WebSocketState.Open)
+ {
+ continue;
+ }
+
+ var buffer = new byte[1024];
+ var res = await webSocket.ReceiveAsync(new ArraySegment(buffer), CancellationToken.None);
+ while (!res.CloseStatus.HasValue)
+ {
+ var result = Encoding.UTF8.GetString(buffer, 0, res.Count);
+ if (!string.IsNullOrEmpty(result))
+ {
+ ParseOutput(result, out ulong up, out ulong down);
+
+ _updateFunc(new ServerSpeedItem()
+ {
+ proxyUp = (long)(up / 1000),
+ proxyDown = (long)(down / 1000)
+ });
+ }
+ res = await webSocket.ReceiveAsync(new ArraySegment(buffer), CancellationToken.None);
+ }
+ }
+ }
+ catch
+ {
+ }
+ finally
+ {
+ Thread.Sleep(1000);
+ }
+ }
+ }
+
+ private void ParseOutput(string source, out ulong up, out ulong down)
+ {
+ up = 0; down = 0;
+ try
+ {
+ var trafficItem = Utils.FromJson(source);
+ if (trafficItem != null)
+ {
+ up = trafficItem.up;
+ down = trafficItem.down;
+ }
+ }
+ catch
+ {
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/v2rayN/v2rayN/Handler/StatisticsV2ray.cs b/v2rayN/v2rayN/Handler/StatisticsV2ray.cs
new file mode 100644
index 00000000..cc4a065b
--- /dev/null
+++ b/v2rayN/v2rayN/Handler/StatisticsV2ray.cs
@@ -0,0 +1,120 @@
+using Grpc.Core;
+using Grpc.Net.Client;
+using ProtosLib.Statistics;
+using v2rayN.Mode;
+
+namespace v2rayN.Handler
+{
+ internal class StatisticsV2ray
+ {
+ private Mode.Config _config;
+ private GrpcChannel _channel;
+ private StatsService.StatsServiceClient _client;
+ private bool _exitFlag;
+ private Action _updateFunc;
+
+ public StatisticsV2ray(Mode.Config config, Action update)
+ {
+ _config = config;
+ _updateFunc = update;
+ _exitFlag = false;
+
+ GrpcInit();
+
+ Task.Run(Run);
+ }
+
+ private void GrpcInit()
+ {
+ if (_channel == null)
+ {
+ _channel = GrpcChannel.ForAddress($"{Global.httpProtocol}{Global.Loopback}:{Global.statePort}");
+ _client = new StatsService.StatsServiceClient(_channel);
+ }
+ }
+
+ public void Close()
+ {
+ _exitFlag = true;
+ }
+
+ private async void Run()
+ {
+ while (!_exitFlag)
+ {
+ try
+ {
+ if (_channel.State == ConnectivityState.Ready)
+ {
+ QueryStatsResponse? res = null;
+ try
+ {
+ res = await _client.QueryStatsAsync(new QueryStatsRequest() { Pattern = "", Reset = true });
+ }
+ catch
+ {
+ }
+
+ if (res != null)
+ {
+ ParseOutput(res.Stat, out ServerSpeedItem server);
+ _updateFunc(server);
+ }
+ }
+ var sleep = _config.guiItem.statisticsFreshRate < 1 ? 1 : _config.guiItem.statisticsFreshRate;
+ Thread.Sleep(1000 * sleep);
+ await _channel.ConnectAsync();
+ }
+ catch
+ {
+ }
+ }
+ }
+
+ private void ParseOutput(Google.Protobuf.Collections.RepeatedField source, out ServerSpeedItem server)
+ {
+ server = new();
+ try
+ {
+ foreach (Stat stat in source)
+ {
+ string name = stat.Name;
+ long value = stat.Value / 1024; //KByte
+ string[] nStr = name.Split(">>>".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
+ string type = "";
+
+ name = name.Trim();
+
+ name = nStr[1];
+ type = nStr[3];
+
+ if (name == Global.agentTag)
+ {
+ if (type == "uplink")
+ {
+ server.proxyUp = value;
+ }
+ else if (type == "downlink")
+ {
+ server.proxyDown = value;
+ }
+ }
+ else if (name == Global.directTag)
+ {
+ if (type == "uplink")
+ {
+ server.directUp = value;
+ }
+ else if (type == "downlink")
+ {
+ server.directDown = value;
+ }
+ }
+ }
+ }
+ catch
+ {
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/v2rayN/v2rayN/Handler/TunHandler.cs b/v2rayN/v2rayN/Handler/TunHandler.cs
deleted file mode 100644
index d446bb82..00000000
--- a/v2rayN/v2rayN/Handler/TunHandler.cs
+++ /dev/null
@@ -1,361 +0,0 @@
-using System.Diagnostics;
-using System.IO;
-using System.Reactive.Linq;
-using v2rayN.Handler;
-using v2rayN.Mode;
-using v2rayN.Resx;
-
-namespace v2rayN.Base
-{
- public sealed class TunHandler
- {
- private static readonly Lazy _instance = new(() => new());
- public static TunHandler Instance => _instance.Value;
- private string _tunConfigName = "tunConfig.json";
- private static Config _config;
- private CoreInfo coreInfo;
- private Process? _process;
- private static int _socksPort;
- private static bool _needRestart = true;
- private static bool _isRunning = false;
-
- public TunHandler()
- {
- _config = LazyConfig.Instance.GetConfig();
-
- Observable.Interval(TimeSpan.FromSeconds(10))
- .Subscribe(x =>
- {
- if (_isRunning && _config.tunModeItem.enableTun)
- {
- if (_process == null || _process.HasExited)
- {
- if (Init() == false)
- {
- return;
- }
- CoreStart();
- Utils.SaveLog("Tun mode monitors restart");
- }
- }
- });
- }
-
- public void Start()
- {
- var socksPort = LazyConfig.Instance.GetLocalPort(Global.InboundSocks);
-
- if (socksPort == _socksPort
- && _process != null
- && !_process.HasExited)
- {
- _needRestart = false;
- }
-
- _socksPort = socksPort;
-
- if (_needRestart)
- {
- CoreStop();
- if (Init() == false)
- {
- return;
- }
- CoreStartTest();
- CoreStart();
- }
- }
-
- public void Stop()
- {
- CoreStop();
- }
-
- private bool Init()
- {
- coreInfo = LazyConfig.Instance.GetCoreInfo(ECoreType.sing_box);
- //Template
- string configStr = Utils.GetEmbedText(Global.TunSingboxFileName);
- if (!Utils.IsNullOrEmpty(_config.tunModeItem.customTemplate) && File.Exists(_config.tunModeItem.customTemplate))
- {
- var customTemplate = File.ReadAllText(_config.tunModeItem.customTemplate);
- if (!Utils.IsNullOrEmpty(customTemplate))
- {
- configStr = customTemplate;
- }
- }
- if (Utils.IsNullOrEmpty(configStr))
- {
- return false;
- }
-
- //settings
- if (_config.tunModeItem.mtu <= 0)
- {
- _config.tunModeItem.mtu = Convert.ToInt32(Global.TunMtus[0]);
- }
- if (Utils.IsNullOrEmpty(_config.tunModeItem.stack))
- {
- _config.tunModeItem.stack = Global.TunStacks[0];
- }
- configStr = configStr.Replace("$mtu$", $"{_config.tunModeItem.mtu}");
- configStr = configStr.Replace("$strict_route$", $"{_config.tunModeItem.strictRoute.ToString().ToLower()}");
- configStr = configStr.Replace("$stack$", $"{_config.tunModeItem.stack}");
-
- //logs
- configStr = configStr.Replace("$log_disabled$", $"{(!_config.tunModeItem.enabledLog).ToString().ToLower()}");
- if (_config.tunModeItem.showWindow)
- {
- configStr = configStr.Replace("$log_output$", $"");
- }
- else
- {
- var dtNow = DateTime.Now;
- var log_output = $"\"output\": \"{Utils.GetLogPath($"singbox_{dtNow:yyyy-MM-dd}.txt")}\", ";
- configStr = configStr.Replace("$log_output$", $"{log_output.Replace(@"\", @"\\")}");
- }
-
- //port
- configStr = configStr.Replace("$socksPort$", $"{_socksPort}");
-
- //dns
- string dnsObject = String.Empty;
- if (_config.tunModeItem.bypassMode)
- {
- dnsObject = _config.tunModeItem.directDNS;
- }
- else
- {
- dnsObject = _config.tunModeItem.proxyDNS;
- }
- if (dnsObject.IsNullOrEmpty() || Utils.ParseJson(dnsObject)?.ContainsKey("servers") == false)
- {
- dnsObject = Utils.GetEmbedText(Global.TunSingboxDNSFileName);
- }
- configStr = configStr.Replace("$dns_object$", dnsObject);
-
- //exe
- routingDirectExe(out List lstDnsExe, out List lstDirectExe);
- string strDns = string.Join("\",\"", lstDnsExe.ToArray());
- configStr = configStr.Replace("$dnsProcessName$", $"\"{strDns}\"");
-
- string strDirect = string.Join("\",\"", lstDirectExe.ToArray());
- configStr = configStr.Replace("$directProcessName$", $"\"{strDirect}\"");
-
- if (_config.tunModeItem.bypassMode)
- {
- //direct ips
- if (_config.tunModeItem.directIP != null && _config.tunModeItem.directIP.Count > 0)
- {
- var ips = new { outbound = "direct", ip_cidr = _config.tunModeItem.directIP };
- configStr = configStr.Replace("$ruleDirectIPs$", "," + Utils.ToJson(ips));
- }
- //direct process
- if (_config.tunModeItem.directProcess != null && _config.tunModeItem.directProcess.Count > 0)
- {
- var process = new { outbound = "direct", process_name = _config.tunModeItem.directProcess };
- configStr = configStr.Replace("$ruleDirectProcess$", "," + Utils.ToJson(process));
- }
- }
- else
- {
- //proxy ips
- if (_config.tunModeItem.proxyIP != null && _config.tunModeItem.proxyIP.Count > 0)
- {
- var ips = new { outbound = "proxy", ip_cidr = _config.tunModeItem.proxyIP };
- configStr = configStr.Replace("$ruleProxyIPs$", "," + Utils.ToJson(ips));
- }
- //proxy process
- if (_config.tunModeItem.proxyProcess != null && _config.tunModeItem.proxyProcess.Count > 0)
- {
- var process = new { outbound = "proxy", process_name = _config.tunModeItem.proxyProcess };
- configStr = configStr.Replace("$ruleProxyProcess$", "," + Utils.ToJson(process));
- }
-
- var final = new { outbound = "direct", inbound = "tun-in" };
- configStr = configStr.Replace("$ruleFinally$", "," + Utils.ToJson(final));
- }
- configStr = configStr.Replace("$ruleDirectIPs$", "");
- configStr = configStr.Replace("$ruleDirectProcess$", "");
- configStr = configStr.Replace("$ruleProxyIPs$", "");
- configStr = configStr.Replace("$ruleProxyProcess$", "");
- configStr = configStr.Replace("$ruleFinally$", "");
-
- File.WriteAllText(Utils.GetConfigPath(_tunConfigName), configStr);
-
- return true;
- }
-
- private void routingDirectExe(out List lstDnsExe, out List lstDirectExe)
- {
- lstDnsExe = new();
- lstDirectExe = new();
- var coreInfos = LazyConfig.Instance.GetCoreInfos();
- foreach (var it in coreInfos)
- {
- if (it.coreType == ECoreType.v2rayN)
- {
- continue;
- }
- foreach (var it2 in it.coreExes)
- {
- if (!lstDnsExe.Contains(it2) && it.coreType != ECoreType.sing_box)
- {
- lstDnsExe.Add($"{it2}.exe");
- }
-
- if (!lstDirectExe.Contains(it2))
- {
- lstDirectExe.Add($"{it2}.exe");
- }
- }
- }
- }
-
- private void CoreStop()
- {
- try
- {
- _isRunning = false;
- if (_process != null)
- {
- KillProcess(_process);
- _process.Dispose();
- _process = null;
- _needRestart = true;
- }
- }
- catch (Exception ex)
- {
- Utils.SaveLog(ex.Message, ex);
- }
- }
-
- private string CoreFindexe()
- {
- string fileName = string.Empty;
- foreach (string name in coreInfo.coreExes)
- {
- string vName = $"{name}.exe";
- vName = Utils.GetBinPath(vName, coreInfo.coreType);
- if (File.Exists(vName))
- {
- fileName = vName;
- break;
- }
- }
- if (Utils.IsNullOrEmpty(fileName))
- {
- string msg = string.Format(ResUI.NotFoundCore, Utils.GetBinPath("", coreInfo.coreType), string.Join(", ", coreInfo.coreExes.ToArray()), coreInfo.coreUrl);
- Utils.SaveLog(msg);
- }
- return fileName;
- }
-
- private void CoreStart()
- {
- try
- {
- string fileName = CoreFindexe();
- if (Utils.IsNullOrEmpty(fileName))
- {
- return;
- }
- var showWindow = _config.tunModeItem.showWindow;
- Process p = new()
- {
- StartInfo = new ProcessStartInfo
- {
- FileName = fileName,
- Arguments = $"run -c \"{Utils.GetConfigPath(_tunConfigName)}\"",
- WorkingDirectory = Utils.GetConfigPath(),
- UseShellExecute = showWindow,
- CreateNoWindow = !showWindow,
- //RedirectStandardError = !showWindow,
- Verb = "runas",
- }
- };
- p.Start();
- _process = p;
- _isRunning = true;
- if (p.WaitForExit(1000))
- {
- //if (showWindow)
- //{
- throw new Exception("start tun mode fail");
- //}
- //else
- //{
- // throw new Exception(p.StandardError.ReadToEnd());
- //}
- }
-
- Global.processJob.AddProcess(p.Handle);
- }
- catch (Exception ex)
- {
- Utils.SaveLog(ex.Message, ex);
- }
- }
-
- private void KillProcess(Process p)
- {
- try
- {
- p.CloseMainWindow();
- p.WaitForExit(100);
- if (!p.HasExited)
- {
- p.Kill();
- p.WaitForExit(100);
- }
- }
- catch (Exception ex)
- {
- Utils.SaveLog(ex.Message, ex);
- }
- }
-
- private int CoreStartTest()
- {
- Utils.SaveLog("Tun mode configuration file test start");
- try
- {
- string fileName = CoreFindexe();
- if (fileName == "")
- {
- return -1;
- }
- Process p = new Process
- {
- StartInfo = new ProcessStartInfo
- {
- FileName = fileName,
- Arguments = $"run -c \"{Utils.GetConfigPath(_tunConfigName)}\"",
- WorkingDirectory = Utils.GetConfigPath(),
- UseShellExecute = false,
- CreateNoWindow = true,
- RedirectStandardError = true,
- Verb = "runas",
- }
- };
- p.Start();
- if (p.WaitForExit(2000))
- {
- throw new Exception(p.StandardError.ReadToEnd());
- }
- KillProcess(p);
- return 0;
- }
- catch (Exception ex)
- {
- Utils.SaveLog(ex.Message, ex);
- return -1;
- }
- finally
- {
- Utils.SaveLog("Tun mode configuration file test end");
- }
- }
- }
-}
\ No newline at end of file
diff --git a/v2rayN/v2rayN/Mode/Config.cs b/v2rayN/v2rayN/Mode/Config.cs
index 978508e8..f6639b93 100644
--- a/v2rayN/v2rayN/Mode/Config.cs
+++ b/v2rayN/v2rayN/Mode/Config.cs
@@ -27,6 +27,7 @@
public UIItem uiItem { get; set; }
public ConstItem constItem { get; set; }
public SpeedTestItem speedTestItem { get; set; }
+ public Mux4Sbox mux4Sbox { get; set; }
public List inbound { get; set; }
public List globalHotkeys { get; set; }
public List coreTypeItem { get; set; }
diff --git a/v2rayN/v2rayN/Mode/ConfigItems.cs b/v2rayN/v2rayN/Mode/ConfigItems.cs
index 4ab9d3ce..22817422 100644
--- a/v2rayN/v2rayN/Mode/ConfigItems.cs
+++ b/v2rayN/v2rayN/Mode/ConfigItems.cs
@@ -161,19 +161,9 @@ namespace v2rayN.Mode
public class TunModeItem
{
public bool enableTun { get; set; }
- public bool showWindow { get; set; }
- public bool enabledLog { get; set; }
public bool strictRoute { get; set; }
public string stack { get; set; }
public int mtu { get; set; }
- public string customTemplate { get; set; }
- public bool bypassMode { get; set; } = true;
- public List directIP { get; set; }
- public List directProcess { get; set; }
- public string directDNS { get; set; }
- public List proxyIP { get; set; }
- public List proxyProcess { get; set; }
- public string proxyDNS { get; set; }
}
[Serializable]
@@ -191,6 +181,7 @@ namespace v2rayN.Mode
/// 域名解析策略
///
public string domainStrategy { get; set; }
+
public string domainStrategy4Singbox { get; set; }
public string domainMatcher { get; set; }
@@ -205,4 +196,14 @@ namespace v2rayN.Mode
public int Width { get; set; }
public int Index { get; set; }
}
+
+ [Serializable]
+ public class Mux4Sbox
+ {
+ public string protocol { get; set; }
+ public int max_connections { get; set; }
+ public int min_streams { get; set; }
+ public int max_streams { get; set; }
+ public bool padding { get; set; }
+ }
}
\ No newline at end of file
diff --git a/v2rayN/v2rayN/Mode/DNSItem.cs b/v2rayN/v2rayN/Mode/DNSItem.cs
index bf21822b..fef779ec 100644
--- a/v2rayN/v2rayN/Mode/DNSItem.cs
+++ b/v2rayN/v2rayN/Mode/DNSItem.cs
@@ -12,8 +12,7 @@ namespace v2rayN.Mode
public bool enabled { get; set; } = true;
public ECoreType coreType { get; set; }
public string? normalDNS { get; set; }
- public string? directDNS { get; set; }
- public string? proxyDNS { get; set; }
+ public string? tunDNS { get; set; }
public string? domainStrategy4Freedom { get; set; }
}
}
\ No newline at end of file
diff --git a/v2rayN/v2rayN/Mode/RulesItem.cs b/v2rayN/v2rayN/Mode/RulesItem.cs
index e9a5395c..1985c258 100644
--- a/v2rayN/v2rayN/Mode/RulesItem.cs
+++ b/v2rayN/v2rayN/Mode/RulesItem.cs
@@ -18,6 +18,8 @@
public List protocol { get; set; }
+ public List process { get; set; }
+
public bool enabled { get; set; } = true;
}
}
\ No newline at end of file
diff --git a/v2rayN/v2rayN/Mode/ServerSpeedItem.cs b/v2rayN/v2rayN/Mode/ServerSpeedItem.cs
index 8f953159..c51f6d11 100644
--- a/v2rayN/v2rayN/Mode/ServerSpeedItem.cs
+++ b/v2rayN/v2rayN/Mode/ServerSpeedItem.cs
@@ -23,4 +23,18 @@
get; set;
}
}
+
+ [Serializable]
+ public class TrafficItem
+ {
+ public ulong up
+ {
+ get; set;
+ }
+
+ public ulong down
+ {
+ get; set;
+ }
+ }
}
\ No newline at end of file
diff --git a/v2rayN/v2rayN/Mode/SingboxConfig.cs b/v2rayN/v2rayN/Mode/SingboxConfig.cs
index fc8a09df..ed5ada0e 100644
--- a/v2rayN/v2rayN/Mode/SingboxConfig.cs
+++ b/v2rayN/v2rayN/Mode/SingboxConfig.cs
@@ -127,6 +127,7 @@
public int max_connections { get; set; }
public int min_streams { get; set; }
public int max_streams { get; set; }
+ public bool padding { get; set; }
}
public class Utls4Sbox
@@ -147,12 +148,19 @@
public string type { get; set; }
public List? host { get; set; }
public string? path { get; set; }
+ public Headers4Sbox? headers { get; set; }
+
public string service_name { get; set; }
public string idle_timeout { get; set; }
public string ping_timeout { get; set; }
public bool? permit_without_stream { get; set; }
}
+ public class Headers4Sbox
+ {
+ public string? Host { get; set; }
+ }
+
public class Server4Sbox
{
public string tag { get; set; }
@@ -165,6 +173,7 @@
public class Experimental4Sbox
{
public V2ray_Api4Sbox v2ray_api { get; set; }
+ public Clash_Api4Sbox clash_api { get; set; }
}
public class V2ray_Api4Sbox
@@ -173,6 +182,12 @@
public Stats4Sbox stats { get; set; }
}
+ public class Clash_Api4Sbox
+ {
+ public string external_controller { get; set; }
+ public bool store_selected { get; set; }
+ }
+
public class Stats4Sbox
{
public bool enabled { get; set; }
diff --git a/v2rayN/v2rayN/Mode/V2rayConfig.cs b/v2rayN/v2rayN/Mode/V2rayConfig.cs
index a9888312..b20f526d 100644
--- a/v2rayN/v2rayN/Mode/V2rayConfig.cs
+++ b/v2rayN/v2rayN/Mode/V2rayConfig.cs
@@ -11,28 +11,28 @@ namespace v2rayN.Mode
///
/// 日志配置
///
- public Log log { get; set; }
+ public Log4Ray log { get; set; }
///
/// 传入连接配置
///
- public List inbounds { get; set; }
+ public List inbounds { get; set; }
///
/// 传出连接配置
///
- public List outbounds { get; set; }
+ public List outbounds { get; set; }
///
/// 统计需要, 空对象
///
- public Stats stats { get; set; }
+ public Stats4Ray stats { get; set; }
///
- public API api { get; set; }
+ public API4Ray api { get; set; }
///
- public Policy policy;
+ public Policy4Ray policy;
///
/// DNS 配置
@@ -42,30 +42,30 @@ namespace v2rayN.Mode
///
/// 路由配置
///
- public Routing routing { get; set; }
+ public Routing4Ray routing { get; set; }
}
- public class Stats
+ public class Stats4Ray
{ };
- public class API
+ public class API4Ray
{
public string tag { get; set; }
public List services { get; set; }
}
- public class Policy
+ public class Policy4Ray
{
- public SystemPolicy system;
+ public SystemPolicy4Ray system;
}
- public class SystemPolicy
+ public class SystemPolicy4Ray
{
public bool statsOutboundUplink;
public bool statsOutboundDownlink;
}
- public class Log
+ public class Log4Ray
{
///
///
@@ -83,7 +83,7 @@ namespace v2rayN.Mode
public string loglevel { get; set; }
}
- public class Inbounds
+ public class Inbounds4Ray
{
public string tag { get; set; }
@@ -105,20 +105,20 @@ namespace v2rayN.Mode
///
///
///
- public Sniffing sniffing { get; set; }
+ public Sniffing4Ray sniffing { get; set; }
///
///
///
- public Inboundsettings settings { get; set; }
+ public Inboundsettings4Ray settings { get; set; }
///
///
///
- public StreamSettings streamSettings { get; set; }
+ public StreamSettings4Ray streamSettings { get; set; }
}
- public class Inboundsettings
+ public class Inboundsettings4Ray
{
///
///
@@ -143,7 +143,7 @@ namespace v2rayN.Mode
///
///
///
- public List clients { get; set; }
+ public List clients { get; set; }
///
/// VLESS
@@ -152,10 +152,10 @@ namespace v2rayN.Mode
public bool allowTransparent { get; set; }
- public List accounts { get; set; }
+ public List accounts { get; set; }
}
- public class UsersItem
+ public class UsersItem4Ray
{
///
///
@@ -188,14 +188,14 @@ namespace v2rayN.Mode
public string flow { get; set; }
}
- public class Sniffing
+ public class Sniffing4Ray
{
public bool enabled { get; set; }
public List destOverride { get; set; }
public bool routeOnly { get; set; }
}
- public class Outbounds
+ public class Outbounds4Ray
{
///
/// 默认值agentout
@@ -210,35 +210,35 @@ namespace v2rayN.Mode
///
///
///
- public Outboundsettings settings { get; set; }
+ public Outboundsettings4Ray settings { get; set; }
///
///
///
- public StreamSettings streamSettings { get; set; }
+ public StreamSettings4Ray streamSettings { get; set; }
///
///
///
- public Mux mux { get; set; }
+ public Mux4Ray mux { get; set; }
}
- public class Outboundsettings
+ public class Outboundsettings4Ray
{
///
///
///
- public List vnext { get; set; }
+ public List vnext { get; set; }
///
///
///
- public List servers { get; set; }
+ public List servers { get; set; }
///
///
///
- public Response response { get; set; }
+ public Response4Ray response { get; set; }
///
///
@@ -251,7 +251,7 @@ namespace v2rayN.Mode
public int? userLevel { get; set; }
}
- public class VnextItem
+ public class VnextItem4Ray
{
///
///
@@ -266,10 +266,10 @@ namespace v2rayN.Mode
///
///
///
- public List users { get; set; }
+ public List users { get; set; }
}
- public class ServersItem
+ public class ServersItem4Ray
{
///
///
@@ -314,10 +314,10 @@ namespace v2rayN.Mode
///
///
///
- public List users { get; set; }
+ public List users { get; set; }
}
- public class SocksUsersItem
+ public class SocksUsersItem4Ray
{
///
///
@@ -335,7 +335,7 @@ namespace v2rayN.Mode
public int level { get; set; }
}
- public class Mux
+ public class Mux4Ray
{
///
///
@@ -348,7 +348,7 @@ namespace v2rayN.Mode
public int concurrency { get; set; }
}
- public class Response
+ public class Response4Ray
{
///
///
@@ -356,7 +356,7 @@ namespace v2rayN.Mode
public string type { get; set; }
}
- public class Dns
+ public class Dns4Ray
{
///
///
@@ -364,7 +364,7 @@ namespace v2rayN.Mode
public List servers { get; set; }
}
- public class Routing
+ public class Routing4Ray
{
///
///
@@ -379,10 +379,28 @@ namespace v2rayN.Mode
///
///
///
- public List rules { get; set; }
+ public List rules { get; set; }
}
- public class StreamSettings
+ [Serializable]
+ public class RulesItem4Ray
+ {
+ public string type { get; set; }
+
+ public string port { get; set; }
+
+ public List inboundTag { get; set; }
+
+ public string outboundTag { get; set; }
+
+ public List ip { get; set; }
+
+ public List domain { get; set; }
+
+ public List protocol { get; set; }
+ }
+
+ public class StreamSettings4Ray
{
///
///
@@ -397,45 +415,45 @@ namespace v2rayN.Mode
///
///
///
- public TlsSettings tlsSettings { get; set; }
+ public TlsSettings4Ray tlsSettings { get; set; }
///
/// Tcp传输额外设置
///
- public TcpSettings tcpSettings { get; set; }
+ public TcpSettings4Ray tcpSettings { get; set; }
///
/// Kcp传输额外设置
///
- public KcpSettings kcpSettings { get; set; }
+ public KcpSettings4Ray kcpSettings { get; set; }
///
/// ws传输额外设置
///
- public WsSettings wsSettings { get; set; }
+ public WsSettings4Ray wsSettings { get; set; }
///
/// h2传输额外设置
///
- public HttpSettings httpSettings { get; set; }
+ public HttpSettings4Ray httpSettings { get; set; }
///
/// QUIC
///
- public QuicSettings quicSettings { get; set; }
+ public QuicSettings4Ray quicSettings { get; set; }
///
/// VLESS only
///
- public TlsSettings realitySettings { get; set; }
+ public TlsSettings4Ray realitySettings { get; set; }
///
/// grpc
///
- public GrpcSettings grpcSettings { get; set; }
+ public GrpcSettings4Ray grpcSettings { get; set; }
}
- public class TlsSettings
+ public class TlsSettings4Ray
{
///
/// 是否允许不安全连接(用于客户端)
@@ -460,15 +478,15 @@ namespace v2rayN.Mode
public string? spiderX { get; set; }
}
- public class TcpSettings
+ public class TcpSettings4Ray
{
///
/// 数据包头部伪装设置
///
- public Header header { get; set; }
+ public Header4Ray header { get; set; }
}
- public class Header
+ public class Header4Ray
{
///
/// 伪装
@@ -486,7 +504,7 @@ namespace v2rayN.Mode
public object response { get; set; }
}
- public class KcpSettings
+ public class KcpSettings4Ray
{
///
///
@@ -526,7 +544,7 @@ namespace v2rayN.Mode
///
///
///
- public Header header { get; set; }
+ public Header4Ray header { get; set; }
///
///
@@ -534,7 +552,7 @@ namespace v2rayN.Mode
public string seed { get; set; }
}
- public class WsSettings
+ public class WsSettings4Ray
{
///
///
@@ -544,10 +562,10 @@ namespace v2rayN.Mode
///
///
///
- public Headers headers { get; set; }
+ public Headers4Ray headers { get; set; }
}
- public class Headers
+ public class Headers4Ray
{
///
///
@@ -561,7 +579,7 @@ namespace v2rayN.Mode
public string UserAgent { get; set; }
}
- public class HttpSettings
+ public class HttpSettings4Ray
{
///
///
@@ -574,7 +592,7 @@ namespace v2rayN.Mode
public List host { get; set; }
}
- public class QuicSettings
+ public class QuicSettings4Ray
{
///
///
@@ -589,10 +607,10 @@ namespace v2rayN.Mode
///
///
///
- public Header header { get; set; }
+ public Header4Ray header { get; set; }
}
- public class GrpcSettings
+ public class GrpcSettings4Ray
{
public string serviceName { get; set; }
public bool multiMode { get; set; }
@@ -602,7 +620,7 @@ namespace v2rayN.Mode
public int initial_windows_size { get; set; }
}
- public class AccountsItem
+ public class AccountsItem4Ray
{
///
///
diff --git a/v2rayN/v2rayN/Resx/ResUI.Designer.cs b/v2rayN/v2rayN/Resx/ResUI.Designer.cs
index c09993d2..6c208a7c 100644
--- a/v2rayN/v2rayN/Resx/ResUI.Designer.cs
+++ b/v2rayN/v2rayN/Resx/ResUI.Designer.cs
@@ -1853,7 +1853,7 @@ namespace v2rayN.Resx {
}
///
- /// 查找类似 Domain and ip are auto sorted when saving 的本地化字符串。
+ /// 查找类似 Domain, ip, process are auto sorted when saving 的本地化字符串。
///
public static string TbAutoSort {
get {
@@ -1961,7 +1961,7 @@ namespace v2rayN.Resx {
}
///
- /// 查找类似 Sing-box domain strategy 的本地化字符串。
+ /// 查找类似 sing-box domain strategy 的本地化字符串。
///
public static string TbdomainStrategy4Singbox {
get {
@@ -2167,6 +2167,33 @@ namespace v2rayN.Resx {
}
}
+ ///
+ /// 查找类似 Domain 的本地化字符串。
+ ///
+ public static string TbRoutingRuleDomain {
+ get {
+ return ResourceManager.GetString("TbRoutingRuleDomain", resourceCulture);
+ }
+ }
+
+ ///
+ /// 查找类似 IP or IP CIDR 的本地化字符串。
+ ///
+ public static string TbRoutingRuleIP {
+ get {
+ return ResourceManager.GetString("TbRoutingRuleIP", resourceCulture);
+ }
+ }
+
+ ///
+ /// 查找类似 Full process name (Tun mode) 的本地化字符串。
+ ///
+ public static string TbRoutingRuleProcess {
+ get {
+ return ResourceManager.GetString("TbRoutingRuleProcess", resourceCulture);
+ }
+ }
+
///
/// 查找类似 3.Block Domain or IP 的本地化字符串。
///
@@ -2348,7 +2375,7 @@ namespace v2rayN.Resx {
}
///
- /// 查找类似 Sing-box DNS settings 的本地化字符串。
+ /// 查找类似 sing-box DNS settings 的本地化字符串。
///
public static string TbSettingsCoreDnsSingbox {
get {
@@ -2572,6 +2599,15 @@ namespace v2rayN.Resx {
}
}
+ ///
+ /// 查找类似 sing-box Mux Protocol 的本地化字符串。
+ ///
+ public static string TbSettingsMux4SboxProtocol {
+ get {
+ return ResourceManager.GetString("TbSettingsMux4SboxProtocol", resourceCulture);
+ }
+ }
+
///
/// 查找类似 Turn on Mux Multiplexing 的本地化字符串。
///
@@ -2770,15 +2806,6 @@ namespace v2rayN.Resx {
}
}
- ///
- /// 查找类似 Enable: If no route matches, the final proxy 的本地化字符串。
- ///
- public static string TbSettingsTunModeBypassModeTip {
- get {
- return ResourceManager.GetString("TbSettingsTunModeBypassModeTip", resourceCulture);
- }
- }
-
///
/// 查找类似 Custom Template 的本地化字符串。
///
@@ -2951,7 +2978,7 @@ namespace v2rayN.Resx {
}
///
- /// 查找类似 * After setting this value, an socks service will be started using Sing-box to provide functions such as speed display 的本地化字符串。
+ /// 查找类似 * After setting this value, an socks service will be started using sing-box to provide functions such as speed display 的本地化字符串。
///
public static string TipPreSocksPort {
get {
diff --git a/v2rayN/v2rayN/Resx/ResUI.fa-Ir.resx b/v2rayN/v2rayN/Resx/ResUI.fa-Ir.resx
index 6bd3a9ec..39f211d2 100644
--- a/v2rayN/v2rayN/Resx/ResUI.fa-Ir.resx
+++ b/v2rayN/v2rayN/Resx/ResUI.fa-Ir.resx
@@ -701,7 +701,7 @@
txtPreSocksPort
- * After setting this value, an socks service will be started using Sing-box to provide functions such as speed display
+ * After setting this value, an socks service will be started using sing-box to provide functions such as speed display
Browse
diff --git a/v2rayN/v2rayN/Resx/ResUI.resx b/v2rayN/v2rayN/Resx/ResUI.resx
index d4c2f302..1625e449 100644
--- a/v2rayN/v2rayN/Resx/ResUI.resx
+++ b/v2rayN/v2rayN/Resx/ResUI.resx
@@ -701,7 +701,7 @@
txtPreSocksPort
- * After setting this value, an socks service will be started using Sing-box to provide functions such as speed display
+ * After setting this value, an socks service will be started using sing-box to provide functions such as speed display
Browse
@@ -941,7 +941,7 @@
RoutingRuleDetailsSetting
- Domain and ip are auto sorted when saving
+ Domain, ip, process are auto sorted when saving
Ruleobject Doc
@@ -1057,9 +1057,6 @@
Bypass Mode
-
- Enable: If no route matches, the final proxy
-
SpeedTest Single Timeout Value
@@ -1118,7 +1115,7 @@
DNS Settings
- Sing-box DNS settings
+ sing-box DNS settings
Please fill in DNS Structure, Click to view the document
@@ -1127,6 +1124,18 @@
Click to import default DNS config
- Sing-box domain strategy
+ sing-box domain strategy
+
+
+ sing-box Mux Protocol
+
+
+ Full process name (Tun mode)
+
+
+ IP or IP CIDR
+
+
+ Domain
\ No newline at end of file
diff --git a/v2rayN/v2rayN/Resx/ResUI.ru.resx b/v2rayN/v2rayN/Resx/ResUI.ru.resx
index 9e2309d8..99be3632 100644
--- a/v2rayN/v2rayN/Resx/ResUI.ru.resx
+++ b/v2rayN/v2rayN/Resx/ResUI.ru.resx
@@ -701,7 +701,7 @@
txtPreSocksPort
- * После установки этого значения служба socks будет запущена с использованием Sing-box для обеспечения таких функций, как отображение скорости
+ * После установки этого значения служба socks будет запущена с использованием sing-box для обеспечения таких функций, как отображение скорости
Просмотр
diff --git a/v2rayN/v2rayN/Resx/ResUI.zh-Hans.resx b/v2rayN/v2rayN/Resx/ResUI.zh-Hans.resx
index da34e169..0363c124 100644
--- a/v2rayN/v2rayN/Resx/ResUI.zh-Hans.resx
+++ b/v2rayN/v2rayN/Resx/ResUI.zh-Hans.resx
@@ -701,7 +701,7 @@
Socks端口
- * 自定义配置的Socks端口值,可不设置;当设置此值后,将使用Sing-box额外启动一个前置Socks服务,提供分流和速度显示等功能
+ * 自定义配置的Socks端口值,可不设置;当设置此值后,将使用sing-box额外启动一个前置Socks服务,提供分流和速度显示等功能
浏览
@@ -941,7 +941,7 @@
路由规则详情设置
- 保存时Domain和IP自动排序
+ 保存时Domain, IP, 进程名 自动排序
规则详细说明文档
@@ -1057,9 +1057,6 @@
绕行模式
-
- 启用:路由无匹配则最终代理
-
测速单个超时值
@@ -1115,7 +1112,7 @@
DNS设置
- Sing-box DNS设置
+ sing-box DNS设置
请填写 DNS JSON 结构,点击查看文档
@@ -1124,6 +1121,18 @@
点击导入默认DNS配置
- Sing-box域名解析策略
+ sing-box域名解析策略
+
+
+ sing-box Mux 多路复用协议
+
+
+ 进程名全称 (Tun模式)
+
+
+ Domain
+
+
+ IP 或 IP CIDR
\ No newline at end of file
diff --git a/v2rayN/v2rayN/Sample/tun_singbox b/v2rayN/v2rayN/Sample/tun_singbox
deleted file mode 100644
index 1710b0e3..00000000
--- a/v2rayN/v2rayN/Sample/tun_singbox
+++ /dev/null
@@ -1,96 +0,0 @@
-{
- "log": {
- "disabled": $log_disabled$,
- "level": "debug",
- $log_output$
- "timestamp": true
- },
- "dns": $dns_object$ ,
- "inbounds": [
- {
- "type": "tun",
- "tag": "tun-in",
- "interface_name": "singbox_tun",
- "inet4_address": "172.19.0.1/30",
-
- "mtu": $mtu$,
- "auto_route": true,
- "strict_route": $strict_route$,
- "stack": "$stack$",
- "sniff": true
- }
- ],
- "outbounds": [
- {
- "type": "socks",
- "tag": "proxy",
- "udp_fragment": true,
- "server": "127.0.0.1",
- "server_port": $socksPort$
- },
- {
- "type": "block",
- "tag": "block"
- },
- {
- "type": "direct",
- "tag": "direct"
- },
- {
- "type": "dns",
- "tag": "dns_out"
- }
- ],
- "route": {
- "auto_detect_interface": true,
- "rules": [
- {
- "inbound": "dns_in",
- "outbound": "dns_out"
- },
- {
- "protocol": "dns",
- "outbound": "dns_out"
- },
- {
- "network": "udp",
- "port": [
- 135,
- 137,
- 138,
- 139,
- 5353
- ],
- "outbound": "block"
- },
- {
- "ip_cidr": [
- "224.0.0.0/3",
- "ff00::/8"
- ],
- "outbound": "block"
- },
- {
- "source_ip_cidr": [
- "224.0.0.0/3",
- "ff00::/8"
- ],
- "outbound": "block"
- },
- {
- "port": 53,
- "process_name": [ $dnsProcessName$],
- "outbound": "dns_out"
- },
- {
- "process_name": [ $directProcessName$],
- "outbound": "direct"
- }
- $ruleDirectIPs$
- $ruleDirectProcess$
- $ruleProxyIPs$
- $ruleProxyProcess$
- $ruleFinally$
- ]
- }
-}
\ No newline at end of file
diff --git a/v2rayN/v2rayN/ViewModels/DNSSettingViewModel.cs b/v2rayN/v2rayN/ViewModels/DNSSettingViewModel.cs
index c1e1ee6c..3ead0dcf 100644
--- a/v2rayN/v2rayN/ViewModels/DNSSettingViewModel.cs
+++ b/v2rayN/v2rayN/ViewModels/DNSSettingViewModel.cs
@@ -18,6 +18,7 @@ namespace v2rayN.ViewModels
[Reactive] public string domainStrategy4Freedom { get; set; }
[Reactive] public string normalDNS { get; set; }
[Reactive] public string normalDNS2 { get; set; }
+ [Reactive] public string tunDNS2 { get; set; }
public ReactiveCommand SaveCmd { get; }
public ReactiveCommand ImportDefConfig4V2rayCmd { get; }
@@ -35,6 +36,7 @@ namespace v2rayN.ViewModels
var item2 = LazyConfig.Instance.GetDNSItem(ECoreType.sing_box);
normalDNS2 = item2?.normalDNS!;
+ tunDNS2 = item2?.tunDNS!;
SaveCmd = ReactiveCommand.Create(() =>
{
@@ -49,6 +51,7 @@ namespace v2rayN.ViewModels
ImportDefConfig4SingboxCmd = ReactiveCommand.Create(() =>
{
normalDNS2 = Utils.GetEmbedText(Global.DNSSingboxNormalFileName);
+ tunDNS2 = Utils.GetEmbedText(Global.TunSingboxDNSFileName);
});
Utils.SetDarkBorder(view, _config.uiItem.colorModeDark);
@@ -80,6 +83,15 @@ namespace v2rayN.ViewModels
return;
}
}
+ if (!Utils.IsNullOrEmpty(tunDNS2))
+ {
+ var obj2 = Utils.FromJson(tunDNS2);
+ if (obj2 == null)
+ {
+ UI.Show(ResUI.FillCorrectDNSText);
+ return;
+ }
+ }
var item = LazyConfig.Instance.GetDNSItem(ECoreType.Xray);
item.domainStrategy4Freedom = domainStrategy4Freedom;
@@ -88,6 +100,7 @@ namespace v2rayN.ViewModels
var item2 = LazyConfig.Instance.GetDNSItem(ECoreType.sing_box);
item2.normalDNS = Utils.ToJson(Utils.ParseJson(normalDNS2));
+ item2.tunDNS = Utils.ToJson(Utils.ParseJson(tunDNS2));
ConfigHandler.SaveDNSItems(_config, item2);
_noticeHandler?.Enqueue(ResUI.OperationSuccess);
diff --git a/v2rayN/v2rayN/ViewModels/MainWindowViewModel.cs b/v2rayN/v2rayN/ViewModels/MainWindowViewModel.cs
index 1e90d7aa..7a250e96 100644
--- a/v2rayN/v2rayN/ViewModels/MainWindowViewModel.cs
+++ b/v2rayN/v2rayN/ViewModels/MainWindowViewModel.cs
@@ -1617,18 +1617,6 @@ namespace v2rayN.ViewModels
}
}
- private void TunModeSwitch()
- {
- if (EnableTun)
- {
- TunHandler.Instance.Start();
- }
- else
- {
- TunHandler.Instance.Stop();
- }
- }
-
#endregion System proxy and Routings
#region UI
diff --git a/v2rayN/v2rayN/ViewModels/OptionSettingViewModel.cs b/v2rayN/v2rayN/ViewModels/OptionSettingViewModel.cs
index 3f74de06..b1d9e803 100644
--- a/v2rayN/v2rayN/ViewModels/OptionSettingViewModel.cs
+++ b/v2rayN/v2rayN/ViewModels/OptionSettingViewModel.cs
@@ -31,6 +31,7 @@ namespace v2rayN.ViewModels
[Reactive] public bool defAllowInsecure { get; set; }
[Reactive] public string defFingerprint { get; set; }
[Reactive] public string defUserAgent { get; set; }
+ [Reactive] public string mux4SboxProtocol { get; set; }
#endregion Core
@@ -78,20 +79,9 @@ namespace v2rayN.ViewModels
#region Tun mode
- [Reactive] public bool TunShowWindow { get; set; }
- [Reactive] public bool TunEnabledLog { get; set; }
[Reactive] public bool TunStrictRoute { get; set; }
[Reactive] public string TunStack { get; set; }
[Reactive] public int TunMtu { get; set; }
- [Reactive] public string TunCustomTemplate { get; set; }
- [Reactive] public bool TunBypassMode { get; set; }
- [Reactive] public bool TunBypassMode2 { get; set; }
- [Reactive] public string TunDirectIP { get; set; }
- [Reactive] public string TunDirectProcess { get; set; }
- [Reactive] public string TunDirectDNS { get; set; }
- [Reactive] public string TunProxyIP { get; set; }
- [Reactive] public string TunProxyProcess { get; set; }
- [Reactive] public string TunProxyDNS { get; set; }
#endregion Tun mode
@@ -131,6 +121,7 @@ namespace v2rayN.ViewModels
defAllowInsecure = _config.coreBasicItem.defAllowInsecure;
defFingerprint = _config.coreBasicItem.defFingerprint;
defUserAgent = _config.coreBasicItem.defUserAgent;
+ mux4SboxProtocol = _config.mux4Sbox.protocol;
#endregion Core
@@ -178,22 +169,9 @@ namespace v2rayN.ViewModels
#region Tun mode
- TunShowWindow = _config.tunModeItem.showWindow;
- TunEnabledLog = _config.tunModeItem.enabledLog;
TunStrictRoute = _config.tunModeItem.strictRoute;
TunStack = _config.tunModeItem.stack;
TunMtu = _config.tunModeItem.mtu;
- TunCustomTemplate = _config.tunModeItem.customTemplate;
- TunBypassMode = _config.tunModeItem.bypassMode;
- TunDirectIP = Utils.List2String(_config.tunModeItem.directIP, true);
- TunDirectProcess = Utils.List2String(_config.tunModeItem.directProcess, true);
- TunDirectDNS = _config.tunModeItem.directDNS;
- TunProxyIP = Utils.List2String(_config.tunModeItem.proxyIP, true);
- TunProxyProcess = Utils.List2String(_config.tunModeItem.proxyProcess, true);
- TunProxyDNS = _config.tunModeItem.proxyDNS;
- this.WhenAnyValue(
- x => x.TunBypassMode)
- .Subscribe(c => TunBypassMode2 = !TunBypassMode);
#endregion Tun mode
@@ -298,6 +276,7 @@ namespace v2rayN.ViewModels
_config.coreBasicItem.defAllowInsecure = defAllowInsecure;
_config.coreBasicItem.defFingerprint = defFingerprint;
_config.coreBasicItem.defUserAgent = defUserAgent;
+ _config.mux4Sbox.protocol = mux4SboxProtocol;
//Kcp
//_config.kcpItem.mtu = Kcpmtu;
@@ -338,19 +317,9 @@ namespace v2rayN.ViewModels
_config.systemProxyAdvancedProtocol = systemProxyAdvancedProtocol;
//tun mode
- _config.tunModeItem.showWindow = TunShowWindow;
- _config.tunModeItem.enabledLog = TunEnabledLog;
_config.tunModeItem.strictRoute = TunStrictRoute;
_config.tunModeItem.stack = TunStack;
_config.tunModeItem.mtu = TunMtu;
- _config.tunModeItem.customTemplate = TunCustomTemplate;
- _config.tunModeItem.bypassMode = TunBypassMode;
- _config.tunModeItem.directIP = Utils.String2List(Utils.Convert2Comma(TunDirectIP));
- _config.tunModeItem.directProcess = Utils.String2List(Utils.Convert2Comma(TunDirectProcess));
- _config.tunModeItem.directDNS = Utils.ToJson(Utils.ParseJson(TunDirectDNS));
- _config.tunModeItem.proxyIP = Utils.String2List(Utils.Convert2Comma(TunProxyIP));
- _config.tunModeItem.proxyProcess = Utils.String2List(Utils.Convert2Comma(TunProxyProcess));
- _config.tunModeItem.proxyDNS = Utils.ToJson(Utils.ParseJson(TunProxyDNS));
//coreType
SaveCoreType();
diff --git a/v2rayN/v2rayN/ViewModels/RoutingRuleDetailsViewModel.cs b/v2rayN/v2rayN/ViewModels/RoutingRuleDetailsViewModel.cs
index 6ba2cfe2..a21486aa 100644
--- a/v2rayN/v2rayN/ViewModels/RoutingRuleDetailsViewModel.cs
+++ b/v2rayN/v2rayN/ViewModels/RoutingRuleDetailsViewModel.cs
@@ -28,6 +28,9 @@ namespace v2rayN.ViewModels
[Reactive]
public string IP { get; set; }
+ [Reactive]
+ public string Process { get; set; }
+
[Reactive]
public bool AutoSort { get; set; }
@@ -53,6 +56,7 @@ namespace v2rayN.ViewModels
Domain = Utils.List2String(SelectedSource.domain, true);
IP = Utils.List2String(SelectedSource.ip, true);
+ Process = Utils.List2String(SelectedSource.process, true);
SaveCmd = ReactiveCommand.Create(() =>
{
@@ -66,16 +70,19 @@ namespace v2rayN.ViewModels
{
Domain = Utils.Convert2Comma(Domain);
IP = Utils.Convert2Comma(IP);
+ Process = Utils.Convert2Comma(Process);
if (AutoSort)
{
SelectedSource.domain = Utils.String2ListSorted(Domain);
SelectedSource.ip = Utils.String2ListSorted(IP);
+ SelectedSource.process = Utils.String2ListSorted(Process);
}
else
{
SelectedSource.domain = Utils.String2List(Domain);
SelectedSource.ip = Utils.String2List(IP);
+ SelectedSource.process = Utils.String2List(Process);
}
SelectedSource.protocol = ProtocolItems?.ToList();
SelectedSource.inboundTag = InboundTagItems?.ToList();
diff --git a/v2rayN/v2rayN/Views/DNSSettingWindow.xaml b/v2rayN/v2rayN/Views/DNSSettingWindow.xaml
index c19509ef..4fe14cbb 100644
--- a/v2rayN/v2rayN/Views/DNSSettingWindow.xaml
+++ b/v2rayN/v2rayN/Views/DNSSettingWindow.xaml
@@ -4,7 +4,6 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:conv="clr-namespace:v2rayN.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
- xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:reactiveui="http://reactiveui.net"
xmlns:resx="clr-namespace:v2rayN.Resx"
@@ -115,18 +114,46 @@
Cursor="Hand"
Style="{StaticResource DefButton}" />
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
\ No newline at end of file
diff --git a/v2rayN/v2rayN/Views/DNSSettingWindow.xaml.cs b/v2rayN/v2rayN/Views/DNSSettingWindow.xaml.cs
index c20943fe..f35c3b18 100644
--- a/v2rayN/v2rayN/Views/DNSSettingWindow.xaml.cs
+++ b/v2rayN/v2rayN/Views/DNSSettingWindow.xaml.cs
@@ -29,6 +29,7 @@ namespace v2rayN.Views
this.Bind(ViewModel, vm => vm.domainStrategy4Freedom, v => v.cmbdomainStrategy4Freedom.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.normalDNS, v => v.txtnormalDNS.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.normalDNS2, v => v.txtnormalDNS2.Text).DisposeWith(disposables);
+ this.Bind(ViewModel, vm => vm.tunDNS2, v => v.txttunDNS2.Text).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.ImportDefConfig4V2rayCmd, v => v.btnImportDefConfig4V2ray).DisposeWith(disposables);
diff --git a/v2rayN/v2rayN/Views/MainWindow.xaml b/v2rayN/v2rayN/Views/MainWindow.xaml
index 0f2ed7f0..b994f28f 100644
--- a/v2rayN/v2rayN/Views/MainWindow.xaml
+++ b/v2rayN/v2rayN/Views/MainWindow.xaml
@@ -235,7 +235,7 @@
+ Header="sing-box Core" />
+
@@ -291,6 +292,21 @@
Margin="{StaticResource SettingItemMargin}"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsDefUserAgentTips}" />
+
+
+
@@ -776,13 +792,6 @@
-
-
-
-
-
-
-
@@ -790,34 +799,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/v2rayN/v2rayN/Views/OptionSettingWindow.xaml.cs b/v2rayN/v2rayN/Views/OptionSettingWindow.xaml.cs
index 14ab4f41..5a70e301 100644
--- a/v2rayN/v2rayN/Views/OptionSettingWindow.xaml.cs
+++ b/v2rayN/v2rayN/Views/OptionSettingWindow.xaml.cs
@@ -39,6 +39,10 @@ namespace v2rayN.Views
{
cmbdefUserAgent.Items.Add(it);
});
+ Global.SingboxMuxs.ForEach(it =>
+ {
+ cmbmux4SboxProtocol.Items.Add(it);
+ });
for (int i = 1; i <= 10; i++)
{
@@ -134,6 +138,7 @@ namespace v2rayN.Views
this.Bind(ViewModel, vm => vm.defAllowInsecure, v => v.togdefAllowInsecure.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.defFingerprint, v => v.cmbdefFingerprint.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.defUserAgent, v => v.cmbdefUserAgent.Text).DisposeWith(disposables);
+ this.Bind(ViewModel, vm => vm.mux4SboxProtocol, v => v.cmbmux4SboxProtocol.Text).DisposeWith(disposables);
//this.Bind(ViewModel, vm => vm.Kcpmtu, v => v.txtKcpmtu.Text).DisposeWith(disposables);
//this.Bind(ViewModel, vm => vm.Kcptti, v => v.txtKcptti.Text).DisposeWith(disposables);
@@ -165,21 +170,9 @@ namespace v2rayN.Views
this.Bind(ViewModel, vm => vm.systemProxyAdvancedProtocol, v => v.cmbsystemProxyAdvancedProtocol.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.systemProxyExceptions, v => v.txtsystemProxyExceptions.Text).DisposeWith(disposables);
- this.Bind(ViewModel, vm => vm.TunShowWindow, v => v.togShowWindow.IsChecked).DisposeWith(disposables);
- this.Bind(ViewModel, vm => vm.TunEnabledLog, v => v.togEnabledLog.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.TunStrictRoute, v => v.togStrictRoute.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.TunStack, v => v.cmbStack.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.TunMtu, v => v.cmbMtu.Text).DisposeWith(disposables);
- this.Bind(ViewModel, vm => vm.TunCustomTemplate, v => v.txtCustomTemplate.Text).DisposeWith(disposables);
- this.Bind(ViewModel, vm => vm.TunBypassMode, v => v.togBypassMode.IsChecked).DisposeWith(disposables);
- this.OneWayBind(ViewModel, vm => vm.TunBypassMode, v => v.gridTunModeDirect.Visibility, vmToViewConverterOverride: new BooleanToVisibilityTypeConverter()).DisposeWith(disposables);
- this.OneWayBind(ViewModel, vm => vm.TunBypassMode2, v => v.gridTunModeProxy.Visibility, vmToViewConverterOverride: new BooleanToVisibilityTypeConverter()).DisposeWith(disposables);
- this.Bind(ViewModel, vm => vm.TunDirectIP, v => v.txtDirectIP.Text).DisposeWith(disposables);
- this.Bind(ViewModel, vm => vm.TunDirectProcess, v => v.txtDirectProcess.Text).DisposeWith(disposables);
- this.Bind(ViewModel, vm => vm.TunDirectDNS, v => v.txtDirectDNS.Text).DisposeWith(disposables);
- this.Bind(ViewModel, vm => vm.TunProxyIP, v => v.txtProxyIP.Text).DisposeWith(disposables);
- this.Bind(ViewModel, vm => vm.TunProxyProcess, v => v.txtProxyProcess.Text).DisposeWith(disposables);
- this.Bind(ViewModel, vm => vm.TunProxyDNS, v => v.txtProxyDNS.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.CoreType1, v => v.cmbCoreType1.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.CoreType2, v => v.cmbCoreType2.Text).DisposeWith(disposables);
@@ -203,7 +196,7 @@ namespace v2rayN.Views
openFileDialog1.Filter = "tunConfig|*.json|All|*.*";
openFileDialog1.ShowDialog();
- txtCustomTemplate.Text = openFileDialog1.FileName;
+ // txtCustomTemplate.Text = openFileDialog1.FileName;
}
}
}
\ No newline at end of file
diff --git a/v2rayN/v2rayN/Views/RoutingRuleDetailsWindow.xaml b/v2rayN/v2rayN/Views/RoutingRuleDetailsWindow.xaml
index ec0461ea..bbce43c4 100644
--- a/v2rayN/v2rayN/Views/RoutingRuleDetailsWindow.xaml
+++ b/v2rayN/v2rayN/Views/RoutingRuleDetailsWindow.xaml
@@ -172,10 +172,12 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/v2rayN/v2rayN/Views/RoutingRuleDetailsWindow.xaml.cs b/v2rayN/v2rayN/Views/RoutingRuleDetailsWindow.xaml.cs
index 81170483..45d16c69 100644
--- a/v2rayN/v2rayN/Views/RoutingRuleDetailsWindow.xaml.cs
+++ b/v2rayN/v2rayN/Views/RoutingRuleDetailsWindow.xaml.cs
@@ -49,6 +49,7 @@ namespace v2rayN.Views
this.Bind(ViewModel, vm => vm.SelectedSource.enabled, v => v.togEnabled.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.Domain, v => v.txtDomain.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.IP, v => v.txtIP.Text).DisposeWith(disposables);
+ this.Bind(ViewModel, vm => vm.Process, v => v.txtProcess.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.AutoSort, v => v.chkAutoSort.IsChecked).DisposeWith(disposables);
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
diff --git a/v2rayN/v2rayN/Views/RoutingRuleSettingWindow.xaml.cs b/v2rayN/v2rayN/Views/RoutingRuleSettingWindow.xaml.cs
index 07fc91df..cfdb4432 100644
--- a/v2rayN/v2rayN/Views/RoutingRuleSettingWindow.xaml.cs
+++ b/v2rayN/v2rayN/Views/RoutingRuleSettingWindow.xaml.cs
@@ -38,7 +38,7 @@ namespace v2rayN.Views
this.Bind(ViewModel, vm => vm.SelectedRouting.remarks, v => v.txtRemarks.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SelectedRouting.domainStrategy, v => v.cmbdomainStrategy.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SelectedRouting.domainStrategy4Singbox, v => v.cmbdomainStrategy4Singbox.Text).DisposeWith(disposables);
-
+
this.Bind(ViewModel, vm => vm.SelectedRouting.url, v => v.txtUrl.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SelectedRouting.customIcon, v => v.txtCustomIcon.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SelectedRouting.sort, v => v.txtSort.Text).DisposeWith(disposables);
diff --git a/v2rayN/v2rayN/Views/SubEditWindow.xaml b/v2rayN/v2rayN/Views/SubEditWindow.xaml
index 43569ddf..3a8c3885 100644
--- a/v2rayN/v2rayN/Views/SubEditWindow.xaml
+++ b/v2rayN/v2rayN/Views/SubEditWindow.xaml
@@ -196,7 +196,6 @@
AcceptsReturn="True"
Style="{StaticResource MyOutlinedTextBox}" />
-
-
Never
-
-
- Never
-
+
Never