mirror of
https://github.com/MatsuriDayo/nekoray.git
synced 2025-12-18 13:04:37 +03:00
refactor core
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
find_package(Protobuf CONFIG REQUIRED)
|
||||
|
||||
set(PROTO_FILES
|
||||
go/gen/libcore.proto
|
||||
go/grpc_server/gen/libcore.proto
|
||||
)
|
||||
|
||||
add_library(myproto STATIC ${PROTO_FILES})
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
package box_main
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
box "github.com/sagernet/sing-box"
|
||||
"github.com/sagernet/sing-box/log"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var commandCheck = &cobra.Command{
|
||||
Use: "check",
|
||||
Short: "Check configuration",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
err := check()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
},
|
||||
Args: cobra.NoArgs,
|
||||
}
|
||||
|
||||
func init() {
|
||||
mainCommand.AddCommand(commandCheck)
|
||||
}
|
||||
|
||||
func check() error {
|
||||
options, err := readConfig(nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
_, err = box.New(ctx, options, nil)
|
||||
cancel()
|
||||
return err
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
package box_main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/sagernet/sing-box/common/json"
|
||||
"github.com/sagernet/sing-box/log"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var commandFormatFlagWrite bool
|
||||
|
||||
var commandFormat = &cobra.Command{
|
||||
Use: "format",
|
||||
Short: "Format configuration",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
err := format()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
},
|
||||
Args: cobra.NoArgs,
|
||||
}
|
||||
|
||||
func init() {
|
||||
commandFormat.Flags().BoolVarP(&commandFormatFlagWrite, "write", "w", false, "write result to (source) file instead of stdout")
|
||||
mainCommand.AddCommand(commandFormat)
|
||||
}
|
||||
|
||||
func format() error {
|
||||
configContent, err := os.ReadFile(configPath)
|
||||
if err != nil {
|
||||
return E.Cause(err, "read config")
|
||||
}
|
||||
var options option.Options
|
||||
err = options.UnmarshalJSON(configContent)
|
||||
if err != nil {
|
||||
return E.Cause(err, "decode config")
|
||||
}
|
||||
buffer := new(bytes.Buffer)
|
||||
encoder := json.NewEncoder(buffer)
|
||||
encoder.SetIndent("", " ")
|
||||
err = encoder.Encode(options)
|
||||
if err != nil {
|
||||
return E.Cause(err, "encode config")
|
||||
}
|
||||
if !commandFormatFlagWrite {
|
||||
os.Stdout.WriteString(buffer.String() + "\n")
|
||||
return nil
|
||||
}
|
||||
if bytes.Equal(configContent, buffer.Bytes()) {
|
||||
return nil
|
||||
}
|
||||
output, err := os.Create(configPath)
|
||||
if err != nil {
|
||||
return E.Cause(err, "open output")
|
||||
}
|
||||
_, err = output.Write(buffer.Bytes())
|
||||
output.Close()
|
||||
if err != nil {
|
||||
return E.Cause(err, "write output")
|
||||
}
|
||||
outputPath, _ := filepath.Abs(configPath)
|
||||
os.Stderr.WriteString(outputPath + "\n")
|
||||
return nil
|
||||
}
|
||||
@@ -1,130 +0,0 @@
|
||||
package box_main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"neko/pkg/protect_server"
|
||||
"os"
|
||||
"os/signal"
|
||||
runtimeDebug "runtime/debug"
|
||||
"syscall"
|
||||
|
||||
box "github.com/sagernet/sing-box"
|
||||
"github.com/sagernet/sing-box/log"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var commandRun = &cobra.Command{
|
||||
Use: "run",
|
||||
Short: "Run service",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if protectListenPath != "" {
|
||||
// for v2ray now
|
||||
go protect_server.ServeProtect(protectListenPath, protectFwMark)
|
||||
}
|
||||
|
||||
err := run()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
mainCommand.AddCommand(commandRun)
|
||||
}
|
||||
|
||||
func readConfig(nekoConfigContent []byte) (option.Options, error) {
|
||||
var (
|
||||
configContent []byte
|
||||
err error
|
||||
)
|
||||
if nekoConfigContent == nil {
|
||||
if configPath == "stdin" {
|
||||
configContent, err = io.ReadAll(os.Stdin)
|
||||
} else {
|
||||
configContent, err = os.ReadFile(configPath)
|
||||
}
|
||||
} else {
|
||||
configContent = nekoConfigContent
|
||||
}
|
||||
if err != nil {
|
||||
return option.Options{}, E.Cause(err, "read config")
|
||||
}
|
||||
var options option.Options
|
||||
err = options.UnmarshalJSON(configContent)
|
||||
if err != nil {
|
||||
return option.Options{}, E.Cause(err, "decode config")
|
||||
}
|
||||
return options, nil
|
||||
}
|
||||
|
||||
func Create(nekoConfigContent []byte, forceDisableColor bool) (*box.Box, context.CancelFunc, error) {
|
||||
options, err := readConfig(nekoConfigContent)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if disableColor || forceDisableColor {
|
||||
if options.Log == nil {
|
||||
options.Log = &option.LogOptions{}
|
||||
}
|
||||
options.Log.DisableColor = true
|
||||
}
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
instance, err := box.New(ctx, options, nil)
|
||||
if err != nil {
|
||||
cancel()
|
||||
return nil, nil, E.Cause(err, "create service")
|
||||
}
|
||||
osSignals := make(chan os.Signal, 1)
|
||||
signal.Notify(osSignals, os.Interrupt, syscall.SIGTERM, syscall.SIGHUP)
|
||||
defer func() {
|
||||
signal.Stop(osSignals)
|
||||
close(osSignals)
|
||||
}()
|
||||
|
||||
go func() {
|
||||
_, loaded := <-osSignals
|
||||
if loaded {
|
||||
cancel()
|
||||
}
|
||||
}()
|
||||
err = instance.Start()
|
||||
if err != nil {
|
||||
cancel()
|
||||
return nil, nil, E.Cause(err, "start service")
|
||||
}
|
||||
return instance, cancel, nil
|
||||
}
|
||||
|
||||
func run() error {
|
||||
osSignals := make(chan os.Signal, 1)
|
||||
signal.Notify(osSignals, os.Interrupt, syscall.SIGTERM, syscall.SIGHUP)
|
||||
defer signal.Stop(osSignals)
|
||||
for {
|
||||
instance, cancel, err := Create(nil, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
runtimeDebug.FreeOSMemory()
|
||||
for {
|
||||
osSignal := <-osSignals
|
||||
if osSignal == syscall.SIGHUP {
|
||||
err = check()
|
||||
if err != nil {
|
||||
log.Error(E.Cause(err, "reload service"))
|
||||
continue
|
||||
}
|
||||
}
|
||||
cancel()
|
||||
instance.Close()
|
||||
if osSignal != syscall.SIGHUP {
|
||||
return nil
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
package box_main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"runtime"
|
||||
"runtime/debug"
|
||||
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var commandVersion = &cobra.Command{
|
||||
Use: "version",
|
||||
Short: "Print current version of sing-box",
|
||||
Run: printVersion,
|
||||
Args: cobra.NoArgs,
|
||||
}
|
||||
|
||||
var nameOnly bool
|
||||
|
||||
func init() {
|
||||
commandVersion.Flags().BoolVarP(&nameOnly, "name", "n", false, "print version name only")
|
||||
mainCommand.AddCommand(commandVersion)
|
||||
}
|
||||
|
||||
func printVersion(cmd *cobra.Command, args []string) {
|
||||
if nameOnly {
|
||||
os.Stdout.WriteString(C.Version + "\n")
|
||||
return
|
||||
}
|
||||
version := "sing-box version " + C.Version + "\n\n"
|
||||
version += "Environment: " + runtime.Version() + " " + runtime.GOOS + "/" + runtime.GOARCH + "\n"
|
||||
|
||||
var tags string
|
||||
var revision string
|
||||
|
||||
debugInfo, loaded := debug.ReadBuildInfo()
|
||||
if loaded {
|
||||
for _, setting := range debugInfo.Settings {
|
||||
switch setting.Key {
|
||||
case "-tags":
|
||||
tags = setting.Value
|
||||
case "vcs.revision":
|
||||
revision = setting.Value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if tags != "" {
|
||||
version += "Tags: " + tags + "\n"
|
||||
}
|
||||
if revision != "" {
|
||||
version += "Revision: " + revision + "\n"
|
||||
}
|
||||
|
||||
if C.CGO_ENABLED {
|
||||
version += "CGO: enabled\n"
|
||||
} else {
|
||||
version += "CGO: disabled\n"
|
||||
}
|
||||
|
||||
os.Stdout.WriteString(version)
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
//go:build debug
|
||||
|
||||
package box_main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
_ "net/http/pprof"
|
||||
"runtime"
|
||||
"runtime/debug"
|
||||
|
||||
"github.com/sagernet/sing-box/common/badjson"
|
||||
"github.com/sagernet/sing-box/log"
|
||||
|
||||
"github.com/dustin/go-humanize"
|
||||
)
|
||||
|
||||
func init() {
|
||||
http.HandleFunc("/debug/gc", func(writer http.ResponseWriter, request *http.Request) {
|
||||
writer.WriteHeader(http.StatusNoContent)
|
||||
go debug.FreeOSMemory()
|
||||
})
|
||||
http.HandleFunc("/debug/memory", func(writer http.ResponseWriter, request *http.Request) {
|
||||
var memStats runtime.MemStats
|
||||
runtime.ReadMemStats(&memStats)
|
||||
|
||||
var memObject badjson.JSONObject
|
||||
memObject.Put("heap", humanize.Bytes(memStats.HeapInuse))
|
||||
memObject.Put("stack", humanize.Bytes(memStats.StackInuse))
|
||||
memObject.Put("idle", humanize.Bytes(memStats.HeapIdle-memStats.HeapReleased))
|
||||
memObject.Put("goroutines", runtime.NumGoroutine())
|
||||
memObject.Put("rss", rusageMaxRSS())
|
||||
|
||||
encoder := json.NewEncoder(writer)
|
||||
encoder.SetIndent("", " ")
|
||||
encoder.Encode(memObject)
|
||||
})
|
||||
go func() {
|
||||
err := http.ListenAndServe("0.0.0.0:8964", nil)
|
||||
if err != nil {
|
||||
log.Debug(err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
//go:build debug
|
||||
|
||||
package box_main
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func rusageMaxRSS() float64 {
|
||||
ru := syscall.Rusage{}
|
||||
err := syscall.Getrusage(syscall.RUSAGE_SELF, &ru)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
rss := float64(ru.Maxrss)
|
||||
if runtime.GOOS == "darwin" || runtime.GOOS == "ios" {
|
||||
rss /= 1 << 20 // ru_maxrss is bytes on darwin
|
||||
} else {
|
||||
// ru_maxrss is kilobytes elsewhere (linux, openbsd, etc)
|
||||
rss /= 1 << 10
|
||||
}
|
||||
return rss
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
//go:build debug && !linux
|
||||
|
||||
package box_main
|
||||
|
||||
func rusageMaxRSS() float64 {
|
||||
return -1
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
package box_main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
_ "github.com/sagernet/sing-box/include"
|
||||
"github.com/sagernet/sing-box/log"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
configPath string
|
||||
workingDir string
|
||||
disableColor bool
|
||||
//
|
||||
protectListenPath string
|
||||
protectFwMark int
|
||||
)
|
||||
|
||||
var mainCommand = &cobra.Command{
|
||||
Use: "sing-box",
|
||||
PersistentPreRun: preRun,
|
||||
}
|
||||
|
||||
func Main() {
|
||||
mainCommand.PersistentFlags().StringVarP(&configPath, "config", "c", "config.json", "set configuration file path")
|
||||
mainCommand.PersistentFlags().StringVarP(&workingDir, "directory", "D", "", "set working directory")
|
||||
mainCommand.PersistentFlags().BoolVarP(&disableColor, "disable-color", "", false, "disable color output")
|
||||
mainCommand.PersistentFlags().StringVarP(&protectListenPath, "protect-listen-path", "", "", "Linux Only")
|
||||
mainCommand.PersistentFlags().IntVarP(&protectFwMark, "protect-fwmark", "", 0, "Linux Only")
|
||||
if err := mainCommand.Execute(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func preRun(cmd *cobra.Command, args []string) {
|
||||
if workingDir != "" {
|
||||
if err := os.Chdir(workingDir); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,14 +3,15 @@ package main
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"neko/pkg/neko_common"
|
||||
"neko/pkg/neko_log"
|
||||
"net"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/matsuridayo/libneko/neko_common"
|
||||
"github.com/matsuridayo/libneko/neko_log"
|
||||
|
||||
box "github.com/sagernet/sing-box"
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
"github.com/sagernet/sing-box/common/dialer"
|
||||
|
||||
@@ -3,15 +3,11 @@ module nekobox_core
|
||||
go 1.19
|
||||
|
||||
require (
|
||||
github.com/dustin/go-humanize v1.0.1
|
||||
github.com/gofrs/uuid v4.4.0+incompatible
|
||||
github.com/matsuridayo/libneko v0.0.0-20230304130313-5ea96b79b3c3
|
||||
github.com/matsuridayo/sing-box-extra v0.0.0-20230304131029-37eeda33b862
|
||||
github.com/sagernet/sing v0.1.8-0.20230301160041-9fab0a9f4304
|
||||
github.com/sagernet/sing-box v1.1.6-0.20230301163156-e8802357e1e7
|
||||
github.com/sagernet/sing-dns v0.1.4
|
||||
github.com/sagernet/sing-tun v0.1.2-0.20230226091124-0cdb0eed74d9
|
||||
github.com/spf13/cobra v1.6.1
|
||||
golang.org/x/sys v0.5.0
|
||||
neko v1.0.0
|
||||
grpc_server v1.0.0
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -22,11 +18,13 @@ require (
|
||||
github.com/caddyserver/certmagic v0.17.2 // indirect
|
||||
github.com/cloudflare/circl v1.2.1-0.20221019164342-6ab4dfed8f3c // indirect
|
||||
github.com/cretz/bine v0.2.0 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||
github.com/go-chi/chi/v5 v5.0.8 // indirect
|
||||
github.com/go-chi/cors v1.2.1 // indirect
|
||||
github.com/go-chi/render v1.0.2 // indirect
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
|
||||
github.com/gofrs/uuid v4.4.0+incompatible // indirect
|
||||
github.com/golang/mock v1.6.0 // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/google/btree v1.0.1 // indirect
|
||||
@@ -57,14 +55,17 @@ require (
|
||||
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 // indirect
|
||||
github.com/sagernet/quic-go v0.0.0-20230202071646-a8c8afb18b32 // indirect
|
||||
github.com/sagernet/reality v0.0.0-20230228045158-d3e085a8e5d1 // indirect
|
||||
github.com/sagernet/sing-dns v0.1.4 // indirect
|
||||
github.com/sagernet/sing-shadowsocks v0.1.2-0.20230221080503-769c01d6bba9 // indirect
|
||||
github.com/sagernet/sing-shadowtls v0.0.0-20230221123345-78e50cd7b587 // indirect
|
||||
github.com/sagernet/sing-tun v0.1.2-0.20230226091124-0cdb0eed74d9 // indirect
|
||||
github.com/sagernet/sing-vmess v0.1.2 // indirect
|
||||
github.com/sagernet/smux v0.0.0-20220831015742-e0f1988e3195 // indirect
|
||||
github.com/sagernet/tfo-go v0.0.0-20230207095944-549363a7327d // indirect
|
||||
github.com/sagernet/utls v0.0.0-20230225061716-536a007c8b01 // indirect
|
||||
github.com/sagernet/websocket v0.0.0-20220913015213-615516348b4e // indirect
|
||||
github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c // indirect
|
||||
github.com/spf13/cobra v1.6.1 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/u-root/uio v0.0.0-20230215032506-9aa6f7e2d72c // indirect
|
||||
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect
|
||||
@@ -77,6 +78,7 @@ require (
|
||||
golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb // indirect
|
||||
golang.org/x/mod v0.6.0 // indirect
|
||||
golang.org/x/net v0.7.0 // indirect
|
||||
golang.org/x/sys v0.5.0 // indirect
|
||||
golang.org/x/text v0.7.0 // indirect
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect
|
||||
golang.org/x/tools v0.2.0 // indirect
|
||||
@@ -87,6 +89,6 @@ require (
|
||||
lukechampine.com/blake3 v1.1.7 // indirect
|
||||
)
|
||||
|
||||
replace neko v1.0.0 => ../../
|
||||
replace grpc_server v1.0.0 => ../../grpc_server
|
||||
|
||||
// replace github.com/sagernet/sing-box => ../../../../sing-box
|
||||
|
||||
@@ -105,6 +105,10 @@ github.com/libdns/libdns v0.2.1 h1:Wu59T7wSHRgtA0cfxC+n1c/e+O3upJGWytknkmFEDis=
|
||||
github.com/libdns/libdns v0.2.1/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40=
|
||||
github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8=
|
||||
github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
|
||||
github.com/matsuridayo/libneko v0.0.0-20230304130313-5ea96b79b3c3 h1:emqnGHIlezKjm24Lz5aos9Lc1bhxFL8Ynp20EprSNJc=
|
||||
github.com/matsuridayo/libneko v0.0.0-20230304130313-5ea96b79b3c3/go.mod h1:IRO07Queptz/rGFvEW+3Hmwpx7MCup6WiDs4p5jMt4g=
|
||||
github.com/matsuridayo/sing-box-extra v0.0.0-20230304131029-37eeda33b862 h1:z8qC1cSVDZrhJbZPgsp1oM8rxnzMb+aU3FxAYG27S+k=
|
||||
github.com/matsuridayo/sing-box-extra v0.0.0-20230304131029-37eeda33b862/go.mod h1:5YMikmz+Vpr5P7/rSigF92Yf5pBsCzDq9IpQRjoLb3E=
|
||||
github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7/go.mod h1:U6ZQobyTjI/tJyq2HG+i/dfSoFUt8/aZCM+GKtmFk/Y=
|
||||
github.com/mdlayher/netlink v0.0.0-20190409211403-11939a169225/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA=
|
||||
github.com/mdlayher/netlink v1.0.0/go.mod h1:KxeJAFOFLG6AjpyDkQ/iIhxygIUKD+vcwqcnu43w/+M=
|
||||
|
||||
@@ -4,14 +4,18 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"grpc_server"
|
||||
"grpc_server/gen"
|
||||
|
||||
"github.com/matsuridayo/libneko/neko_common"
|
||||
"github.com/matsuridayo/libneko/neko_log"
|
||||
"github.com/matsuridayo/libneko/speedtest"
|
||||
"github.com/matsuridayo/sing-box-extra/boxapi"
|
||||
"github.com/matsuridayo/sing-box-extra/boxmain"
|
||||
|
||||
"io"
|
||||
"log"
|
||||
"neko/gen"
|
||||
"neko/pkg/grpc_server"
|
||||
"neko/pkg/neko_common"
|
||||
"neko/pkg/neko_log"
|
||||
"neko/pkg/speedtest"
|
||||
"nekobox_core/box_main"
|
||||
"reflect"
|
||||
"time"
|
||||
"unsafe"
|
||||
@@ -44,7 +48,7 @@ func (s *server) Start(ctx context.Context, in *gen.LoadConfigReq) (out *gen.Err
|
||||
return
|
||||
}
|
||||
|
||||
instance, instance_cancel, err = box_main.Create([]byte(in.CoreConfig), true)
|
||||
instance, instance_cancel, err = boxmain.Create([]byte(in.CoreConfig), true)
|
||||
|
||||
if instance != nil {
|
||||
// Logger
|
||||
@@ -55,7 +59,7 @@ func (s *server) Start(ctx context.Context, in *gen.LoadConfigReq) (out *gen.Err
|
||||
writer_ = reflect.NewAt(writer_.Type(), unsafe.Pointer(writer_.UnsafeAddr())).Elem() // get unexported io.Writer
|
||||
writer_.Set(reflect.ValueOf(neko_log.LogWriter))
|
||||
// V2ray Service
|
||||
instance.Router().SetV2RayServer(NewSbV2rayServer())
|
||||
instance.Router().SetV2RayServer(boxapi.NewSbV2rayServer())
|
||||
}
|
||||
|
||||
return
|
||||
@@ -111,7 +115,7 @@ func (s *server) Test(ctx context.Context, in *gen.TestReq) (out *gen.TestResp,
|
||||
var i *box.Box
|
||||
if in.Config != nil {
|
||||
// Test instance
|
||||
i, instance_cancel, err = box_main.Create([]byte(in.Config.CoreConfig), true)
|
||||
i, instance_cancel, err = boxmain.Create([]byte(in.Config.CoreConfig), true)
|
||||
if instance_cancel != nil {
|
||||
defer instance_cancel()
|
||||
}
|
||||
@@ -139,10 +143,10 @@ func (s *server) Test(ctx context.Context, in *gen.TestReq) (out *gen.TestResp,
|
||||
func (s *server) QueryStats(ctx context.Context, in *gen.QueryStatsReq) (out *gen.QueryStatsResp, _ error) {
|
||||
out = &gen.QueryStatsResp{}
|
||||
|
||||
var box_v2ray_service *sbV2rayStatsService
|
||||
var box_v2ray_service *boxapi.SbV2rayStatsService
|
||||
|
||||
if instance != nil && instance.Router().V2RayServer() != nil {
|
||||
box_v2ray_service, _ = instance.Router().V2RayServer().StatsService().(*sbV2rayStatsService)
|
||||
box_v2ray_service, _ = instance.Router().V2RayServer().StatsService().(*boxapi.SbV2rayStatsService)
|
||||
}
|
||||
|
||||
if box_v2ray_service != nil {
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"unsafe"
|
||||
|
||||
D "github.com/sagernet/sing-dns"
|
||||
"github.com/sagernet/sing/common/logger"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
)
|
||||
|
||||
var underlyingDNS string
|
||||
|
||||
func init() {
|
||||
D.RegisterTransport([]string{"underlying"}, CreateUnderlyingTransport)
|
||||
}
|
||||
|
||||
func CreateUnderlyingTransport(ctx context.Context, logger logger.ContextLogger, dialer N.Dialer, link string) (D.Transport, error) {
|
||||
if runtime.GOOS != "windows" {
|
||||
// Linux no resolv.conf change
|
||||
return D.CreateLocalTransport(ctx, logger, dialer, "local")
|
||||
}
|
||||
// Windows Underlying DNS hook
|
||||
t, _ := D.CreateUDPTransport(ctx, logger, dialer, link)
|
||||
udp := t.(*D.UDPTransport)
|
||||
handler_ := reflect.Indirect(reflect.ValueOf(udp)).FieldByName("handler")
|
||||
handler_ = reflect.NewAt(handler_.Type(), unsafe.Pointer(handler_.UnsafeAddr())).Elem()
|
||||
handler_.Set(reflect.ValueOf(&myTransportHandler{udp, dialer}))
|
||||
return t, nil
|
||||
}
|
||||
|
||||
type myTransportHandler struct {
|
||||
*D.UDPTransport
|
||||
dialer N.Dialer
|
||||
}
|
||||
|
||||
func (t *myTransportHandler) DialContext(ctx context.Context, queryCtx context.Context) (net.Conn, error) {
|
||||
if underlyingDNS == "" {
|
||||
return nil, errors.New("no underlyingDNS")
|
||||
}
|
||||
return t.dialer.DialContext(ctx, "udp", M.ParseSocksaddrHostPort(underlyingDNS, 53))
|
||||
}
|
||||
@@ -5,15 +5,17 @@ import (
|
||||
"os"
|
||||
_ "unsafe"
|
||||
|
||||
"neko/pkg/grpc_server"
|
||||
"neko/pkg/neko_common"
|
||||
"nekobox_core/box_main"
|
||||
"grpc_server"
|
||||
|
||||
"github.com/matsuridayo/libneko/neko_common"
|
||||
"github.com/matsuridayo/sing-box-extra/boxmain"
|
||||
_ "github.com/matsuridayo/sing-box-extra/distro/all"
|
||||
|
||||
"github.com/sagernet/sing-box/constant"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println("sing-box:", constant.Version, "Neko:", neko_common.Version_neko)
|
||||
fmt.Println("sing-box:", constant.Version, "NekoBox:", neko_common.Version_neko)
|
||||
fmt.Println()
|
||||
|
||||
// local DNS transport
|
||||
@@ -27,5 +29,5 @@ func main() {
|
||||
}
|
||||
|
||||
// sing-box
|
||||
box_main.Main()
|
||||
boxmain.Main()
|
||||
}
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"neko/pkg/iphlpapi"
|
||||
"net/netip"
|
||||
"strings"
|
||||
|
||||
tun "github.com/sagernet/sing-tun"
|
||||
|
||||
"github.com/gofrs/uuid"
|
||||
"golang.org/x/sys/windows/registry"
|
||||
)
|
||||
|
||||
var monitorNU tun.NetworkUpdateMonitor
|
||||
var monitorDI tun.DefaultInterfaceMonitor
|
||||
|
||||
func init() {
|
||||
monitorNU, _ = tun.NewNetworkUpdateMonitor(&emptyErrorHandler{})
|
||||
monitorDI, _ = tun.NewDefaultInterfaceMonitor(monitorNU, tun.DefaultInterfaceMonitorOptions{})
|
||||
monitorDI.RegisterCallback(monitorForUnderlyingDNS)
|
||||
monitorDI.Start()
|
||||
monitorNU.Start()
|
||||
}
|
||||
|
||||
type emptyErrorHandler struct{}
|
||||
|
||||
func (e *emptyErrorHandler) NewError(ctx context.Context, err error) {}
|
||||
|
||||
func monitorForUnderlyingDNS(event int) error {
|
||||
index := monitorDI.DefaultInterfaceIndex(netip.IPv4Unspecified())
|
||||
var guid iphlpapi.GUID
|
||||
if errno := iphlpapi.Index2GUID(uint64(index), &guid); errno != 0 {
|
||||
return nil
|
||||
}
|
||||
u, _ := uuid.FromBytes([]byte{
|
||||
guid.Data1[3], guid.Data1[2], guid.Data1[1], guid.Data1[0],
|
||||
guid.Data2[1], guid.Data2[0],
|
||||
guid.Data3[1], guid.Data3[0],
|
||||
guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
|
||||
guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7],
|
||||
})
|
||||
guidStr := "{" + u.String() + "}"
|
||||
underlyingDNS = getFirstDNS(guidStr)
|
||||
log.Println("underlyingDNS:", guidStr, underlyingDNS)
|
||||
return nil
|
||||
}
|
||||
|
||||
func getFirstDNS(guid string) string {
|
||||
dns, err := getNameServersForInterface(guid)
|
||||
if err != nil || len(dns) == 0 {
|
||||
return ""
|
||||
}
|
||||
return dns[0]
|
||||
}
|
||||
|
||||
func getNameServersForInterface(guid string) ([]string, error) {
|
||||
key, err := registry.OpenKey(registry.LOCAL_MACHINE, `SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\`+guid, registry.QUERY_VALUE)
|
||||
if err != nil {
|
||||
log.Println("getNameServersForInterface OpenKey:", err)
|
||||
return nil, err
|
||||
}
|
||||
defer key.Close()
|
||||
|
||||
nameservers := make([]string, 0, 4)
|
||||
for _, name := range []string{`NameServer`, `DhcpNameServer`} {
|
||||
s, _, err := key.GetStringValue(name)
|
||||
if err != nil {
|
||||
log.Println("getNameServersForInterface GetStringValue:", name, err)
|
||||
continue
|
||||
}
|
||||
s = strings.ReplaceAll(s, ",", " ")
|
||||
for _, server := range strings.Split(s, " ") {
|
||||
if server != "" {
|
||||
nameservers = append(nameservers, server)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nameservers, nil
|
||||
}
|
||||
2
go/cmd/nekobox_core/update-extra.sh
Normal file
2
go/cmd/nekobox_core/update-extra.sh
Normal file
@@ -0,0 +1,2 @@
|
||||
go get github.com/matsuridayo/sing-box-extra@"$1"
|
||||
go mod tidy
|
||||
@@ -1,41 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
"github.com/sagernet/sing-box/experimental/v2rayapi"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
"github.com/sagernet/sing/common/network"
|
||||
)
|
||||
|
||||
type sbV2rayServer struct {
|
||||
ss *sbV2rayStatsService
|
||||
}
|
||||
|
||||
func NewSbV2rayServer() adapter.V2RayServer {
|
||||
options := option.V2RayStatsServiceOptions{
|
||||
Enabled: true,
|
||||
Outbounds: []string{"proxy", "bypass"}, // TODO
|
||||
}
|
||||
return &sbV2rayServer{
|
||||
ss: &sbV2rayStatsService{v2rayapi.NewStatsService(options)},
|
||||
}
|
||||
}
|
||||
|
||||
func (s *sbV2rayServer) Start() error { return nil }
|
||||
func (s *sbV2rayServer) Close() error { return nil }
|
||||
func (s *sbV2rayServer) StatsService() adapter.V2RayStatsService { return s.ss }
|
||||
|
||||
type sbV2rayStatsService struct {
|
||||
*v2rayapi.StatsService
|
||||
}
|
||||
|
||||
func (s *sbV2rayStatsService) RoutedConnection(inbound string, outbound string, user string, conn net.Conn) net.Conn {
|
||||
// TODO track
|
||||
return s.StatsService.RoutedConnection(inbound, outbound, user, conn)
|
||||
}
|
||||
|
||||
func (s *sbV2rayStatsService) RoutedPacketConnection(inbound string, outbound string, user string, conn network.PacketConn) network.PacketConn {
|
||||
return s.StatsService.RoutedPacketConnection(inbound, outbound, user, conn)
|
||||
}
|
||||
@@ -4,13 +4,14 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"neko/pkg/neko_common"
|
||||
"neko/pkg/neko_log"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/matsuridayo/libneko/neko_common"
|
||||
"github.com/matsuridayo/libneko/neko_log"
|
||||
|
||||
core "github.com/v2fly/v2ray-core/v5"
|
||||
appLog "github.com/v2fly/v2ray-core/v5/app/log"
|
||||
commonLog "github.com/v2fly/v2ray-core/v5/common/log"
|
||||
|
||||
@@ -5,9 +5,10 @@ go 1.19
|
||||
require (
|
||||
github.com/Dreamacro/clash v1.9.0
|
||||
github.com/jsimonetti/rtnetlink v1.2.2
|
||||
github.com/matsuridayo/libneko v0.0.0-20230304130313-5ea96b79b3c3
|
||||
github.com/v2fly/v2ray-core/v5 v5.0.0
|
||||
grpc_server v1.0.0
|
||||
kernel.org/pub/linux/libs/security/libcap/cap v1.2.65
|
||||
neko v1.0.0
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -75,6 +76,8 @@ require (
|
||||
kernel.org/pub/linux/libs/security/libcap/psx v1.2.65 // indirect
|
||||
)
|
||||
|
||||
replace neko v1.0.0 => ../../
|
||||
replace neko v1.0.0 => ../../neko
|
||||
|
||||
replace grpc_server v1.0.0 => ../../grpc_server
|
||||
|
||||
replace github.com/v2fly/v2ray-core/v5 v5.0.0 => ../../../../v2ray-core
|
||||
|
||||
@@ -249,6 +249,8 @@ github.com/lunixbochs/struc v0.0.0-20190916212049-a5c72983bc42/go.mod h1:vy1vK6w
|
||||
github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 h1:EnfXoSqDfSNJv0VBNqY/88RNnhSGYkrHaO0mmFGbVsc=
|
||||
github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40/go.mod h1:vy1vK6wD6j7xX6O6hXe621WabdtNkou2h7uRtTfRMyg=
|
||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/matsuridayo/libneko v0.0.0-20230304130313-5ea96b79b3c3 h1:emqnGHIlezKjm24Lz5aos9Lc1bhxFL8Ynp20EprSNJc=
|
||||
github.com/matsuridayo/libneko v0.0.0-20230304130313-5ea96b79b3c3/go.mod h1:IRO07Queptz/rGFvEW+3Hmwpx7MCup6WiDs4p5jMt4g=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
|
||||
@@ -6,16 +6,17 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"grpc_server"
|
||||
"grpc_server/gen"
|
||||
"io"
|
||||
"log"
|
||||
"neko/gen"
|
||||
"neko/pkg/grpc_server"
|
||||
"neko/pkg/neko_common"
|
||||
"neko/pkg/speedtest"
|
||||
"net"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/matsuridayo/libneko/neko_common"
|
||||
"github.com/matsuridayo/libneko/speedtest"
|
||||
|
||||
core "github.com/v2fly/v2ray-core/v5"
|
||||
"github.com/v2fly/v2ray-core/v5/nekoutils"
|
||||
)
|
||||
|
||||
@@ -2,11 +2,12 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"neko/pkg/grpc_server"
|
||||
"neko/pkg/neko_common"
|
||||
"grpc_server"
|
||||
"os"
|
||||
_ "unsafe"
|
||||
|
||||
"github.com/matsuridayo/libneko/neko_common"
|
||||
|
||||
"github.com/v2fly/v2ray-core/v5/main/commands"
|
||||
"github.com/v2fly/v2ray-core/v5/main/commands/base"
|
||||
)
|
||||
|
||||
@@ -3,13 +3,14 @@ package main
|
||||
import (
|
||||
"encoding/binary"
|
||||
"log"
|
||||
"neko/pkg/iphlpapi"
|
||||
"net"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/matsuridayo/libneko/iphlpapi"
|
||||
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet"
|
||||
)
|
||||
|
||||
|
||||
@@ -4,12 +4,13 @@ import (
|
||||
"flag"
|
||||
"io"
|
||||
"log"
|
||||
"neko/pkg/protect_server"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"syscall"
|
||||
|
||||
"github.com/matsuridayo/libneko/protect_server"
|
||||
|
||||
"github.com/jsimonetti/rtnetlink"
|
||||
linuxcap "kernel.org/pub/linux/libs/security/libcap/cap"
|
||||
)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package neko_auth
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -894,8 +894,9 @@ var file_libcore_proto_rawDesc = []byte{
|
||||
0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x11, 0x2e, 0x6c, 0x69, 0x62, 0x63, 0x6f,
|
||||
0x72, 0x65, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x52, 0x65, 0x71, 0x1a, 0x1c, 0x2e, 0x6c, 0x69,
|
||||
0x62, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x42, 0x0a, 0x5a, 0x08, 0x6e,
|
||||
0x65, 0x6b, 0x6f, 0x2f, 0x67, 0x65, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x42, 0x16, 0x5a, 0x14, 0x6e,
|
||||
0x65, 0x6b, 0x6f, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f,
|
||||
0x67, 0x65, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -1,7 +1,7 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package libcore;
|
||||
option go_package = "neko/gen";
|
||||
option go_package = "grpc_server/gen";
|
||||
|
||||
service LibcoreService {
|
||||
rpc Exit(EmptyReq) returns (EmptyResp) {}
|
||||
@@ -1,9 +1,10 @@
|
||||
module neko
|
||||
module grpc_server
|
||||
|
||||
go 1.19
|
||||
|
||||
require (
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0
|
||||
github.com/matsuridayo/libneko v0.0.0-20230304130313-5ea96b79b3c3
|
||||
google.golang.org/grpc v1.49.0
|
||||
google.golang.org/protobuf v1.28.1
|
||||
)
|
||||
@@ -56,6 +56,8 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/matsuridayo/libneko v0.0.0-20230304130313-5ea96b79b3c3 h1:emqnGHIlezKjm24Lz5aos9Lc1bhxFL8Ynp20EprSNJc=
|
||||
github.com/matsuridayo/libneko v0.0.0-20230304130313-5ea96b79b3c3/go.mod h1:IRO07Queptz/rGFvEW+3Hmwpx7MCup6WiDs4p5jMt4g=
|
||||
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
@@ -5,10 +5,9 @@ import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"grpc_server/auth"
|
||||
"grpc_server/gen"
|
||||
"log"
|
||||
"neko/gen"
|
||||
"neko/pkg/neko_auth"
|
||||
"neko/pkg/neko_common"
|
||||
"net"
|
||||
"os"
|
||||
"runtime"
|
||||
@@ -17,6 +16,8 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/matsuridayo/libneko/neko_common"
|
||||
|
||||
grpc_auth "github.com/grpc-ecosystem/go-grpc-middleware/auth"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
@@ -83,7 +84,7 @@ func RunCore(setupCore func(), server gen.LibcoreServiceServer) {
|
||||
}
|
||||
os.Stderr.WriteString("token is set\n")
|
||||
|
||||
auther := neko_auth.Authenticator{
|
||||
auther := auth.Authenticator{
|
||||
Token: token,
|
||||
}
|
||||
|
||||
@@ -3,14 +3,15 @@ package grpc_server
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"grpc_server/gen"
|
||||
"io"
|
||||
"neko/gen"
|
||||
"neko/pkg/neko_common"
|
||||
"net/http"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/matsuridayo/libneko/neko_common"
|
||||
)
|
||||
|
||||
var update_download_url string
|
||||
@@ -1,18 +0,0 @@
|
||||
package iphlpapi
|
||||
|
||||
import "syscall"
|
||||
|
||||
var (
|
||||
proc_GetIpForwardTable *syscall.LazyProc
|
||||
proc_NotifyRouteChange2 *syscall.LazyProc
|
||||
proc_ConvertInterfaceIndexToLuid *syscall.LazyProc
|
||||
proc_ConvertInterfaceLuidToGuid *syscall.LazyProc
|
||||
)
|
||||
|
||||
func init() {
|
||||
iphlpapi := syscall.NewLazyDLL("iphlpapi.dll")
|
||||
proc_GetIpForwardTable = iphlpapi.NewProc("GetIpForwardTable")
|
||||
proc_NotifyRouteChange2 = iphlpapi.NewProc("NotifyRouteChange2")
|
||||
proc_ConvertInterfaceIndexToLuid = iphlpapi.NewProc("ConvertInterfaceIndexToLuid")
|
||||
proc_ConvertInterfaceLuidToGuid = iphlpapi.NewProc("ConvertInterfaceLuidToGuid")
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package iphlpapi
|
||||
|
||||
import "unsafe"
|
||||
|
||||
type GUID struct {
|
||||
Data1 [4]byte
|
||||
Data2 [2]byte
|
||||
Data3 [2]byte
|
||||
Data4 [8]byte
|
||||
}
|
||||
|
||||
func Index2GUID(index uint64, guid *GUID) uint16 {
|
||||
var luid uint64
|
||||
a, _, _ := proc_ConvertInterfaceIndexToLuid.Call(uintptr(index), uintptr(unsafe.Pointer(&luid)))
|
||||
if a != 0 {
|
||||
return uint16(a)
|
||||
}
|
||||
a, _, _ = proc_ConvertInterfaceLuidToGuid.Call(uintptr(unsafe.Pointer(&luid)), uintptr(unsafe.Pointer(guid)))
|
||||
return uint16(a)
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package iphlpapi
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func notifyRouteChange2(family uint16, callback uintptr, callerContext uintptr, initialNotification bool, notificationHandle *syscall.Handle) (ret error) {
|
||||
var _p0 uint32
|
||||
if initialNotification {
|
||||
_p0 = 1
|
||||
}
|
||||
r0, _, _ := syscall.Syscall6(proc_NotifyRouteChange2.Addr(), 5, uintptr(family), uintptr(callback), uintptr(callerContext), uintptr(_p0), uintptr(unsafe.Pointer(notificationHandle)), 0)
|
||||
if r0 != 0 {
|
||||
ret = syscall.Errno(r0)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func RegisterNotifyRouteChange2(callback func(callerContext uintptr, row uintptr, notificationType uint32) uintptr, initialNotification bool) (handle syscall.Handle) {
|
||||
notifyRouteChange2(syscall.AF_UNSPEC, syscall.NewCallback(callback), 0, initialNotification, &handle)
|
||||
return
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
package iphlpapi
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
/*
|
||||
对于路由表,预期的方法是:
|
||||
查询 0.0.0.0/0 获得原始默认路由
|
||||
然后为 vpn 服务器添加默认路由
|
||||
之后就根据需要下发vpn路由完事。
|
||||
对于0.0.0.0/0 vpn 路由,可以尝试更低的跃点数,也可以尝试分为2个。
|
||||
重新连接时可以删除vpn接口的所有非链路路由表。
|
||||
路由表格式:
|
||||
目标网络 uint32 掩码位数 byte低6位 vpn/默认网关 byte 高1位
|
||||
*/
|
||||
|
||||
// 太低的值添加路由时会返回 106 错误
|
||||
const routeMetric = 93
|
||||
|
||||
type RouteRow struct {
|
||||
ForwardDest [4]byte //目标网络
|
||||
ForwardMask [4]byte //掩码
|
||||
ForwardPolicy uint32 //ForwardPolicy:0x0
|
||||
ForwardNextHop [4]byte //网关
|
||||
ForwardIfIndex uint32 // 网卡索引 id
|
||||
ForwardType uint32 //3 本地接口 4 远端接口
|
||||
ForwardProto uint32 //3静态路由 2本地接口 5EGP网关
|
||||
ForwardAge uint32 //存在时间 秒
|
||||
ForwardNextHopAS uint32 //下一跳自治域号码 0
|
||||
ForwardMetric1 uint32 //度量衡(跃点数),根据 ForwardProto 不同意义不同。
|
||||
ForwardMetric2 uint32
|
||||
ForwardMetric3 uint32
|
||||
ForwardMetric4 uint32
|
||||
ForwardMetric5 uint32
|
||||
}
|
||||
|
||||
func (rr *RouteRow) GetForwardDest() net.IP {
|
||||
return net.IP(rr.ForwardDest[:])
|
||||
}
|
||||
func (rr *RouteRow) GetForwardMask() net.IP {
|
||||
return net.IP(rr.ForwardMask[:])
|
||||
}
|
||||
func (rr *RouteRow) GetForwardNextHop() net.IP {
|
||||
return net.IP(rr.ForwardNextHop[:])
|
||||
}
|
||||
|
||||
func GetRoutes() ([]RouteRow, error) {
|
||||
buf := make([]byte, 4+unsafe.Sizeof(RouteRow{}))
|
||||
buf_len := uint32(len(buf))
|
||||
|
||||
proc_GetIpForwardTable.Call(uintptr(unsafe.Pointer(&buf[0])),
|
||||
uintptr(unsafe.Pointer(&buf_len)), 0)
|
||||
|
||||
var r1 uintptr
|
||||
for i := 0; i < 5; i++ {
|
||||
buf = make([]byte, buf_len)
|
||||
r1, _, _ = proc_GetIpForwardTable.Call(uintptr(unsafe.Pointer(&buf[0])),
|
||||
uintptr(unsafe.Pointer(&buf_len)), 0)
|
||||
if r1 == 122 {
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
if r1 != 0 {
|
||||
return nil, fmt.Errorf("Failed to get the routing table, return value:%v", r1)
|
||||
}
|
||||
|
||||
num := *(*uint32)(unsafe.Pointer(&buf[0]))
|
||||
routes := make([]RouteRow, num)
|
||||
sr := uintptr(unsafe.Pointer(&buf[0])) + unsafe.Sizeof(num)
|
||||
rowSize := unsafe.Sizeof(RouteRow{})
|
||||
|
||||
// 安全检查
|
||||
if len(buf) < int((unsafe.Sizeof(num) + rowSize*uintptr(num))) {
|
||||
return nil, fmt.Errorf("System error: GetIpForwardTable returns the number is too long, beyond the buffer。")
|
||||
}
|
||||
|
||||
for i := uint32(0); i < num; i++ {
|
||||
routes[i] = *((*RouteRow)(unsafe.Pointer(sr + (rowSize * uintptr(i)))))
|
||||
}
|
||||
|
||||
return routes, nil
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package neko_common
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
var Version_v2ray string = "N/A"
|
||||
var Version_neko string = "N/A"
|
||||
|
||||
var Debug bool
|
||||
|
||||
var RunMode int
|
||||
|
||||
const (
|
||||
RunMode_Other = iota
|
||||
RunMode_NekoRay_Core
|
||||
RunMode_NekoBox_Core
|
||||
)
|
||||
|
||||
var GetProxyHttpClient func() *http.Client
|
||||
@@ -1,56 +0,0 @@
|
||||
package neko_log
|
||||
|
||||
import (
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
var f_neko_log *os.File
|
||||
|
||||
var LogWriter *logWriter
|
||||
|
||||
func SetupLog(maxSize int, path string) {
|
||||
if f_neko_log != nil && LogWriter != nil {
|
||||
return
|
||||
}
|
||||
// Truncate mod from libcore, simplify because only 1 proccess.
|
||||
oldBytes, err := os.ReadFile(path)
|
||||
if err == nil && len(oldBytes) > maxSize {
|
||||
if os.Truncate(path, 0) == nil {
|
||||
oldBytes = oldBytes[len(oldBytes)-maxSize:]
|
||||
}
|
||||
}
|
||||
// open
|
||||
f_neko_log, err = os.OpenFile(path, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0644)
|
||||
if err == nil {
|
||||
f_neko_log.Write(oldBytes)
|
||||
} else {
|
||||
log.Println("error open log", err)
|
||||
}
|
||||
//
|
||||
LogWriter = &logWriter{
|
||||
files: []io.Writer{os.Stdout, f_neko_log},
|
||||
}
|
||||
// setup std log
|
||||
log.SetFlags(log.LstdFlags | log.LUTC)
|
||||
log.SetOutput(LogWriter)
|
||||
|
||||
}
|
||||
|
||||
type logWriter struct {
|
||||
files []io.Writer
|
||||
}
|
||||
|
||||
func (w *logWriter) Write(p []byte) (n int, err error) {
|
||||
for _, file := range w.files {
|
||||
if file == nil {
|
||||
continue
|
||||
}
|
||||
n, err = file.Write(p)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
package protect_server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"os/signal"
|
||||
"reflect"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func getOneFd(socket int) (int, error) {
|
||||
// recvmsg
|
||||
buf := make([]byte, syscall.CmsgSpace(4))
|
||||
_, _, _, _, err := syscall.Recvmsg(socket, nil, buf, 0)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// parse control msgs
|
||||
var msgs []syscall.SocketControlMessage
|
||||
msgs, err = syscall.ParseSocketControlMessage(buf)
|
||||
|
||||
if len(msgs) != 1 {
|
||||
return 0, fmt.Errorf("invaild msgs count: %d", len(msgs))
|
||||
}
|
||||
|
||||
var fds []int
|
||||
fds, err = syscall.ParseUnixRights(&msgs[0])
|
||||
if len(fds) != 1 {
|
||||
return 0, fmt.Errorf("invaild fds count: %d", len(fds))
|
||||
}
|
||||
return fds[0], nil
|
||||
}
|
||||
|
||||
// GetFdFromConn get net.Conn's file descriptor.
|
||||
func GetFdFromConn(l net.Conn) int {
|
||||
v := reflect.ValueOf(l)
|
||||
netFD := reflect.Indirect(reflect.Indirect(v).FieldByName("fd"))
|
||||
pfd := reflect.Indirect(netFD.FieldByName("pfd"))
|
||||
fd := int(pfd.FieldByName("Sysfd").Int())
|
||||
return fd
|
||||
}
|
||||
|
||||
func ServeProtect(path string, fwmark int) {
|
||||
fmt.Println("ServeProtect", path, fwmark)
|
||||
|
||||
os.Remove(path)
|
||||
defer os.Remove(path)
|
||||
|
||||
l, err := net.ListenUnix("unix", &net.UnixAddr{Name: path, Net: "unix"})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer l.Close()
|
||||
|
||||
os.Chmod(path, 0777)
|
||||
|
||||
go func() {
|
||||
for {
|
||||
c, err := l.Accept()
|
||||
if err != nil {
|
||||
log.Println("Accept:", err)
|
||||
return
|
||||
}
|
||||
|
||||
go func() {
|
||||
socket := GetFdFromConn(c)
|
||||
defer c.Close()
|
||||
|
||||
fd, err := getOneFd(socket)
|
||||
if err != nil {
|
||||
log.Println("getOneFd:", err)
|
||||
return
|
||||
}
|
||||
defer syscall.Close(fd)
|
||||
|
||||
if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_MARK, fwmark); err != nil {
|
||||
log.Println("syscall.SetsockoptInt:", err)
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
c.Write([]byte{1})
|
||||
} else {
|
||||
c.Write([]byte{0})
|
||||
}
|
||||
}()
|
||||
}
|
||||
}()
|
||||
|
||||
sigCh := make(chan os.Signal, 1)
|
||||
signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
|
||||
<-sigCh
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
//go:build !linux
|
||||
|
||||
package protect_server
|
||||
|
||||
func ServeProtect(path string, fwmark int) {}
|
||||
@@ -1,65 +0,0 @@
|
||||
package speedtest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"math/rand"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func UrlTest(client *http.Client, link string, timeout int32) (int32, error) {
|
||||
if client == nil {
|
||||
return 0, fmt.Errorf("no client")
|
||||
}
|
||||
|
||||
// Test handshake time
|
||||
var time_start time.Time
|
||||
var times = 1
|
||||
var rtt_times = 1
|
||||
|
||||
// Test RTT "true delay"
|
||||
if link2 := strings.TrimLeft(link, "true"); link != link2 {
|
||||
link = link2
|
||||
times = 3
|
||||
rtt_times = 2
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeout)*time.Millisecond)
|
||||
defer cancel()
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", link, nil)
|
||||
req.Header.Set("User-Agent", fmt.Sprintf("curl/7.%d.%d", rand.Int()%84, rand.Int()%2))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
for i := 0; i < times; i++ {
|
||||
if i == 1 || times == 1 {
|
||||
time_start = time.Now()
|
||||
}
|
||||
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
log.Println("Url test failed:", err)
|
||||
return 0, err
|
||||
}
|
||||
resp.Body.Close()
|
||||
}
|
||||
|
||||
return int32(time.Since(time_start).Milliseconds() / int64(rtt_times)), nil
|
||||
}
|
||||
|
||||
func TcpPing(address string, timeout int32) (ms int32, err error) {
|
||||
startTime := time.Now()
|
||||
c, err := net.DialTimeout("tcp", address, time.Duration(timeout)*time.Millisecond)
|
||||
endTime := time.Now()
|
||||
if err == nil {
|
||||
ms = int32(endTime.Sub(startTime).Milliseconds())
|
||||
c.Close()
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -22,14 +22,15 @@ pushd go/cmd/updater
|
||||
popd
|
||||
|
||||
#### Go: nekoray_core ####
|
||||
neko_common="github.com/matsuridayo/libneko/neko_common"
|
||||
pushd ../v2ray-core
|
||||
version_v2ray=$(git log --pretty=format:'%h' -n 1)
|
||||
popd
|
||||
pushd go/cmd/nekoray_core
|
||||
go build -v -o $DEST -trimpath -ldflags "-w -s -X neko/pkg/neko_common.Version_v2ray=$version_v2ray -X neko/pkg/neko_common.Version_neko=$version_standalone"
|
||||
go build -v -o $DEST -trimpath -ldflags "-w -s -X $neko_common.Version_v2ray=$version_v2ray -X $neko_common.Version_neko=$version_standalone"
|
||||
popd
|
||||
|
||||
#### Go: nekobox_core ####
|
||||
pushd go/cmd/nekobox_core
|
||||
go build -v -o $DEST -trimpath -ldflags "-w -s -X neko/pkg/neko_common.Version_neko=$version_standalone" -tags "with_gvisor,with_quic,with_wireguard,with_utls,with_v2ray_api"
|
||||
go build -v -o $DEST -trimpath -ldflags "-w -s -X $neko_common.Version_neko=$version_standalone" -tags "with_gvisor,with_quic,with_wireguard,with_utls,with_v2ray_api"
|
||||
popd
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#ifndef NKR_NO_GRPC
|
||||
|
||||
#include "go/gen/libcore.pb.h"
|
||||
#include "go/grpc_server/gen/libcore.pb.h"
|
||||
#include <QString>
|
||||
|
||||
namespace QtGrpc {
|
||||
|
||||
@@ -174,6 +174,9 @@ void MainWindow::speedtest_current() {
|
||||
last_test_time = QTime::currentTime();
|
||||
|
||||
runOnUiThread([=] {
|
||||
if (!result.error().empty()) {
|
||||
MW_show_log(QString("UrlTest error: %1").arg(result.error().c_str()));
|
||||
}
|
||||
if (latency <= 0) {
|
||||
ui->label_running->setText(tr("Test Result") + ": " + tr("Unavailable"));
|
||||
} else if (latency > 0) {
|
||||
|
||||
Reference in New Issue
Block a user