Blocking C2 servers
pushwarden protect blocks the PolinRider command-and-control (C2) servers for the whole computer and keeps them blocked. Even if a loader runs, it cannot fetch its payload or send stolen data to the known servers.
This is the only part of PushWarden that needs administrator rights, because it edits the firewall and the hosts file.
pushwarden protect [--install | --refresh | --uninstall | --status | --block-c2 | --unblock] [--dry-run]
pushwarden install does this for you. It asks once for administrator rights (the native password dialog on macOS, polkit or sudo on Linux, UAC on Windows). You only need protect directly to check on the block, add it later or remove it.
Options
| Option | Effect |
|---|---|
--install (default) |
block now and register the boot-time job. Asks for administrator rights when run as a normal user |
--status |
is the block active, and will it survive a reboot? No rights needed |
--refresh |
what the job runs: re-apply the rules from the root-owned indicators, then fetch newer ones and re-apply |
--uninstall |
remove the job, the firewall rules and the hosts entries |
--block-c2 |
one-shot block for this boot only, with no job |
--unblock |
remove the rules and hosts entries but keep the job, if any |
--dry-run |
show what --install would do |
What gets installed
| Part | Linux | macOS | Windows |
|---|---|---|---|
| Firewall rule dropping outgoing traffic to every C2 IP | an iptables chain or nftables table named pushwarden |
a pf anchor |
a Windows Firewall rule named “PushWarden C2 block” |
| Hostname sinkhole | hosts-file entries between # BEGIN PUSHWARDEN C2 SINKHOLE and # END markers |
same | same |
| Job that re-applies the block at boot and refreshes the list daily | systemd timer pushwarden-netblock.timer |
LaunchDaemon com.pushwarden.netblock |
Scheduled Task “PushWarden NetBlock”, running as SYSTEM |
Why it keeps its own copy of the indicators
The job runs as root. The iocs.json under your home folder is writable by anything running as you, including malware. A privileged job must not let a user-writable file decide what goes into the hosts file.
So the job keeps:
- a root-owned copy of the indicators, refreshed from the project repository only
- a root-owned copy of the program
| System | Indicators and state | Program |
|---|---|---|
| Linux | /etc/pushwarden |
/usr/local/lib/pushwarden |
| macOS | /Library/Application Support/PushWarden |
/usr/local/libexec/pushwarden |
| Windows | %ProgramData%\PushWarden |
%ProgramFiles%\PushWarden |
Status values
Shown by pushwarden status and pushwarden protect --status.
| Firewall | Meaning |
|---|---|
active (persistent; 25 IPs, 15 hosts; applied 3h ago; indicators ...) |
all good |
active until reboot (...) |
a one-shot block from --block-c2; run protect --install to keep it |
not active (rules from a previous boot were lost) |
the same, after a reboot |
not active |
never installed, or removed |
Opting out
pushwarden install --no-block-c2 # at install time
pushwarden config --set block_c2=false # later; the guard stops reminding you
While block_c2 is on and the block is missing, the guard reminds you once a day.
Setting PUSHWARDEN_NO_BLOCK=1 skips the administrator prompt for one run. The package installers use it because they already did the work as root.
Adding it later
sudo pushwarden protect --install # Linux and macOS
pushwarden protect --install # Windows, from an elevated terminal
pushwarden protect --status
Removing it
pushwarden protect --uninstall
pushwarden uninstall --unblock # together with the guard
Limits
The block covers the addresses on the indicator list. A new C2 server is blocked once it is added to iocs.json, which the job picks up within a day. It is a second line of defence, not a replacement for removing the malware.