refresh back

This commit is contained in:
2025-10-03 16:55:09 +06:00
parent fbb530c619
commit ec2df9e612
7 changed files with 143 additions and 15 deletions

View File

@@ -0,0 +1,116 @@
package main
import (
"bufio"
"encoding/json"
"fmt"
"io"
"os"
"strings"
"time"
"port-knocker/internal"
)
type Request struct {
Targets []string `json:"targets"`
Delay string `json:"delay"`
Verbose bool `json:"verbose"`
Gateway string `json:"gateway"`
}
type Response struct {
Success bool `json:"success"`
Error string `json:"error,omitempty"`
Message string `json:"message,omitempty"`
}
func parseTargets(in []string, delayStr string, gateway string) (*internal.Config, error) {
cfg := &internal.Config{Targets: []internal.Target{}}
d := time.Second
if strings.TrimSpace(delayStr) != "" {
dur, err := time.ParseDuration(delayStr)
if err == nil {
d = dur
}
}
for _, t := range in {
t = strings.TrimSpace(t)
if t == "" {
continue
}
parts := strings.Split(t, ":")
if len(parts) < 3 {
return nil, fmt.Errorf("invalid target: %s", t)
}
protocol := strings.ToLower(parts[0])
host := parts[1]
portStr := parts[2]
gw := ""
if len(parts) >= 4 && strings.TrimSpace(parts[3]) != "" {
gw = strings.TrimSpace(parts[3])
} else if strings.TrimSpace(gateway) != "" {
gw = strings.TrimSpace(gateway)
}
// single port
var port int
fmt.Sscanf(portStr, "%d", &port)
cfg.Targets = append(cfg.Targets, internal.Target{
Host: host,
Ports: []int{port},
Protocol: protocol,
Delay: internal.Duration(d),
WaitConnection: false,
Gateway: gw,
})
}
return cfg, nil
}
func readAllStdin() ([]byte, error) {
reader := bufio.NewReader(os.Stdin)
var b []byte
for {
chunk, isPrefix, err := reader.ReadLine()
if err == io.EOF {
break
}
if err != nil {
return nil, err
}
b = append(b, chunk...)
if !isPrefix {
b = append(b, '\n')
}
}
return b, nil
}
func main() {
// Read JSON from stdin
data, err := readAllStdin()
if err != nil || len(strings.TrimSpace(string(data))) == 0 {
// fallback to args? not required; expect stdin
}
var req Request
if err := json.Unmarshal(data, &req); err != nil {
_ = json.NewEncoder(os.Stdout).Encode(Response{Success: false, Error: fmt.Sprintf("invalid json: %v", err)})
return
}
cfg, err := parseTargets(req.Targets, req.Delay, req.Gateway)
if err != nil {
_ = json.NewEncoder(os.Stdout).Encode(Response{Success: false, Error: err.Error()})
return
}
pk := internal.NewPortKnocker()
// Всегда без лишних логов на stdout (stdout должен содержать только JSON ответ)
verbose := false
if err := pk.ExecuteWithConfig(cfg, verbose, false); err != nil {
_ = json.NewEncoder(os.Stdout).Encode(Response{Success: false, Error: err.Error()})
return
}
_ = json.NewEncoder(os.Stdout).Encode(Response{Success: true, Message: "ok"})
}

View File

@@ -24,10 +24,13 @@ func setupKnockRoutes(api *gin.RouterGroup) {
ConfigYaml string `json:"config_yaml"`
}
if err := c.BindJSON(&req); err != nil {
// fmt.Printf("bad json: %v\n", err)
c.JSON(400, gin.H{"error": fmt.Sprintf("bad json: %v", err)})
return
}
// fmt.Printf("req: %+v\n", req)
knocker := internal.NewPortKnocker()
// Определяем режим: inline или YAML
@@ -39,6 +42,8 @@ func setupKnockRoutes(api *gin.RouterGroup) {
return
}
fmt.Printf("config: %+v\n", config)
// Применяем дополнительные параметры из запроса
if req.Gateway != "" {
for i := range config.Targets {
@@ -47,7 +52,8 @@ func setupKnockRoutes(api *gin.RouterGroup) {
}
if err := knocker.ExecuteWithConfig(config, req.Verbose, req.WaitConnection); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
fmt.Printf("error: %v\n", err)
c.JSON(400, gin.H{"status": "error","error": err.Error()})
return
}
c.JSON(200, gin.H{"status": "ok"})
@@ -71,7 +77,7 @@ func setupKnockRoutes(api *gin.RouterGroup) {
}
}
if err := knocker.ExecuteWithConfig(&config, true || req.Verbose, req.WaitConnection); err != nil {
if err := knocker.ExecuteWithConfig(&config, true || req.Verbose, req.WaitConnection); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
@@ -100,8 +106,7 @@ func parseInlineTargetsWithWait(targets, delay string, waitConnection bool, gate
protocol := strings.TrimSpace(parts[0])
host := strings.TrimSpace(parts[1])
portStr := strings.TrimSpace(parts[2])
if len(parts) == 4 {
gateway = strings.TrimSpace(parts[3])
}

View File

@@ -1,6 +1,6 @@
package cmd
import (
import (
"fmt"
"strconv"
"strings"
@@ -100,13 +100,17 @@ func parseInlineTargets(targetsStr, delayStr string) (*internal.Config, error) {
// Разбираем формат [proto]:[host]:[port]
parts := strings.Split(targetStr, ":")
if len(parts) != 3 {
return nil, fmt.Errorf("неверный формат цели '%s', ожидается [proto]:[host]:[port]", targetStr)
if len(parts) != 3 && len(parts) != 4 {
return nil, fmt.Errorf("неверный формат цели '%s', ожидается [proto]:[host]:[port] или [proto]:[host]:[port]:[gateway]", targetStr)
}
protocol := strings.TrimSpace(parts[0])
host := strings.TrimSpace(parts[1])
portStr := strings.TrimSpace(parts[2])
gateway := ""
if len(parts) == 4 {
gateway = strings.TrimSpace(parts[3])
}
// Проверяем протокол
if protocol != "tcp" && protocol != "udp" {
@@ -130,7 +134,7 @@ func parseInlineTargets(targetsStr, delayStr string) (*internal.Config, error) {
Protocol: protocol,
Delay: internal.Duration(delay),
WaitConnection: false,
Gateway: "",
Gateway: gateway,
}
config.Targets = append(config.Targets, target)

View File

@@ -43,11 +43,16 @@ func runServe(cmd *cobra.Command, args []string) error {
port = "8888"
}
host := os.Getenv("GO_KNOCKER_SERVE_HOST")
if strings.TrimSpace(port) == "" {
host = ""
}
r := gin.Default()
// CORS: разрешаем для локальной разработки
r.Use(cors.New(cors.Config{
AllowOrigins: []string{"http://localhost:4200", "http://127.0.0.1:8888", "http://localhost:8888"},
AllowOrigins: []string{"http://localhost:4200", "http://127.0.0.1:8888", "http://localhost:" + port},
AllowMethods: []string{"GET", "POST", "OPTIONS"},
AllowHeaders: []string{"Authorization", "Content-Type"},
AllowCredentials: true,
@@ -65,6 +70,6 @@ func runServe(cmd *cobra.Command, args []string) error {
setupCryptoRoutes(api, passHash)
setupStaticRoutes(r, embeddedFS)
fmt.Printf("Serving on :%s\n", port)
return r.Run(":" + port)
fmt.Printf("Serving on %s:%s\n", host, port)
return r.Run(host + ":" + port)
}