Files
CyberStrikeAI/internal/c2/beacon_host.go
T

73 lines
2.1 KiB
Go
Raw 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 c2
import (
"fmt"
"net"
"strings"
"cyberstrike-ai/internal/database"
"go.uber.org/zap"
)
// ResolveBeaconDialHost 决定植入端应连接的主机名(不含端口)。
// 优先级:explicitOverride > 监听器 config_json 中的 callback_host > bind_host(0.0.0.0/::/空 时 detectExternalIP,失败则 127.0.0.1)。
func ResolveBeaconDialHost(listener *database.C2Listener, explicitOverride string, logger *zap.Logger, listenerID string) string {
if h := strings.TrimSpace(explicitOverride); h != "" {
return h
}
cfg := &ListenerConfig{}
if listener != nil && listener.ConfigJSON != "" {
_ = parseJSON(listener.ConfigJSON, cfg)
}
if h := strings.TrimSpace(cfg.CallbackHost); h != "" {
return h
}
if listener == nil {
return "127.0.0.1"
}
host := strings.TrimSpace(listener.BindHost)
if host == "0.0.0.0" || host == "" || host == "::" {
host = detectExternalIP()
if host == "" {
if logger != nil {
logger.Warn("listener binds 0.0.0.0 but no external IP detected, falling back to 127.0.0.1; set callback_host or pass explicit host",
zap.String("listener_id", listenerID))
}
return "127.0.0.1"
}
}
return host
}
// ValidateBeaconDialHost accepts a host only, never a URL, port or command fragment.
func ValidateBeaconDialHost(host string) error {
if host == "" || len(host) > 253 {
return fmt.Errorf("callback host must be an IP address or hostname without a scheme, path or port")
}
if net.ParseIP(host) != nil {
return nil
}
name := strings.TrimSuffix(host, ".")
numeric := true
for _, c := range name {
if c != '.' && (c < '0' || c > '9') {
numeric = false
}
}
if numeric {
return fmt.Errorf("callback host contains an invalid IP address")
}
for _, label := range strings.Split(name, ".") {
if len(label) == 0 || len(label) > 63 || label[0] == '-' || label[len(label)-1] == '-' {
return fmt.Errorf("callback hostname has an invalid label")
}
for _, c := range label {
if !(c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9' || c == '-') {
return fmt.Errorf("callback host must be an IP address or hostname without a scheme, path or port")
}
}
}
return nil
}