Download vspam-agent
Lightweight mail policy daemon that protects Postfix from phishing in real-time. Checks sender domains and IPs against the vspam.org threat database with local caching. Fail-open design โ mail is never blocked due to agent errors.
Get a free API key to unlock all agent features โ higher rate limits, async threat reporting, and community voting. Sign up at vspam.org/account
Operator-Safe Enforcement Defaults
The agent is best used for canonical phishing domains and exact IPv4 or IPv6 host decisions, where direct evidence and score-aware publication are strongest.
IPv6 prefix watch and ASN reputation are better as operator review signals unless your environment has its own policy layer for broader throttling or inspection.
Delist requests are reviewed by a human within 48 hours, need no account, and are tracked publicly by ID โ see delist policy. Review speed and false-positive trends are public on status, statistics, and methodology.
Install from Repositoryrecommended
Automatic updates via your system package manager. Packages hosted on packages.vspam.org.
Debian / Ubuntu
# Add GPG key
curl -fsSL https://packages.vspam.org/apt/vspam-archive-keyring.gpg \
| sudo gpg --dearmor -o /usr/share/keyrings/vspam-archive-keyring.gpg
# Add repository
echo "deb [signed-by=/usr/share/keyrings/vspam-archive-keyring.gpg] \
https://packages.vspam.org/apt stable main" \
| sudo tee /etc/apt/sources.list.d/vspam.list
# Install
sudo apt update && sudo apt install vspam-agentRHEL / CentOS / Fedora
# Add repository
sudo tee /etc/yum.repos.d/vspam.repo <<EOF
[vspam]
name=vspam.org packages
baseurl=https://packages.vspam.org/rpm/el/9/\$basearch/
enabled=1
gpgcheck=1
gpgkey=https://packages.vspam.org/rpm/RPM-GPG-KEY-vspam
EOF
# Install
sudo dnf install vspam-agentManual Download
Download individual packages if you prefer manual installation or don't have repo access.
vspam-agent_0.1.2_amd64.debsudo dpkg -i vspam-agent_0.1.2_amd64.debvspam-agent_0.1.2_arm64.debsudo dpkg -i vspam-agent_0.1.2_arm64.debvspam-agent-0.1.2-1.x86_64.rpmsudo rpm -i vspam-agent-0.1.2-1.x86_64.rpmvspam-agent-0.1.2-1.aarch64.rpmsudo rpm -i vspam-agent-0.1.2-1.aarch64.rpmvspam-agent-0.1.2-linux-amd64.tar.gztar xzf vspam-agent-0.1.2-linux-amd64.tar.gz && sudo cp vspam-agent-*/vspam-agent /usr/local/bin/vspam-agent-0.1.2-linux-arm64.tar.gztar xzf vspam-agent-0.1.2-linux-arm64.tar.gz && sudo cp vspam-agent-*/vspam-agent /usr/local/bin/All packages available on GitHub Releases and packages.vspam.org/releases.
Verify Packages
All packages are GPG-signed. Verify integrity before installing.
Import GPG public key
# Debian/Ubuntu โ key is imported automatically with the repo setup above
# For manual verification:
curl -fsSL https://packages.vspam.org/apt/vspam-archive-keyring.gpg | gpg --import
# RHEL/CentOS/Fedora
sudo rpm --import https://packages.vspam.org/rpm/RPM-GPG-KEY-vspamVerify tarball checksums
curl -fsSLO https://packages.vspam.org/releases/SHA256SUMS
curl -fsSLO https://packages.vspam.org/releases/SHA256SUMS.asc
# Verify the checksum file signature
gpg --verify SHA256SUMS.asc SHA256SUMS
# Verify your download
sha256sum -c SHA256SUMS --ignore-missingVerify tarball GPG signature
# Each tarball has a detached .asc signature
curl -fsSLO https://packages.vspam.org/releases/vspam-agent-0.1.2-linux-amd64.tar.gz
curl -fsSLO https://packages.vspam.org/releases/vspam-agent-0.1.2-linux-amd64.tar.gz.asc
gpg --verify vspam-agent-0.1.2-linux-amd64.tar.gz.ascGPG key fingerprint
Key ID: admin@vspam.org โ verify at packages.vspam.org/apt/vspam-archive-keyring.gpg
Quick Start
1. Install via package manager
# Debian/Ubuntu (after adding repo โ see above)
sudo apt update && sudo apt install vspam-agent
# RHEL/CentOS/Fedora (after adding repo โ see above)
sudo dnf install vspam-agent2. Configure (optional โ works with defaults)
# /etc/vspam/agent.yml
api_url: https://api.vspam.org
api_key: "your-key-here" # optional, get one at vspam.org/account
listen: tcp://127.0.0.1:10045
cache_ttl: 10m
dnsbl_enabled: true
dnsbl_zone: dnsbl.vspam.org3. Start the agent
sudo systemctl enable --now vspam-agent
sudo systemctl status vspam-agent4. Add to Postfix
# /etc/postfix/main.cf
# Fail open. Postfix defaults to deferring every message with a 451 when a
# policy service is unreachable, on a 100s timeout, so these two lines matter
# more than the third: without them, an agent restart stops your mail.
smtpd_policy_service_default_action = DUNNO
smtpd_policy_service_timeout = 10s
smtpd_recipient_restrictions =
permit_mynetworks,
permit_sasl_authenticated,
reject_unauth_destination,
check_policy_service inet:127.0.0.1:10045
# Then reload
sudo postfix reloadHow It Works
Incoming email โ Postfix (SMTP)
โ smtpd_recipient_restrictions
โ check_policy_service inet:127.0.0.1:10045
โ vspam-agent
1. Check local BoltDB cache (sub-ms)
2. Query vspam.org operator lookup / exact-host RBL
3. Query dnsbl.vspam.org (DNS blocklist)
โ DUNNO (allow) or REJECT (block)
โ Async report new threats back to API- Fail-open โ API down or DNS errors = allow (DUNNO). Mail never blocked by agent failure.
- Fast โ BoltDB cache means repeat lookups are sub-millisecond.
- Async reporting โ blocked senders are reported to the API in the background. SMTP response is never delayed.
- Lightweight โ single Go binary, ~10 MB, no dependencies.
- Operator-safe by design โ exact hosts and canonical domains are the main enforcement path; broader IPv6 prefix and ASN context should stay in review workflows unless you have explicit policy for them.
Configuration Reference
Config file: /etc/vspam/agent.yml
# vspam.org API endpoint
api_url: https://api.vspam.org
# API key (get one at https://vspam.org/account)
api_key: "vspam_xxxxxxxxxxxx"
# Policy daemon listen address
listen: tcp://127.0.0.1:10045
# Local cache (BoltDB)
cache_ttl: 10m
cache_path: /var/lib/vspam/cache.db
# DNSBL lookup
dnsbl_enabled: true
dnsbl_zone: dnsbl.vspam.org
# Reject message for blocked senders
reject_message: "550 Message rejected: sender listed in vspam.org (phishing)"
# Auto-report (requires api_key)
reporting_enabled: true
queue_size: 1000
log_level: infoCommand Line
The same binary is the CLI, so installing the package gets you both โ one version, one signature, one thing to upgrade. Serving stays the default, so the systemd unit is unaffected.
vspam-agent check <indicator>... # exit 1 if any are listed
vspam-agent report <indicator> # submit one
vspam-agent bulk [file] # submit many, one per line (stdin by default)
vspam-agent eml [file] # extract indicators from a messageChecking
Exit codes are the interface: 0 nothing listed, 1 something listed, 2 the lookup failed. A failed lookup is deliberately not 0 โ a script gating mail on this should fail loudly rather than let a message through because DNS was down. No API key is needed; one raises the rate limit.
$ vspam-agent check login-paypa1.com safe.example.org
login-paypa1.com LISTED phishing_domain (consensus)
safe.example.org clean
if ! vspam-agent check "$DOMAIN" >/dev/null; then echo "refusing $DOMAIN"; fiReporting
Type and category are inferred using the same rules as the web submit form, and defanged input is normalized. Lists longer than the APIโs 100-per-request cap are split across requests rather than rejected. --dry-run prints what would be sent and submits nothing.
vspam-agent report --evidence "credential harvest, seen 2026-08-26" \
'hxxps://login-paypa1[.]com/verify'
grep -oP 'https?://\S+' quarantine.log | vspam-agent bulkMessage files
Reads the sender addresses, the connecting IP from the header your own MX wrote, and links in the text parts. The message is parsed locally and never uploaded โ only the extracted indicators are sent, and only with --report.
$ vspam-agent eml suspicious.eml
email from support@evil.example.net
ip received 203.0.113.66
url body https://login.evil.example.net/verify?u=1
3 indicators. Re-run with --report to submit them.Running the daemon
# Serving is the default, so the subcommand is optional
vspam-agent
vspam-agent --config /etc/vspam/agent.yml serve
vspam-agent versionSystemd Service
sudo systemctl start vspam-agent # Start
sudo systemctl stop vspam-agent # Stop
sudo systemctl restart vspam-agent # Restart
sudo systemctl status vspam-agent # Status
sudo journalctl -u vspam-agent -f # LogsLookup Chain
- Local cache (BoltDB) โ sub-millisecond, avoids network calls for repeat senders
- REST API (
GET /api/v1/public/operator-lookup) โ canonical domain and ASN checks without client-side hashing - IP RBL / DNSBL (
GET /api/v1/rbl/check?ip=...ordig <domain>.dnsbl.vspam.org A) โ exact IPv4 / IPv6 host checks and direct DNSBL policy lookups
First definitive result wins. Cache stores both positive (malicious) and negative (clean) results with configurable TTL.
Security
- Runs as unprivileged
vspamsystem user - Systemd hardening: NoNewPrivileges, ProtectSystem=strict, PrivateTmp
- API key stored in config file with 0640 permissions
- Fail-open: lookup errors never block mail delivery
- Cache prevents API/DNS amplification from high mail volume
Troubleshooting
Agent not starting
sudo journalctl -u vspam-agent -e
# Common: config parse error, port already in use, permission deniedMail not being checked
# Verify Postfix config
postconf smtpd_recipient_restrictions | grep policy
# Verify agent is listening
ss -tlnp | grep 10045False positives
# Check why a domain was blocked
sudo journalctl -u vspam-agent | grep "domain.com"
# Request delisting at https://vspam.org/delistCache issues
sudo systemctl stop vspam-agent
sudo rm /var/lib/vspam/cache.db
sudo systemctl start vspam-agentSource
The filter configuration โ the Rspamd module, the SpamAssassin rules, the Ansible role and the mailcow overlay โ is public and AGPL-3.0 licensed at github.com/vspam-org/integrations. The agent daemon's repository is not published yet; the binaries above are built from it and signed with the key below.