Add custom outbound support (#9817)

* Add custom outbound support

* Add test

* Add inner fmt support

* Full config to outbounds

* Rename to `Outbound`

* AI optimized

* Fix

* Add bind interface placeholder

---------

Co-authored-by: 2dust <31833384+2dust@users.noreply.github.com>
This commit is contained in:
DHR60
2026-08-05 06:25:16 +00:00
committed by GitHub
parent ccf18ba0fb
commit eff584597f
43 changed files with 1364 additions and 367 deletions
@@ -592,4 +592,43 @@ public class CoreConfigV2rayServiceTests
tunInbound!.settings.autoSystemRoutingTable.Should().Contain("10.0.0.0/32");
tunInbound!.settings.autoSystemRoutingTable.Should().Contain("10.0.0.2/31");
}
[Fact]
public void GenerateClientConfigContent_CustomOutbound_ShouldReplaceWithUserCustomOutboundJson()
{
var config = CoreConfigTestFactory.CreateConfig(ECoreType.Xray);
CoreConfigTestFactory.BindAppManagerConfig(config);
var customNode = CoreConfigTestFactory.CreateCustomOutboundNode(ECoreType.Xray, "n-custom", "custom-xray");
var customJsonContent = """
{
"protocol": "shadowsocks",
"settings": {
"servers": [
{
"address": "1.2.3.4",
"port": 8388,
"method": "aes-128-gcm",
"password": "custom_password"
}
]
}
}
""";
var context = CoreConfigTestFactory.CreateContext(config, customNode, ECoreType.Xray);
context.CustomOutboundContent[customNode.IndexId] = customJsonContent;
var result = new CoreConfigV2rayService(context).GenerateClientConfigContent();
result.Success.Should().BeTrue($"ret msg: {result.Msg}");
result.Data.Should().NotBeNull();
var cfg = JsonUtils.Deserialize<V2rayConfig>(result.Data!.ToString());
cfg.Should().NotBeNull();
var proxyOutbound = cfg!.outbounds.FirstOrDefault(o => o.tag == Global.ProxyTag);
proxyOutbound.Should().NotBeNull();
proxyOutbound!.protocol.Should().Be("shadowsocks");
proxyOutbound.settings.servers.Should().NotBeNull();
}
}