You shouldn't use this simple script here. Scroll to first reply and use the current version
Google operates several services that are commonly abused for sending spam. The following sections describe each service and the filtering strategies used.
cat > /usr/local/bin/policyguard.py
Don't forget to set execution bit:
copy templates, if not already done:
Add the policy_service to the existing smtpd_sender_restrictions to main.cf.in:
Add the two lines to the bottom of the master.cf.in
pmgconfig sync --restart
How to test?
Connect to service:
Enter address and an empty line:
Output:
Enter firebasespammail
Output:
Enter google groups spam
Output:
Google operates several services that are commonly abused for sending spam. The following sections describe each service and the filtering strategies used.
Firebasemail / Firebaseapp
Firebase is a Google-hosted platform that is frequently exploited for sending unsolicited email.- Emails sent directly through Firebase use the domain firebaseapp.com and can be blocked by sender domain.
- Some senders use Firebase with their own custom domains, making direct domain blocking ineffective. However, these senders can still be identified early: their domain's SPF record (DNS TXT) contains _spf.firebasemail.com. This allows rejection before the SMTP DATA command, conserving server resources and preventing spam from entering the queue.
Google Groups
Google Groups provides no opt-in or opt-out mechanism, making it trivially abusable: a spammer can add millions of recipients to a group and broadcast spam to all of them at once.- The sender domain can be any arbitrary registered domain, making domain-based filtering unreliable.
- A Google Groups-specific header is present in each message, but inspecting it requires waiting for the full email data to be transmitted.
- Fortunately, the envelope sender address always matches a predictable regular expression, which allows filtering before the DATA command is issued — the approach used by this policy daemon.
Google Usercontent
googleusercontent.com is a Google server that, in practice, is a source of spam exclusively. Connections from this host are blocked at the client level.Google Workspace & Gmail
This filter intentionally does not block legitimate Google-based senders, including:- Google Workspace customers (e.g. ryanair.com, doctolib.com, willidrop.com)
- Personal Gmail accounts (gmail.com, googlemail.com)
- Google Notification Mails vom bounces.google.com (Security Alerts, Google Mybusiness Information, etc.)
Code:
apt install python3-dnspython
cat > /usr/local/bin/policyguard.py
Code:
#!/usr/bin/env python3
import sys
import time
import re
import dns.resolver
from functools import lru_cache
MAX_SPF_DEPTH = 10
CACHE_SIZE = 4096
SPF_BLOCK_INCLUDE = ["_spf.firebasemail.com"]
SENDER_BLOCK_INCLUDE = ["firebaseapp.com"]
BLOCKLIST_CLIENTNAME = ["googleusercontent.com"]
SENDER_REGEX_PATTERNS = [
r'^[a-z0-9]{1,3}\+bncB[A-Z0-9]{25,}@',
]
SENDER_REGEXES = [re.compile(p) for p in SENDER_REGEX_PATTERNS]
resolver = dns.resolver.Resolver()
resolver.timeout = 2
resolver.lifetime = 3
def log(msg):
sys.stderr.write(f"spf-policy: {msg}\n")
sys.stderr.flush()
@lru_cache(maxsize=CACHE_SIZE)
def get_spf(domain):
try:
answers = resolver.resolve(domain, "TXT")
for r in answers:
txt = "".join([s.decode() for s in r.strings])
if txt.startswith("v=spf1"):
return txt
except Exception:
pass
return None
def spf_contains_block(domain, depth=0, visited=None):
if visited is None:
visited = set()
if depth > MAX_SPF_DEPTH:
return False
if domain in visited:
return False
visited.add(domain)
spf = get_spf(domain)
if not spf:
return False
parts = spf.split()
for p in parts:
if p.startswith("include:"):
include = p.split(":", 1)[1]
if include in SPF_BLOCK_INCLUDE:
return True
if spf_contains_block(include, depth + 1, visited):
return True
return False
def sender_matches_regex(sender):
for regex in SENDER_REGEXES:
if regex.match(sender):
return True, regex.pattern
return False, None
def handle_request(attrs):
sender = attrs.get("sender", "")
client_name = attrs.get("client_name", "").lower()
# Block Clients
if any(client_name == b or client_name.endswith("." + b) for b in BLOCKLIST_CLIENTNAME):
log(f"blocked client hostname: {client_name}")
return "reject reject for policy reasons [policyguard] [guc]"
if sender:
matched, pattern = sender_matches_regex(sender)
if matched:
log(f"blocked sender by regex ({pattern}): {sender}")
return "reject reject for policy reasons [gg]"
if "@" not in sender:
return "dunno"
domain = sender.split("@", 1)[1].lower()
try:
if any(domain == base or domain.endswith('.' + base) for base in SENDER_BLOCK_INCLUDE):
log(f"blocked sender domain {domain}")
return "reject reject for policy reasons [fbm]"
elif spf_contains_block(domain):
log(f"blocked sender domain {domain}")
return "reject reject for policy reasons [fbs]"
except Exception as e:
log(f"error checking {domain}: {e}")
return "dunno"
def main():
while True:
attrs = {}
while True:
line = sys.stdin.readline()
if line == "":
return
line = line.strip()
if not line:
break
if "=" in line:
k, v = line.split("=", 1)
attrs[k] = v
if not attrs:
continue
action = handle_request(attrs)
print(f"action={action}\n")
sys.stdout.flush()
if __name__ == "__main__":
main()
Don't forget to set execution bit:
Code:
chmod +x /usr/local/bin/policyguard.py
copy templates, if not already done:
Code:
mkdir -p /etc/pmg/templates/
cp /var/lib/pmg/templates/master.cf.in /etc/pmg/templates/
cp /var/lib/pmg/templates/main.cf.in /etc/pmg/templates/
Add the policy_service to the existing smtpd_sender_restrictions to main.cf.in:
Code:
smtpd_sender_restrictions =
check_policy_service unix:private/policygrd
Code:
policygrd unix - n n - 0 spawn
user=nobody argv=/usr/local/bin/policyguard.py
pmgconfig sync --restart
How to test?
Connect to service:
Code:
apt install socat
socat - UNIX-CONNECT:/var/spool/postfix/private/policygrd
Enter address and an empty line:
Code:
sender=test@example.com
<--- empty line
Output:
Code:
action=dunno
Enter firebasespammail
Code:
sender=fckw@babyamerica.com
<--- empty line
Output:
Code:
firebase-spf-policy: blocked sender domain babyamerica.com
action=reject Rejected for policy reasons [fbs]
Enter google groups spam
Code:
sender=aw7+bncBDIYHYXXTENBBUE76TGQMGQEVOOGNYY@teamkurofune.com
<--- empty line
Output:
Code:
spf-policy: blocked sender by regex (^[a-z0-9]{1,3}\+bnc[A-Z0-9]{10,}@): aw7+bncBDIYHYXXTENBBUE76TGQMGQEVOOGNYY@teamkurofune.com
action=reject reject for policy reasons [gg]
Attachments
Last edited: