Files
umbrix-libcore/config/outbound.go

197 lines
5.3 KiB
Go
Raw Normal View History

2024-01-19 17:10:55 +03:30
package config
import (
"encoding/json"
"fmt"
"net"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/option"
)
2024-01-19 21:27:41 +03:30
type outboundMap map[string]interface{}
func patchOutboundMux(base option.Outbound, configOpt ConfigOptions, obj outboundMap) outboundMap {
if configOpt.EnableMux {
multiplex := option.OutboundMultiplexOptions{
Enabled: true,
Padding: configOpt.MuxPadding,
MaxStreams: configOpt.MaxStreams,
Protocol: configOpt.MuxProtocol,
}
obj["multiplex"] = multiplex
// } else {
// delete(obj, "multiplex")
}
return obj
}
func patchOutboundTLSTricks(base option.Outbound, configOpt ConfigOptions, obj outboundMap) outboundMap {
2024-01-29 14:21:42 +01:00
if base.Type == C.TypeSelector || base.Type == C.TypeURLTest || base.Type == C.TypeBlock || base.Type == C.TypeDNS {
return obj
}
if isOutboundReality(base) {
return obj
}
var tls *option.OutboundTLSOptions
var transport *option.V2RayTransportOptions
2024-01-26 18:33:16 +01:00
if base.VLESSOptions.OutboundTLSOptionsContainer.TLS != nil {
tls = base.VLESSOptions.OutboundTLSOptionsContainer.TLS
transport = base.VLESSOptions.Transport
2024-01-26 18:33:16 +01:00
} else if base.TrojanOptions.OutboundTLSOptionsContainer.TLS != nil {
tls = base.TrojanOptions.OutboundTLSOptionsContainer.TLS
transport = base.TrojanOptions.Transport
2024-01-26 18:33:16 +01:00
} else if base.VMessOptions.OutboundTLSOptionsContainer.TLS != nil {
tls = base.VMessOptions.OutboundTLSOptionsContainer.TLS
transport = base.VMessOptions.Transport
}
if base.Type == C.TypeDirect {
return patchOutboundFragment(base, configOpt, obj)
}
if tls == nil || !tls.Enabled || transport == nil {
return obj
}
2024-01-29 14:21:42 +01:00
if transport.Type != C.V2RayTransportTypeWebsocket && transport.Type != C.V2RayTransportTypeGRPC {
return obj
}
2024-01-29 14:21:42 +01:00
if outtls, ok := obj["tls"].(map[string]interface{}); ok {
tlsTricks := tls.TLSTricks
tlsTricks.MixedCaseSNI = tlsTricks.MixedCaseSNI || configOpt.TLSTricks.EnableMixedSNICase
if configOpt.TLSTricks.EnablePadding {
tlsTricks.PaddingMode = "random"
tlsTricks.PaddingSize = configOpt.TLSTricks.PaddingSize
2024-01-29 14:21:42 +01:00
fmt.Printf("--------------------%+v----%+v", tlsTricks.PaddingSize, configOpt)
outtls["utls"] = map[string]interface{}{
"enabled": true,
"fingerprint": "custom",
}
}
2024-01-29 14:21:42 +01:00
outtls["tls_tricks"] = tlsTricks
// if tlsTricks.MixedCaseSNI || tlsTricks.PaddingMode != "" {
// // } else {
// // tls["tls_tricks"] = nil
// }
fmt.Printf("-------%+v------------- ", tlsTricks)
}
return obj
}
func patchOutboundFragment(base option.Outbound, configOpt ConfigOptions, obj outboundMap) outboundMap {
if configOpt.EnableFragment {
obj["tls_fragment"] = option.TLSFragmentOptions{
Enabled: configOpt.TLSTricks.EnableFragment,
Size: configOpt.TLSTricks.FragmentSize,
Sleep: configOpt.TLSTricks.FragmentSleep,
}
}
return obj
}
func isOutboundReality(base option.Outbound) bool {
// this function checks reality status ONLY FOR VLESS.
// Some other protocols can also use reality, but it's discouraged as stated in the reality document
isReality := false
switch base.Type {
case C.TypeVLESS:
if base.VLESSOptions.OutboundTLSOptionsContainer.TLS == nil {
return false
}
if base.VLESSOptions.OutboundTLSOptionsContainer.TLS.Reality != nil {
isReality = base.VLESSOptions.OutboundTLSOptionsContainer.TLS.Reality.Enabled
}
}
return isReality
}
2024-01-19 17:10:55 +03:30
func patchOutbound(base option.Outbound, configOpt ConfigOptions) (*option.Outbound, string, error) {
formatErr := func(err error) error {
return fmt.Errorf("error patching outbound[%s][%s]: %w", base.Tag, base.Type, err)
}
2024-01-25 23:09:24 +01:00
err := patchWarp(&base)
if err != nil {
return nil, "", formatErr(err)
}
var outbound option.Outbound
2024-01-19 17:10:55 +03:30
jsonData, err := base.MarshalJSON()
if err != nil {
return nil, "", formatErr(err)
}
2024-01-19 21:27:41 +03:30
var obj outboundMap
2024-01-19 17:10:55 +03:30
err = json.Unmarshal(jsonData, &obj)
if err != nil {
return nil, "", formatErr(err)
}
2024-01-25 23:09:24 +01:00
var serverDomain string
2024-01-19 17:10:55 +03:30
if server, ok := obj["server"].(string); ok {
if server != "" && net.ParseIP(server) == nil {
serverDomain = fmt.Sprintf("full:%s", server)
}
}
obj = patchOutboundTLSTricks(base, configOpt, obj)
2024-01-19 21:27:41 +03:30
switch base.Type {
case C.TypeVMess, C.TypeVLESS, C.TypeTrojan, C.TypeShadowsocks:
obj = patchOutboundMux(base, configOpt, obj)
2024-01-19 21:27:41 +03:30
}
2024-01-19 17:10:55 +03:30
modifiedJson, err := json.Marshal(obj)
if err != nil {
return nil, "", formatErr(err)
}
err = outbound.UnmarshalJSON(modifiedJson)
if err != nil {
return nil, "", formatErr(err)
}
return &outbound, serverDomain, nil
}
2024-01-19 21:27:41 +03:30
2024-01-25 23:09:24 +01:00
func patchWarp(base *option.Outbound) error {
2024-01-25 18:37:08 +00:00
if base.Type == C.TypeCustom {
if warp, ok := base.CustomOptions["warp"].(map[string]interface{}); ok {
key, _ := warp["key"].(string)
host, _ := warp["host"].(string)
port, _ := warp["port"].(float64)
2024-01-26 18:33:16 +01:00
detour, _ := warp["detour"].(string)
2024-01-25 18:37:08 +00:00
fakePackets, _ := warp["fake_packets"].(string)
2024-01-26 14:01:13 +01:00
warpConfig, err := generateWarp(key, host, uint16(port), fakePackets)
2024-01-25 18:37:08 +00:00
if err != nil {
2024-01-25 23:09:24 +01:00
fmt.Printf("Error generating warp config: %v", err)
2024-01-25 18:37:08 +00:00
return err
}
base.Type = C.TypeWireGuard
2024-01-26 18:33:16 +01:00
warpConfig.WireGuardOptions.Detour = detour
2024-01-25 18:37:08 +00:00
base.WireGuardOptions = warpConfig.WireGuardOptions
}
}
return nil
}
2024-01-19 21:27:41 +03:30
// func (o outboundMap) transportType() string {
// if transport, ok := o["transport"].(map[string]interface{}); ok {
// if transportType, ok := transport["type"].(string); ok {
// return transportType
// }
// }
// return ""
// }