Files
netch/Netch/Servers/V2ray/V2rayConfigUtils.cs
Hellojack 77e1d5a80c [Netch] Add SSH protocol support (#875)
* [Netch] Optimize code

* [Netch] Add SSH protocol support
2022-07-12 01:47:23 +08:00

437 lines
15 KiB
C#

using Netch.Models;
using Netch.Utils;
#pragma warning disable VSTHRD200
namespace Netch.Servers;
public static class V2rayConfigUtils
{
public static async Task<V2rayConfig> GenerateClientConfigAsync(Server server)
{
var v2rayConfig = new V2rayConfig
{
inbounds = new object[]
{
new
{
port = Global.Settings.Socks5LocalPort,
protocol = "socks",
listen = Global.Settings.LocalAddress,
settings = new
{
auth = "noauth",
udp = true
}
}
}
};
v2rayConfig.outbounds = new[] { await outbound(server) };
return v2rayConfig;
}
private static async Task<Outbound> outbound(Server server)
{
var outbound = new Outbound
{
settings = new OutboundConfiguration(),
mux = new Mux()
};
switch (server)
{
case Socks5Server socks:
{
outbound.protocol = "socks";
outbound.settings.servers = new object[]
{
new
{
address = await server.AutoResolveHostnameAsync(),
port = server.Port,
users = socks.Auth()
? new[]
{
new
{
user = socks.Username,
pass = socks.Password,
level = 1
}
}
: null
}
};
outbound.settings.version = socks.Version;
outbound.mux.enabled = false;
outbound.mux.concurrency = -1;
break;
}
case VLESSServer vless:
{
outbound.protocol = "vless";
outbound.settings.vnext = new[]
{
new VnextItem
{
address = await server.AutoResolveHostnameAsync(),
port = server.Port,
users = new[]
{
new User
{
id = getUUID(vless.UserID),
flow = vless.TLSSecureType == "xtls" ? "xtls-rprx-direct" : "",
encryption = vless.EncryptMethod
}
}
}
};
outbound.settings.packetEncoding = Global.Settings.V2RayConfig.XrayCone ? vless.PacketEncoding : "none";
outbound.mux.packetEncoding = Global.Settings.V2RayConfig.XrayCone ? vless.PacketEncoding : "none";
outbound.streamSettings = boundStreamSettings(vless);
if (vless.TLSSecureType == "xtls")
{
outbound.mux.enabled = false;
outbound.mux.concurrency = -1;
}
else
{
outbound.mux.enabled = vless.UseMux ?? Global.Settings.V2RayConfig.UseMux;
outbound.mux.concurrency = vless.UseMux ?? Global.Settings.V2RayConfig.UseMux ? 8 : -1;
}
break;
}
case VMessServer vmess:
{
outbound.protocol = "vmess";
if (vmess.EncryptMethod == "auto" && vmess.TLSSecureType != "none" && !Global.Settings.V2RayConfig.AllowInsecure)
{
vmess.EncryptMethod = "zero";
}
outbound.settings.vnext = new[]
{
new VnextItem
{
address = await server.AutoResolveHostnameAsync(),
port = server.Port,
users = new[]
{
new User
{
id = getUUID(vmess.UserID),
alterId = vmess.AlterID,
security = vmess.EncryptMethod
}
}
}
};
outbound.settings.packetEncoding = Global.Settings.V2RayConfig.XrayCone ? vmess.PacketEncoding : "none";
outbound.mux.packetEncoding = Global.Settings.V2RayConfig.XrayCone ? vmess.PacketEncoding : "none";
outbound.streamSettings = boundStreamSettings(vmess);
outbound.mux.enabled = vmess.UseMux ?? Global.Settings.V2RayConfig.UseMux;
outbound.mux.concurrency = vmess.UseMux ?? Global.Settings.V2RayConfig.UseMux ? 8 : -1;
break;
}
case ShadowsocksServer ss:
outbound.protocol = "shadowsocks";
outbound.settings.servers = new[]
{
new ShadowsocksServerItem
{
address = await server.AutoResolveHostnameAsync(),
port = server.Port,
method = ss.EncryptMethod,
password = ss.Password
}
};
outbound.settings.plugin = ss.Plugin ?? "";
outbound.settings.pluginOpts = ss.PluginOption ?? "";
if (Global.Settings.V2RayConfig.TCPFastOpen)
{
outbound.streamSettings = new StreamSettings
{
sockopt = new Sockopt
{
tcpFastOpen = true
}
};
}
break;
case ShadowsocksRServer ssr:
outbound.protocol = "shadowsocks";
outbound.settings.servers = new[]
{
new ShadowsocksServerItem
{
address = await server.AutoResolveHostnameAsync(),
port = server.Port,
method = ssr.EncryptMethod,
password = ssr.Password,
}
};
outbound.settings.plugin = "shadowsocksr";
outbound.settings.pluginArgs = new string[]
{
"--obfs=" + ssr.OBFS,
"--obfs-param=" + ssr.OBFSParam ?? "",
"--protocol=" + ssr.Protocol,
"--protocol-param=" + ssr.ProtocolParam ?? ""
};
if (Global.Settings.V2RayConfig.TCPFastOpen)
{
outbound.streamSettings = new StreamSettings
{
sockopt = new Sockopt
{
tcpFastOpen = true
}
};
}
break;
case TrojanServer trojan:
outbound.protocol = "trojan";
outbound.settings.servers = new[]
{
new ShadowsocksServerItem // I'm not serious
{
address = await server.AutoResolveHostnameAsync(),
port = server.Port,
method = "",
password = trojan.Password,
flow = trojan.TLSSecureType == "xtls" ? "xtls-rprx-direct" : ""
}
};
outbound.streamSettings = new StreamSettings
{
network = "tcp",
security = trojan.TLSSecureType
};
if (trojan.TLSSecureType != "none")
{
var tlsSettings = new TlsSettings
{
allowInsecure = Global.Settings.V2RayConfig.AllowInsecure,
serverName = trojan.Host ?? ""
};
switch (trojan.TLSSecureType)
{
case "tls":
outbound.streamSettings.tlsSettings = tlsSettings;
break;
case "xtls":
outbound.streamSettings.xtlsSettings = tlsSettings;
break;
}
}
if (Global.Settings.V2RayConfig.TCPFastOpen)
{
outbound.streamSettings.sockopt = new Sockopt
{
tcpFastOpen = true
};
}
break;
case WireGuardServer wg:
outbound.protocol = "wireguard";
outbound.settings.address = await server.AutoResolveHostnameAsync();
outbound.settings.port = server.Port;
outbound.settings.localAddresses = wg.LocalAddresses.SplitOrDefault();
outbound.settings.peerPublicKey = wg.PeerPublicKey;
outbound.settings.privateKey = wg.PrivateKey;
outbound.settings.preSharedKey = wg.PreSharedKey;
outbound.settings.mtu = wg.MTU;
if (Global.Settings.V2RayConfig.TCPFastOpen)
{
outbound.streamSettings = new StreamSettings
{
sockopt = new Sockopt
{
tcpFastOpen = true
}
};
}
break;
case SSHServer ssh:
outbound.protocol = "ssh";
outbound.settings.address = await server.AutoResolveHostnameAsync();
outbound.settings.port = server.Port;
outbound.settings.user = ssh.User;
outbound.settings.password = ssh.Password;
outbound.settings.privateKey = ssh.PrivateKey;
outbound.settings.publicKey = ssh.PublicKey;
if (Global.Settings.V2RayConfig.TCPFastOpen)
{
outbound.streamSettings = new StreamSettings
{
sockopt = new Sockopt
{
tcpFastOpen = true
}
};
}
break;
}
return outbound;
}
private static StreamSettings boundStreamSettings(VMessServer server)
{
// https://xtls.github.io/config/transports
var streamSettings = new StreamSettings
{
network = server.TransferProtocol,
security = server.TLSSecureType
};
if (server.TLSSecureType != "none")
{
var tlsSettings = new TlsSettings
{
allowInsecure = Global.Settings.V2RayConfig.AllowInsecure,
serverName = server.ServerName.ValueOrDefault() ?? server.Host.SplitOrDefault()?[0]
};
switch (server.TLSSecureType)
{
case "tls":
streamSettings.tlsSettings = tlsSettings;
break;
case "xtls":
streamSettings.xtlsSettings = tlsSettings;
break;
}
}
switch (server.TransferProtocol)
{
case "tcp":
streamSettings.tcpSettings = new TcpSettings
{
header = new
{
type = server.FakeType,
request = server.FakeType switch
{
"none" => null,
"http" => new
{
path = server.Path.SplitOrDefault(),
headers = new
{
Host = server.Host.SplitOrDefault()
}
},
_ => throw new MessageException($"Invalid tcp type {server.FakeType}")
}
}
};
break;
case "ws":
streamSettings.wsSettings = new WsSettings
{
path = server.Path.ValueOrDefault(),
headers = new
{
Host = server.Host.ValueOrDefault()
}
};
break;
case "kcp":
streamSettings.kcpSettings = new KcpSettings
{
mtu = Global.Settings.V2RayConfig.KcpConfig.mtu,
tti = Global.Settings.V2RayConfig.KcpConfig.tti,
uplinkCapacity = Global.Settings.V2RayConfig.KcpConfig.uplinkCapacity,
downlinkCapacity = Global.Settings.V2RayConfig.KcpConfig.downlinkCapacity,
congestion = Global.Settings.V2RayConfig.KcpConfig.congestion,
readBufferSize = Global.Settings.V2RayConfig.KcpConfig.readBufferSize,
writeBufferSize = Global.Settings.V2RayConfig.KcpConfig.writeBufferSize,
header = new
{
type = server.FakeType
},
seed = server.Path.ValueOrDefault()
};
break;
case "h2":
streamSettings.httpSettings = new HttpSettings
{
host = server.Host.SplitOrDefault(),
path = server.Path.ValueOrDefault()
};
break;
case "quic":
streamSettings.quicSettings = new QuicSettings
{
security = server.QUICSecure,
key = server.QUICSecret,
header = new
{
type = server.FakeType
}
};
break;
case "grpc":
streamSettings.grpcSettings = new GrpcSettings
{
serviceName = server.Path,
multiMode = server.FakeType == "multi"
};
break;
default:
throw new MessageException($"transfer protocol \"{server.TransferProtocol}\" not implemented yet");
}
if (Global.Settings.V2RayConfig.TCPFastOpen)
{
streamSettings.sockopt = new Sockopt
{
tcpFastOpen = true
};
}
return streamSettings;
}
public static string getUUID(string uuid)
{
if (uuid.Length == 36 || uuid.Length == 32)
{
return uuid;
}
return uuid.GenerateUUIDv5();
}
}