All checks were successful
Build Multi-Platform Binaries / build-frontend (push) Successful in 30s
Build Multi-Platform Binaries / build-binaries (amd64, darwin, server, false) (push) Successful in 48s
Build Multi-Platform Binaries / build-binaries (amd64, linux, client, true) (push) Successful in 48s
Build Multi-Platform Binaries / build-binaries (amd64, linux, server, true) (push) Successful in 58s
Build Multi-Platform Binaries / build-binaries (amd64, windows, client, true) (push) Successful in 1m47s
Build Multi-Platform Binaries / build-binaries (amd64, windows, server, true) (push) Successful in 57s
Build Multi-Platform Binaries / build-binaries (arm, 7, linux, client, true) (push) Successful in 49s
Build Multi-Platform Binaries / build-binaries (arm, 7, linux, server, true) (push) Successful in 1m5s
Build Multi-Platform Binaries / build-binaries (arm64, darwin, server, false) (push) Successful in 50s
Build Multi-Platform Binaries / build-binaries (arm64, linux, client, true) (push) Successful in 45s
Build Multi-Platform Binaries / build-binaries (arm64, linux, server, true) (push) Successful in 58s
Build Multi-Platform Binaries / build-binaries (arm64, windows, server, false) (push) Successful in 51s
117 lines
2.8 KiB
Go
117 lines
2.8 KiB
Go
package main
|
||
|
||
import (
|
||
"flag"
|
||
"fmt"
|
||
"log"
|
||
"os"
|
||
|
||
"github.com/gotunnel/internal/server/app"
|
||
"github.com/gotunnel/internal/server/config"
|
||
"github.com/gotunnel/internal/server/db"
|
||
"github.com/gotunnel/internal/server/tunnel"
|
||
"github.com/gotunnel/pkg/crypto"
|
||
"github.com/gotunnel/pkg/plugin"
|
||
"github.com/gotunnel/pkg/plugin/builtin"
|
||
)
|
||
|
||
func main() {
|
||
configPath := flag.String("c", "server.yaml", "config file path")
|
||
flag.Parse()
|
||
|
||
// 加载 YAML 配置
|
||
cfg, err := config.LoadServerConfig(*configPath)
|
||
if err != nil {
|
||
log.Fatalf("Load config error: %v", err)
|
||
}
|
||
|
||
// 初始化数据库
|
||
clientStore, err := db.NewSQLiteStore(cfg.Server.DBPath)
|
||
if err != nil {
|
||
log.Fatalf("Init database error: %v", err)
|
||
}
|
||
defer clientStore.Close()
|
||
|
||
// 打印 token(便于客户端连接)
|
||
log.Printf("[Server] Token: %s", cfg.Server.Token)
|
||
|
||
// 创建隧道服务
|
||
server := tunnel.NewServer(
|
||
clientStore,
|
||
cfg.Server.BindAddr,
|
||
cfg.Server.BindPort,
|
||
cfg.Server.Token,
|
||
cfg.Server.HeartbeatSec,
|
||
cfg.Server.HeartbeatTimeout,
|
||
)
|
||
|
||
// 配置 TLS(默认启用)
|
||
if !cfg.Server.TLSDisabled {
|
||
tlsConfig, err := crypto.GenerateTLSConfig()
|
||
if err != nil {
|
||
log.Fatalf("Generate TLS config error: %v", err)
|
||
}
|
||
server.SetTLSConfig(tlsConfig)
|
||
log.Printf("[Server] TLS enabled")
|
||
}
|
||
|
||
// 初始化插件系统
|
||
registry := plugin.NewRegistry()
|
||
if err := registry.RegisterAllServer(builtin.GetServerPlugins()); err != nil {
|
||
log.Fatalf("[Plugin] Register error: %v", err)
|
||
}
|
||
server.SetPluginRegistry(registry)
|
||
log.Printf("[Plugin] Registered %d plugins", len(builtin.GetServerPlugins()))
|
||
|
||
// 加载 JS 插件配置
|
||
if len(cfg.JSPlugins) > 0 {
|
||
jsPlugins := loadJSPlugins(cfg.JSPlugins)
|
||
server.LoadJSPlugins(jsPlugins)
|
||
}
|
||
|
||
// 启动 Web 控制台
|
||
if cfg.Web.Enabled {
|
||
ws := app.NewWebServer(clientStore, server, cfg, *configPath, clientStore)
|
||
addr := fmt.Sprintf("%s:%d", cfg.Web.BindAddr, cfg.Web.BindPort)
|
||
|
||
go func() {
|
||
var err error
|
||
if cfg.Web.Username != "" && cfg.Web.Password != "" {
|
||
err = ws.RunWithJWT(addr, cfg.Web.Username, cfg.Web.Password, cfg.Server.Token)
|
||
} else {
|
||
err = ws.Run(addr)
|
||
}
|
||
if err != nil {
|
||
log.Printf("[Web] Server error: %v", err)
|
||
}
|
||
}()
|
||
}
|
||
|
||
log.Fatal(server.Run())
|
||
}
|
||
|
||
// loadJSPlugins 加载 JS 插件文件
|
||
func loadJSPlugins(configs []config.JSPluginConfig) []tunnel.JSPluginEntry {
|
||
var plugins []tunnel.JSPluginEntry
|
||
|
||
for _, cfg := range configs {
|
||
source, err := os.ReadFile(cfg.Path)
|
||
if err != nil {
|
||
log.Printf("[JSPlugin] Failed to load %s: %v", cfg.Path, err)
|
||
continue
|
||
}
|
||
|
||
plugins = append(plugins, tunnel.JSPluginEntry{
|
||
Name: cfg.Name,
|
||
Source: string(source),
|
||
AutoPush: cfg.AutoPush,
|
||
Config: cfg.Config,
|
||
AutoStart: cfg.AutoStart,
|
||
})
|
||
|
||
log.Printf("[JSPlugin] Loaded: %s from %s", cfg.Name, cfg.Path)
|
||
}
|
||
|
||
return plugins
|
||
}
|