Remove manual client ID and TLS CLI options
Some checks failed
Build Multi-Platform Binaries / build-frontend (push) Successful in 34s
Build Multi-Platform Binaries / build-binaries (amd64, linux, client, true) (push) Successful in 1m20s
Build Multi-Platform Binaries / build-binaries (amd64, darwin, server, false) (push) Successful in 1m33s
Build Multi-Platform Binaries / build-binaries (amd64, windows, client, true) (push) Successful in 1m16s
Build Multi-Platform Binaries / build-binaries (amd64, linux, server, true) (push) Successful in 1m48s
Build Multi-Platform Binaries / build-binaries (arm, 7, linux, client, true) (push) Successful in 1m7s
Build Multi-Platform Binaries / build-binaries (amd64, windows, server, true) (push) Successful in 1m46s
Build Multi-Platform Binaries / build-binaries (arm64, darwin, server, false) (push) Successful in 1m31s
Build Multi-Platform Binaries / build-binaries (arm, 7, linux, server, true) (push) Successful in 1m58s
Build Multi-Platform Binaries / build-binaries (arm64, linux, client, true) (push) Successful in 1m35s
Build Multi-Platform Binaries / build-binaries (arm64, linux, server, true) (push) Has been cancelled
Build Multi-Platform Binaries / build-binaries (arm64, windows, server, false) (push) Has been cancelled

This commit is contained in:
2026-03-19 19:32:57 +08:00
parent 937536e422
commit e4999abf47
14 changed files with 112 additions and 202 deletions

View File

@@ -5,8 +5,8 @@ func (s *SQLiteStore) CreateInstallToken(token *InstallToken) error {
s.mu.Lock()
defer s.mu.Unlock()
_, err := s.db.Exec(`INSERT INTO install_tokens (token, client_id, created_at, used) VALUES (?, ?, ?, ?)`,
token.Token, token.ClientID, token.CreatedAt, 0)
_, err := s.db.Exec(`INSERT INTO install_tokens (token, client_id, created_at, used) VALUES (?, '', ?, ?)`,
token.Token, token.CreatedAt, 0)
return err
}
@@ -17,8 +17,8 @@ func (s *SQLiteStore) GetInstallToken(token string) (*InstallToken, error) {
var t InstallToken
var used int
err := s.db.QueryRow(`SELECT token, client_id, created_at, used FROM install_tokens WHERE token = ?`, token).
Scan(&t.Token, &t.ClientID, &t.CreatedAt, &used)
err := s.db.QueryRow(`SELECT token, created_at, used FROM install_tokens WHERE token = ?`, token).
Scan(&t.Token, &t.CreatedAt, &used)
if err != nil {
return nil, err
}

View File

@@ -46,7 +46,6 @@ type TrafficStore interface {
// InstallToken 安装token
type InstallToken struct {
Token string `json:"token"`
ClientID string `json:"client_id"`
CreatedAt int64 `json:"created_at"`
Used bool `json:"used"`
}

View File

@@ -81,7 +81,7 @@ func (s *SQLiteStore) init() error {
_, err = s.db.Exec(`
CREATE TABLE IF NOT EXISTS install_tokens (
token TEXT PRIMARY KEY,
client_id TEXT NOT NULL,
client_id TEXT NOT NULL DEFAULT '',
created_at INTEGER NOT NULL,
used INTEGER NOT NULL DEFAULT 0
)

View File

@@ -21,34 +21,21 @@ func NewInstallHandler(app AppInterface) *InstallHandler {
return &InstallHandler{app: app}
}
// GenerateInstallCommandRequest 生成安装命令请求
type GenerateInstallCommandRequest struct {
ClientID string `json:"client_id" binding:"required"`
}
// InstallCommandResponse 安装命令响应
type InstallCommandResponse struct {
Token string `json:"token"`
Commands map[string]string `json:"commands"`
ExpiresAt int64 `json:"expires_at"`
ServerAddr string `json:"server_addr"`
Token string `json:"token"`
Commands map[string]string `json:"commands"`
ExpiresAt int64 `json:"expires_at"`
ServerAddr string `json:"server_addr"`
}
// GenerateInstallCommand 生成安装命令
// @Summary 生成客户端安装命令
// @Tags install
// @Accept json
// @Produce json
// @Param body body GenerateInstallCommandRequest true "客户端ID"
// @Success 200 {object} InstallCommandResponse
// @Router /api/install/generate [post]
func (h *InstallHandler) GenerateInstallCommand(c *gin.Context) {
var req GenerateInstallCommandRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
// 生成随机token
tokenBytes := make([]byte, 32)
if _, err := rand.Read(tokenBytes); err != nil {
@@ -61,7 +48,6 @@ func (h *InstallHandler) GenerateInstallCommand(c *gin.Context) {
now := time.Now().Unix()
installToken := &db.InstallToken{
Token: token,
ClientID: req.ClientID,
CreatedAt: now,
Used: false,
}
@@ -85,18 +71,13 @@ func (h *InstallHandler) GenerateInstallCommand(c *gin.Context) {
// 生成安装命令
expiresAt := now + 3600 // 1小时过期
tlsFlag := ""
if h.app.GetConfig().Server.TLSDisabled {
tlsFlag = " -no-tls"
}
commands := map[string]string{
"linux": fmt.Sprintf("curl -fsSL https://raw.githubusercontent.com/gotunnel/gotunnel/main/scripts/install.sh | bash -s -- -s %s -t %s -id %s%s",
serverAddr, token, req.ClientID, tlsFlag),
"macos": fmt.Sprintf("curl -fsSL https://raw.githubusercontent.com/gotunnel/gotunnel/main/scripts/install.sh | bash -s -- -s %s -t %s -id %s%s",
serverAddr, token, req.ClientID, tlsFlag),
"windows": fmt.Sprintf("powershell -c \"irm https://raw.githubusercontent.com/gotunnel/gotunnel/main/scripts/install.ps1 | iex; Install-GoTunnel -Server '%s' -Token '%s' -ClientID '%s'%s\"",
serverAddr, token, req.ClientID, tlsFlag),
"linux": fmt.Sprintf("curl -fsSL https://raw.githubusercontent.com/gotunnel/gotunnel/main/scripts/install.sh | bash -s -- -s %s -t %s",
serverAddr, token),
"macos": fmt.Sprintf("curl -fsSL https://raw.githubusercontent.com/gotunnel/gotunnel/main/scripts/install.sh | bash -s -- -s %s -t %s",
serverAddr, token),
"windows": fmt.Sprintf("powershell -c \"irm https://raw.githubusercontent.com/gotunnel/gotunnel/main/scripts/install.ps1 | iex; Install-GoTunnel -Server '%s' -Token '%s'\"",
serverAddr, token),
}
c.JSON(http.StatusOK, InstallCommandResponse{

View File

@@ -1,10 +1,8 @@
package tunnel
import (
"crypto/rand"
"crypto/tls"
"encoding/base64"
"encoding/hex"
"fmt"
"log"
"net"
@@ -38,13 +36,6 @@ func isValidClientID(id string) bool {
return clientIDRegex.MatchString(id)
}
// generateClientID 生成随机客户端 ID
func generateClientID() string {
bytes := make([]byte, 8)
rand.Read(bytes)
return hex.EncodeToString(bytes)
}
// Server 隧道服务端
type Server struct {
clientStore db.ClientStore
@@ -239,13 +230,7 @@ func (s *Server) handleConnection(conn net.Conn) {
validToken = true
isInstallToken = true
// 验证客户端ID匹配
if authReq.ClientID != "" && authReq.ClientID != installToken.ClientID {
security.LogInvalidClientID(clientIP, authReq.ClientID)
s.sendAuthResponse(conn, false, "client id mismatch", "")
return
}
// 使用token中的客户端ID
authReq.ClientID = installToken.ClientID
}
}
}
@@ -259,9 +244,7 @@ func (s *Server) handleConnection(conn net.Conn) {
// 处理客户端 ID
clientID := authReq.ClientID
if clientID == "" {
clientID = generateClientID()
} else if !isValidClientID(clientID) {
if clientID == "" || !isValidClientID(clientID) {
security.LogInvalidClientID(clientIP, clientID)
s.sendAuthResponse(conn, false, "invalid client id format", "")
return
@@ -757,11 +740,6 @@ func (s *Server) DisconnectClient(clientID string) error {
return cs.Session.Close()
}
// startUDPListener 启动 UDP 监听
func (s *Server) startUDPListener(cs *ClientSession, rule *protocol.ProxyRule) {
if err := s.portManager.Reserve(rule.RemotePort, cs.ID); err != nil {
@@ -856,15 +834,6 @@ func (s *Server) sendUDPPacket(cs *ClientSession, conn *net.UDPConn, clientAddr
}
}
// checkHTTPBasicAuth 检查 HTTP Basic Auth
// 返回 (认证成功, 已读取的数据)
func (s *Server) checkHTTPBasicAuth(conn net.Conn, username, password string) (bool, []byte) {
@@ -933,8 +902,6 @@ func (s *Server) sendHTTPUnauthorized(conn net.Conn) {
conn.Write([]byte(response))
}
// shouldPushToClient 检查是否应推送到指定客户端
func (s *Server) shouldPushToClient(autoPush []string, clientID string) bool {
if len(autoPush) == 0 {
@@ -980,11 +947,6 @@ func (s *Server) RestartClient(clientID string) error {
return nil
}
// IsPortAvailable 检查端口是否可用
func (s *Server) IsPortAvailable(port int, excludeClientID string) bool {
// 检查系统端口
@@ -1008,11 +970,6 @@ func (s *Server) IsPortAvailable(port int, excludeClientID string) bool {
return true
}
// SendUpdateToClient 发送更新命令到客户端
func (s *Server) SendUpdateToClient(clientID, downloadURL string) error {
s.mu.RLock()