diff --git a/config/config.go b/config/config.go index 8a1cd40..cbadebf 100644 --- a/config/config.go +++ b/config/config.go @@ -346,6 +346,8 @@ func BuildConfig(configOpt ConfigOptions, input option.Options) (*option.Options continue case C.TypeSelector, C.TypeURLTest: continue + case C.TypeCustom: + continue default: tags = append(tags, out.Tag) outbounds = append(outbounds, out) diff --git a/config/outbound.go b/config/outbound.go index 73bbb8c..2e52cf5 100644 --- a/config/outbound.go +++ b/config/outbound.go @@ -134,10 +134,36 @@ func patchOutbound(base option.Outbound, configOpt ConfigOptions) (*option.Outbo if err != nil { return nil, "", formatErr(err) } + err = patchWarp(outbound) + if err != nil { + return nil, "", formatErr(err) + } return &outbound, serverDomain, nil } +func patchWarp(base option.Outbound) error { + 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) + fakePackets, _ := warp["fake_packets"].(string) + warpConfig, err := generateWarp(key, host, uint16(port)) + if err != nil { + return err + } + + base.Type = C.TypeWireGuard + base.WireGuardOptions = warpConfig.WireGuardOptions + base.WireGuardOptions.FakePackets = fakePackets + + } + + } + return nil +} + // func (o outboundMap) transportType() string { // if transport, ok := o["transport"].(map[string]interface{}); ok { // if transportType, ok := transport["type"].(string); ok { diff --git a/config/warp.go b/config/warp.go new file mode 100644 index 0000000..3334654 --- /dev/null +++ b/config/warp.go @@ -0,0 +1,158 @@ +package config + +import ( + "bufio" + "encoding/json" + "fmt" + "net/netip" + "os" + "strings" + + T "github.com/sagernet/sing-box/option" + "github.com/uoosef/wireguard-go/warp" +) + +type WireGuardConfig struct { + Interface InterfaceConfig `json:"Interface"` + Peer PeerConfig `json:"Peer"` +} + +type InterfaceConfig struct { + PrivateKey string `json:"PrivateKey"` + DNS string `json:"DNS"` + Address []string `json:"Address"` +} + +type PeerConfig struct { + PublicKey string `json:"PublicKey"` + AllowedIPs []string `json:"AllowedIPs"` + Endpoint string `json:"Endpoint"` +} + +type SingboxConfig struct { + Type string `json:"type"` + Tag string `json:"tag"` + Server string `json:"server"` + ServerPort int `json:"server_port"` + LocalAddress []string `json:"local_address"` + PrivateKey string `json:"private_key"` + PeerPublicKey string `json:"peer_public_key"` + Reserved []int `json:"reserved"` + MTU int `json:"mtu"` +} + +func wireGuardToSingbox(wgConfig WireGuardConfig, server string, port uint16) (*T.Outbound, error) { + // splt := strings.Split(wgConfig.Peer.Endpoint, ":") + // port, err := strconv.Atoi(splt[1]) + // if err != nil { + // fmt.Printf("%v", err) + // return nil + // } + out := T.Outbound{ + Type: "wireguard", + Tag: "WARP", + WireGuardOptions: T.WireGuardOutboundOptions{ + ServerOptions: T.ServerOptions{ + Server: server, + ServerPort: port, + }, + + PrivateKey: wgConfig.Interface.PrivateKey, + PeerPublicKey: wgConfig.Peer.PublicKey, + Reserved: []uint8{0, 0, 0}, + MTU: 1280, + }, + } + + for _, addr := range wgConfig.Interface.Address { + prefix, err := netip.ParsePrefix(addr) + if err != nil { + return nil, err // Handle the error appropriately + } + out.WireGuardOptions.LocalAddress = append(out.WireGuardOptions.LocalAddress, prefix) + + } + + return &out, nil +} +func readWireGuardConfig(filePath string) (WireGuardConfig, error) { + file, err := os.Open(filePath) + if err != nil { + return WireGuardConfig{}, err + } + defer file.Close() + + scanner := bufio.NewScanner(file) + + var wgConfig WireGuardConfig + var currentSection string + + for scanner.Scan() { + line := scanner.Text() + + if strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]") { + currentSection = strings.TrimSpace(line[1 : len(line)-1]) + continue + } + + if currentSection == "Interface" { + parseInterfaceConfig(&wgConfig.Interface, line) + } else if currentSection == "Peer" { + parsePeerConfig(&wgConfig.Peer, line) + } + } + + return wgConfig, nil +} + +func parseInterfaceConfig(interfaceConfig *InterfaceConfig, line string) { + if strings.HasPrefix(line, "PrivateKey") { + interfaceConfig.PrivateKey = strings.TrimSpace(strings.SplitN(line, "=", 2)[1]) + } else if strings.HasPrefix(line, "DNS") { + interfaceConfig.DNS = strings.TrimSpace(strings.SplitN(line, "=", 2)[1]) + } else if strings.HasPrefix(line, "Address") { + interfaceConfig.Address = append(interfaceConfig.Address, strings.TrimSpace(strings.SplitN(line, "=", 2)[1])) + } +} + +func parsePeerConfig(peerConfig *PeerConfig, line string) { + if strings.HasPrefix(line, "PublicKey") { + peerConfig.PublicKey = strings.TrimSpace(strings.SplitN(line, "=", 2)[1]) + } else if strings.HasPrefix(line, "AllowedIPs") { + peerConfig.AllowedIPs = append(peerConfig.AllowedIPs, strings.TrimSpace(strings.SplitN(line, "=", 2)[1])) + } else if strings.HasPrefix(line, "Endpoint") { + peerConfig.Endpoint = strings.TrimSpace(strings.SplitN(line, "=", 2)[1]) + } +} +func generateWarp(license string, host string, port uint16) (*T.Outbound, error) { + if host == "" { + host = "engage.cloudflareclient.com" + } + if port == 0 { + port = 2408 + } + endpoint := fmt.Sprint("%s:%p", host, port) + + if !warp.CheckProfileExists(license) { + fmt.Printf("profile s not exit! ---%s---", license) + err := warp.LoadOrCreateIdentity(license, endpoint) + if err != nil { + return nil, err + } + } + + wgConfig, err := readWireGuardConfig("wgcf-profile.ini") + if err != nil { + fmt.Println("Error reading WireGuard configuration:", err) + return nil, err + } + // fmt.Printf("%v", wgConfig) + singboxConfig, err := wireGuardToSingbox(wgConfig, host, port) + singboxJSON, err := json.MarshalIndent(singboxConfig, "", " ") + if err != nil { + fmt.Println("Error marshaling Singbox configuration:", err) + return nil, err + } + fmt.Println(string(singboxJSON)) + return singboxConfig, nil +} diff --git a/go.mod b/go.mod index 1f163e2..47f1c61 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/hiddify/libcore go 1.21.5 require ( - github.com/hiddify/ray2sing v0.0.0-20240121100507-259925872efd + github.com/hiddify/ray2sing v0.0.0-20240125183524-4c65b1065c27 github.com/sagernet/gomobile v0.1.1 github.com/sagernet/sing v0.3.0 github.com/sagernet/sing-box v1.8.2 @@ -102,4 +102,6 @@ require ( lukechampine.com/blake3 v1.2.1 // indirect ) -replace github.com/sagernet/sing-box => github.com/hiddify/hiddify-sing-box v1.7.9-0.20240123220037-92acce523aa6 +replace github.com/sagernet/sing-box => github.com/hiddify/hiddify-sing-box v1.7.9-0.20240125155948-df6318730338 + +replace github.com/uoosef/wireguard-go => github.com/hiddify-com/wireguard-go v0.0.2-alpha.0.20240125181314-631084b0cc77 diff --git a/go.sum b/go.sum index b6d3e26..b040840 100644 --- a/go.sum +++ b/go.sum @@ -49,10 +49,12 @@ github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a h1:fEBsGL/sjAuJrgah5X github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= -github.com/hiddify/hiddify-sing-box v1.7.9-0.20240123220037-92acce523aa6 h1:2WTZz+09BLS0jhMrr11UrmsGKf7rANd1t8bzGziZ9a4= -github.com/hiddify/hiddify-sing-box v1.7.9-0.20240123220037-92acce523aa6/go.mod h1:OPT7VAz77rWOHNOwQ9xgXo2TW4orQGunODQxIcHiX+E= -github.com/hiddify/ray2sing v0.0.0-20240121100507-259925872efd h1:UkGX1fEji0A7qAuTZECUe/QIBZKkeWBYGCWjFGQVPvg= -github.com/hiddify/ray2sing v0.0.0-20240121100507-259925872efd/go.mod h1:Hu3sHxOP4odkokDUqzJUL24uml5/I8ddTRERIMrio34= +github.com/hiddify-com/wireguard-go v0.0.2-alpha.0.20240125181314-631084b0cc77 h1:o/Z0hFHJpZG6gya150FOVoolf1QbJBqjIdhMTYtdw+A= +github.com/hiddify-com/wireguard-go v0.0.2-alpha.0.20240125181314-631084b0cc77/go.mod h1:uEnuKQ/PHpFdYwftT4bzwI8F3d2l9zsWZ9iDbLBIm0c= +github.com/hiddify/hiddify-sing-box v1.7.9-0.20240125155948-df6318730338 h1:8Sqfq36q1f9La853T/6VnY7IgCvfPL0uhkguyrTl3t8= +github.com/hiddify/hiddify-sing-box v1.7.9-0.20240125155948-df6318730338/go.mod h1:DnlHl/vlinL9Mn95+qJ3RzgE3E/9pWlAvTsauo7F5HM= +github.com/hiddify/ray2sing v0.0.0-20240125183524-4c65b1065c27 h1:toSrcgHiLimlQqWaMqN334H8cm7udEsrkwLktko9T58= +github.com/hiddify/ray2sing v0.0.0-20240125183524-4c65b1065c27/go.mod h1:zYKnf7EoPqrk7JOMO9BApTXxfH0sva8AKfoFywN7uuA= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2 h1:9K06NfxkBh25x56yVhWWlKFE8YpicaSfHwoV8SFbueA= @@ -181,8 +183,6 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 h1:tHNk7XK9GkmKUR6Gh8gVBKXc2MVSZ4G/NnWLtzw4gNA= github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923/go.mod h1:eLL9Nub3yfAho7qB0MzZizFhTU2QkLeoVsWdHtDW264= -github.com/uoosef/wireguard-go v0.0.2-alpha h1:fJw/0+MYfuj2IyfyzuCXXJqs186K+gSPiUDWIf0vHKs= -github.com/uoosef/wireguard-go v0.0.2-alpha/go.mod h1:uEnuKQ/PHpFdYwftT4bzwI8F3d2l9zsWZ9iDbLBIm0c= github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg= github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= github.com/xmdhs/clash2singbox v0.0.2 h1:/gxaFm8fmv+UcUZzK508Z0yR01wg1LHrrq872Qibk1I=