Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 2 additions & 8 deletions v2rayN/ServiceLib.Tests/CoreConfigV2rayServiceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,7 @@ public void GenerateClientConfigContent_DoesNotApplySendThroughToTunRelayLoopbac
var service = new CoreConfigV2rayService(CreateContext(
node,
config,
isTunEnabled: true,
tunProtectSsPort: 10811,
proxyRelaySsPort: 10812));
isTunEnabled: true));

var result = service.GenerateClientConfigContent();

Expand All @@ -91,9 +89,7 @@ private static CoreConfigContext CreateContext(
ProfileItem node,
Config? config = null,
Dictionary<string, ProfileItem>? allProxiesMap = null,
bool isTunEnabled = false,
int tunProtectSsPort = 0,
int proxyRelaySsPort = 0)
bool isTunEnabled = false)
{
return new CoreConfigContext
{
Expand All @@ -103,8 +99,6 @@ private static CoreConfigContext CreateContext(
AllProxiesMap = allProxiesMap ?? new(),
SimpleDnsItem = new SimpleDNSItem(),
IsTunEnabled = isTunEnabled,
TunProtectSocksPort = tunProtectSsPort,
ProxyRelaySocksPort = proxyRelaySsPort,
};
}

Expand Down
26 changes: 15 additions & 11 deletions v2rayN/ServiceLib/Common/WindowsUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,19 +53,23 @@ public static void RegWriteValue(string path, string name, object value)

public static async Task RemoveTunDevice()
{
try
var tunNameList = new List<string> { "singbox_tun", "xray_tun" };
foreach (var tunName in tunNameList)
{
var sum = MD5.HashData(Encoding.UTF8.GetBytes("wintunsingbox_tun"));
var guid = new Guid(sum);
var pnpUtilPath = @"C:\Windows\System32\pnputil.exe";
var arg = $$""" /remove-device "SWD\Wintun\{{{guid}}}" """;
try
{
var sum = MD5.HashData(Encoding.UTF8.GetBytes($"wintun{tunName}"));
var guid = new Guid(sum);
var pnpUtilPath = @"C:\Windows\System32\pnputil.exe";
var arg = $$""" /remove-device "SWD\Wintun\{{{guid}}}" """;

// Try to remove the device
_ = await Utils.GetCliWrapOutput(pnpUtilPath, arg);
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
// Try to remove the device
_ = await Utils.GetCliWrapOutput(pnpUtilPath, arg);
}
catch (Exception ex)
{
Logging.SaveLog(_tag, ex);
}
}
}
}
3 changes: 3 additions & 0 deletions v2rayN/ServiceLib/Global.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ public class Global
public const string V2raySampleHttpResponseFileName = NamespaceSample + "SampleHttpResponse";
public const string V2raySampleInbound = NamespaceSample + "SampleInbound";
public const string V2raySampleOutbound = NamespaceSample + "SampleOutbound";
public const string V2raySampleTunInbound = NamespaceSample + "SampleTunInbound";
public const string V2raySampleTunRules = NamespaceSample + "SampleTunRules";
public const string SingboxSampleOutbound = NamespaceSample + "SingboxSampleOutbound";
public const string CustomRoutingFileName = NamespaceSample + "custom_routing_";
public const string TunSingboxDNSFileName = NamespaceSample + "tun_singbox_dns";
Expand All @@ -48,6 +50,7 @@ public class Global
public const string ProxyTag = "proxy";
public const string DirectTag = "direct";
public const string BlockTag = "block";
public const string DnsOutboundTag = "dns";
public const string DnsTag = "dns-module";
public const string DirectDnsTag = "direct-dns";
public const string BalancerTagSuffix = "-round";
Expand Down
57 changes: 15 additions & 42 deletions v2rayN/ServiceLib/Handler/Builder/CoreConfigContextBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,6 @@ public record CoreConfigContextBuilderAllResult(
public NodeValidatorResult CombinedValidatorResult => new(
[.. MainResult.ValidatorResult.Errors, .. PreSocksResult?.ValidatorResult.Errors ?? []],
[.. MainResult.ValidatorResult.Warnings, .. PreSocksResult?.ValidatorResult.Warnings ?? []]);

/// <summary>
/// The main context with TunProtectSocksPort/ProxyRelaySocksPort and ProtectDomainList merged in
/// from the pre-socks result (if any). Pass this to the core runner.
/// </summary>
public CoreConfigContext ResolvedMainContext => PreSocksResult is not null
? MainResult.Context with
{
TunProtectSocksPort = PreSocksResult.Context.TunProtectSocksPort,
ProxyRelaySocksPort = PreSocksResult.Context.ProxyRelaySocksPort,
ProtectDomainList = [.. MainResult.Context.ProtectDomainList ?? [], .. PreSocksResult.Context.ProtectDomainList ?? []],
}
: MainResult.Context;
}

public class CoreConfigContextBuilder
Expand All @@ -58,8 +45,6 @@ public static async Task<CoreConfigContextBuilderResult> Build(Config config, Pr
IsTunEnabled = config.TunModeItem.EnableTun,
SimpleDnsItem = config.SimpleDNSItem,
ProtectDomainList = [],
TunProtectSocksPort = 0,
ProxyRelaySocksPort = 0,
RawDnsItem = await AppManager.Instance.GetDNSItem(coreType),
RoutingItem = await ConfigHandler.GetDefaultRouting(config),
};
Expand Down Expand Up @@ -122,7 +107,20 @@ public static async Task<CoreConfigContextBuilderAllResult> BuildAll(Config conf
}

var preResult = await BuildPreSocksIfNeeded(mainResult.Context);
return new CoreConfigContextBuilderAllResult(mainResult, preResult);
if (preResult is null)
{
return new CoreConfigContextBuilderAllResult(mainResult, null);
}

var resolvedMainResult = mainResult with
{
Context = mainResult.Context with
{
IsTunEnabled = false, // main core doesn't handle tun directly when pre-socks is used
ProtectDomainList = [.. mainResult.Context.ProtectDomainList, .. preResult.Context.ProtectDomainList],
}
};
return new CoreConfigContextBuilderAllResult(resolvedMainResult, preResult);
}

/// <summary>
Expand All @@ -148,32 +146,7 @@ public static async Task<CoreConfigContextBuilderAllResult> BuildAll(Config conf
};
}

if (!nodeContext.IsTunEnabled
|| coreType != ECoreType.Xray
|| node.ConfigType == EConfigType.Custom)
{
return null;
}

var tunProtectSocksPort = Utils.GetFreePort();
var proxyRelaySocksPort = Utils.GetFreePort();
var preItem = new ProfileItem()
{
CoreType = ECoreType.sing_box,
ConfigType = EConfigType.SOCKS,
Address = Global.Loopback,
Port = proxyRelaySocksPort,
};
var preResult2 = await Build(nodeContext.AppConfig, preItem);
return preResult2 with
{
Context = preResult2.Context with
{
ProtectDomainList = [.. nodeContext.ProtectDomainList ?? [], .. preResult2.Context.ProtectDomainList ?? []],
TunProtectSocksPort = tunProtectSocksPort,
ProxyRelaySocksPort = proxyRelaySocksPort,
}
};
return null;
}

/// <summary>
Expand Down
4 changes: 3 additions & 1 deletion v2rayN/ServiceLib/Handler/ConfigHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1417,10 +1417,12 @@ public static async Task<RetResult> AddGroupRegionServer(Config config, SubItem?
public static ProfileItem? GetPreSocksItem(Config config, ProfileItem node, ECoreType coreType)
{
ProfileItem? itemSocks = null;
var enableLegacyProtect = config.TunModeItem.EnableLegacyProtect
|| Utils.IsNonWindows();
if (node.ConfigType != EConfigType.Custom
&& coreType != ECoreType.sing_box
&& config.TunModeItem.EnableTun
&& config.TunModeItem.EnableLegacyProtect)
&& enableLegacyProtect)
{
itemSocks = new ProfileItem()
{
Expand Down
7 changes: 1 addition & 6 deletions v2rayN/ServiceLib/Models/CoreConfigContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,5 @@ public record CoreConfigContext

// TUN Compatibility
public bool IsTunEnabled { get; init; } = false;
public HashSet<string> ProtectDomainList { get; init; } = new();
// -> 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 TunProtectSocksPort { get; init; } = 0;
public int ProxyRelaySocksPort { get; init; } = 0;
public HashSet<string> ProtectDomainList { get; init; } = [];
}
18 changes: 16 additions & 2 deletions v2rayN/ServiceLib/Models/V2rayConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ public class Inbounds4Ray
{
public string tag { get; set; }

public int port { get; set; }
public int? port { get; set; }

public string listen { get; set; }
public string? listen { get; set; }

public string protocol { get; set; }

Expand All @@ -75,6 +75,18 @@ public class Inboundsettings4Ray
public bool? allowTransparent { get; set; }

public List<AccountsItem4Ray>? accounts { get; set; }

public string? name { get; set; }

public int? MTU { get; set; }

public List<string>? gateway { get; set; }

public List<string>? autoSystemRoutingTable { get; set; }

public string? autoOutboundsInterface { get; set; }

// public List<string>? dns { get; set; }
}

public class UsersItem4Ray
Expand Down Expand Up @@ -511,6 +523,8 @@ public class AccountsItem4Ray
public class Sockopt4Ray
{
public string? dialerProxy { get; set; }
[JsonPropertyName("interface")]
public string? Interface { get; set; }
}

public class FragmentItem4Ray
Expand Down
24 changes: 24 additions & 0 deletions v2rayN/ServiceLib/Sample/SampleTunInbound
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"tag": "tun",
"protocol": "tun",
"settings": {
"name": "xray_tun",
"MTU": 9000,
"gateway": [
"172.18.0.1/30",
"fdfe:dcba:9876::1/126"
],
"autoSystemRoutingTable": [
"0.0.0.0/0",
"::/0"
],
"autoOutboundsInterface": "auto"
},
"sniffing": {
"enabled": true,
"destOverride": [
"http",
"tls"
]
}
}
14 changes: 14 additions & 0 deletions v2rayN/ServiceLib/Sample/SampleTunRules
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[
{
"network": "udp",
"port": "135,137-139,5353",
"outboundTag": "block"
},
{
"ip": [
"224.0.0.0/3",
"ff00::/8"
],
"outboundTag": "block"
}
]
2 changes: 2 additions & 0 deletions v2rayN/ServiceLib/ServiceLib.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
<EmbeddedResource Include="Sample\SampleHttpResponse" />
<EmbeddedResource Include="Sample\SampleInbound" />
<EmbeddedResource Include="Sample\SampleOutbound" />
<EmbeddedResource Include="Sample\SampleTunInbound" />
<EmbeddedResource Include="Sample\SampleTunRules" />
<EmbeddedResource Include="Sample\SingboxSampleClientConfig" />
<EmbeddedResource Include="Sample\SingboxSampleOutbound" />
<EmbeddedResource Include="Sample\tun_singbox_dns" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,59 +63,6 @@ public RetResult GenerateClientConfigContent()
ret.Success = true;

ret.Data = ApplyFullConfigTemplate();
if (!context.AppConfig.TunModeItem.EnableLegacyProtect
&& context.TunProtectSocksPort is > 0 and <= 65535)
{
// Replace relay proxy outbound, avoid mux or other feature cause issue, and add a socks inbound for tun protect
var relayProxyIndex = _coreConfig.outbounds.FindIndex(o => o.tag == Global.ProxyTag);
_coreConfig.outbounds[relayProxyIndex] = new Outbound4Sbox()
{
type = Global.ProtocolTypes[EConfigType.SOCKS],
tag = Global.ProxyTag,
server = Global.Loopback,
server_port = context.ProxyRelaySocksPort,
};
var ssInbound = new
{
type = "socks",
tag = "tun-protect-socks",
listen = Global.Loopback,
listen_port = context.TunProtectSocksPort,
};
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;
}
catch (Exception ex)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ private void GenRouting()
strategy = directDnsStrategy
};

if (_config.TunModeItem.EnableTun)
if (context.IsTunEnabled)
{
_coreConfig.route.auto_detect_interface = true;

Expand Down
Loading