Files
knock-gui/back/cmd/knock_routes.go
2025-08-17 00:43:58 +06:00

142 lines
3.9 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package cmd
import (
"fmt"
"strconv"
"strings"
"time"
"port-knocker/internal"
"github.com/gin-gonic/gin"
)
// setupKnockRoutes настраивает роуты для выполнения port knocking
func setupKnockRoutes(api *gin.RouterGroup) {
// Execute: вход inline или YAML конфиг
api.POST("/execute", func(c *gin.Context) {
var req struct {
Targets string `json:"targets"`
Delay string `json:"delay"`
Verbose bool `json:"verbose"`
WaitConnection bool `json:"waitConnection"`
Gateway string `json:"gateway"`
ConfigYaml string `json:"config_yaml"`
}
if err := c.BindJSON(&req); err != nil {
c.JSON(400, gin.H{"error": fmt.Sprintf("bad json: %v", err)})
return
}
knocker := internal.NewPortKnocker()
// Определяем режим: inline или YAML
if strings.TrimSpace(req.ConfigYaml) != "" {
// YAML режим - загружаем конфигурацию из строки
config, err := internal.LoadConfigFromString(req.ConfigYaml)
if err != nil {
c.JSON(400, gin.H{"error": fmt.Sprintf("invalid yaml: %v", err)})
return
}
// Применяем дополнительные параметры из запроса
if req.Gateway != "" {
for i := range config.Targets {
config.Targets[i].Gateway = req.Gateway
}
}
if err := knocker.ExecuteWithConfig(config, req.Verbose, req.WaitConnection); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
c.JSON(200, gin.H{"status": "ok"})
return
} else {
// Inline режим
if strings.TrimSpace(req.Targets) == "" {
c.JSON(400, gin.H{"error": "targets is required in inline mode"})
return
}
config, err := parseInlineTargetsWithWait(req.Targets, req.Delay, req.WaitConnection)
if err != nil {
c.JSON(400, gin.H{"error": fmt.Sprintf("invalid targets: %v", err)})
return
}
// Применяем gateway к каждой цели
if req.Gateway != "" {
for i := range config.Targets {
config.Targets[i].Gateway = req.Gateway
}
}
if err := knocker.ExecuteWithConfig(&config, req.Verbose, req.WaitConnection); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
c.JSON(200, gin.H{"status": "ok"})
}
})
}
// parseInlineTargetsWithWait парсит inline строку целей в Config с поддержкой waitConnection
func parseInlineTargetsWithWait(targets, delay string, waitConnection bool) (internal.Config, error) {
var config internal.Config
// Парсим targets
targetStrings := strings.Split(targets, ";")
for _, targetStr := range targetStrings {
targetStr = strings.TrimSpace(targetStr)
if targetStr == "" {
continue
}
parts := strings.Split(targetStr, ":")
if len(parts) != 3 {
return config, fmt.Errorf("invalid target format: %s (expected protocol:host:port)", targetStr)
}
protocol := strings.TrimSpace(parts[0])
host := strings.TrimSpace(parts[1])
portStr := strings.TrimSpace(parts[2])
if protocol != "tcp" && protocol != "udp" {
return config, fmt.Errorf("unsupported protocol: %s (only tcp/udp supported)", protocol)
}
port, err := strconv.Atoi(portStr)
if err != nil {
return config, fmt.Errorf("invalid port: %s", portStr)
}
// Парсим delay
var targetDelay internal.Duration
if delay != "" {
duration, err := time.ParseDuration(delay)
if err != nil {
return config, fmt.Errorf("invalid delay: %s", delay)
}
targetDelay = internal.Duration(duration)
} else {
targetDelay = internal.Duration(time.Second)
}
target := internal.Target{
Protocol: protocol,
Host: host,
Ports: []int{port},
Delay: targetDelay,
WaitConnection: waitConnection,
}
config.Targets = append(config.Targets, target)
}
if len(config.Targets) == 0 {
return config, fmt.Errorf("no valid targets found")
}
return config, nil
}