Custom Policies¶
Creating advanced custom filtering policies beyond the standard configuration.
Policy Architecture¶
Policy Types¶
Connection Policies: - IP-based restrictions - Geographic filtering - Rate limiting - Greylisting
Authentication Policies: - SASL authentication rules - Relay restrictions - Sender verification
Content Policies: - Header-based filtering - Body content scanning - Attachment restrictions - Size limits
Recipient Policies: - Per-domain rules - Per-user rules - Distribution list handling
Custom Policy Files¶
Policy File Structure¶
Main policy directory:
/etc/mailborder/custom/
├── policies/
│ ├── connection.cf
│ ├── content.cf
│ ├── recipient.cf
│ └── custom.cf
├── rules/
│ ├── rspamd/
│ └── spamassassin/
└── scripts/
└── policy-helpers/
Creating Custom Policies¶
Example connection policy:
sudo tee /etc/mailborder/custom/policies/connection.cf << 'EOF'
# Custom connection policies
# Block specific networks
smtpd_client_restrictions =
check_client_access cidr:/etc/mailborder/custom/blocked_networks.cidr,
permit
# Rate limiting by IP
smtpd_client_connection_rate_limit = 10
smtpd_client_connection_count_limit = 5
smtpd_client_event_limit_exceptions =
192.168.1.0/24,
10.0.0.0/8
# Greylisting exceptions
smtpd_client_restrictions =
check_client_access hash:/etc/mailborder/custom/greylist_whitelist,
permit
EOF
Include in main configuration:
# Include custom policies
import_environment = MAIL_CONFIG=/etc/mailborder/custom/policies/connection.cf
Reload configuration:
Advanced Content Filtering¶
Custom Rspamd Rules¶
Create custom rule file:
sudo mkdir -p /etc/rspamd/local.d
sudo tee /etc/rspamd/local.d/custom_content.conf << 'EOF'
# Detect internal document leakage
INTERNAL_DOCUMENT_LEAK {
type = "composite";
expression = "HAS_ATTACHMENT & CONTAINS_CONFIDENTIAL";
score = 10.0;
description = "Potential internal document leakage";
group = "custom_policies";
}
HAS_ATTACHMENT {
type = "header";
header = "Content-Type";
regexp = "/(multipart|application)\/(mixed|octet-stream)/i";
}
CONTAINS_CONFIDENTIAL {
type = "content";
regexp = "/(confidential|internal only|not for distribution)/i";
}
# Detect suspicious invoice emails
FAKE_INVOICE {
type = "composite";
expression = "INVOICE_SUBJECT & SUSPICIOUS_SENDER & HAS_LINK";
score = 7.5;
description = "Suspicious invoice email";
group = "custom_policies";
}
INVOICE_SUBJECT {
type = "header";
header = "Subject";
regexp = "/(invoice|payment|bill|receipt)/i";
}
SUSPICIOUS_SENDER {
type = "from";
map = "file:///etc/mailborder/custom/trusted_invoice_senders.map";
regexp = true;
inverse = true;
}
HAS_LINK {
type = "urls";
regexp = "/^https?:/i";
}
# Detect phishing keywords
PHISHING_KEYWORDS {
type = "content";
regexp = "/(verify your account|suspended|unusual activity|click here immediately)/i";
score = 5.0;
description = "Common phishing keywords";
group = "custom_policies";
}
# Company-specific policy: Block competitor domains
COMPETITOR_DOMAIN {
type = "from";
map = "file:///etc/mailborder/custom/competitor_domains.map";
score = 15.0;
description = "Email from competitor domain";
group = "custom_policies";
}
EOF
Create supporting map files:
# Trusted invoice senders
sudo tee /etc/mailborder/custom/trusted_invoice_senders.map << 'EOF'
/@accounting\.company\.com$/
/@billing\.company\.com$/
/@invoices\.company\.com$/
EOF
# Competitor domains
sudo tee /etc/mailborder/custom/competitor_domains.map << 'EOF'
/@competitor1\.com$/
/@competitor2\.net$/
/@rival-company\.com$/
EOF
Test rules:
Test with sample email:
Advanced SpamAssassin Rules¶
Create custom rule file:
sudo tee /etc/spamassassin/local_custom.cf << 'EOF'
# Custom SpamAssassin rules
# Detect executive impersonation
header CEO_IMPERSONATION From =~ /ceo@/i
describe CEO_IMPERSONATION Possible CEO impersonation
score CEO_IMPERSONATION 4.0
body CEO_REQUEST /urgent.*transfer.*funds/i
describe CEO_REQUEST CEO-style urgent transfer request
score CEO_REQUEST 3.0
# Combine for higher score
meta EXECUTIVE_FRAUD CEO_IMPERSONATION && CEO_REQUEST
describe EXECUTIVE_FRAUD Executive impersonation fraud attempt
score EXECUTIVE_FRAUD 8.0
# Block known malicious patterns
body MALICIOUS_MACRO /Document_\d{8}\.doc/
describe MALICIOUS_MACRO Malicious macro document pattern
score MALICIOUS_MACRO 6.0
# Detect credential phishing
uri PHISHING_PORTAL /login.*verify/i
describe PHISHING_PORTAL Credential phishing portal
score PHISHING_PORTAL 5.0
# Custom scoring for internal use
header EXTERNAL_SENDER X-Mailborder-External =~ /true/
describe EXTERNAL_SENDER External sender
score EXTERNAL_SENDER 0.5
header NO_SPF X-Mailborder-SPF =~ /none/
describe NO_SPF No SPF record
score NO_SPF 1.0
# Combination rules
meta EXTERNAL_NO_AUTH EXTERNAL_SENDER && NO_SPF && !DKIM_VALID
describe EXTERNAL_NO_AUTH External sender with no authentication
score EXTERNAL_NO_AUTH 3.0
EOF
sudo systemctl restart spamassassin
Test rules:
spamassassin --lint
echo "From: ceo@company.com\nSubject: Urgent transfer funds\n\nPlease transfer funds immediately." | \
spamassassin -t
Scripted Policies¶
Policy Service Protocol¶
Create custom policy daemon:
sudo tee /usr/local/bin/mb-policy-daemon.py << 'EOF'
#!/usr/bin/env python3
import sys
import socket
def check_policy(request):
"""
Custom policy logic
Returns: 'DUNNO', 'OK', 'REJECT reason', 'DEFER_IF_PERMIT reason'
"""
params = {}
for line in request.split('\n'):
if '=' in line:
key, value = line.split('=', 1)
params[key] = value
# Example: Block emails from specific sender during business hours
import datetime
hour = datetime.datetime.now().hour
sender = params.get('sender', '')
if 9 <= hour <= 17 and 'spam' in sender:
return 'REJECT Sender blocked during business hours'
# Example: Require authentication for external senders
if params.get('sasl_username', '') == '':
client_address = params.get('client_address', '')
if not client_address.startswith('192.168.'):
return 'REJECT Authentication required'
# Example: Rate limit per sender
sender_count = get_sender_count(sender) # Implement counting logic
if sender_count > 100:
return 'DEFER_IF_PERMIT Rate limit exceeded'
return 'DUNNO' # No action, continue processing
def main():
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('127.0.0.1', 10040))
sock.listen(5)
while True:
conn, addr = sock.accept()
request = ''
while True:
data = conn.recv(4096).decode('utf-8')
if not data:
break
request += data
if '\n\n' in request:
break
response = check_policy(request)
conn.sendall(f'action={response}\n\n'.encode('utf-8'))
conn.close()
if __name__ == '__main__':
main()
EOF
sudo chmod +x /usr/local/bin/mb-policy-daemon.py
Create SystemD service:
sudo tee /etc/systemd/system/mb-policy-daemon.service << 'EOF'
[Unit]
Description=Mailborder Custom Policy Daemon
After=network.target
[Service]
Type=simple
User=mailborder
ExecStart=/usr/local/bin/mb-policy-daemon.py
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable mb-policy-daemon
sudo systemctl start mb-policy-daemon
Configure Postfix to use policy service:
smtpd_recipient_restrictions =
permit_mynetworks,
permit_sasl_authenticated,
check_policy_service inet:127.0.0.1:10040,
reject_unauth_destination
Test policy service:
Type:
request=smtpd_access_policy
protocol_state=RCPT
protocol_name=ESMTP
client_address=203.0.113.5
client_name=unknown
sender=spam@example.com
recipient=user@yourdomain.com
sasl_username=
Press Enter twice to see response.
Domain-Specific Policies¶
Per-Domain Filtering¶
Create domain policy file:
sudo tee /etc/mailborder/custom/domain_policies.cf << 'EOF'
# Domain-specific policies
# Strict filtering for executives
/^ceo@company\.com$/ FILTER smtp:[127.0.0.1]:10050
/^cfo@company\.com$/ FILTER smtp:[127.0.0.1]:10050
# Relaxed filtering for partners
/^.*@partner1\.com$/ FILTER smtp:[127.0.0.1]:10051
/^.*@partner2\.com$/ FILTER smtp:[127.0.0.1]:10051
# Quarantine-only for testing
/^.*@test\.company\.com$/ FILTER smtp:[127.0.0.1]:10052
EOF
postmap /etc/mailborder/custom/domain_policies.cf
Configure Postfix:
Executive Protection Policy¶
Enhanced filtering for executives:
sudo tee /etc/mailborder/custom/policies/executive.cf << 'EOF'
# Executive protection policy
# Stricter spam threshold
spam_threshold_executive = 3.0 # vs 5.0 standard
# Block all external executables
attachment_extensions_blocked = exe,com,bat,cmd,scr,vbs,js,jar,zip
# Require authentication for external senders
require_spf = pass
require_dkim = pass
require_dmarc = pass
# Enhanced phishing detection
check_url_reputation = strict
check_sender_reputation = strict
# Alert on suspicious patterns
alert_on_keyword = urgent,wire transfer,verify account,suspended
# Quarantine questionable emails instead of rejecting
action_suspicious = quarantine
action_threshold = 2.0
EOF
Implement in Rspamd:
sudo tee /etc/rspamd/local.d/settings.conf << 'EOF'
executive {
priority = high;
rcpt = ["ceo@company.com", "cfo@company.com"];
apply {
actions {
reject = 3.0; # Stricter than default 15.0
add_header = 2.0; # Stricter than default 6.0
greylist = 1.0;
}
symbols {
PHISHING_KEYWORDS.weight = 8.0; # Increase weight
EXECUTIVE_FRAUD.weight = 10.0;
}
}
}
EOF
sudo systemctl restart rspamd
Time-Based Policies¶
Business Hours Filtering¶
Create time-based policy script:
sudo tee /usr/local/bin/mb-time-policy.sh << 'EOF'
#!/bin/bash
HOUR=$(date +%H)
DAY=$(date +%u) # 1=Monday, 7=Sunday
# Business hours: Mon-Fri 9am-5pm
if [ $DAY -le 5 ] && [ $HOUR -ge 9 ] && [ $HOUR -lt 17 ]; then
echo "business_hours"
else
echo "after_hours"
fi
EOF
sudo chmod +x /usr/local/bin/mb-time-policy.sh
Implement in Rspamd:
sudo tee /etc/rspamd/local.d/time_policy.conf << 'EOF'
AFTER_HOURS_EXTERNAL {
type = "composite";
expression = "TIME_AFTER_HOURS & EXTERNAL_SENDER";
score = 2.0;
description = "External email received after hours";
group = "custom_policies";
}
TIME_AFTER_HOURS {
type = "lua";
script = [[
return function(task)
local hour = tonumber(os.date("%H"))
local day = tonumber(os.date("%w"))
if day == 0 or day == 6 then
return true -- Weekend
end
if hour < 9 or hour >= 17 then
return true -- After hours
end
return false
end
]];
}
EOF
sudo systemctl restart rspamd
Geographic Policies¶
Regional Filtering¶
Block specific countries except for partners:
sudo tee /etc/mailborder/custom/geo_policy.cf << 'EOF'
# Geographic policies
# High-risk countries (higher spam score)
high_risk_countries = CN,RU,NG,BR,IN
# Blocked countries (reject)
blocked_countries = KP,IR
# Trusted partners (whitelist by country + domain)
trusted_partners = UK:partner-uk.com,DE:partner-de.com
# Scoring
score_high_risk = 3.0
score_medium_risk = 1.5
score_low_risk = 0.5
EOF
Implement in custom script:
sudo tee /usr/local/bin/mb-geo-policy.py << 'EOF'
#!/usr/bin/env python3
import sys
import maxminddb
def check_ip(ip_address):
reader = maxminddb.open_database('/var/lib/mailborder/geoip/GeoLite2-Country.mmdb')
result = reader.get(ip_address)
reader.close()
if result:
country = result.get('country', {}).get('iso_code', '')
# Block list
if country in ['KP', 'IR']:
return 'REJECT Country blocked'
# High risk list
if country in ['CN', 'RU', 'NG', 'BR', 'IN']:
return 'PREPEND X-Mailborder-Risk: high'
return 'DUNNO'
if __name__ == '__main__':
ip = sys.argv[1] if len(sys.argv) > 1 else '8.8.8.8'
print(check_policy(ip))
EOF
sudo chmod +x /usr/local/bin/mb-geo-policy.py
Attachment Policies¶
Advanced Attachment Filtering¶
Create attachment policy:
sudo tee /etc/mailborder/custom/attachment_policy.cf << 'EOF'
# Attachment policies
# Block dangerous extensions
blocked_extensions = exe,com,bat,cmd,scr,pif,vbs,js,jar,msi,dll
# Size limits by type
max_size_executable = 0 # Block all
max_size_archive = 10485760 # 10MB
max_size_document = 52428800 # 50MB
max_size_image = 10485760 # 10MB
# Scan archives
scan_zip = yes
scan_rar = yes
scan_7z = yes
max_archive_depth = 3
# Document macro detection
block_office_macros = yes
allow_signed_macros = yes
# Quarantine suspicious attachments
action_suspicious_attachment = quarantine
action_blocked_extension = reject
EOF
Implement in ClamAV:
sudo tee -a /etc/clamav/clamd.conf << 'EOF'
# Custom attachment policies
ArchiveBlockEncrypted yes
AlertBrokenExecutables yes
AlertExceedsMax yes
MaxScanSize 100M
MaxFileSize 50M
MaxRecursion 5
MaxFiles 1000
EOF
sudo systemctl restart clamd@scan
Machine Learning Policies¶
Bayesian Learning Integration¶
Train Bayes filter:
# Train on spam corpus
sudo sa-learn --spam /var/spool/mailborder/spam-corpus/
# Train on ham corpus
sudo sa-learn --ham /var/spool/mailborder/ham-corpus/
# Check statistics
sudo sa-learn --dump magic
Auto-learning configuration:
sudo tee -a /etc/spamassassin/local.cf << 'EOF'
# Bayesian auto-learning
bayes_auto_learn 1
bayes_auto_learn_threshold_nonspam -0.1
bayes_auto_learn_threshold_spam 6.0
bayes_auto_learn_on_error 1
# Increase Bayes weight for custom policy
score BAYES_99 4.5
score BAYES_95 3.5
score BAYES_80 2.5
EOF
sudo systemctl restart spamassassin
Policy Testing¶
Test Custom Policies¶
Create test email:
cat > /tmp/test-email.eml << 'EOF'
From: test@example.com
To: admin@yourdomain.com
Subject: Test Policy Email
This is a test email to verify custom policies.
Keyword: urgent
Keyword: verify account
EOF
Test with Rspamd:
Test with SpamAssassin:
Test policy daemon:
Policy Documentation¶
Document all custom policies:
sudo tee /etc/mailborder/custom/README.md << 'EOF'
# Custom Mailborder Policies
## Active Policies
### Executive Protection
- File: `policies/executive.cf`
- Purpose: Enhanced filtering for executive accounts
- Threshold: 3.0 (vs 5.0 standard)
### Geographic Filtering
- File: `geo_policy.cf`
- Purpose: Block/score based on country
- High-risk: CN, RU, NG, BR, IN
- Blocked: KP, IR
### Time-Based Filtering
- File: `time_policy.conf`
- Purpose: Additional scrutiny for after-hours emails
- Business hours: Mon-Fri 9am-5pm
### Content Policies
- File: `custom_content.conf`
- Purpose: Detect internal document leakage, fake invoices
- Rules: INTERNAL_DOCUMENT_LEAK, FAKE_INVOICE
## Maintenance
Last updated: 2025-11-12
Review schedule: Quarterly
Contact: admin@company.com
EOF