new: make tunnel service working

This commit is contained in:
Hiddify
2024-02-02 13:47:41 +01:00
parent ad764a86b1
commit 7bdfee5459
14 changed files with 232 additions and 94 deletions

View File

@@ -34,14 +34,20 @@ ios: lib_install
windows-amd64:
env GOOS=windows GOARCH=amd64 CC=x86_64-w64-mingw32-gcc $(GOBUILD) -o $(BINDIR)/$(NAME).dll ./custom
rsrc -manifest admin_service\cmd\admin_service.manifest -ico ..\assets\images\tray_icon_connected.ico -o admin_service\cmd\admin_service.syso
env GOOS=windows GOARCH=amd64 CC=x86_64-w64-mingw32-gcc $(GOBUILD) -o $(BINDIR)/hiddify-service.exe ./admin_service/cmd
linux-amd64:
env GOOS=linux GOARCH=amd64 $(GOBUILD) -o $(BINDIR)/$(NAME).so ./custom
env GOOS=linux GOARCH=amd64 $(GOBUILD) -o $(BINDIR)/hiddify-service ./admin_service/cmd
chmod +x $(BINDIR)/hiddify-service
macos-amd64:
env GOOS=darwin GOARCH=amd64 CGO_CFLAGS="-mmacosx-version-min=10.11" CGO_LDFLAGS="-mmacosx-version-min=10.11" CGO_ENABLED=1 go build -trimpath -tags $(TAGS),$(IOS_TAGS) -buildmode=c-shared -o $(BINDIR)/$(NAME).dylib ./custom
env GOOS=darwin GOARCH=amd64 CGO_CFLAGS="-mmacosx-version-min=10.11" CGO_LDFLAGS="-mmacosx-version-min=10.11" CGO_ENABLED=1 go build -trimpath -tags $(TAGS),$(IOS_TAGS) -o $(BINDIR)/hiddify-service ./admin_service/cmd
macos-arm64:
env GOOS=darwin GOARCH=arm64 CGO_CFLAGS="-mmacosx-version-min=10.11" CGO_LDFLAGS="-mmacosx-version-min=10.11" CGO_ENABLED=1 go build -trimpath -tags $(TAGS),$(IOS_TAGS) -buildmode=c-shared -o $(BINDIR)/$(NAME).dylib ./custom
macos-universal: macos-amd64 macos-arm64
lipo -create $(BINDIR)/$(BASENAME)-macos-amd64.dylib $(BINDIR)/$(BASENAME)-macos-arm64.dylib -output $(BINDIR)/$(NAME).dylib
@@ -69,3 +75,5 @@ release: # Create a new tag for release.
git tag v$${TAG} && \
git push -u origin HEAD --tags && \
echo "Github Actions will detect the new tag and release the new version."'

View File

@@ -6,12 +6,16 @@ package main
#include <stdint.h>
// Import the function from the DLL
extern void AdminServiceStart(char *arg);
char* AdminServiceStart(const char* arg);
*/
import "C"
import (
"fmt"
"os"
"strings"
"unsafe"
)
func main() {
@@ -29,5 +33,24 @@ func main() {
// defer C.free(unsafe.Pointer(arg))
// Call AdminServiceStart with the C string
C.AdminServiceStart(arg)
result := C.AdminServiceStart(arg)
goRes := C.GoString(result)
defer C.free(unsafe.Pointer(result))
parts := strings.SplitN(goRes, " ", 2)
var parsedExitCode int
_, err := fmt.Sscanf(parts[0], "%d", &parsedExitCode)
parsedOutMessage := parts[1]
if err != nil {
fmt.Println("Error parsing the string:", err)
return
}
fmt.Printf("%d %s", parsedExitCode, parsedOutMessage)
if parsedExitCode != 0 {
os.Exit(int(parsedExitCode))
}
}

View File

@@ -1,7 +1,10 @@
package admin_service
import (
"fmt"
"log"
"os"
"path/filepath"
"github.com/hiddify/libcore/global"
"github.com/kardianos/service"
@@ -18,7 +21,7 @@ func (m *hiddifyNext) Start(s service.Service) error {
return nil
}
func (m *hiddifyNext) Stop(s service.Service) error {
err := global.StopService()
err := global.StopServiceC()
if err != nil {
return err
}
@@ -30,45 +33,115 @@ func (m *hiddifyNext) run() {
StartWebServer(port, false)
}
func StartService(goArg string) {
func getCurrentExecutableDirectory() string {
executablePath, err := os.Executable()
if err != nil {
return ""
}
// Extract the directory (folder) containing the executable
executableDirectory := filepath.Dir(executablePath)
return executableDirectory
}
func StartService(goArg string) (int, string) {
svcConfig := &service.Config{
Name: "Hiddify Tunnel Service",
DisplayName: "Hiddify Tunnel Service",
Description: "This is a bridge for tunnel",
Option: map[string]interface{}{
"RunAtLoad": true,
"WorkingDirectory": getCurrentExecutableDirectory(),
},
}
prg := &hiddifyNext{}
s, err := service.New(prg, svcConfig)
if err != nil {
log.Fatal(err)
// log.Printf("Error: %v", err)
return 1, fmt.Sprintf("Error: %v", err)
}
if len(goArg) > 0 {
if goArg == "uninstall" {
err = s.Stop()
if err != nil {
log.Fatal(err)
}
}
err = service.Control(s, goArg)
if err != nil {
log.Fatal(err)
}
if goArg == "install" {
err = s.Start()
if err != nil {
log.Fatal(err)
}
}
return
if len(goArg) > 0 {
return control(s, goArg)
}
logger, err = s.Logger(nil)
if err != nil {
log.Fatal(err)
log.Printf("Error: %v", err)
}
err = s.Run()
if err != nil {
logger.Error(err)
return 3, fmt.Sprintf("Error: %v", err)
}
return 0, ""
}
func control(s service.Service, goArg string) (int, string) {
dolog := false
var err error
status, serr := s.Status()
if dolog {
fmt.Printf("Current Status: %+v %+v!\n", status, serr)
}
switch goArg {
case "uninstall":
if status == service.StatusRunning {
s.Stop()
}
if dolog {
fmt.Printf("Tunnel Service Uninstalled Successfully.\n")
}
err = s.Uninstall()
case "start":
if status == service.StatusRunning {
if dolog {
fmt.Printf("Tunnel Service Already Running.\n")
}
return 0, "Tunnel Service Already Running."
} else if status == service.StatusUnknown {
s.Install()
status, serr = s.Status()
if dolog {
fmt.Printf("Check status again: %+v %+v!", status, serr)
}
}
if status != service.StatusRunning {
err = s.Start()
}
case "install":
err = s.Install()
status, serr = s.Status()
if dolog {
fmt.Printf("Check Status Again: %+v %+v", status, serr)
}
if status != service.StatusRunning {
err = s.Start()
}
case "stop":
if status == service.StatusStopped {
if dolog {
fmt.Printf("Tunnel Service Already Stopped.\n")
}
return 0, "Tunnel Service Already Stopped."
}
err = s.Stop()
default:
err = service.Control(s, goArg)
}
if err == nil {
out := fmt.Sprintf("Tunnel Service %sed Successfully.", goArg)
if dolog {
fmt.Printf(out)
}
return 0, out
} else {
out := fmt.Sprintf("Error: %v", err)
if dolog {
log.Printf(out)
}
return 2, out
}
}

View File

@@ -65,11 +65,11 @@ func startHandler(w http.ResponseWriter, r *http.Request) {
parameters := global.Parameters{Ipv6: ipv6, ServerPort: serverPort, StrictRoute: strictRoute, EndpointIndependentNat: endpointIndependentNat, Stack: theStack}
err = global.WriteParameters(parameters.Ipv6, parameters.ServerPort, parameters.StrictRoute, parameters.EndpointIndependentNat, GetStringFromStack(parameters.Stack))
if err != nil {
http.Error(w, fmt.Sprintf("Error: %v", err), http.StatusBadRequest)
return
}
// err = global.WriteParameters(parameters.Ipv6, parameters.ServerPort, parameters.StrictRoute, parameters.EndpointIndependentNat, GetStringFromStack(parameters.Stack))
// if err != nil {
// http.Error(w, fmt.Sprintf("Error: %v", err), http.StatusBadRequest)
// return
// }
err = global.SetupC("./", "./", "./tmp", false)
if err != nil {
@@ -84,11 +84,12 @@ func startHandler(w http.ResponseWriter, r *http.Request) {
http.Error(w, fmt.Sprintf("Ok"), http.StatusOK)
}
func StopHandler(w http.ResponseWriter, r *http.Request) {
err := global.StopService()
err := global.StopServiceC()
if err != nil {
http.Error(w, fmt.Sprintf("Error: %v", err), http.StatusBadRequest)
return
}
http.Error(w, fmt.Sprintf("Ok"), http.StatusOK)
}
func GetStack(stack string) global.Stack {

View File

@@ -5,6 +5,5 @@ set CC=x86_64-w64-mingw32-gcc
set CGO_ENABLED=1
go build -trimpath -tags with_gvisor,with_quic,with_wireguard,with_ech,with_utls,with_clash_api,with_grpc -ldflags="-w -s" -buildmode=c-shared -o bin/libcore.dll ./custom
rsrc -manifest admin_service_cmd\admin_service.manifest -ico ..\assets\images\tray_icon_connected.ico -o admin_service_cmd\admin_service.syso
go build -o bin/hiddify-service.exe ./admin_service_cmd
@REM copy .\admin_service_cmd\admin_service.manifest bin\hiddify-service.exe.manifest
rsrc -manifest admin_service\cmd\admin_service.manifest -ico ..\assets\images\tray_icon_connected.ico -o admin_service\cmd\admin_service.syso
go build -o bin/hiddify-service.exe ./admin_service/cmd/

View File

@@ -1,6 +1,8 @@
package main
import (
"fmt"
"github.com/hiddify/libcore/admin_service"
"github.com/spf13/cobra"
@@ -11,9 +13,12 @@ var commandService = &cobra.Command{
Short: "Sign box service start/stop/install/uninstall",
Args: cobra.MaximumNArgs(1),
Run: func(cmd *cobra.Command, args []string) {
if len(args) < 2 {
admin_service.StartService("")
arg := ""
if len(args) > 1 {
arg = args[1]
}
admin_service.StartService(args[1])
code, out := admin_service.StartService(arg)
fmt.Printf("exitCode:%d msg=%s", code, out)
},
}

View File

@@ -2,7 +2,9 @@ package main
import (
"fmt"
"time"
"os"
"os/signal"
"syscall"
"github.com/hiddify/libcore/config"
"github.com/hiddify/libcore/global"
@@ -53,6 +55,11 @@ func runSingbox(configPath string) error {
}
go global.StartServiceC(false, configStr)
fmt.Printf("Waiting for 30 seconds\n")
<-time.After(time.Second * 30)
// <-time.After(time.Second * 30)
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
<-sigChan
return err
}

View File

@@ -7,6 +7,7 @@ import (
"net"
"net/netip"
"net/url"
"runtime"
"strings"
C "github.com/sagernet/sing-box/constant"
@@ -118,40 +119,42 @@ func BuildConfig(configOpt ConfigOptions, input option.Options) (*option.Options
}
if configOpt.EnableTun {
tunInbound := option.Inbound{
Type: C.TypeTun,
Tag: "tun-in",
TunOptions: option.TunInboundOptions{
Stack: configOpt.TUNStack,
MTU: configOpt.MTU,
AutoRoute: true,
StrictRoute: configOpt.StrictRoute,
EndpointIndependentNat: true,
InboundOptions: option.InboundOptions{
SniffEnabled: true,
SniffOverrideDestination: true,
DomainStrategy: inboundDomainStrategy,
if runtime.GOOS != "windows" && runtime.GOOS != "darwin" && runtime.GOOS != "linux" {
tunInbound := option.Inbound{
Type: C.TypeTun,
Tag: "tun-in",
TunOptions: option.TunInboundOptions{
Stack: configOpt.TUNStack,
MTU: configOpt.MTU,
AutoRoute: true,
StrictRoute: configOpt.StrictRoute,
EndpointIndependentNat: true,
InboundOptions: option.InboundOptions{
SniffEnabled: true,
SniffOverrideDestination: true,
DomainStrategy: inboundDomainStrategy,
},
},
},
}
switch configOpt.IPv6Mode {
case option.DomainStrategy(dns.DomainStrategyUseIPv4):
tunInbound.TunOptions.Inet4Address = []netip.Prefix{
netip.MustParsePrefix("172.19.0.1/28"),
}
case option.DomainStrategy(dns.DomainStrategyUseIPv6):
tunInbound.TunOptions.Inet6Address = []netip.Prefix{
netip.MustParsePrefix("fdfe:dcba:9876::1/126"),
}
default:
tunInbound.TunOptions.Inet4Address = []netip.Prefix{
netip.MustParsePrefix("172.19.0.1/28"),
}
tunInbound.TunOptions.Inet6Address = []netip.Prefix{
netip.MustParsePrefix("fdfe:dcba:9876::1/126"),
}
}
options.Inbounds = append(options.Inbounds, tunInbound)
}
switch configOpt.IPv6Mode {
case option.DomainStrategy(dns.DomainStrategyUseIPv4):
tunInbound.TunOptions.Inet4Address = []netip.Prefix{
netip.MustParsePrefix("172.19.0.1/28"),
}
case option.DomainStrategy(dns.DomainStrategyUseIPv6):
tunInbound.TunOptions.Inet6Address = []netip.Prefix{
netip.MustParsePrefix("fdfe:dcba:9876::1/126"),
}
default:
tunInbound.TunOptions.Inet4Address = []netip.Prefix{
netip.MustParsePrefix("172.19.0.1/28"),
}
tunInbound.TunOptions.Inet6Address = []netip.Prefix{
netip.MustParsePrefix("fdfe:dcba:9876::1/126"),
}
}
options.Inbounds = append(options.Inbounds, tunInbound)
}
options.Inbounds = append(

View File

@@ -70,7 +70,7 @@ func patchOutboundTLSTricks(base option.Outbound, configOpt ConfigOptions, obj o
if configOpt.TLSTricks.EnablePadding {
tlsTricks.PaddingMode = "random"
tlsTricks.PaddingSize = configOpt.TLSTricks.PaddingSize
fmt.Printf("--------------------%+v----%+v", tlsTricks.PaddingSize, configOpt)
// fmt.Printf("--------------------%+v----%+v", tlsTricks.PaddingSize, configOpt)
outtls["utls"] = map[string]interface{}{
"enabled": true,
"fingerprint": "custom",
@@ -82,7 +82,7 @@ func patchOutboundTLSTricks(base option.Outbound, configOpt ConfigOptions, obj o
// // } else {
// // tls["tls_tricks"] = nil
// }
fmt.Printf("-------%+v------------- ", tlsTricks)
// fmt.Printf("-------%+v------------- ", tlsTricks)
}
return obj
}
@@ -190,6 +190,12 @@ func patchWarp(base *option.Outbound) error {
base.Type = C.TypeWireGuard
warpConfig.WireGuardOptions.Detour = detour
if detour != "" {
if warpConfig.WireGuardOptions.MTU > 1000 {
warpConfig.WireGuardOptions.MTU -= 100
}
warpConfig.WireGuardOptions.FakePackets = ""
}
base.WireGuardOptions = warpConfig.WireGuardOptions
}

View File

@@ -188,6 +188,7 @@ func generateWarp(license string, host string, port uint16, fakePackets string)
fmt.Println("Error marshaling Singbox configuration:", err)
return nil, err
}
fmt.Println(string(singboxJSON))
return singboxConfig, nil
}

View File

@@ -6,10 +6,19 @@
package main
import "C"
import "github.com/hiddify/libcore/admin_service"
import (
"fmt"
"github.com/hiddify/libcore/admin_service"
)
//export AdminServiceStart
func AdminServiceStart(arg *C.char) {
func AdminServiceStart(arg *C.char) *C.char {
goArg := C.GoString(arg)
admin_service.StartService(goArg)
exitCode, outMessage := admin_service.StartService(goArg)
// Allocate memory for the message and copy the string content
return C.CString(fmt.Sprintf("%d %s", exitCode, outMessage))
}

View File

@@ -236,7 +236,9 @@ func urlTest(groupTag string) error {
}
func StartServiceC(delayStart bool, content string) error {
if box != nil {
return errors.New("instance already started")
}
options, err := parseConfig(content)
// if err != nil {
// return stopAndAlert(EmptyConfiguration, err)
@@ -254,13 +256,14 @@ func StartServiceC(delayStart bool, content string) error {
// err = startCommandServer(*logFactory)
// if err != nil {
// return stopAndAlert(StartCommandServer, err)
// return err
// }
instance, err := NewService(options)
// if err != nil {
// return stopAndAlert(CreateService, err)
// }
if err != nil {
// return stopAndAlert(CreateService, err)
return err
}
// if delayStart {
// time.Sleep(250 * time.Millisecond)
@@ -272,34 +275,34 @@ func StartServiceC(delayStart bool, content string) error {
fmt.Printf("String Service Error: %v\n", err)
return err
}
// box = instance
box = instance
// commandServer.SetService(box)
// propagateStatus(Started)
status = Started
return nil
}
func StopService() error {
if status != Started {
return nil
}
func StopServiceC() error {
// if status != Started {
// return errors.New("instance not started")
// }
if box == nil {
return errors.New("instance not found")
}
propagateStatus(Stopping)
commandServer.SetService(nil)
// propagateStatus(Stopping)
err := box.Close()
// commandServer.SetService(nil)
if err != nil {
return err
}
box = nil
err = commandServer.Close()
if err != nil {
return err
}
// err = commandServer.Close()
// if err != nil {
// return err
// }
commandServer = nil
propagateStatus(Stopped)
status = Stopped
return nil
}
@@ -347,7 +350,7 @@ func MakeConfig(Ipv6 bool, ServerPort int, StrictRoute bool, EndpointIndependent
{
"type": "tun",
"tag": "tun-in",
"interface_name": "tun0",
"interface_name": "HiddifyTunnel",
"inet4_address": "172.19.0.1/30",
` + ipv6 + `
"mtu": 9000,