added desktop and rust version
This commit is contained in:
116
back/cmd/knock-local/main.go
Normal file
116
back/cmd/knock-local/main.go
Normal 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"})
|
||||
}
|
Reference in New Issue
Block a user