package app import ( "encoding/json" "fmt" "os" "path/filepath" ) // WebServiceConfig defines configuration for a custom web honeypot service type WebServiceConfig struct { Enabled bool `json:"enabled"` Port int `json:"port"` Name string `json:"name"` // Service name (e.g., "admin-panel", "webmail") Path string `json:"path"` // URL path (e.g., "/login", "/admin") TemplateName string `json:"template_name"` // Template filename (e.g., "admin-login.html") UseHTTPS bool `json:"use_https"` // Whether to use HTTPS } // WebServicesConfig holds configuration for custom web services type WebServicesConfig struct { Generic []WebServiceConfig `json:"generic"` } // Config contains runtime configuration for the honeypot type Config struct { LogMode string `json:"log_mode"` // "file" | "stdout" | "sqlite" LogPath string `json:"log_path"` Web struct { Enabled bool `json:"enabled"` Bind string `json:"bind"` Port int `json:"port"` HTTPTemplateName string `json:"http_template_name"` // Optional template for HTTP service HTTPSTemplateName string `json:"https_template_name"` // Optional template for HTTPS service } `json:"web"` Services struct { HTTP bool `json:"http"` HTTPS bool `json:"https"` SSH bool `json:"ssh"` FTP bool `json:"ftp"` SMTP bool `json:"smtp"` IMAP bool `json:"imap"` Telnet bool `json:"telnet"` MySQL bool `json:"mysql"` PostgreSQL bool `json:"postgresql"` MongoDB bool `json:"mongodb"` RDP bool `json:"rdp"` SMB bool `json:"smb"` SIP bool `json:"sip"` VNC bool `json:"vnc"` } `json:"services"` WebServices WebServicesConfig `json:"web_services"` Ports struct { HTTP int `json:"http"` HTTPS int `json:"https"` SSH int `json:"ssh"` FTP int `json:"ftp"` SMTP int `json:"smtp"` IMAP int `json:"imap"` Telnet int `json:"telnet"` MySQL int `json:"mysql"` PostgreSQL int `json:"postgresql"` MongoDB int `json:"mongodb"` RDP int `json:"rdp"` SMB int `json:"smb"` SIP int `json:"sip"` VNC int `json:"vnc"` } `json:"ports"` Security struct { MaxInputLength int `json:"max_input_length"` // Maximum input length per command MaxConnDuration string `json:"max_conn_duration"` // Maximum connection duration (e.g., "5m") MaxCommands int `json:"max_commands"` // Maximum commands per connection RateLimitWindow string `json:"rate_limit_window"` // Rate limiting window (e.g., "1m") MaxConnPerIP int `json:"max_conn_per_ip"` // Maximum concurrent connections per IP ReadTimeout string `json:"read_timeout"` // Read timeout for each operation WriteTimeout string `json:"write_timeout"` // Write timeout for each operation EnableRateLimit bool `json:"enable_rate_limit"` // Enable rate limiting BlockHighThreatIPs bool `json:"block_high_threat_ips"` // Automatically block high threat IPs ThreatScoreThreshold int `json:"threat_score_threshold"` // Threshold for automatic blocking } `json:"security"` // Certificates allows overriding default certificate/key locations. Certificates struct { // SSHHostKeyPath points to a PEM-encoded RSA private key to use as SSH host key. // If empty, a persistent key will be created in the same directory as LogPath. SSHHostKeyPath string `json:"ssh_host_key_path"` // TLSCertPath and TLSKeyPath are used by TLS-capable services if provided. // If empty, a self-signed certificate will be generated and stored next to LogPath. TLSCertPath string `json:"tls_cert_path"` TLSKeyPath string `json:"tls_key_path"` } `json:"certificates"` } // LastConfigPath holds the last path used to load/save config.json var LastConfigPath string // EnsureConfig writes a default config file if the given path doesn't exist func EnsureConfig(path string) error { if _, err := os.Stat(path); os.IsNotExist(err) { if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil { return fmt.Errorf("create config dir: %w", err) } def := defaultConfig() b, _ := json.MarshalIndent(def, "", " ") if err := os.WriteFile(path, b, 0644); err != nil { return fmt.Errorf("write default config: %w", err) } } return nil } // LoadConfig loads JSON config from path func LoadConfig(path string) (Config, error) { var cfg Config b, err := os.ReadFile(path) if err != nil { return cfg, err } if err := json.Unmarshal(b, &cfg); err != nil { return cfg, err } LastConfigPath = path return cfg, nil } // SaveConfig writes the given config to the provided path func SaveConfig(path string, cfg Config) error { b, err := json.MarshalIndent(cfg, "", " ") if err != nil { return err } if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil { return err } return os.WriteFile(path, b, 0644) } func defaultConfig() Config { var c Config c.LogMode = "file" c.LogPath = "honeypot.log" c.Web.Enabled = true c.Web.Bind = "127.0.0.1" c.Web.Port = 6333 // Enable common services by default c.Services.HTTP = true c.Services.HTTPS = false c.Services.SSH = true c.Services.FTP = true c.Services.SMTP = true c.Services.Telnet = true c.Services.MySQL = false c.Services.PostgreSQL = false c.Services.MongoDB = false c.Services.IMAP = false c.Services.RDP = false c.Services.SMB = false c.Services.SIP = false c.Services.VNC = false // Standard ports c.Ports.HTTP = 8080 c.Ports.HTTPS = 8443 c.Ports.SSH = 2222 c.Ports.FTP = 2121 c.Ports.SMTP = 2525 c.Ports.IMAP = 1143 c.Ports.Telnet = 2323 c.Ports.MySQL = 3306 c.Ports.PostgreSQL = 5432 c.Ports.MongoDB = 27017 c.Ports.RDP = 3389 c.Ports.SIP = 5060 c.Ports.VNC = 5900 // Security defaults c.Security.MaxInputLength = 4096 c.Security.MaxConnDuration = "5m" c.Security.MaxCommands = 100 c.Security.RateLimitWindow = "1m" c.Security.MaxConnPerIP = 10 c.Security.ReadTimeout = "30s" c.Security.WriteTimeout = "10s" c.Security.EnableRateLimit = true c.Security.BlockHighThreatIPs = false c.Security.ThreatScoreThreshold = 80 // Web services defaults - only generic services, configurable from dashboard c.WebServices.Generic = []WebServiceConfig{ { Enabled: false, Port: 9001, Name: "admin-panel", Path: "/admin", TemplateName: "admin-login.html", UseHTTPS: false, }, } return c }