Skip to content

Instantly share code, notes, and snippets.

@robinsmidsrod
Last active December 27, 2015 20:49
Show Gist options
  • Save robinsmidsrod/7387679 to your computer and use it in GitHub Desktop.
Save robinsmidsrod/7387679 to your computer and use it in GitHub Desktop.
Postfix/DSPAM/ClamAV/Dovecot with MySQL mail server setup (all encrypted with SSL/TLS)
#Automatically Generated by clamav-base postinst
#To reconfigure clamd run #dpkg-reconfigure clamav-base
#Please read /usr/share/doc/clamav-base/README.Debian.gz for details
TCPSocket 3310
TCPAddr 127.0.0.1
# TemporaryDirectory is not set to its default /tmp here to make overriding
# the default with environment variables TMPDIR/TMP/TEMP possible
User clamav
AllowSupplementaryGroups true
ScanMail true
ScanArchive true
ArchiveBlockEncrypted false
MaxDirectoryRecursion 15
FollowDirectorySymlinks false
FollowFileSymlinks false
ReadTimeout 180
MaxThreads 12
MaxConnectionQueueLength 15
LogSyslog true
LogFacility LOG_LOCAL6
LogClean false
LogVerbose false
PidFile /var/run/clamav/clamd.pid
DatabaseDirectory /var/lib/clamav
SelfCheck 3600
Foreground false
Debug false
ScanPE true
ScanOLE2 true
ScanHTML true
DetectBrokenExecutables false
ExitOnOOM false
LeaveTemporaryFiles false
AlgorithmicDetection true
ScanELF true
IdleTimeout 30
PhishingSignatures true
PhishingScanURLs true
PhishingAlwaysBlockSSLMismatch false
PhishingAlwaysBlockCloak false
DetectPUA false
ScanPartialMessages false
HeuristicScanPrecedence false
StructuredDataDetection false
CommandReadTimeout 5
SendBufTimeout 200
MaxQueue 100
ExtendedDetectionInfo true
OLE2BlockMacros false
StreamMaxLength 10M
LogFile /var/log/clamav/clamav.log
LogTime true
LogFileUnlock false
LogFileMaxSize 0
Bytecode true
BytecodeSecurity TrustSigned
BytecodeTimeout 60000
OfficialDatabaseOnly false
CrossFilesystems true
# Automatically created by the clamav-freshclam postinst
# Comments will get lost when you reconfigure the clamav-freshclam package
DatabaseOwner clamav
UpdateLogFile /var/log/clamav/freshclam.log
LogVerbose false
LogSyslog false
LogFacility LOG_LOCAL6
LogFileMaxSize 0
LogTime no
Foreground false
Debug false
MaxAttempts 5
DatabaseDirectory /var/lib/clamav/
DNSDatabaseInfo current.cvd.clamav.net
AllowSupplementaryGroups false
PidFile /var/run/clamav/freshclam.pid
ConnectTimeout 30
ReceiveTimeout 30
TestDatabases yes
ScriptedUpdates yes
CompressLocalDatabase no
Bytecode true
# Check for new database 24 times a day
Checks 24
DatabaseMirror db.local.clamav.net
DatabaseMirror database.clamav.net
protocols = imap pop3 imaps pop3s managesieve
disable_plaintext_auth = no
log_timestamp = "%Y-%m-%d %H:%M:%S "
ssl = yes
ssl_cert_file = /etc/ssl/certs/mail.example.com.crt
ssl_key_file = /etc/ssl/private/mail.example.com.key
ssl_ca_file = /etc/ssl/certs/RapidSSL_CA.pem
ssl_cipher_list = ALL:!LOW:!SSLv2:ALL:!aNULL:!ADH:!eNULL:!EXP:RC4+RSA:+HIGH:+MEDIUM
mail_location = maildir:~/.maildir/
mail_privileged_group = mail
verbose_proctitle = yes
protocol imap {
mail_max_userip_connections = 15
imap_client_workarounds = outlook-idle delay-newmail
mail_plugins = antispam
}
protocol pop3 {
pop3_uidl_format = %08Xu%08Xv
mail_max_userip_connections = 15
pop3_client_workarounds = outlook-no-nuls oe-ns-eoh
}
protocol managesieve {
}
protocol lda {
postmaster_address = postmaster
mail_plugins = sieve
quota_full_tempfail = yes
deliver_log_format = msgid=%m: %$
rejection_reason = Your message to <%t> was automatically rejected:%n%r
}
auth_username_chars = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890.-_@
auth default {
mechanisms = plain login
passdb sql {
args = /etc/dovecot/sql.conf
}
userdb prefetch {
}
userdb sql {
args = /etc/dovecot/sql.conf
}
user = vmail
socket listen {
master {
path = /var/run/dovecot/auth-master
mode = 0600
user = vmail
group = vmail
}
client {
path = /var/spool/postfix/private/dovecot-auth
mode = 0660
user = postfix
group = postfix
}
}
}
dict {
}
plugin {
# sieve defaults, see http://wiki.dovecot.org/LDA/Sieve
# Default script used if user doesn't have one
sieve_global_path = /home/vmail/.default.sieve
# Global sieve scripts go here (for users to include)
sieve_global_dir = /home/vmail/.sieve/
# Main active user sieve script
sieve = %h/.dovecot.sieve
# User personal sieve script dir
sieve_dir = %h/.sieve
# antispam settings, see man 7 antispam
# Spam folder
antispam_spam = Junk
# List of possible trash folders (semicolon separated)
antispam_trash_pattern_ignorecase = trash;Deleted *
# spam/not-spam addresses (default unset which will give errors)
antispam_mail_spam = spam@mail.example.com
antispam_mail_notspam = notspam@mail.example.com
}
# Unfortunately the only scheme which is compatible with
# SMTP, MANAGESIEVE and POP/IMAP AUTH is to store the passwords
# in plaintext. If you're willing to store multiple hashed versions
# of the same password for the different authentication protocols you
# might be able to avoid storing it in plaintext in the database.
# We use mysql here
driver = mysql
connect = host=localhost dbname=your-mysql-database-name user=your-mysql-user password=your-mysql-password
# Cleartext password scheme
default_pass_scheme = PLAIN
# This is for passdb sql (with support for userdb prefect)
password_query = \
SELECT email AS user, clear AS password, \
10000 AS userdb_uid, 10000 AS userdb_gid, homedir AS userdb_home, CONCAT('maildir:',homedir,'.maildir/') AS userdb_mail \
FROM users WHERE email = lower('%u')
# This is for userdb sql
user_query = \
SELECT 10000 AS uid, 10000 AS gid, homedir AS home, CONCAT('maildir:',homedir,'.maildir/') AS mail \
FROM users WHERE email = lower('%u')
Home /var/spool/dspam
StorageDriver /usr/lib/dspam/libmysql_drv.so
DeliveryHost 127.0.0.1
DeliveryPort 10025
DeliveryIdent localhost
DeliveryProto SMTP
OnFail unlearn
Trust root
Trust dspam
Trust mail
Trust postfix
Trust vmail
TrainingMode teft
Feature chained
Feature whitelist
Algorithm graham burton
PValue graham
AllowOverride trainingMode
AllowOverride spamAction spamSubject
AllowOverride statisticalSedation
AllowOverride enableBNR
AllowOverride enableWhitelist
AllowOverride signatureLocation
AllowOverride showFactors
AllowOverride optIn optOut
AllowOverride whitelistThreshold
Notifications on
PurgeSignatures 14 # Stale signatures
PurgeNeutral 90 # Tokens with neutralish probabilities
PurgeUnused 90 # Unused tokens
PurgeHapaxes 30 # Tokens with less than 5 hits (hapaxes)
PurgeHits1S 15 # Tokens with only 1 spam hit
PurgeHits1I 15 # Tokens with only 1 innocent hit
LocalMX 127.0.0.1
SystemLog on
UserLog on
Opt out
ClamAVPort 3310
ClamAVHost 127.0.0.1
# ClamAVResponse: reject (reject or drop the message with a permanent failure)
# accept (accept the message and quietly drop the message)
# spam (treat as spam and quarantine/tag/whatever)
ClamAVResponse spam
ProcessorBias on
MySQLServer /var/run/mysqld/mysqld.sock
MySQLUser your-mysql-username
MySQLPass your-mysql-password
MySQLDb your-mysql-database-name
MySQLUIDInSignature on
MySQLVirtualTable dspam_virtual_uids
MySQLVirtualUIDField uid
MySQLVirtualUsernameField username
# See /usr/share/postfix/main.cf.dist for a commented, more complete version
# See /etc/postfix/main.cf.dovecot-postfix for the automatically created config from dovecot-postfix package
# Default setting likes to search NIS, which we don't use, so just disable it
alias_maps = hash:/etc/aliases
# These are the machines that can forward mail without SASL auth
# The default is mynetworks_style = subnet, which is a bit too big
mynetworks = $config_directory/mynetworks
# These are the domains we handle root mail and such for
#mydestination = $myhostname, localhost.$mydomain, localhost, $config_directory/mydestination
mydestination = $myhostname, localhost.$mydomain, localhost
# Enable delivery to all virtual domains listed in database
# NB: Prefix 'mysql:' requires postfix-mysql package
virtual_mailbox_domains = mysql:$config_directory/sql/virtual_mailbox_domains.cf
# Enable use of Dovecot LDA specified in master.cf for virtual_mailbox_domains
virtual_transport = dovecot
# To get the Delivered-To: header we need to use flags=D and set this entry
dovecot_destination_recipient_limit = 1
# Enable forward addresses for virtual domains
virtual_alias_maps = mysql:$config_directory/sql/virtual_alias_maps.cf
# Enable incoming TLS, but allow unencrypted connections
smtpd_tls_security_level = may
# Add TLS Received: message header
smtpd_tls_received_header = yes
# Enable outgoing TLS, but allow unencrypted connections
smtp_tls_security_level = may
# Use this CA directory for outgoing TLS challenges
# Use c_rehash from OpenSSL to update symlinks
smtp_tls_CApath = /etc/ssl/certs
smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt
# Specify certificate to use for TLS
smtpd_tls_CApath = /etc/ssl/certs
smtpd_tls_CAfile = /etc/ssl/certs/RapidSSL_CA.pem
smtpd_tls_cert_file = /etc/ssl/certs/mail.example.com.crt
smtpd_tls_key_file = /etc/ssl/private/mail.example.com.key
# Enable SASL auth for clients
smtpd_sasl_auth_enable = yes
# Specify that we want SASL auth to use Dovecot auth
smtpd_sasl_type = dovecot
# Specify the location of the Dovecot authentication agent
smtpd_sasl_path = private/dovecot-auth
# Add SASL Received: message header
smtpd_sasl_authenticated_header = yes
# Increase the max message size to something more useful, approx 16MB
message_size_limit = 16000000
# Since we're generating bounces, let's minimize the backscatter
bounce_queue_lifetime = 2d
############### RESTRICTIONS #####################
######## Phase connect
smtpd_client_restrictions =
# always allow hosts listed in mynetworks to connect
permit_mynetworks,
# check for blacklisted hosts (REJECT rules)
check_client_access mysql:$config_directory/sql/check_client_access.cf,
# allow everyone else
permit
######## Phase HELO/EHLO:
smtpd_helo_required = yes
smtpd_helo_restrictions =
# always allow hosts listed in mynetworks
permit_mynetworks,
# this requires smtpd_delay_reject to be active (default) because there is no way to ask for AUTH before HELO is done
permit_sasl_authenticated,
# accept servers with bad HELO (OK rules) - this checks against the IP/hostname of the server, not the HELO response
# check_client_access mysql:$config_directory/sql/accept_bad_helo.cf,
# reject all mail servers that doesn't know how to specify a correct HELO/EHLO
# From /dev/rob0: Bracketed IP/HELO IS valid. "Invalid" means "not valid under RFC standards."
reject_invalid_helo_hostname,
# reject all mail servers that doesn't use FQDN in HELO
# From /dev/rob0: A bracketed [ip.add.re.ss] is not a non-FQDN HELO.
reject_non_fqdn_helo_hostname,
# reject all mail servers that doesn't list at least a DNS A or MX record
# see: http://www.irbs.net/internet/postfix/0302/0183.html
# reject_unknown_helo_hostname,
# allow the rest (behaving servers)
permit
######## Phase MAIL FROM:
smtpd_sender_restrictions =
# always allow hosts listed in mynetworks to use fake sender
permit_mynetworks,
# reject sender email which is not complete
reject_non_fqdn_sender,
# reject sender email which has no DNS A or MX record
reject_unknown_sender_domain,
# allow any other from address
permit
######## Phase RCPT TO:
smtpd_recipient_restrictions =
# allow hosts listed in mynetworks to use non-conforming (fake/local) recipient address
permit_mynetworks,
# reject recipient email which is not complete
reject_non_fqdn_recipient,
# reject recipient email which has no DNS A or MX record
reject_unknown_recipient_domain,
# allow AUTH clients to relay mail
permit_sasl_authenticated,
# rejects everything we're not final destination for
reject_unauth_destination,
#-----------------------------------------------------------------------------
# everything below this line is local delivery which needs to be run through proper policies
# accept whitelisted servers (OK rules)
# duplicate test for blacklisted servers (REJECT rules)
check_client_access mysql:$config_directory/sql/check_client_access.cf,
# reject blacklisted recipient addresses (REJECT/DISCARD rules)
# don't to any more policy checking (OK rules)
check_recipient_access mysql:$config_directory/sql/check_recipient_access.cf,
# filter all virtual users (not aliases) through DSPAM (which we are final destination for)
# Cannot use nexthop here, because it is only evaluated once per message (not per recipient)
# See recipient_canonical_maps below instead
check_recipient_access mysql:$config_directory/sql/dspam_filter.cf,
# everything else we let through (probably unknown user or virtual alias)
permit
# Map virtual alias to actual account so that DSPAM registers correct account for delivery
# used in combination with check_recipient_access in smtpd_recipient_restrictions
recipient_canonical_maps = mysql:$config_directory/sql/recipient_canonical_maps.cf
# DSPAM only supports one concurrent delivery (each message must be classified separately for each recipient)
dspam_destination_recipient_limit = 1
# What user to run commands in /etc/aliases as
default_privs = dspam
#
# Postfix master process configuration file. For details on the format
# of the file, see the master(5) manual page (command: "man 5 master").
#
# Do not forget to execute "postfix reload" after editing this file.
#
# ==========================================================================
# service type private unpriv chroot wakeup maxproc command + args
# (yes) (yes) (yes) (never) (100)
# ==========================================================================
smtp inet n - - - - smtpd
# Allow submissions using port 587 (see RFC4409)
submission inet n - - - - smtpd
pickup fifo n - - 60 1 pickup
cleanup unix n - - - 0 cleanup
qmgr fifo n - n 300 1 qmgr
tlsmgr unix - - - 1000? 1 tlsmgr
rewrite unix - - - - - trivial-rewrite
bounce unix - - - - 0 bounce
defer unix - - - - 0 bounce
trace unix - - - - 0 bounce
verify unix - - - - 1 verify
flush unix n - - 1000? 0 flush
proxymap unix - - n - - proxymap
proxywrite unix - - n - 1 proxymap
smtp unix - - - - - smtp
# When relaying mail as backup MX, disable fallback_relay to avoid MX loops
relay unix - - - - - smtp
-o smtp_fallback_relay=
showq unix n - - - - showq
error unix - - - - - error
retry unix - - - - - error
discard unix - - - - - discard
local unix - n n - - local
virtual unix - n n - - virtual
lmtp unix - - - - - lmtp
anvil unix - - - - 1 anvil
scache unix - - - - 1 scache
#
# ====================================================================
# Interfaces to non-Postfix software. Be sure to examine the manual
# pages of the non-Postfix software to find out what options it wants.
#
# Many of the following services use the Postfix pipe(8) delivery
# agent. See the pipe(8) man page for information about ${recipient}
# and other message envelope options.
# ====================================================================
######################################################################
#
# Dovecot LDA - http://wiki.dovecot.org/LDA
# http://wiki.dovecot.org/LDA/Postfix
# http://www.postfix.org/pipe.8.html for info about flags
#
dovecot unix - n n - - pipe
flags=DOXRhu user=vmail:vmail null_sender= argv=/usr/lib/dovecot/deliver -s -f ${sender} -d ${recipient}
######################################################################
#
# DSPAM content filter
# requires dspam, dspam-webfrontend and libdspam7-drv-mysql
dspam unix - n n - 10 pipe
flags=hu user=dspam argv=/usr/bin/dspam --deliver=innocent --user ${recipient}
localhost:10025 inet n - n - - smtpd
-o content_filter=
-o receive_override_options=no_unknown_recipient_checks,no_header_body_checks
-o smtpd_helo_restrictions=
-o smtpd_client_restrictions=
-o smtpd_sender_restrictions=
-o smtpd_recipient_restrictions=permit_mynetworks,reject
-o mynetworks=127.0.0.0/8
-o smtpd_authorized_xforward_hosts=127.0.0.0/8
hosts = 127.0.0.1
user = yoursqlusername
password = yoursqlpassword
dbname = yoursqldatabase
query = SELECT rule FROM dspam_filter WHERE email = '%s'
require ["include"];
include :global "dspam.sieve";
require ["fileinto","envelope","reject","vacation","imap4flags","relational","comparator-i;ascii-numeric","regex","body","date"];
if header :contains "X-DSPAM-Reclassified" "Innocent" {
keep;
stop;
}
if anyof (header :contains "X-DSPAM-Result" "Spam", header :contains "X-DSPAM-Result" "Virus") {
fileinto "Junk";
stop;
}
#!/bin/bash
# Useful script to check how your current postfix config differs from the default
diff -u <(postconf -d) <(postconf) | grep -v '^ '|grep -v '^@' |grep -v '^---' | grep -v '^+++'
@robinsmidsrod
Copy link
Author

If you notice a reference to a missing file, or something requires a bit more information to understand, get in touch and I'll upload it as well.

@wridgers
Copy link

Thanks for this.

@sethuper
Copy link

sethuper commented May 6, 2015

I have noticed some missing files:

check_client_access.cf -- check_client_access mysql:$config_directory/sql/check_client_access.cf
accept_bad_helo.cf -- check_client_access mysql:$config_directory/sql/accept_bad_helo.cf
check_recipient_access.cf -- check_recipient_access mysql:$config_directory/sql/check_recipient_access.cf
dspam_filter.cf -- check_recipient_access mysql:$config_directory/sql/dspam_filter.cf
recipient_canonical_maps.cf -- recipient_canonical_maps = mysql:$config_directory/sql/recipient_canonical_maps.cf

THX.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment