mirror of
https://github.com/shtorm-7/sing-box-extended.git
synced 2026-05-14 00:51:12 +03:00
206 lines
4.8 KiB
Go
206 lines
4.8 KiB
Go
package clash
|
|
|
|
import (
|
|
"strconv"
|
|
"strings"
|
|
|
|
C "github.com/sagernet/sing-box/constant"
|
|
"github.com/sagernet/sing-box/option"
|
|
"github.com/sagernet/sing/common"
|
|
"github.com/sagernet/sing/common/byteformats"
|
|
F "github.com/sagernet/sing/common/format"
|
|
"github.com/sagernet/sing/common/json/badoption"
|
|
N "github.com/sagernet/sing/common/network"
|
|
)
|
|
|
|
func clashClientFingerprint(clientFingerprint string) *option.OutboundUTLSOptions {
|
|
if clientFingerprint == "" {
|
|
return nil
|
|
}
|
|
return &option.OutboundUTLSOptions{
|
|
Enabled: true,
|
|
Fingerprint: clientFingerprint,
|
|
}
|
|
}
|
|
|
|
func clashHeaders(headers map[string]string) map[string]badoption.Listable[string] {
|
|
if headers == nil {
|
|
return nil
|
|
}
|
|
result := make(map[string]badoption.Listable[string])
|
|
for key, value := range headers {
|
|
result[key] = []string{value}
|
|
}
|
|
return result
|
|
}
|
|
|
|
func clashHysteria2Obfs(obfs string, password string) *option.Hysteria2Obfs {
|
|
if obfs == "" {
|
|
return nil
|
|
}
|
|
return &option.Hysteria2Obfs{
|
|
Type: obfs,
|
|
Password: password,
|
|
}
|
|
}
|
|
|
|
func clashNetworks(udpEnabled bool) option.NetworkList {
|
|
if !udpEnabled {
|
|
return N.NetworkTCP
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func clashPluginName(plugin string) string {
|
|
switch plugin {
|
|
case "obfs":
|
|
return "obfs-local"
|
|
}
|
|
return plugin
|
|
}
|
|
|
|
func clashPluginOptions(plugin string, opts map[string]any) string {
|
|
options := make(shadowsocksPluginOptionsBuilder)
|
|
switch plugin {
|
|
case "obfs":
|
|
options["obfs"] = opts["mode"]
|
|
options["obfs-host"] = opts["host"]
|
|
case "v2ray-plugin":
|
|
options["mode"] = opts["mode"]
|
|
options["tls"] = opts["tls"]
|
|
options["host"] = opts["host"]
|
|
options["path"] = opts["path"]
|
|
}
|
|
return options.Build()
|
|
}
|
|
|
|
func clashPorts(ports string) badoption.Listable[string] {
|
|
if ports == "" {
|
|
return nil
|
|
}
|
|
serverPorts := badoption.Listable[string]{}
|
|
ports = strings.ReplaceAll(ports, "/", ",")
|
|
for _, port := range strings.Split(ports, ",") {
|
|
if port == "" {
|
|
continue
|
|
}
|
|
port = strings.Replace(port, "-", ":", 1)
|
|
serverPorts = append(serverPorts, port)
|
|
}
|
|
return serverPorts
|
|
}
|
|
|
|
func clashShadowsocksCipher(cipher string) string {
|
|
switch cipher {
|
|
case "dummy":
|
|
return "none"
|
|
}
|
|
return cipher
|
|
}
|
|
|
|
func clashStringList(list []string) string {
|
|
if len(list) > 0 {
|
|
return list[0]
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func clashSpeedToIntMbps(speed string) int {
|
|
if speed == "" {
|
|
return 0
|
|
}
|
|
if num, err := strconv.Atoi(speed); err == nil {
|
|
return num
|
|
}
|
|
networkBytes := byteformats.NetworkBytesCompat{}
|
|
if err := networkBytes.UnmarshalJSON([]byte(speed)); err != nil {
|
|
return 0
|
|
}
|
|
return int(networkBytes.Value() / byteformats.MByte * 8)
|
|
}
|
|
|
|
func clashSpeedToNetworkBytes(speed string) *byteformats.NetworkBytesCompat {
|
|
if speed == "" {
|
|
return nil
|
|
}
|
|
networkBytes := &byteformats.NetworkBytesCompat{}
|
|
if num, err := strconv.Atoi(speed); err == nil {
|
|
speed = F.ToString(num, "Mbps")
|
|
}
|
|
if err := networkBytes.UnmarshalJSON([]byte(speed)); err != nil {
|
|
return nil
|
|
}
|
|
return networkBytes
|
|
}
|
|
|
|
func clashTransport(network string, httpOpts HTTPOptions, h2Opts HTTP2Options, grpcOpts GrpcOptions, wsOpts WSOptions) *option.V2RayTransportOptions {
|
|
switch network {
|
|
case "http":
|
|
return &option.V2RayTransportOptions{
|
|
Type: C.V2RayTransportTypeHTTP,
|
|
HTTPOptions: option.V2RayHTTPOptions{
|
|
Method: httpOpts.Method,
|
|
Path: clashStringList(httpOpts.Path),
|
|
Headers: httpOpts.Headers,
|
|
},
|
|
}
|
|
case "h2":
|
|
return &option.V2RayTransportOptions{
|
|
Type: C.V2RayTransportTypeHTTP,
|
|
HTTPOptions: option.V2RayHTTPOptions{
|
|
Path: h2Opts.Path,
|
|
Host: h2Opts.Host,
|
|
},
|
|
}
|
|
case "grpc":
|
|
return &option.V2RayTransportOptions{
|
|
Type: C.V2RayTransportTypeGRPC,
|
|
GRPCOptions: option.V2RayGRPCOptions{
|
|
ServiceName: grpcOpts.GrpcServiceName,
|
|
},
|
|
}
|
|
case "ws":
|
|
headers := clashHeaders(wsOpts.Headers)
|
|
if wsOpts.V2rayHttpUpgrade {
|
|
var host string
|
|
if headers != nil && headers["Host"] != nil {
|
|
host = headers["Host"][0]
|
|
}
|
|
return &option.V2RayTransportOptions{
|
|
Type: C.V2RayTransportTypeHTTPUpgrade,
|
|
HTTPUpgradeOptions: option.V2RayHTTPUpgradeOptions{
|
|
Host: host,
|
|
Path: wsOpts.Path,
|
|
Headers: headers,
|
|
},
|
|
}
|
|
}
|
|
return &option.V2RayTransportOptions{
|
|
Type: C.V2RayTransportTypeWebsocket,
|
|
WebsocketOptions: option.V2RayWebsocketOptions{
|
|
Path: wsOpts.Path,
|
|
Headers: headers,
|
|
MaxEarlyData: uint32(wsOpts.MaxEarlyData),
|
|
EarlyDataHeaderName: wsOpts.EarlyDataHeaderName,
|
|
},
|
|
}
|
|
default:
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func clashTLSOptions(server string, tlsOptions *TLSOptions) option.OutboundTLSOptionsContainer {
|
|
if tlsOptions != nil && tlsOptions.SNI == "" {
|
|
tlsOptions.SNI = server
|
|
}
|
|
return option.OutboundTLSOptionsContainer{
|
|
TLS: tlsOptions.Build(),
|
|
}
|
|
}
|
|
|
|
func trimStringArray(array []string) []string {
|
|
return common.Filter(array, func(it string) bool {
|
|
return strings.TrimSpace(it) != ""
|
|
})
|
|
}
|