Files
umbrix-libcore/config/warp.go

267 lines
8.5 KiB
Go
Raw Normal View History

2024-01-25 18:37:08 +00:00
package config
import (
"encoding/base64"
2024-01-25 18:37:08 +00:00
"fmt"
2024-09-26 23:27:04 +02:00
"log/slog"
2024-01-25 18:37:08 +00:00
"net/netip"
"os"
2024-08-05 18:39:47 +02:00
"strings"
"github.com/bepass-org/warp-plus/warp"
2024-09-29 20:11:52 +02:00
"github.com/hiddify/hiddify-core/v2/common"
C "github.com/sagernet/sing-box/constant"
// "github.com/bepass-org/wireguard-go/warp"
2024-09-30 21:10:33 +02:00
"github.com/hiddify/hiddify-core/v2/db"
2024-01-25 18:37:08 +00:00
"github.com/sagernet/sing-box/option"
2024-01-25 18:37:08 +00:00
T "github.com/sagernet/sing-box/option"
)
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 WarpWireguardConfig, server string, port uint16) (*T.Outbound, error) {
clientID, _ := base64.StdEncoding.DecodeString(wgConfig.ClientID)
if len(clientID) < 2 {
clientID = []byte{0, 0, 0}
}
2024-01-25 18:37:08 +00:00
out := T.Outbound{
Type: "wireguard",
Tag: "WARP",
WireGuardOptions: T.WireGuardOutboundOptions{
ServerOptions: T.ServerOptions{
Server: server,
ServerPort: port,
},
PrivateKey: wgConfig.PrivateKey,
PeerPublicKey: wgConfig.PeerPublicKey,
Reserved: []uint8{clientID[0], clientID[1], clientID[2]},
// Reserved: []uint8{0, 0, 0},
MTU: 1330,
2024-01-25 18:37:08 +00:00
},
}
ips := []string{wgConfig.LocalAddressIPv4 + "/24", wgConfig.LocalAddressIPv6 + "/128"}
for _, addr := range ips {
if addr == "" {
continue
}
2024-01-25 18:37:08 +00:00
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
}
2024-01-26 13:29:37 +01:00
func getRandomIP() string {
ipPort, err := warp.RandomWarpEndpoint(true, true)
2024-01-26 13:29:37 +01:00
if err == nil {
return ipPort.Addr().String()
2024-01-26 13:29:37 +01:00
}
return "engage.cloudflareclient.com"
}
2024-07-18 00:55:37 +02:00
func generateWarp(license string, host string, port uint16, fakePackets string, fakePacketsSize string, fakePacketsDelay string, fakePacketsMode string) (*T.Outbound, error) {
_, _, wgConfig, err := GenerateWarpInfo(license, "", "")
2024-02-20 07:56:47 +01:00
if err != nil {
return nil, err
}
if wgConfig == nil {
return nil, fmt.Errorf("invalid warp config")
}
2024-07-18 00:55:37 +02:00
return GenerateWarpSingbox(*wgConfig, host, port, fakePackets, fakePacketsSize, fakePacketsDelay, fakePacketsMode)
2024-02-20 07:56:47 +01:00
}
2024-07-18 00:55:37 +02:00
func GenerateWarpSingbox(wgConfig WarpWireguardConfig, host string, port uint16, fakePackets string, fakePacketsSize string, fakePacketsDelay string, fakePacketMode string) (*T.Outbound, error) {
2024-02-20 09:18:53 +01:00
if host == "" {
2024-07-18 00:55:37 +02:00
host = "auto4"
2024-01-26 13:29:37 +01:00
}
2024-07-18 00:55:37 +02:00
if (host == "auto" || host == "auto4" || host == "auto6") && fakePackets == "" {
2024-07-12 21:43:17 +02:00
fakePackets = "1-3"
2024-01-26 14:01:13 +01:00
}
if fakePackets != "" && fakePacketsSize == "" {
2024-07-12 21:43:17 +02:00
fakePacketsSize = "10-30"
}
if fakePackets != "" && fakePacketsDelay == "" {
2024-07-12 21:43:17 +02:00
fakePacketsDelay = "10-30"
}
2024-02-20 07:56:47 +01:00
singboxConfig, err := wireGuardToSingbox(wgConfig, host, port)
2024-01-25 18:37:08 +00:00
if err != nil {
fmt.Printf("%v %v", singboxConfig, err)
2024-01-25 18:37:08 +00:00
return nil, err
}
2024-01-26 14:01:13 +01:00
singboxConfig.WireGuardOptions.FakePackets = fakePackets
singboxConfig.WireGuardOptions.FakePacketsSize = fakePacketsSize
singboxConfig.WireGuardOptions.FakePacketsDelay = fakePacketsDelay
2024-07-18 00:55:37 +02:00
singboxConfig.WireGuardOptions.FakePacketsMode = fakePacketMode
2024-02-02 13:47:41 +01:00
2024-01-25 18:37:08 +00:00
return singboxConfig, nil
}
func GenerateWarpInfo(license string, oldAccountId string, oldAccessToken string) (*warp.Identity, string, *WarpWireguardConfig, error) {
if oldAccountId != "" && oldAccessToken != "" {
err := warp.DeleteDevice(oldAccessToken, oldAccountId)
if err != nil {
fmt.Printf("Error in removing old device: %v\n", err)
} else {
fmt.Printf("Old Device Removed")
}
}
l := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelInfo}))
identity, err := warp.CreateIdentityOnly(l, license)
res := "Error!"
var warpcfg WarpWireguardConfig
if err == nil {
res = "Success"
res = fmt.Sprintf("Warp+ enabled: %t\n", identity.Account.WarpPlus)
res += fmt.Sprintf("\nAccount type: %s\n", identity.Account.AccountType)
warpcfg = WarpWireguardConfig{
PrivateKey: identity.PrivateKey,
2024-05-29 18:47:04 +02:00
PeerPublicKey: identity.Config.Peers[0].PublicKey,
LocalAddressIPv4: identity.Config.Interface.Addresses.V4,
LocalAddressIPv6: identity.Config.Interface.Addresses.V6,
ClientID: identity.Config.ClientID,
}
}
return &identity, res, &warpcfg, err
}
2024-09-30 21:10:33 +02:00
func getOrGenerateWarpLocallyIfNeeded(warpOptions *WarpOptions) WarpWireguardConfig {
if warpOptions.WireguardConfig.PrivateKey != "" {
return warpOptions.WireguardConfig
}
2024-09-30 21:10:33 +02:00
table := db.GetTable[WarpOptions]()
dbWarpOptions, err := table.First(func(data WarpOptions) bool { return data.UniqueId == warpOptions.UniqueId })
if err == nil && dbWarpOptions.WireguardConfig.PrivateKey != "" {
return warpOptions.WireguardConfig
}
license := ""
2024-09-30 21:10:33 +02:00
if len(warpOptions.UniqueId) > 28 && warpOptions.UniqueId[2] == '_' { // warp key is 26 characters long
license = warpOptions.UniqueId[3:]
}
accountidentity, _, wireguardConfig, err := GenerateWarpInfo(license, warpOptions.Account.AccountID, warpOptions.Account.AccessToken)
if err != nil {
return WarpWireguardConfig{}
}
2024-09-30 21:10:33 +02:00
warpOptions.Account = WarpAccount{
AccountID: accountidentity.ID,
AccessToken: accountidentity.Token,
}
2024-09-30 21:10:33 +02:00
warpOptions.WireguardConfig = *wireguardConfig
table.ReplaceOrInsert(func(data WarpOptions) bool { return data.UniqueId == warpOptions.UniqueId }, *warpOptions)
return *wireguardConfig
}
2024-09-26 23:27:04 +02:00
func patchWarp(base *option.Outbound, configOpt *HiddifyOptions, final bool, staticIpsDns map[string][]string) 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"].(uint16)
detour, _ := warp["detour"].(string)
fakePackets, _ := warp["fake_packets"].(string)
fakePacketsSize, _ := warp["fake_packets_size"].(string)
fakePacketsDelay, _ := warp["fake_packets_delay"].(string)
2024-07-18 00:55:37 +02:00
fakePacketsMode, _ := warp["fake_packets_mode"].(string)
var warpOutbound *T.Outbound
var err error
is_saved_key := len(key) > 1 && key[0] == 'p'
if (configOpt == nil || !final) && is_saved_key {
return nil
}
var wireguardConfig WarpWireguardConfig
if is_saved_key {
var warpOpt *WarpOptions
if key == "p1" {
warpOpt = &configOpt.Warp
} else if key == "p2" {
warpOpt = &configOpt.Warp2
2024-09-30 21:10:33 +02:00
} else {
warpOpt = &WarpOptions{
UniqueId: key,
}
}
2024-09-30 21:10:33 +02:00
warpOpt.UniqueId = key
wireguardConfig = getOrGenerateWarpLocallyIfNeeded(warpOpt)
} else {
_, _, wgConfig, err := GenerateWarpInfo(key, "", "")
if err != nil {
return err
}
wireguardConfig = *wgConfig
}
warpOutbound, err = GenerateWarpSingbox(wireguardConfig, host, port, fakePackets, fakePacketsSize, fakePacketsDelay, fakePacketsMode)
if err != nil {
fmt.Printf("Error generating warp config: %v", err)
return err
}
warpOutbound.WireGuardOptions.Detour = detour
base.Type = C.TypeWireGuard
base.WireGuardOptions = warpOutbound.WireGuardOptions
}
}
if final && base.Type == C.TypeWireGuard {
host := base.WireGuardOptions.Server
2024-07-18 00:55:37 +02:00
if host == "default" || host == "random" || host == "auto" || host == "auto4" || host == "auto6" || isBlockedDomain(host) {
// if base.WireGuardOptions.Detour != "" {
// base.WireGuardOptions.Server = "162.159.192.1"
// } else {
rndDomain := strings.ToLower(generateRandomString(20))
staticIpsDns[rndDomain] = []string{}
if host != "auto4" {
if host == "auto6" || common.CanConnectIPv6() {
randomIpPort, _ := warp.RandomWarpEndpoint(false, true)
2024-07-18 00:55:37 +02:00
staticIpsDns[rndDomain] = append(staticIpsDns[rndDomain], randomIpPort.Addr().String())
}
2024-05-31 21:01:33 +02:00
}
if host != "auto6" {
randomIpPort, _ := warp.RandomWarpEndpoint(true, false)
staticIpsDns[rndDomain] = append(staticIpsDns[rndDomain], randomIpPort.Addr().String())
}
base.WireGuardOptions.Server = rndDomain
// }
}
if base.WireGuardOptions.ServerPort == 0 {
port := warp.RandomWarpPort()
base.WireGuardOptions.ServerPort = port
}
if base.WireGuardOptions.Detour != "" {
if base.WireGuardOptions.MTU < 100 {
base.WireGuardOptions.MTU = 1280
}
base.WireGuardOptions.FakePackets = ""
base.WireGuardOptions.FakePacketsDelay = ""
base.WireGuardOptions.FakePacketsSize = ""
}
// if base.WireGuardOptions.Detour == "" {
// base.WireGuardOptions.GSO = runtime.GOOS != "windows"
// }
}
return nil
}