├── .gitignore ├── utils.go ├── log.go ├── cmd └── build │ ├── osversion.go │ ├── osversion_windows.go │ └── arch.go ├── LICENSE ├── go.mod ├── log_android.go ├── README.md ├── utils_android.go ├── args.go ├── main.go └── go.sum /.gitignore: -------------------------------------------------------------------------------- 1 | xray-plugin* 2 | /bin/ 3 | /.idea/ 4 | -------------------------------------------------------------------------------- /utils.go: -------------------------------------------------------------------------------- 1 | // +build !android 2 | 3 | package main 4 | 5 | func registerControlFunc() { 6 | } 7 | -------------------------------------------------------------------------------- /log.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build !android 6 | 7 | package main 8 | 9 | import "log" 10 | 11 | func logInit() { 12 | } 13 | 14 | func logFatal(v ...interface{}) { 15 | log.Println(v...) 16 | } 17 | 18 | func logWarn(v ...interface{}) { 19 | log.Println(v...) 20 | } 21 | 22 | func logInfo(v ...interface{}) { 23 | log.Println(v...) 24 | } 25 | -------------------------------------------------------------------------------- /cmd/build/osversion.go: -------------------------------------------------------------------------------- 1 | //go:build !windows 2 | 3 | package build 4 | 5 | import ( 6 | "strings" 7 | 8 | "github.com/shirou/gopsutil/v4/host" 9 | ) 10 | 11 | // GetOSVersion returns OS version, kernel and bitness 12 | func GetOSVersion() (osVersion, osKernel string) { 13 | if platform, _, version, err := host.PlatformInformation(); err == nil && platform != "" { 14 | osVersion = platform 15 | if version != "" { 16 | osVersion += " " + version 17 | } 18 | } 19 | 20 | if version, err := host.KernelVersion(); err == nil && version != "" { 21 | osKernel = version 22 | } 23 | 24 | if arch, err := host.KernelArch(); err == nil && arch != "" { 25 | if strings.HasSuffix(arch, "64") && osVersion != "" { 26 | osVersion += " (64 bit)" 27 | } 28 | if osKernel != "" { 29 | osKernel += " (" + arch + ")" 30 | } 31 | } 32 | 33 | return 34 | } 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 by Max Lv 4 | Copyright (C) 2019 by Mygod Studio 5 | Copyright (c) 2021 by Teddysun 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/teddysun/xray-plugin 2 | 3 | go 1.25 4 | 5 | require ( 6 | github.com/shirou/gopsutil/v4 v4.25.9 7 | github.com/xtls/xray-core v1.8.24 8 | golang.org/x/sys v0.35.0 9 | google.golang.org/protobuf v1.34.2 10 | ) 11 | 12 | require ( 13 | github.com/andybalholm/brotli v1.1.0 // indirect 14 | github.com/cloudflare/circl v1.4.0 // indirect 15 | github.com/ebitengine/purego v0.9.0 // indirect 16 | github.com/francoispqt/gojay v1.2.13 // indirect 17 | github.com/go-ole/go-ole v1.2.6 // indirect 18 | github.com/go-task/slim-sprig/v3 v3.0.0 // indirect 19 | github.com/google/pprof v0.0.0-20240528025155-186aa0362fba // indirect 20 | github.com/gorilla/websocket v1.5.3 // indirect 21 | github.com/klauspost/compress v1.17.8 // indirect 22 | github.com/klauspost/cpuid/v2 v2.2.7 // indirect 23 | github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect 24 | github.com/onsi/ginkgo/v2 v2.19.0 // indirect 25 | github.com/pires/go-proxyproto v0.7.0 // indirect 26 | github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect 27 | github.com/quic-go/quic-go v0.46.0 // indirect 28 | github.com/refraction-networking/utls v1.6.7 // indirect 29 | github.com/sagernet/sing v0.4.1 // indirect 30 | github.com/tklauser/go-sysconf v0.3.15 // indirect 31 | github.com/tklauser/numcpus v0.10.0 // indirect 32 | github.com/xtls/reality v0.0.0-20240712055506-48f0b2d5ed6d // indirect 33 | github.com/yusufpapurcu/wmi v1.2.4 // indirect 34 | go.uber.org/mock v0.4.0 // indirect 35 | golang.org/x/crypto v0.26.0 // indirect 36 | golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc // indirect 37 | golang.org/x/mod v0.18.0 // indirect 38 | golang.org/x/net v0.28.0 // indirect 39 | golang.org/x/text v0.17.0 // indirect 40 | golang.org/x/tools v0.22.0 // indirect 41 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 // indirect 42 | google.golang.org/grpc v1.66.0 // indirect 43 | lukechampine.com/blake3 v1.3.0 // indirect 44 | ) 45 | -------------------------------------------------------------------------------- /log_android.go: -------------------------------------------------------------------------------- 1 | // +build android 2 | 3 | package main 4 | 5 | /* 6 | #cgo LDFLAGS: -landroid -llog 7 | 8 | #include 9 | #include 10 | #include 11 | */ 12 | import "C" 13 | 14 | import ( 15 | "fmt" 16 | "unsafe" 17 | 18 | alog "github.com/xtls/xray-core/app/log" 19 | 20 | "github.com/xtls/xray-core/common" 21 | "github.com/xtls/xray-core/common/log" 22 | "github.com/xtls/xray-core/common/serial" 23 | ) 24 | 25 | var ( 26 | ctag = C.CString("xray") 27 | ) 28 | 29 | type androidLogger struct{} 30 | 31 | func (l *androidLogger) Handle(msg log.Message) { 32 | var priority = C.ANDROID_LOG_FATAL // this value should never be used in client mode 33 | var message string 34 | switch msg := msg.(type) { 35 | case *log.GeneralMessage: 36 | switch msg.Severity { 37 | case log.Severity_Error: 38 | priority = C.ANDROID_LOG_ERROR 39 | case log.Severity_Warning: 40 | priority = C.ANDROID_LOG_WARN 41 | case log.Severity_Info: 42 | priority = C.ANDROID_LOG_INFO 43 | case log.Severity_Debug: 44 | priority = C.ANDROID_LOG_DEBUG 45 | } 46 | message = serial.ToString(msg.Content) 47 | default: 48 | message = msg.String() 49 | } 50 | cstr := C.CString(message) 51 | defer C.free(unsafe.Pointer(cstr)) 52 | C.__android_log_write(C.int(priority), ctag, cstr) 53 | } 54 | 55 | func logInit() { 56 | common.Must(alog.RegisterHandlerCreator(alog.LogType_Console, func(_ alog.LogType, _ alog.HandlerCreatorOptions) (log.Handler, error) { 57 | return &androidLogger{}, nil 58 | })) 59 | } 60 | 61 | func logFatal(v ...interface{}) { 62 | cstr := C.CString(fmt.Sprintln(v...)) 63 | defer C.free(unsafe.Pointer(cstr)) 64 | C.__android_log_write(C.ANDROID_LOG_FATAL, ctag, cstr) 65 | } 66 | 67 | func logWarn(v ...interface{}) { 68 | (&androidLogger{}).Handle(&log.GeneralMessage{Severity: log.Severity_Warning, Content: fmt.Sprintln(v...)}) 69 | } 70 | 71 | func logInfo(v ...interface{}) { 72 | (&androidLogger{}).Handle(&log.GeneralMessage{Severity: log.Severity_Info, Content: fmt.Sprintln(v...)}) 73 | } 74 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Yet another SIP003 plugin for shadowsocks, based on [Xray-core](https://github.com/xtls/xray-core) 2 | 3 | ## Build 4 | 5 | * `go build` 6 | 7 | ## Usage 8 | 9 | See command line args for advanced usages. 10 | 11 | ### Shadowsocks over websocket (HTTP) 12 | 13 | On your server 14 | 15 | ```sh 16 | ss-server -c config.json -p 80 --plugin xray-plugin --plugin-opts "server" 17 | ``` 18 | 19 | On your client 20 | 21 | ```sh 22 | ss-local -c config.json -p 80 --plugin xray-plugin 23 | ``` 24 | 25 | ### Shadowsocks over websocket with TLS (HTTPS) 26 | 27 | On your server 28 | 29 | ```sh 30 | ss-server -c config.json -p 443 --plugin xray-plugin --plugin-opts "server;tls;host=mydomain.com" 31 | ``` 32 | 33 | On your client 34 | 35 | ```sh 36 | ss-local -c config.json -p 443 --plugin xray-plugin --plugin-opts "tls;host=mydomain.com" 37 | ``` 38 | 39 | ### Shadowsocks over QUIC 40 | 41 | On your server 42 | 43 | ```sh 44 | ss-server -c config.json -p 443 --plugin xray-plugin --plugin-opts "server;mode=quic;host=mydomain.com" 45 | ``` 46 | 47 | On your client 48 | 49 | ```sh 50 | ss-local -c config.json -p 443 --plugin xray-plugin --plugin-opts "mode=quic;host=mydomain.com" 51 | ``` 52 | 53 | ### Shadowsocks over gRPC 54 | 55 | On your server 56 | 57 | ```sh 58 | ss-server -c config.json -p 443 --plugin xray-plugin --plugin-opts "server;mode=grpc" 59 | ``` 60 | 61 | On your client 62 | 63 | ```sh 64 | ss-local -c config.json -p 443 --plugin xray-plugin --plugin-opts "mode=grpc" 65 | ``` 66 | 67 | ### Shadowsocks over gRPC with TLS 68 | 69 | On your server 70 | 71 | ```sh 72 | ss-server -c config.json -p 443 --plugin xray-plugin --plugin-opts "server;mode=grpc;tls;host=mydomain.com" 73 | ``` 74 | 75 | On your client 76 | 77 | ```sh 78 | ss-local -c config.json -p 443 --plugin xray-plugin --plugin-opts "tls;mode=grpc;host=mydomain.com" 79 | ``` 80 | 81 | ### Issue a cert for TLS and QUIC 82 | 83 | `xray-plugin` will look for TLS certificates signed by [acme.sh](https://github.com/acmesh-official/acme.sh) by default. 84 | Here's some sample commands for issuing a certificate using CloudFlare. 85 | You can find commands for issuing certificates for other DNS providers at acme.sh. 86 | 87 | ```sh 88 | wget -O- https://get.acme.sh | sh 89 | ~/.acme.sh/acme.sh --issue --dns dns_cf -d mydomain.com 90 | ``` 91 | 92 | Alternatively, you can specify path to your certificates using option `cert` and `key`. 93 | 94 | ### Use `certRaw` to pass certificate 95 | 96 | Instead of using `cert` to pass the certificate file, `certRaw` could be used to pass in PEM format certificate, that is the content between `-----BEGIN CERTIFICATE-----` and `-----END CERTIFICATE-----` without the line breaks. 97 | -------------------------------------------------------------------------------- /utils_android.go: -------------------------------------------------------------------------------- 1 | // +build android 2 | 3 | package main 4 | 5 | /* 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #define ANCIL_FD_BUFFER(n) \ 16 | struct { \ 17 | struct cmsghdr h; \ 18 | int fd[n]; \ 19 | } 20 | 21 | int 22 | ancil_send_fds_with_buffer(int sock, const int *fds, unsigned n_fds, void *buffer) 23 | { 24 | struct msghdr msghdr; 25 | char nothing = '!'; 26 | struct iovec nothing_ptr; 27 | struct cmsghdr *cmsg; 28 | int i; 29 | 30 | nothing_ptr.iov_base = ¬hing; 31 | nothing_ptr.iov_len = 1; 32 | msghdr.msg_name = NULL; 33 | msghdr.msg_namelen = 0; 34 | msghdr.msg_iov = ¬hing_ptr; 35 | msghdr.msg_iovlen = 1; 36 | msghdr.msg_flags = 0; 37 | msghdr.msg_control = buffer; 38 | msghdr.msg_controllen = sizeof(struct cmsghdr) + sizeof(int) * n_fds; 39 | cmsg = CMSG_FIRSTHDR(&msghdr); 40 | cmsg->cmsg_len = msghdr.msg_controllen; 41 | cmsg->cmsg_level = SOL_SOCKET; 42 | cmsg->cmsg_type = SCM_RIGHTS; 43 | for(i = 0; i < n_fds; i++) 44 | ((int *)CMSG_DATA(cmsg))[i] = fds[i]; 45 | return(sendmsg(sock, &msghdr, 0) >= 0 ? 0 : -1); 46 | } 47 | 48 | int 49 | ancil_send_fd(int sock, int fd) 50 | { 51 | ANCIL_FD_BUFFER(1) buffer; 52 | 53 | return(ancil_send_fds_with_buffer(sock, &fd, 1, &buffer)); 54 | } 55 | 56 | void 57 | set_timeout(int sock) 58 | { 59 | struct timeval tv; 60 | tv.tv_sec = 3; 61 | tv.tv_usec = 0; 62 | setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval)); 63 | setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(struct timeval)); 64 | } 65 | 66 | */ 67 | import "C" 68 | 69 | import ( 70 | "log" 71 | "syscall" 72 | 73 | vinternet "github.com/xtls/xray-core/transport/internet" 74 | ) 75 | 76 | func ControlOnConnSetup(network string, address string, conn syscall.RawConn) error { 77 | return conn.Control(func(s uintptr) { 78 | fd := int(s) 79 | path := "protect_path" 80 | 81 | socket, err := syscall.Socket(syscall.AF_UNIX, syscall.SOCK_STREAM, 0) 82 | if err != nil { 83 | log.Println(err) 84 | } 85 | 86 | defer syscall.Close(socket) 87 | 88 | C.set_timeout(C.int(socket)) 89 | 90 | err = syscall.Connect(socket, &syscall.SockaddrUnix{Name: path}) 91 | if err != nil { 92 | log.Println(err) 93 | } 94 | 95 | C.ancil_send_fd(C.int(socket), C.int(fd)) 96 | 97 | dummy := []byte{1} 98 | n, err := syscall.Read(socket, dummy) 99 | if err != nil { 100 | log.Println(err) 101 | } 102 | if n != 1 { 103 | log.Println("Failed to protect fd: ", fd) 104 | } 105 | }) 106 | } 107 | 108 | func registerControlFunc() { 109 | vinternet.RegisterDialerController(ControlOnConnSetup) 110 | vinternet.RegisterListenerController(ControlOnConnSetup) 111 | } 112 | -------------------------------------------------------------------------------- /cmd/build/osversion_windows.go: -------------------------------------------------------------------------------- 1 | package build 2 | 3 | import ( 4 | "regexp" 5 | "strings" 6 | "unsafe" 7 | 8 | "github.com/shirou/gopsutil/v4/host" 9 | "golang.org/x/sys/windows" 10 | ) 11 | 12 | // GetOSVersion returns OS version, kernel and bitness 13 | // On Windows it performs additional output enhancements. 14 | func GetOSVersion() (osVersion, osKernel string) { 15 | if platform, _, version, err := host.PlatformInformation(); err == nil && platform != "" { 16 | osVersion = platform 17 | if version != "" { 18 | osVersion += " " + version 19 | } 20 | } 21 | 22 | if version, err := host.KernelVersion(); err == nil && version != "" { 23 | osKernel = version 24 | 25 | // Prevent duplication of output on Windows 26 | if strings.Contains(osVersion, osKernel) { 27 | deduped := strings.TrimSpace(strings.Replace(osVersion, osKernel, "", 1)) 28 | if deduped != "" { 29 | osVersion = deduped 30 | } 31 | } 32 | 33 | // Simplify kernel output: `MAJOR.MINOR.BUILD.REVISION Build BUILD.REVISION` -> `MAJOR.MINOR.BUILD.REVISION` 34 | match := regexp.MustCompile(`^(\d+\.\d+\.(\d+\.\d+)) Build (\d+\.\d+)$`).FindStringSubmatch(osKernel) 35 | if len(match) == 4 && match[2] == match[3] { 36 | osKernel = match[1] 37 | } 38 | } 39 | 40 | if osVersion != "" { 41 | // Include the friendly-name of the version, which is typically what is referred to. 42 | // Until Windows 10 version 2004 (May 2020) this can be found from registry entry 43 | // ReleaseID, after that we must use entry DisplayVersion (ReleaseId is stuck at 2009). 44 | // Source: https://ss64.com/nt/ver.html 45 | friendlyName := getRegistryVersionString("DisplayVersion") 46 | if friendlyName == "" { 47 | friendlyName = getRegistryVersionString("ReleaseId") 48 | } 49 | if friendlyName != "" { 50 | osVersion += " " + friendlyName 51 | } 52 | } 53 | 54 | if arch, err := host.KernelArch(); err == nil && arch != "" { 55 | if strings.HasSuffix(arch, "64") && osVersion != "" { 56 | osVersion += " (64 bit)" 57 | } 58 | if osKernel != "" { 59 | osKernel += " (" + arch + ")" 60 | } 61 | } 62 | 63 | return 64 | } 65 | 66 | var regVersionKeyUTF16 = windows.StringToUTF16Ptr(`SOFTWARE\Microsoft\Windows NT\CurrentVersion`) 67 | 68 | func getRegistryVersionString(name string) string { 69 | var ( 70 | err error 71 | handle windows.Handle 72 | bufLen uint32 73 | valType uint32 74 | ) 75 | 76 | err = windows.RegOpenKeyEx(windows.HKEY_LOCAL_MACHINE, regVersionKeyUTF16, 0, windows.KEY_READ|windows.KEY_WOW64_64KEY, &handle) 77 | if err != nil { 78 | return "" 79 | } 80 | defer func() { 81 | _ = windows.RegCloseKey(handle) 82 | }() 83 | 84 | nameUTF16 := windows.StringToUTF16Ptr(name) 85 | err = windows.RegQueryValueEx(handle, nameUTF16, nil, &valType, nil, &bufLen) 86 | if err != nil { 87 | return "" 88 | } 89 | 90 | regBuf := make([]uint16, bufLen/2+1) 91 | err = windows.RegQueryValueEx(handle, nameUTF16, nil, &valType, (*byte)(unsafe.Pointer(®Buf[0])), &bufLen) 92 | if err != nil { 93 | return "" 94 | } 95 | 96 | return windows.UTF16ToString(regBuf) 97 | } 98 | -------------------------------------------------------------------------------- /cmd/build/arch.go: -------------------------------------------------------------------------------- 1 | package build 2 | 3 | import ( 4 | "runtime" 5 | 6 | "golang.org/x/sys/cpu" 7 | ) 8 | 9 | // GetSupportedGOARM returns the ARM compatibility level of the current CPU. 10 | // 11 | // Returns the integer value that can be set for the GOARM variable to 12 | // build with this level as target, a value which normally corresponds to the 13 | // ARM architecture version number, although it is the floating point hardware 14 | // support which is the decicive factor. 15 | // 16 | // Only relevant for 32-bit ARM architectures, where GOARCH=arm, which means 17 | // ARMv7 and lower (ARMv8 is GOARCH=arm64 and GOARM is not considered). 18 | // Highest possible value is therefore 7, while other possible values are 19 | // 6 (for ARMv6) and 5 (for ARMv5, which is the lowest currently supported 20 | // in go. Returns value 0 for anything else. 21 | // 22 | // See also: 23 | // 24 | // https://go.dev/src/runtime/os_linux_arm.go 25 | // https://github.com/golang/go/wiki/GoArm 26 | func GetSupportedGOARM() int { 27 | if runtime.GOARCH == "arm" && cpu.Initialized { 28 | // This CPU is an ARM (32-bit), and cpu.Initialized true means its 29 | // features could be retrieved on current GOOS so that we can check 30 | // for floating point hardware support. 31 | if cpu.ARM.HasVFPv3 { 32 | // This CPU has VFPv3 floating point hardware, which means it can 33 | // run programs built with any GOARM value, 7 and lower. 34 | return 7 35 | } else if cpu.ARM.HasVFP { 36 | // This CPU has VFP floating point hardware, but not VFPv3, which 37 | // means it can run programs built with GOARM value 6 and lower, 38 | // but not 7. 39 | return 6 40 | } 41 | // This CPU has no VFP floating point hardware, which means it can 42 | // only run programs built with GOARM value 5, which is minimum supported. 43 | // Note that the CPU can still in reality be based on e.g. ARMv7 44 | // architecture, but simply lack hardfloat support. 45 | return 5 46 | } 47 | return 0 48 | } 49 | 50 | // GetArch tells the rclone executable's architecture target. 51 | func GetArch() string { 52 | // Get the running program's architecture target. 53 | arch := runtime.GOARCH 54 | 55 | // For ARM architectures there are several variants, with different 56 | // inconsistent and ambiguous naming. 57 | // 58 | // The most interesting thing here is which compatibility level of go is 59 | // used, as controlled by GOARM build variable. We cannot in runtime get 60 | // the actual value of GOARM used for building this program, but we can 61 | // check the value supported by the current CPU by calling GetSupportedGOARM. 62 | // This means we return information about the compatibility level (GOARM 63 | // value) supported, when the current rclone executable may in reality be 64 | // built with a lower level. 65 | // 66 | // Note that the kernel architecture, as returned by "uname -m", is not 67 | // considered or included in results here, but it is included in the output 68 | // from function GetOSVersion. It can have values such as armv6l, armv7l, 69 | // armv8l, arm64 and aarch64, which may give relevant information. But it 70 | // can also simply have value "arm", or it can have value "armv7l" for a 71 | // processor based on ARMv7 but without floating point hardware - which 72 | // means it in go needs to be built in ARMv5 compatibility mode (GOARM=5). 73 | if arch == "arm64" { 74 | // 64-bit ARM architecture, known as AArch64, was introduced with ARMv8. 75 | // In go this architecture is a specific one, separate from other ARMs. 76 | arch += " (ARMv8 compatible)" 77 | } else if arch == "arm" { 78 | // 32-bit ARM architecture, which is ARMv7 and lower. 79 | // In go there are different compatibility levels represented by ARM 80 | // architecture version number (like 5, 6 or 7). 81 | switch GetSupportedGOARM() { 82 | case 7: 83 | arch += " (ARMv7 compatible)" 84 | case 6: 85 | arch += " (ARMv6 compatible)" 86 | case 5: 87 | arch += " (ARMv5 compatible, no hardfloat)" 88 | } 89 | } 90 | return arch 91 | } 92 | -------------------------------------------------------------------------------- /args.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "net" 7 | "os" 8 | "sort" 9 | "strings" 10 | ) 11 | 12 | func isIPv6(str string) bool { 13 | ip := net.ParseIP(str) 14 | return ip != nil && strings.Contains(str, ":") 15 | } 16 | 17 | // Key–value mappings for the representation of client and server options. 18 | 19 | // Args maps a string key to a list of values. It is similar to url.Values. 20 | type Args map[string][]string 21 | 22 | // Get the first value associated with the given key. If there are any values 23 | // associated with the key, the value return has the value and ok is set to 24 | // true. If there are no values for the given key, value is "" and ok is false. 25 | // If you need access to multiple values, use the map directly. 26 | func (args Args) Get(key string) (value string, ok bool) { 27 | if args == nil { 28 | return "", false 29 | } 30 | vals, ok := args[key] 31 | if !ok || len(vals) == 0 { 32 | return "", false 33 | } 34 | return vals[0], true 35 | } 36 | 37 | // Append value to the list of values for key. 38 | func (args Args) Add(key, value string) { 39 | args[key] = append(args[key], value) 40 | } 41 | 42 | // Return the index of the next unescaped byte in s that is in the term set, or 43 | // else the length of the string if no terminators appear. Additionally return 44 | // the unescaped string up to the returned index. 45 | func indexUnescaped(s string, term []byte) (int, string, error) { 46 | var i int 47 | unesc := make([]byte, 0) 48 | for i = 0; i < len(s); i++ { 49 | b := s[i] 50 | // A terminator byte? 51 | if bytes.IndexByte(term, b) != -1 { 52 | break 53 | } 54 | if b == '\\' { 55 | i++ 56 | if i >= len(s) { 57 | return 0, "", fmt.Errorf("nothing following final escape in %q", s) 58 | } 59 | b = s[i] 60 | } 61 | unesc = append(unesc, b) 62 | } 63 | return i, string(unesc), nil 64 | } 65 | 66 | // Parse SS_PLUGIN options from environment variables 67 | func parseEnv() (opts Args, err error) { 68 | opts = make(Args) 69 | ss_remote_host := os.Getenv("SS_REMOTE_HOST") 70 | ss_remote_port := os.Getenv("SS_REMOTE_PORT") 71 | ss_local_host := os.Getenv("SS_LOCAL_HOST") 72 | ss_local_port := os.Getenv("SS_LOCAL_PORT") 73 | if len(ss_remote_host) == 0 { 74 | return 75 | } 76 | if len(ss_remote_port) == 0 { 77 | return 78 | } 79 | if len(ss_local_host) == 0 { 80 | return 81 | } 82 | if len(ss_local_port) == 0 { 83 | return 84 | } 85 | 86 | opts.Add("remoteAddr", ss_remote_host) 87 | opts.Add("remotePort", ss_remote_port) 88 | opts.Add("localAddr", ss_local_host) 89 | opts.Add("localPort", ss_local_port) 90 | 91 | ss_plugin_options := os.Getenv("SS_PLUGIN_OPTIONS") 92 | if len(ss_plugin_options) > 0 { 93 | other_opts, err := parsePluginOptions(ss_plugin_options) 94 | if err != nil { 95 | return nil, err 96 | } 97 | for k, v := range other_opts { 98 | opts[k] = v 99 | } 100 | } 101 | return opts, nil 102 | } 103 | 104 | // Parse a name–value mapping as from SS_PLUGIN_OPTIONS. 105 | // 106 | // " is a k=v string value with options that are to be passed to the 107 | // transport. semicolons, equal signs and backslashes must be escaped 108 | // with a backslash." 109 | // Example: secret=nou;cache=/tmp/cache;secret=yes 110 | func parsePluginOptions(s string) (opts Args, err error) { 111 | opts = make(Args) 112 | if len(s) == 0 { 113 | return 114 | } 115 | i := 0 116 | for { 117 | var key, value string 118 | var offset, begin int 119 | 120 | if i >= len(s) { 121 | break 122 | } 123 | begin = i 124 | // Read the key. 125 | offset, key, err = indexUnescaped(s[i:], []byte{'=', ';'}) 126 | if err != nil { 127 | return 128 | } 129 | if len(key) == 0 { 130 | err = fmt.Errorf("empty key in %q", s[begin:i]) 131 | return 132 | } 133 | i += offset 134 | // End of string or no equals sign? 135 | if i >= len(s) || s[i] != '=' { 136 | opts.Add(key, "1") 137 | // Skip the semicolon. 138 | i++ 139 | continue 140 | } 141 | // Skip the equals sign. 142 | i++ 143 | // Read the value. 144 | offset, value, err = indexUnescaped(s[i:], []byte{';'}) 145 | if err != nil { 146 | return 147 | } 148 | i += offset 149 | opts.Add(key, value) 150 | // Skip the semicolon. 151 | i++ 152 | } 153 | return opts, nil 154 | } 155 | 156 | // Escape backslashes and all the bytes that are in set. 157 | func backslashEscape(s string, set []byte) string { 158 | var buf bytes.Buffer 159 | for _, b := range []byte(s) { 160 | if b == '\\' || bytes.IndexByte(set, b) != -1 { 161 | buf.WriteByte('\\') 162 | } 163 | buf.WriteByte(b) 164 | } 165 | return buf.String() 166 | } 167 | 168 | // Encode a name–value mapping so that it is suitable to go in the ARGS option 169 | // of an SMETHOD line. The output is sorted by key. The "ARGS:" prefix is not 170 | // added. 171 | // 172 | // "Equal signs and commas [and backslashes] must be escaped with a backslash." 173 | func encodeSmethodArgs(args Args) string { 174 | if args == nil { 175 | return "" 176 | } 177 | 178 | keys := make([]string, 0, len(args)) 179 | for key := range args { 180 | keys = append(keys, key) 181 | } 182 | sort.Strings(keys) 183 | 184 | escape := func(s string) string { 185 | return backslashEscape(s, []byte{'=', ','}) 186 | } 187 | 188 | var pairs []string 189 | for _, key := range keys { 190 | for _, value := range args[key] { 191 | pairs = append(pairs, escape(key)+"="+escape(value)) 192 | } 193 | } 194 | 195 | return strings.Join(pairs, ",") 196 | } 197 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | //go:generate errorgen 4 | 5 | import ( 6 | "flag" 7 | "fmt" 8 | "os" 9 | "os/signal" 10 | "os/user" 11 | "runtime" 12 | "strconv" 13 | "strings" 14 | "syscall" 15 | "net/url" 16 | 17 | "google.golang.org/protobuf/proto" 18 | 19 | "github.com/xtls/xray-core/core" 20 | 21 | "github.com/xtls/xray-core/app/dispatcher" 22 | "github.com/xtls/xray-core/app/proxyman" 23 | _ "github.com/xtls/xray-core/app/proxyman/inbound" 24 | _ "github.com/xtls/xray-core/app/proxyman/outbound" 25 | 26 | "github.com/xtls/xray-core/common/net" 27 | "github.com/xtls/xray-core/common/protocol" 28 | "github.com/xtls/xray-core/common/serial" 29 | "github.com/xtls/xray-core/common/errors" 30 | 31 | "github.com/xtls/xray-core/proxy/dokodemo" 32 | "github.com/xtls/xray-core/proxy/freedom" 33 | 34 | "github.com/xtls/xray-core/transport/internet" 35 | "github.com/xtls/xray-core/transport/internet/grpc" 36 | "github.com/xtls/xray-core/transport/internet/quic" 37 | "github.com/xtls/xray-core/transport/internet/tls" 38 | "github.com/xtls/xray-core/transport/internet/websocket" 39 | 40 | vlog "github.com/xtls/xray-core/app/log" 41 | clog "github.com/xtls/xray-core/common/log" 42 | 43 | "github.com/xtls/xray-core/common/platform/filesystem" 44 | "github.com/teddysun/xray-plugin/cmd/build" 45 | ) 46 | 47 | var ( 48 | VERSION = "custom" 49 | ) 50 | 51 | var ( 52 | vpn = flag.Bool("V", false, "Run in VPN mode.") 53 | fastOpen = flag.Bool("fast-open", false, "Enable TCP fast open.") 54 | localAddr = flag.String("localAddr", "127.0.0.1", "local address to listen on.") 55 | localPort = flag.String("localPort", "1984", "local port to listen on.") 56 | remoteAddr = flag.String("remoteAddr", "127.0.0.1", "remote address to forward.") 57 | remotePort = flag.String("remotePort", "1080", "remote port to forward.") 58 | path = flag.String("path", "/", "URL path for websocket.") 59 | serviceName = flag.String("serviceName", "GunService", "Service name for grpc.") 60 | host = flag.String("host", "cloudfront.com", "Hostname for server.") 61 | tlsEnabled = flag.Bool("tls", false, "Enable TLS.") 62 | cert = flag.String("cert", "", "Path to TLS certificate file. Overrides certRaw. Default: ~/.acme.sh/{host}/fullchain.cer") 63 | certRaw = flag.String("certRaw", "", "Raw TLS certificate content. Intended only for Android.") 64 | key = flag.String("key", "", "(server) Path to TLS key file. Default: ~/.acme.sh/{host}/{host}.key") 65 | mode = flag.String("mode", "websocket", "Transport mode: websocket, quic (enforced tls), grpc.") 66 | mux = flag.Int("mux", 1, "Concurrent multiplexed connections (websocket client mode only).") 67 | server = flag.Bool("server", false, "Run in server mode") 68 | logLevel = flag.String("loglevel", "", "loglevel for xray: debug, info, warning (default), error, none.") 69 | version = flag.Bool("version", false, "Show current version of xray-plugin") 70 | fwmark = flag.Int("fwmark", 0, "Set SO_MARK option for outbound sockets.") 71 | ) 72 | 73 | func homeDir() string { 74 | usr, err := user.Current() 75 | if err != nil { 76 | logFatal(err) 77 | os.Exit(1) 78 | } 79 | return usr.HomeDir 80 | } 81 | 82 | func readCertificate() ([]byte, error) { 83 | if *cert != "" { 84 | return filesystem.ReadFile(*cert) 85 | } 86 | if *certRaw != "" { 87 | certHead := "-----BEGIN CERTIFICATE-----" 88 | certTail := "-----END CERTIFICATE-----" 89 | fixedCert := certHead + "\n" + *certRaw + "\n" + certTail 90 | return []byte(fixedCert), nil 91 | } 92 | panic("thou shalt not reach hear") 93 | } 94 | 95 | func logConfig(logLevel string) *vlog.Config { 96 | config := &vlog.Config{ 97 | ErrorLogLevel: clog.Severity_Warning, 98 | ErrorLogType: vlog.LogType_Console, 99 | AccessLogType: vlog.LogType_Console, 100 | } 101 | level := strings.ToLower(logLevel) 102 | switch level { 103 | case "debug": 104 | config.ErrorLogLevel = clog.Severity_Debug 105 | case "info": 106 | config.ErrorLogLevel = clog.Severity_Info 107 | case "error": 108 | config.ErrorLogLevel = clog.Severity_Error 109 | case "none": 110 | config.ErrorLogType = vlog.LogType_None 111 | config.AccessLogType = vlog.LogType_None 112 | } 113 | return config 114 | } 115 | 116 | func parseLocalAddr(localAddr string) []string { 117 | return strings.Split(localAddr, "|") 118 | } 119 | 120 | func generateConfig() (*core.Config, error) { 121 | lport, err := net.PortFromString(*localPort) 122 | if err != nil { 123 | return nil, errors.New("invalid localPort:", *localPort).Base(err) 124 | } 125 | rport, err := strconv.ParseUint(*remotePort, 10, 32) 126 | if err != nil { 127 | return nil, errors.New("invalid remotePort:", *remotePort).Base(err) 128 | } 129 | outboundProxy := serial.ToTypedMessage(&freedom.Config{ 130 | DestinationOverride: &freedom.DestinationOverride{ 131 | Server: &protocol.ServerEndpoint{ 132 | Address: net.NewIPOrDomain(net.ParseAddress(*remoteAddr)), 133 | Port: uint32(rport), 134 | }, 135 | }, 136 | }) 137 | 138 | var transportSettings proto.Message 139 | var connectionReuse bool 140 | switch *mode { 141 | case "websocket": 142 | var ed uint32 143 | if u, err := url.Parse(*path); err == nil { 144 | if q := u.Query(); q.Get("ed") != "" { 145 | Ed, _ := strconv.Atoi(q.Get("ed")) 146 | ed = uint32(Ed) 147 | q.Del("ed") 148 | u.RawQuery = q.Encode() 149 | *path = u.String() 150 | } 151 | } 152 | transportSettings = &websocket.Config{ 153 | Path: *path, 154 | Host: *host, 155 | Header: map[string]string{ 156 | "host": *host, 157 | }, 158 | Ed: ed, 159 | } 160 | if *mux != 0 { 161 | connectionReuse = true 162 | } 163 | case "quic": 164 | transportSettings = &quic.Config{ 165 | Security: &protocol.SecurityConfig{Type: protocol.SecurityType_NONE}, 166 | } 167 | *tlsEnabled = true 168 | case "grpc": 169 | transportSettings = &grpc.Config{ 170 | ServiceName: *serviceName, 171 | } 172 | default: 173 | return nil, errors.New("unsupported mode:", *mode) 174 | } 175 | 176 | streamConfig := internet.StreamConfig{ 177 | ProtocolName: *mode, 178 | TransportSettings: []*internet.TransportConfig{{ 179 | ProtocolName: *mode, 180 | Settings: serial.ToTypedMessage(transportSettings), 181 | }}, 182 | } 183 | if *fastOpen || *fwmark != 0 { 184 | socketConfig := &internet.SocketConfig{} 185 | if *fastOpen { 186 | socketConfig.Tfo = 256 187 | } 188 | if *fwmark != 0 { 189 | socketConfig.Mark = int32(*fwmark) 190 | } 191 | 192 | streamConfig.SocketSettings = socketConfig 193 | } 194 | if *tlsEnabled { 195 | tlsConfig := tls.Config{ServerName: *host} 196 | if *server { 197 | certificate := tls.Certificate{} 198 | if *cert == "" && *certRaw == "" { 199 | *cert = fmt.Sprintf("%s/.acme.sh/%s/fullchain.cer", homeDir(), *host) 200 | logWarn("No TLS cert specified, trying", *cert) 201 | } 202 | certificate.Certificate, err = readCertificate() 203 | if err != nil { 204 | return nil, errors.New("failed to read cert").Base(err) 205 | } 206 | if *key == "" { 207 | *key = fmt.Sprintf("%[1]s/.acme.sh/%[2]s/%[2]s.key", homeDir(), *host) 208 | logWarn("No TLS key specified, trying", *key) 209 | } 210 | certificate.Key, err = filesystem.ReadFile(*key) 211 | if err != nil { 212 | return nil, errors.New("failed to read key file").Base(err) 213 | } 214 | tlsConfig.Certificate = []*tls.Certificate{&certificate} 215 | } else if *cert != "" || *certRaw != "" { 216 | certificate := tls.Certificate{Usage: tls.Certificate_AUTHORITY_VERIFY} 217 | certificate.Certificate, err = readCertificate() 218 | if err != nil { 219 | return nil, errors.New("failed to read cert").Base(err) 220 | } 221 | tlsConfig.Certificate = []*tls.Certificate{&certificate} 222 | } 223 | streamConfig.SecurityType = serial.GetMessageType(&tlsConfig) 224 | streamConfig.SecuritySettings = []*serial.TypedMessage{serial.ToTypedMessage(&tlsConfig)} 225 | } 226 | 227 | apps := []*serial.TypedMessage{ 228 | serial.ToTypedMessage(&dispatcher.Config{}), 229 | serial.ToTypedMessage(&proxyman.InboundConfig{}), 230 | serial.ToTypedMessage(&proxyman.OutboundConfig{}), 231 | serial.ToTypedMessage(logConfig(*logLevel)), 232 | } 233 | 234 | if *server { 235 | proxyAddress := net.LocalHostIP 236 | if connectionReuse { 237 | // This address is required when mux is used on client. 238 | // dokodemo is not aware of mux connections by itself. 239 | proxyAddress = net.ParseAddress("v1.mux.cool") 240 | } 241 | localAddrs := parseLocalAddr(*localAddr) 242 | inbounds := make([]*core.InboundHandlerConfig, len(localAddrs)) 243 | 244 | for i := 0; i < len(localAddrs); i++ { 245 | inbounds[i] = &core.InboundHandlerConfig{ 246 | ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ 247 | PortList: &net.PortList{ 248 | Range: []*net.PortRange{net.SinglePortRange(lport)}, 249 | }, 250 | Listen: net.NewIPOrDomain(net.ParseAddress(localAddrs[i])), 251 | StreamSettings: &streamConfig, 252 | }), 253 | ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ 254 | Address: net.NewIPOrDomain(proxyAddress), 255 | Networks: []net.Network{net.Network_TCP}, 256 | }), 257 | } 258 | } 259 | 260 | return &core.Config{ 261 | Inbound: inbounds, 262 | Outbound: []*core.OutboundHandlerConfig{{ 263 | ProxySettings: outboundProxy, 264 | }}, 265 | App: apps, 266 | }, nil 267 | } else { 268 | senderConfig := proxyman.SenderConfig{StreamSettings: &streamConfig} 269 | if connectionReuse { 270 | senderConfig.MultiplexSettings = &proxyman.MultiplexingConfig{Enabled: true, Concurrency: int32(*mux)} 271 | } 272 | return &core.Config{ 273 | Inbound: []*core.InboundHandlerConfig{{ 274 | ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{ 275 | PortList: &net.PortList{ 276 | Range: []*net.PortRange{net.SinglePortRange(lport)}, 277 | }, 278 | Listen: net.NewIPOrDomain(net.ParseAddress(*localAddr)), 279 | }), 280 | ProxySettings: serial.ToTypedMessage(&dokodemo.Config{ 281 | Address: net.NewIPOrDomain(net.LocalHostIP), 282 | Networks: []net.Network{net.Network_TCP}, 283 | }), 284 | }}, 285 | Outbound: []*core.OutboundHandlerConfig{{ 286 | SenderSettings: serial.ToTypedMessage(&senderConfig), 287 | ProxySettings: outboundProxy, 288 | }}, 289 | App: apps, 290 | }, nil 291 | } 292 | } 293 | 294 | func startXRay() (core.Server, error) { 295 | 296 | opts, err := parseEnv() 297 | 298 | if err == nil { 299 | if c, b := opts.Get("mode"); b { 300 | *mode = c 301 | } 302 | if c, b := opts.Get("mux"); b { 303 | if i, err := strconv.Atoi(c); err == nil { 304 | *mux = i 305 | } else { 306 | logWarn("failed to parse mux, use default value") 307 | } 308 | } 309 | if _, b := opts.Get("tls"); b { 310 | *tlsEnabled = true 311 | } 312 | if c, b := opts.Get("host"); b { 313 | *host = c 314 | } 315 | if c, b := opts.Get("path"); b { 316 | *path = c 317 | } 318 | if c, b := opts.Get("serviceName"); b { 319 | *serviceName = c 320 | } 321 | if c, b := opts.Get("cert"); b { 322 | *cert = c 323 | } 324 | if c, b := opts.Get("certRaw"); b { 325 | *certRaw = c 326 | } 327 | if c, b := opts.Get("key"); b { 328 | *key = c 329 | } 330 | if c, b := opts.Get("loglevel"); b { 331 | *logLevel = c 332 | } 333 | if _, b := opts.Get("server"); b { 334 | *server = true 335 | } 336 | if c, b := opts.Get("localAddr"); b { 337 | if *server { 338 | *remoteAddr = c 339 | } else { 340 | *localAddr = c 341 | } 342 | } 343 | if c, b := opts.Get("localPort"); b { 344 | if *server { 345 | *remotePort = c 346 | } else { 347 | *localPort = c 348 | } 349 | } 350 | if c, b := opts.Get("remoteAddr"); b { 351 | if *server { 352 | *localAddr = c 353 | } else { 354 | *remoteAddr = c 355 | } 356 | } 357 | if c, b := opts.Get("remotePort"); b { 358 | if *server { 359 | *localPort = c 360 | } else { 361 | *remotePort = c 362 | } 363 | } 364 | 365 | if _, b := opts.Get("fastOpen"); b { 366 | *fastOpen = true 367 | } 368 | 369 | if _, b := opts.Get("__android_vpn"); b { 370 | *vpn = true 371 | } 372 | 373 | if c, b := opts.Get("fwmark"); b { 374 | if i, err := strconv.Atoi(c); err == nil { 375 | *fwmark = i 376 | } else { 377 | logWarn("failed to parse fwmark, use default value") 378 | } 379 | } 380 | 381 | if *vpn { 382 | registerControlFunc() 383 | } 384 | } 385 | 386 | config, err := generateConfig() 387 | if err != nil { 388 | return nil, errors.New("failed to parse config").Base(err) 389 | } 390 | instance, err := core.New(config) 391 | if err != nil { 392 | return nil, errors.New("failed to create xray instance").Base(err) 393 | } 394 | return instance, nil 395 | } 396 | 397 | func printCoreVersion() { 398 | version := core.VersionStatement() 399 | for _, s := range version { 400 | logInfo(s) 401 | } 402 | } 403 | 404 | func printVersion() { 405 | osVersion, osKernel := build.GetOSVersion() 406 | if osVersion == "" { 407 | osVersion = "unknown" 408 | } 409 | if osKernel == "" { 410 | osKernel = "unknown" 411 | } 412 | 413 | arch := build.GetArch() 414 | 415 | fmt.Println("xray-plugin", VERSION) 416 | fmt.Println("Yet another SIP003 plugin for shadowsocks") 417 | fmt.Printf("- os/version: %s\n", osVersion) 418 | fmt.Printf("- os/kernel: %s\n", osKernel) 419 | fmt.Printf("- os/type: %s\n", runtime.GOOS) 420 | fmt.Printf("- os/arch: %s\n", arch) 421 | fmt.Printf("- go/version: %s\n", runtime.Version()) 422 | } 423 | 424 | func main() { 425 | flag.Parse() 426 | 427 | if *version { 428 | printVersion() 429 | return 430 | } 431 | 432 | logInit() 433 | 434 | printCoreVersion() 435 | 436 | server, err := startXRay() 437 | if err != nil { 438 | logFatal(err.Error()) 439 | // Configuration error. Exit with a special value to prevent systemd from restarting. 440 | os.Exit(23) 441 | } 442 | if err := server.Start(); err != nil { 443 | logFatal("failed to start server:", err.Error()) 444 | os.Exit(1) 445 | } 446 | 447 | defer func() { 448 | err := server.Close() 449 | if err != nil { 450 | logWarn(err.Error()) 451 | } 452 | }() 453 | 454 | { 455 | osSignals := make(chan os.Signal, 1) 456 | signal.Notify(osSignals, os.Interrupt, os.Kill, syscall.SIGTERM) 457 | <-osSignals 458 | } 459 | } 460 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 3 | cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 4 | cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo= 5 | dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU= 6 | dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU= 7 | dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= 8 | dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= 9 | git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= 10 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 11 | github.com/OmarTariq612/goech v0.0.0-20240405204721-8e2e1dafd3a0 h1:Wo41lDOevRJSGpevP+8Pk5bANX7fJacO2w04aqLiC5I= 12 | github.com/OmarTariq612/goech v0.0.0-20240405204721-8e2e1dafd3a0/go.mod h1:FVGavL/QEBQDcBpr3fAojoK17xX5k9bicBphrOpP7uM= 13 | github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= 14 | github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= 15 | github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= 16 | github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= 17 | github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= 18 | github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= 19 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 20 | github.com/cloudflare/circl v1.4.0 h1:BV7h5MgrktNzytKmWjpOtdYrf0lkkbF8YMlBGPhJQrY= 21 | github.com/cloudflare/circl v1.4.0/go.mod h1:PDRU+oXvdD7KCtgKxW95M5Z8BpSCJXQORiZFnBQS5QU= 22 | github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= 23 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 24 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 25 | github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 h1:y7y0Oa6UawqTFPCDw9JG6pdKt4F9pAhHv0B7FMGaGD0= 26 | github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140/go.mod h1:c9O8+fpSOX1DM8cPNSkX/qsBWdkD4yd2dpciOWQjpBw= 27 | github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= 28 | github.com/ebitengine/purego v0.9.0 h1:mh0zpKBIXDceC63hpvPuGLiJ8ZAa3DfrFTudmfi8A4k= 29 | github.com/ebitengine/purego v0.9.0/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= 30 | github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= 31 | github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk= 32 | github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= 33 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 34 | github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 35 | github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344 h1:Arcl6UOIS/kgO2nW3A65HN+7CMjSDP/gofXL4CZt1V4= 36 | github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I= 37 | github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= 38 | github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= 39 | github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= 40 | github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 41 | github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= 42 | github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= 43 | github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= 44 | github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= 45 | github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= 46 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 47 | github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= 48 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 49 | github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 50 | github.com/golang/mock v1.7.0-rc.1 h1:YojYx61/OLFsiv6Rw1Z96LpldJIy31o+UHmwAUMJ6/U= 51 | github.com/golang/mock v1.7.0-rc.1/go.mod h1:s42URUywIqd+OcERslBJvOjepvNymP31m3q8d/GkuRs= 52 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 53 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 54 | github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 55 | github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= 56 | github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= 57 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 58 | github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 59 | github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= 60 | github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= 61 | github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= 62 | github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= 63 | github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= 64 | github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= 65 | github.com/google/pprof v0.0.0-20240528025155-186aa0362fba h1:ql1qNgCyOB7iAEk8JTNM+zJrgIbnyCKX/wdlyPufP5g= 66 | github.com/google/pprof v0.0.0-20240528025155-186aa0362fba/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= 67 | github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= 68 | github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg= 69 | github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= 70 | github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= 71 | github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= 72 | github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= 73 | github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= 74 | github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= 75 | github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= 76 | github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= 77 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 78 | github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU= 79 | github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= 80 | github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= 81 | github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= 82 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 83 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 84 | github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 85 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 86 | github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= 87 | github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= 88 | github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= 89 | github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= 90 | github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= 91 | github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= 92 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 93 | github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 94 | github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= 95 | github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= 96 | github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA= 97 | github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= 98 | github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= 99 | github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= 100 | github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= 101 | github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= 102 | github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= 103 | github.com/pires/go-proxyproto v0.7.0 h1:IukmRewDQFWC7kfnb66CSomk2q/seBuilHBYFwyq0Hs= 104 | github.com/pires/go-proxyproto v0.7.0/go.mod h1:Vz/1JPY/OACxWGQNIRY2BeyDmpoaWmEP40O9LbuiFR4= 105 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 106 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 107 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 108 | github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU= 109 | github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= 110 | github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= 111 | github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= 112 | github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= 113 | github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= 114 | github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= 115 | github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A= 116 | github.com/quic-go/quic-go v0.46.0 h1:uuwLClEEyk1DNvchH8uCByQVjo3yKL9opKulExNDs7Y= 117 | github.com/quic-go/quic-go v0.46.0/go.mod h1:1dLehS7TIR64+vxGR70GDcatWTOtMX2PUtnKsjbTurI= 118 | github.com/refraction-networking/utls v1.6.7 h1:zVJ7sP1dJx/WtVuITug3qYUq034cDq9B2MR1K67ULZM= 119 | github.com/refraction-networking/utls v1.6.7/go.mod h1:BC3O4vQzye5hqpmDTWUqi4P5DDhzJfkV1tdqtawQIH0= 120 | github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg= 121 | github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s= 122 | github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= 123 | github.com/sagernet/sing v0.4.1 h1:zVlpE+7k7AFoC2pv6ReqLf0PIHjihL/jsBl5k05PQFk= 124 | github.com/sagernet/sing v0.4.1/go.mod h1:ieZHA/+Y9YZfXs2I3WtuwgyCZ6GPsIR7HdKb1SdEnls= 125 | github.com/sagernet/sing-shadowsocks v0.2.7 h1:zaopR1tbHEw5Nk6FAkM05wCslV6ahVegEZaKMv9ipx8= 126 | github.com/sagernet/sing-shadowsocks v0.2.7/go.mod h1:0rIKJZBR65Qi0zwdKezt4s57y/Tl1ofkaq6NlkzVuyE= 127 | github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771 h1:emzAzMZ1L9iaKCTxdy3Em8Wv4ChIAGnfiz18Cda70g4= 128 | github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771/go.mod h1:bR6DqgcAl1zTcOX8/pE2Qkj9XO00eCNqmKb7lXP8EAg= 129 | github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= 130 | github.com/shirou/gopsutil/v4 v4.25.9 h1:JImNpf6gCVhKgZhtaAHJ0serfFGtlfIlSC08eaKdTrU= 131 | github.com/shirou/gopsutil/v4 v4.25.9/go.mod h1:gxIxoC+7nQRwUl/xNhutXlD8lq+jxTgpIkEf3rADHL8= 132 | github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= 133 | github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= 134 | github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0= 135 | github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= 136 | github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= 137 | github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw= 138 | github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI= 139 | github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU= 140 | github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag= 141 | github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg= 142 | github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw= 143 | github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y= 144 | github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= 145 | github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q= 146 | github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ= 147 | github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I= 148 | github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0= 149 | github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ= 150 | github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk= 151 | github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= 152 | github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4= 153 | github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw= 154 | github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= 155 | github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= 156 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 157 | github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= 158 | github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= 159 | github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= 160 | github.com/tklauser/go-sysconf v0.3.15 h1:VE89k0criAymJ/Os65CSn1IXaol+1wrsFHEB8Ol49K4= 161 | github.com/tklauser/go-sysconf v0.3.15/go.mod h1:Dmjwr6tYFIseJw7a3dRLJfsHAMXZ3nEnL/aZY+0IuI4= 162 | github.com/tklauser/numcpus v0.10.0 h1:18njr6LDBk1zuna922MgdjQuJFjrdppsZG60sHGfjso= 163 | github.com/tklauser/numcpus v0.10.0/go.mod h1:BiTKazU708GQTYF4mB+cmlpT2Is1gLk7XVuEeem8LsQ= 164 | github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e h1:5QefA066A1tF8gHIiADmOVOV5LS43gt3ONnlEl3xkwI= 165 | github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e/go.mod h1:5t19P9LBIrNamL6AcMQOncg/r10y3Pc01AbHeMhwlpU= 166 | github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= 167 | github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= 168 | github.com/vishvananda/netlink v1.3.0 h1:X7l42GfcV4S6E4vHTsw48qbrV+9PVojNfIhZcwQdrZk= 169 | github.com/vishvananda/netlink v1.3.0/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn4UKG+hGqeJs= 170 | github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8= 171 | github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= 172 | github.com/xtls/reality v0.0.0-20240712055506-48f0b2d5ed6d h1:+B97uD9uHLgAAulhigmys4BVwZZypzK7gPN3WtpgRJg= 173 | github.com/xtls/reality v0.0.0-20240712055506-48f0b2d5ed6d/go.mod h1:dm4y/1QwzjGaK17ofi0Vs6NpKAHegZky8qk6J2JJZAE= 174 | github.com/xtls/xray-core v1.8.24 h1:Y2NumdlnJ9C9gvh1Ivs2+73ui5XQgB70wZXYCiI9DyY= 175 | github.com/xtls/xray-core v1.8.24/go.mod h1:cWIOI6iBBOsB0HHU9PGhaiBhaMPfiktUjwA0IWolWJc= 176 | github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= 177 | github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= 178 | go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= 179 | go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= 180 | go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= 181 | go4.org v0.0.0-20180809161055-417644f6feb5 h1:+hE86LblG4AyDgwMCLTE6FOlM9+qjHSYS+rKqxUVdsM= 182 | go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= 183 | go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M= 184 | go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y= 185 | golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw= 186 | golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 187 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 188 | golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 189 | golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= 190 | golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= 191 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 192 | golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc h1:O9NuF4s+E/PvMIy+9IUZB9znFwUIXEWSstNjek6VpVg= 193 | golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc= 194 | golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 195 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 196 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 197 | golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= 198 | golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= 199 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 200 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 201 | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 202 | golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 203 | golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 204 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 205 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 206 | golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 207 | golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= 208 | golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= 209 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 210 | golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 211 | golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 212 | golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 213 | golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= 214 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 215 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 216 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 217 | golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 218 | golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= 219 | golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= 220 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 221 | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 222 | golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 223 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 224 | golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 225 | golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 226 | golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 227 | golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 228 | golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= 229 | golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= 230 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 231 | golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 232 | golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= 233 | golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= 234 | golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 235 | golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 236 | golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= 237 | golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= 238 | golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 239 | golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 240 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 241 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 242 | golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA= 243 | golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= 244 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 245 | golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg= 246 | golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI= 247 | golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 h1:/jFs0duh4rdb8uIfPMv78iAJGcPKDeqAFnaLBropIC4= 248 | golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173/go.mod h1:tkCQ4FQXmpAgYVh++1cq16/dH4QJtmvpRv19DWGAHSA= 249 | google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= 250 | google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= 251 | google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y= 252 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 253 | google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 254 | google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 255 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 256 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 257 | google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 258 | google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 259 | google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= 260 | google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 261 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 h1:1GBuWVLM/KMVUv1t1En5Gs+gFZCNd360GGb4sSxtrhU= 262 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= 263 | google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= 264 | google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= 265 | google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= 266 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 267 | google.golang.org/grpc v1.66.0 h1:DibZuoBznOxbDQxRINckZcUvnCEvrW9pcWIE2yF9r1c= 268 | google.golang.org/grpc v1.66.0/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= 269 | google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= 270 | google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= 271 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 272 | gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= 273 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 274 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 275 | gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= 276 | gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 277 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 278 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 279 | grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= 280 | gvisor.dev/gvisor v0.0.0-20231202080848-1f7806d17489 h1:ze1vwAdliUAr68RQ5NtufWaXaOg8WUO2OACzEV+TNdE= 281 | gvisor.dev/gvisor v0.0.0-20231202080848-1f7806d17489/go.mod h1:10sU+Uh5KKNv1+2x2A0Gvzt8FjD3ASIhorV3YsauXhk= 282 | honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 283 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 284 | honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 285 | lukechampine.com/blake3 v1.3.0 h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE= 286 | lukechampine.com/blake3 v1.3.0/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= 287 | sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= 288 | sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= 289 | --------------------------------------------------------------------------------