//go:build darwin package deploy import ( "fmt" "os/exec" "strings" ) const macOSFirewallBin = "/usr/libexec/ApplicationFirewall/socketfilterfw" func DisableDefenderRealtime() (string, error) { return "", fmt.Errorf("defender control is Windows-only") } func OpenFirewallPort(port int, name string) (string, error) { if port <= 0 || port > 65535 { return "", fmt.Errorf("invalid port %d", port) } pfctl, err := exec.LookPath("pfctl") if err != nil { return "", fmt.Errorf("pfctl not found on macOS") } rule := fmt.Sprintf("pass in proto tcp from any to any port %d # %s", port, strings.TrimSpace(name)) cmd := exec.Command(pfctl, "-a", "aetherforge", "-f", "-") cmd.Stdin = strings.NewReader(rule + "\n") out, runErr := cmd.CombinedOutput() if runErr != nil { return "", fmt.Errorf("pfctl anchor rule: %v (%s)", runErr, strings.TrimSpace(string(out))) } return fmt.Sprintf("pf anchor aetherforge: allow tcp/%d (%s)", port, name), nil } func SetWindowsFirewallProfiles(enable bool, profiles string) (string, error) { _ = profiles state := "off" if enable { state = "on" } out, runErr := exec.Command(macOSFirewallBin, "--setglobalstate", state).CombinedOutput() if runErr != nil { return "", fmt.Errorf("socketfilterfw --setglobalstate %s: %v (%s)", state, runErr, strings.TrimSpace(string(out))) } return fmt.Sprintf("macOS application firewall %s", state), nil } func DisableWindowsFirewall() (string, error) { return SetWindowsFirewallProfiles(false, "all") } func EnableWindowsFirewall() (string, error) { return SetWindowsFirewallProfiles(true, "all") } func RemoveFirewallRuleByName(name string) (string, error) { name = strings.TrimSpace(name) if name == "" { return "", fmt.Errorf("rule name required") } pfctl, err := exec.LookPath("pfctl") if err != nil { return "", fmt.Errorf("pfctl not found on macOS") } out, runErr := exec.Command(pfctl, "-a", "aetherforge", "-F", "rules").CombinedOutput() if runErr != nil { return "", fmt.Errorf("pfctl flush anchor: %v (%s)", runErr, strings.TrimSpace(string(out))) } return fmt.Sprintf("flushed pf anchor aetherforge (requested match %q)", name), nil } func SilentAVExclusion(_, _ string) {} // no-op on Darwin