Google sends a lot of spam via different services
Firebasemail / Firebaseapp
This is a service hosted by Google that are used to send spam.
- They send e-mail via their own domain firebaseapp.com
- Some senders use Firebase with their own custom domains, but you can still block them early: their domain’s TXT SPF record contains _spf.firebasemail.com. You can use this information to reject these emails before the DATA command, saving resources and avoiding spam in your queue.
Google Groups
Google Groups has neither a opt-in, nor an opt-out. A spammer just put a million receivers into a google group list and sends spam to the list.
The sender domain could be a random, registered domain. That makes it impossible to filter google groups via the sender-domain.
They send a specific google groups header, but to check for this header, you have to wait until the sender sends the email data.
Out luck: the sender address always matches a specific regex which could be used to filter out e-mails from googlegroups before the smtp data command is send.
The following programm implements a policy daemon for filtering google groups spam.
Google Usercontent
googleusercontent.com is a server from google sending only spam, so we block this connection client.
Google Workspace and gmail.com/googlemail.com
This script does not reject google workspace, eg. ryanair.com, doctolib.com, willidrop.com and others, nor does it reject gmail.com/googlemail.com
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:
Firebasemail / Firebaseapp
This is a service hosted by Google that are used to send spam.
- They send e-mail via their own domain firebaseapp.com
- Some senders use Firebase with their own custom domains, but you can still block them early: their domain’s TXT SPF record contains _spf.firebasemail.com. You can use this information to reject these emails before the DATA command, saving resources and avoiding spam in your queue.
Google Groups
Google Groups has neither a opt-in, nor an opt-out. A spammer just put a million receivers into a google group list and sends spam to the list.
The sender domain could be a random, registered domain. That makes it impossible to filter google groups via the sender-domain.
They send a specific google groups header, but to check for this header, you have to wait until the sender sends the email data.
Out luck: the sender address always matches a specific regex which could be used to filter out e-mails from googlegroups before the smtp data command is send.
The following programm implements a policy daemon for filtering google groups spam.
Google Usercontent
googleusercontent.com is a server from google sending only spam, so we block this connection client.
Google Workspace and gmail.com/googlemail.com
This script does not reject google workspace, eg. ryanair.com, doctolib.com, willidrop.com and others, nor does it reject gmail.com/googlemail.com
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}\+bnc[A-Z0-9]{10,}@',
# weitere Regexe hier hinzufuegen
]
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: