mirror of
https://github.com/2dust/v2rayN.git
synced 2026-02-28 13:13:04 +00:00
Tun protect
This commit is contained in:
parent
0075939a73
commit
2ce52f5392
6 changed files with 206 additions and 27 deletions
|
|
@ -154,7 +154,8 @@ public static class CoreConfigHandler
|
||||||
IsTunEnabled = config.TunModeItem.EnableTun,
|
IsTunEnabled = config.TunModeItem.EnableTun,
|
||||||
SimpleDnsItem = config.SimpleDNSItem,
|
SimpleDnsItem = config.SimpleDNSItem,
|
||||||
ProtectDomainList = [],
|
ProtectDomainList = [],
|
||||||
ProtectSocksPort = 0,
|
TunProtectSsPort = 0,
|
||||||
|
ProxyRelaySsPort = 0,
|
||||||
RawDnsItem = await AppManager.Instance.GetDNSItem(coreType),
|
RawDnsItem = await AppManager.Instance.GetDNSItem(coreType),
|
||||||
RoutingItem = await ConfigHandler.GetDefaultRouting(config),
|
RoutingItem = await ConfigHandler.GetDefaultRouting(config),
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,38 @@ public class CoreManager
|
||||||
|
|
||||||
var fileName = Utils.GetBinConfigPath(Global.CoreConfigFileName);
|
var fileName = Utils.GetBinConfigPath(Global.CoreConfigFileName);
|
||||||
var context = await CoreConfigHandler.BuildCoreConfigContext(_config, node);
|
var context = await CoreConfigHandler.BuildCoreConfigContext(_config, node);
|
||||||
context = context with { IsTunEnabled = _config.TunModeItem.EnableTun };
|
CoreConfigContext? preContext = null;
|
||||||
|
if (context.IsTunEnabled)
|
||||||
|
{
|
||||||
|
var coreType = AppManager.Instance.GetCoreType(node, node.ConfigType);
|
||||||
|
if (coreType == ECoreType.Xray && node.ConfigType != EConfigType.Custom)
|
||||||
|
{
|
||||||
|
var tunProtectSsPort = Utils.GetFreePort();
|
||||||
|
var proxyRelaySsPort = Utils.GetFreePort();
|
||||||
|
context = context with { TunProtectSsPort = tunProtectSsPort, ProxyRelaySsPort = proxyRelaySsPort, };
|
||||||
|
var preItem = new ProfileItem()
|
||||||
|
{
|
||||||
|
CoreType = ECoreType.sing_box,
|
||||||
|
ConfigType = EConfigType.Shadowsocks,
|
||||||
|
Address = Global.Loopback,
|
||||||
|
Port = proxyRelaySsPort,
|
||||||
|
Password = Global.None,
|
||||||
|
};
|
||||||
|
preItem.SetProtocolExtra(preItem.GetProtocolExtra() with
|
||||||
|
{
|
||||||
|
SsMethod = Global.None,
|
||||||
|
});
|
||||||
|
preContext = context with { Node = preItem, };
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var preItem = ConfigHandler.GetPreSocksItem(_config, node, coreType);
|
||||||
|
if (preItem is not null)
|
||||||
|
{
|
||||||
|
preContext = context with { Node = preItem, };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
var result = await CoreConfigHandler.GenerateClientConfig(context, fileName);
|
var result = await CoreConfigHandler.GenerateClientConfig(context, fileName);
|
||||||
if (result.Success != true)
|
if (result.Success != true)
|
||||||
{
|
{
|
||||||
|
|
@ -88,7 +119,7 @@ public class CoreManager
|
||||||
}
|
}
|
||||||
|
|
||||||
await CoreStart(context);
|
await CoreStart(context);
|
||||||
await CoreStartPreService(context);
|
await CoreStartPreService(preContext);
|
||||||
if (_processService != null)
|
if (_processService != null)
|
||||||
{
|
{
|
||||||
await UpdateFunc(true, $"{node.GetSummary()}");
|
await UpdateFunc(true, $"{node.GetSummary()}");
|
||||||
|
|
@ -183,20 +214,13 @@ public class CoreManager
|
||||||
_processService = proc;
|
_processService = proc;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task CoreStartPreService(CoreConfigContext context)
|
private async Task CoreStartPreService(CoreConfigContext? preContext)
|
||||||
{
|
{
|
||||||
var node = context.Node;
|
if (_processService is { HasExited: false } && preContext != null)
|
||||||
if (_processService != null && !_processService.HasExited)
|
|
||||||
{
|
{
|
||||||
var coreType = AppManager.Instance.GetCoreType(node, node.ConfigType);
|
var preCoreType = preContext?.Node?.CoreType ?? ECoreType.sing_box;
|
||||||
var itemSocks = ConfigHandler.GetPreSocksItem(_config, node, coreType);
|
|
||||||
if (itemSocks != null)
|
|
||||||
{
|
|
||||||
var preCoreType = itemSocks.CoreType ?? ECoreType.sing_box;
|
|
||||||
var fileName = Utils.GetBinConfigPath(Global.CorePreConfigFileName);
|
var fileName = Utils.GetBinConfigPath(Global.CorePreConfigFileName);
|
||||||
var itemSocksContext = await CoreConfigHandler.BuildCoreConfigContext(_config, itemSocks);
|
var result = await CoreConfigHandler.GenerateClientConfig(preContext, fileName);
|
||||||
itemSocksContext.ProtectDomainList.AddRangeSafe(context.ProtectDomainList);
|
|
||||||
var result = await CoreConfigHandler.GenerateClientConfig(itemSocksContext, fileName);
|
|
||||||
if (result.Success)
|
if (result.Success)
|
||||||
{
|
{
|
||||||
var coreInfo = CoreInfoManager.Instance.GetCoreInfo(preCoreType);
|
var coreInfo = CoreInfoManager.Instance.GetCoreInfo(preCoreType);
|
||||||
|
|
@ -209,7 +233,6 @@ public class CoreManager
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private async Task UpdateFunc(bool notify, string msg)
|
private async Task UpdateFunc(bool notify, string msg)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -13,5 +13,9 @@ public record CoreConfigContext
|
||||||
// TUN Compatibility
|
// TUN Compatibility
|
||||||
public bool IsTunEnabled { get; init; } = false;
|
public bool IsTunEnabled { get; init; } = false;
|
||||||
public HashSet<string> ProtectDomainList { get; init; } = new();
|
public HashSet<string> ProtectDomainList { get; init; } = new();
|
||||||
public int ProtectSocksPort { get; init; } = 0;
|
// -> tun inbound --(if routing proxy)--> relay outbound
|
||||||
|
// -> proxy core (relay inbound --> proxy outbound --(dialerProxy)--> protect outbound)
|
||||||
|
// -> protect inbound -> direct proxy outbound data -> internet
|
||||||
|
public int TunProtectSsPort { get; init; } = 0;
|
||||||
|
public int ProxyRelaySsPort { get; init; } = 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,51 @@ public partial class CoreConfigSingboxService(CoreConfigContext context)
|
||||||
ret.Success = true;
|
ret.Success = true;
|
||||||
|
|
||||||
ret.Data = ApplyFullConfigTemplate();
|
ret.Data = ApplyFullConfigTemplate();
|
||||||
|
if (context.TunProtectSsPort is > 0 and <= 65535)
|
||||||
|
{
|
||||||
|
var ssInbound = new
|
||||||
|
{
|
||||||
|
type = "shadowsocks",
|
||||||
|
tag = "tun-protect-ss",
|
||||||
|
listen = Global.Loopback,
|
||||||
|
listen_port = context.TunProtectSsPort,
|
||||||
|
method = "none",
|
||||||
|
password = "none",
|
||||||
|
};
|
||||||
|
var directRule = new Rule4Sbox()
|
||||||
|
{
|
||||||
|
inbound = new List<string> { ssInbound.tag },
|
||||||
|
outbound = Global.DirectTag,
|
||||||
|
};
|
||||||
|
var singboxConfigNode = JsonUtils.ParseJson(ret.Data.ToString())!.AsObject();
|
||||||
|
var inboundsNode = singboxConfigNode["inbounds"]!.AsArray();
|
||||||
|
inboundsNode.Add(JsonUtils.SerializeToNode(ssInbound, new JsonSerializerOptions
|
||||||
|
{
|
||||||
|
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
|
||||||
|
}));
|
||||||
|
var routeNode = singboxConfigNode["route"]?.AsObject();
|
||||||
|
var rulesNode = routeNode?["rules"]?.AsArray();
|
||||||
|
var protectRuleNode = JsonUtils.SerializeToNode(directRule,
|
||||||
|
new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull });
|
||||||
|
if (rulesNode != null)
|
||||||
|
{
|
||||||
|
rulesNode.Insert(0, protectRuleNode);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var newRulesNode = new JsonArray() { protectRuleNode };
|
||||||
|
if (routeNode is null)
|
||||||
|
{
|
||||||
|
var newRouteNode = new JsonObject() { ["rules"] = newRulesNode };
|
||||||
|
singboxConfigNode["route"] = newRouteNode;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
routeNode["rules"] = newRulesNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret.Data = JsonUtils.Serialize(singboxConfigNode);
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,11 @@ public partial class CoreConfigSingboxService
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var listen = "0.0.0.0";
|
var listen = "0.0.0.0";
|
||||||
|
var listenPort = AppManager.Instance.GetLocalPort(EInboundProtocol.socks);
|
||||||
_coreConfig.inbounds = [];
|
_coreConfig.inbounds = [];
|
||||||
|
|
||||||
if (!_config.TunModeItem.EnableTun
|
if (!context.IsTunEnabled
|
||||||
|| (_config.TunModeItem.EnableTun && _config.TunModeItem.EnableExInbound && AppManager.Instance.RunningCoreType == ECoreType.sing_box))
|
|| (context.IsTunEnabled && _node.Port != listenPort))
|
||||||
{
|
{
|
||||||
var inbound = new Inbound4Sbox()
|
var inbound = new Inbound4Sbox()
|
||||||
{
|
{
|
||||||
|
|
@ -20,7 +21,7 @@ public partial class CoreConfigSingboxService
|
||||||
};
|
};
|
||||||
_coreConfig.inbounds.Add(inbound);
|
_coreConfig.inbounds.Add(inbound);
|
||||||
|
|
||||||
inbound.listen_port = AppManager.Instance.GetLocalPort(EInboundProtocol.socks);
|
inbound.listen_port = listenPort;
|
||||||
|
|
||||||
if (_config.Inbound.First().SecondLocalPortEnabled)
|
if (_config.Inbound.First().SecondLocalPortEnabled)
|
||||||
{
|
{
|
||||||
|
|
@ -49,7 +50,7 @@ public partial class CoreConfigSingboxService
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_config.TunModeItem.EnableTun)
|
if (context.IsTunEnabled)
|
||||||
{
|
{
|
||||||
if (_config.TunModeItem.Mtu <= 0)
|
if (_config.TunModeItem.Mtu <= 0)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,10 @@ public partial class CoreConfigV2rayService(CoreConfigContext context)
|
||||||
var ret = new RetResult();
|
var ret = new RetResult();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
if (context.IsTunEnabled && context.TunProtectSsPort > 0 && context.ProxyRelaySsPort > 0)
|
||||||
|
{
|
||||||
|
return GenerateClientProxyRelayConfig();
|
||||||
|
}
|
||||||
if (_node == null
|
if (_node == null
|
||||||
|| !_node.IsValid())
|
|| !_node.IsValid())
|
||||||
{
|
{
|
||||||
|
|
@ -262,5 +266,106 @@ public partial class CoreConfigV2rayService(CoreConfigContext context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public RetResult GenerateClientProxyRelayConfig()
|
||||||
|
{
|
||||||
|
var ret = new RetResult();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (_node == null
|
||||||
|
|| !_node.IsValid())
|
||||||
|
{
|
||||||
|
ret.Msg = ResUI.CheckServerSettings;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_node.GetNetwork() is nameof(ETransport.quic))
|
||||||
|
{
|
||||||
|
ret.Msg = ResUI.Incorrectconfiguration + $" - {_node.GetNetwork()}";
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = EmbedUtils.GetEmbedText(Global.V2raySampleClient);
|
||||||
|
if (result.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
ret.Msg = ResUI.FailedGetDefaultConfiguration;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
_coreConfig = JsonUtils.Deserialize<V2rayConfig>(result);
|
||||||
|
if (_coreConfig == null)
|
||||||
|
{
|
||||||
|
ret.Msg = ResUI.FailedGenDefaultConfiguration;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
GenLog();
|
||||||
|
_coreConfig.outbounds.Clear();
|
||||||
|
GenOutbounds();
|
||||||
|
|
||||||
|
var protectNode = new ProfileItem()
|
||||||
|
{
|
||||||
|
CoreType = ECoreType.sing_box,
|
||||||
|
ConfigType = EConfigType.Shadowsocks,
|
||||||
|
Address = Global.Loopback,
|
||||||
|
Port = context.TunProtectSsPort,
|
||||||
|
Password = Global.None,
|
||||||
|
};
|
||||||
|
protectNode.SetProtocolExtra(protectNode.GetProtocolExtra() with
|
||||||
|
{
|
||||||
|
SsMethod = Global.None,
|
||||||
|
});
|
||||||
|
|
||||||
|
foreach (var outbound in _coreConfig.outbounds.Where(outbound => outbound.streamSettings?.sockopt?.dialerProxy?.IsNullOrEmpty() ?? true))
|
||||||
|
{
|
||||||
|
outbound.streamSettings ??= new StreamSettings4Ray();
|
||||||
|
outbound.streamSettings.sockopt ??= new Sockopt4Ray();
|
||||||
|
outbound.streamSettings.sockopt.dialerProxy = "tun-project-ss";
|
||||||
|
}
|
||||||
|
_coreConfig.outbounds.Add(new CoreConfigV2rayService(context with
|
||||||
|
{
|
||||||
|
Node = protectNode,
|
||||||
|
}).BuildProxyOutbound("tun-project-ss"));
|
||||||
|
|
||||||
|
var hasBalancer = _coreConfig.routing.balancers is { Count: > 0 };
|
||||||
|
_coreConfig.routing.rules =
|
||||||
|
[
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
inboundTag = new List<string> { "proxy-relay-ss" },
|
||||||
|
outboundTag = hasBalancer ? null : Global.ProxyTag,
|
||||||
|
balancerTag = hasBalancer ? Global.ProxyTag : null,
|
||||||
|
type = "field"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
_coreConfig.inbounds.Clear();
|
||||||
|
|
||||||
|
var configNode = JsonUtils.ParseJson(JsonUtils.Serialize(_coreConfig))!;
|
||||||
|
configNode["inbounds"]!.AsArray().Add(new
|
||||||
|
{
|
||||||
|
listen = Global.Loopback,
|
||||||
|
port = context.ProxyRelaySsPort,
|
||||||
|
protocol = "shadowsocks",
|
||||||
|
settings = new
|
||||||
|
{
|
||||||
|
network = "tcp,udp",
|
||||||
|
method = Global.None,
|
||||||
|
password = Global.None,
|
||||||
|
},
|
||||||
|
tag = "proxy-relay-ss",
|
||||||
|
});
|
||||||
|
|
||||||
|
ret.Msg = string.Format(ResUI.SuccessfulConfiguration, "");
|
||||||
|
ret.Success = true;
|
||||||
|
ret.Data = JsonUtils.Serialize(configNode);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logging.SaveLog(_tag, ex);
|
||||||
|
ret.Msg = ResUI.FailedGenDefaultConfiguration;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endregion public gen function
|
#endregion public gen function
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue