postfix
Contents
Netiquette
Debugging
When I had no clue what was going on, i took a look into the logs at a higher debugging level. In case of postfix it's as simple as to add -v to the appropriate line in /etc/postfix/master.cf. In this example smtpd -v.
Don't forget to remove it later on.
Mainentance mode
Important commands
Don't forget about the following commands:
Find and delete a stuck Email by address:
Compare custom config to posfix defaults
1 #!/bin/bash
2 # Copyright Rockstable IT 2020
3 # License: GPLv2+
4 # Delivered as is, no warranty, no liability,…
5
6 set -o pipefail
7
8 ### INITIALIZE
9 CONFIG_DIR="/etc/postfix"
10 SELF="$(basename "$0")"
11
12 usage () {
13 cat <<-EOL
14
15 $SELF - Compare postfix configuration to defaults.
16
17 Synopsis:
18 $PROGAM [-h|--help] [-c|--config_dir "/absolute/path/to/directory"]
19
20 []: Optional
21 EOL
22 }
23
24
25 # Note that we use `"$@"' to let each command-line parameter expand to a
26 # separate word. The quotes around `$@' are essential!
27 # We need TEMP as the `eval set --' would nuke the return value of getopt.
28 TEMP=`getopt -o c:h --long config_dir:,help \
29 -n "$SELF" -- "$@"`
30
31 if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
32
33 # Note the quotes around `$TEMP': they are essential!
34 eval set -- "$TEMP"
35
36 while true ; do
37 case "$1" in
38 -h|--help) usage; exit 0; shift ;;
39 -c|--config-dir) CONFIG_DIR="$2" ; shift 2 ;;
40 #-c|--c-long)
41 # # c has an optional argument. As we are in quoted mode,
42 # # an empty parameter will be generated if its optional
43 # # argument is not found.
44 # case "$2" in
45 # "") echo "Option c, no argument"; shift 2 ;;
46 # *) echo "Option c, argument \`$2'" ; shift 2 ;;
47 # esac ;;
48 --) shift ; break ;;
49 *) echo "Internal error!" ; exit 1 ;;
50 esac
51 done
52
53
54 if [ "$CONFIG_DIR" == "/etc/postfix" ]; then
55 echo "Comapring to default config_dir '/etc/postfix'";
56 CONF_CURRENT="$(postconf -n)"
57 elif [ -n "$CONFIG_DIR" ] && [ -d "$CONFIG_DIR" ]; then
58 echo "Comparing to specifed config_dir '$CONFIG_DIR'";
59 CONF_CURRENT="$(postconf -n -c "$CONFIG_DIR")"
60 else
61 cat <<-EOL
62
63 Error: Invalid argument to option '-c|--config_dir': '$CONFIG_DIR'.
64 Maybe:
65 * undefined
66 * not a directory
67 EOL
68 usage
69 exit 1
70 fi
71
72 while read LINE; do
73 KEY="$(sed -r 's/^([[:alnum:]_$-]+)\s*=.*$/\1/' <<< "$LINE")"
74 echo -e "\n= Key: '$KEY' ="
75 VALUE="$(sed -r 's/.*=\s*([^=]+)$/\1/' <<< "$LINE")"
76 VALUE="$(fold -s <<< "$VALUE")"
77 if [ -z "$VALUE" ] || grep -E '=$' <<< "$VALUE"; then
78 VALUE="NULL"
79 fi
80 echo -e "Current: '$VALUE'"
81 DEFAULT="$(postconf -d "$KEY" 2>&1 \
82 |sed -r 's/.*=\s*([^=]+)$/\1/')"
83 if grep -E 'unknown parameter' <<< "$DEFAULT"; then
84 echo "postconf -d '$KEY' -> warned unknown parameter - custom/typo?"
85 DEFAULT="NO DEFAULT"
86 elif [ -z "$DEFAULT" ] || grep -Eq '=$' <<< "$DEFAULT"; then
87 DEFAULT="NULL"
88 fi
89 DEFAULT="$(fold -s <<< "$DEFAULT")"
90 echo -e "Default: '$DEFAULT'"
91
92 done <<< "${CONF_CURRENT}"
Analyse aliases file
1 #!/bin/bash
2 # Copyright Rockstable IT 2020
3 # License: GPLv2+
4 # Delivered as is, no warranty, no liability,…
5
6 set -o pipefail
7
8 ### INITIALIZE
9 CONFIG_DIR="/etc/postfix"
10 SELF="$(basename "$0")"
11
12 usage () {
13 cat <<-EOL
14
15 $SELF - Compare postfix configuration to defaults.
16
17 Synopsis:
18 $PROGAM [-h|--help] [-c|--config_dir "/absolute/path/to/directory"]
19
20 []: Optional
21 EOL
22 }
23
24
25 # Note that we use `"$@"' to let each command-line parameter expand to a
26 # separate word. The quotes around `$@' are essential!
27 # We need TEMP as the `eval set --' would nuke the return value of getopt.
28 TEMP=`getopt -o c:h --long config_dir:,help \
29 -n "$SELF" -- "$@"`
30
31 if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
32
33 # Note the quotes around `$TEMP': they are essential!
34 eval set -- "$TEMP"
35
36 while true ; do
37 case "$1" in
38 -h|--help) usage; exit 0; shift ;;
39 -c|--config-dir) CONFIG_DIR="$2" ; shift 2 ;;
40 #-c|--c-long)
41 # # c has an optional argument. As we are in quoted mode,
42 # # an empty parameter will be generated if its optional
43 # # argument is not found.
44 # case "$2" in
45 # "") echo "Option c, no argument"; shift 2 ;;
46 # *) echo "Option c, argument \`$2'" ; shift 2 ;;
47 # esac ;;
48 --) shift ; break ;;
49 *) echo "Internal error!" ; exit 1 ;;
50 esac
51 done
52
53
54 if [ "$CONFIG_DIR" == "/etc/postfix" ]; then
55 echo "Comapring to default config_dir '/etc/postfix'";
56 CONF_CURRENT="$(postconf -n)"
57 elif [ -n "$CONFIG_DIR" ] && [ -d "$CONFIG_DIR" ]; then
58 echo "Comparing to specifed config_dir '$CONFIG_DIR'";
59 CONF_CURRENT="$(postconf -n -c "$CONFIG_DIR")"
60 else
61 cat <<-EOL
62
63 Error: Invalid argument to option '-c|--config_dir': '$CONFIG_DIR'.
64 Maybe:
65 * undefined
66 * not a directory
67 EOL
68 usage
69 exit 1
70 fi
71
72 while read LINE; do
73 KEY="$(sed -r 's/^([[:alnum:]_$-]+)\s*=.*$/\1/' <<< "$LINE")"
74 echo -e "\n= Key: '$KEY' ="
75 VALUE="$(sed -r 's/.*=\s*([^=]+)$/\1/' <<< "$LINE")"
76 VALUE="$(fold -s <<< "$VALUE")"
77 if [ -z "$VALUE" ] || grep -E '=$' <<< "$VALUE"; then
78 VALUE="NULL"
79 fi
80 echo -e "Current: '$VALUE'"
81 DEFAULT="$(postconf -d "$KEY" 2>&1 \
82 |sed -r 's/.*=\s*([^=]+)$/\1/')"
83 if grep -E 'unknown parameter' <<< "$DEFAULT"; then
84 echo "postconf -d '$KEY' -> warned unknown parameter - custom/typo?"
85 DEFAULT="NO DEFAULT"
86 elif [ -z "$DEFAULT" ] || grep -Eq '=$' <<< "$DEFAULT"; then
87 DEFAULT="NULL"
88 fi
89 DEFAULT="$(fold -s <<< "$DEFAULT")"
90 echo -e "Default: '$DEFAULT'"
91
92 done <<< "${CONF_CURRENT}"
93
94 root@trinity:/home/tobias# tmux attach
95 [detached (from session 0)]
96 root@trinity:/home/tobias# cat test_aliases.sh
97 #!/bin/bash
98 # Copyright Rockstable IT 2020
99 # License: GPLv2+
100 # Delivered as is, no warranty, no liability,…
101
102 ### INITIALIZE
103 declare -a DOMAIN_BLACKLIST
104 BLACKLIST=false
105 FILE="/etc/postfix_new/virtual"
106 ALIAS_COUNT=0
107 ADDRESS_COUNT=0
108 KEEP=0
109 KEEP_FDA=0
110 KEEP_PURPOSE=0
111 REMOVE=0
112 REMOVE_BLACKLIST=0
113 REMOVE_REDUNDANT=0
114 LINE_NUMBER=0
115 PRINT="ALL"
116 PROGRAM="$(basename $0)"
117
118 ### FUNCTIONS
119 split () {
120 local DELIM="$1"
121 local STRING="$2"
122 local IFS
123 local OIFS
124 ### ARRAY IS DECLARED LOCALLY (no -g)
125 declare -a ARRAY
126
127 OIFS="$IFS"
128 IFS="$DELIM"
129 ARRAY=( ${STRING// /} )
130 IFS="$OIFS"
131 echo "${ARRAY[@]}"
132 }
133
134 usage () {
135 cat <<-EOL
136 $PROGRAM - Analyse postfix aliases file
137
138 Synopsis:
139 $PROGRAM \\
140 [-a|--aliases /path/to/aliases] [-k|--keepable] [-r|--removeable [-s|--short] \\
141 [--] [domain1.tld] [domain2.tld2] […]
142
143 []: optional
144 (): mandatory
145
146 Most useful when blacklist domain is specified.
147 EOL
148 }
149
150 ### PARSE OPTIONS
151 # Note that we use `"$@"' to let each command-line parameter expand to a
152 # separate word. The quotes around `$@' are essential!
153 # We need TEMP as the `eval set --' would nuke the return value of getopt.
154 TEMP=`getopt -o a:hkrs --long aliases:,help,keepable,removeable,short \
155 -n "$PROGRAM" -- "$@"`
156
157 if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
158
159 # Note the quotes around `$TEMP': they are essential!
160 eval set -- "$TEMP"
161
162 while true ; do
163 case "$1" in
164 -a|--aliases) FILE="$2" ; shift 2 ;;
165 -h|--help) usage; exit 0 ; shift ;;
166 -k|--keepable) PRINT="KEEPABLE" ; shift ;;
167 -r|--removeable) PRINT="REMOVABLE" ; shift ;;
168 -s|--short) SHORT=true ; shift ;;
169
170 #-c|--c-long)
171 # # c has an optional argument. As we are in quoted mode,
172 # # an empty parameter will be generated if its optional
173 # # argument is not found.
174 # case "$2" in
175 # "") echo "Option c, no argument"; shift 2 ;;
176 # *) echo "Option c, argument \`$2'" ; shift 2 ;;
177 # esac ;;
178 --) shift ; break ;;
179 *) echo "Internal error!" ; exit 1 ;;
180 esac
181 done
182 ##echo "Remaining arguments:"
183 ##for arg do echo '--> '"\`$arg'" ; done
184
185 DOMAIN_BLACKLIST=( "$@" )
186
187 if [ ${#DOMAIN_BLACKLIST[@]} -ge 1 ]; then
188 BLACKLIST=true
189 echo "Blacklisted domains '${DOMAIN_BLACKLIST[@]}'"
190 fi
191
192 ### MAIN
193 while read LINE; do
194 ((ALIAS_COUNT++))
195 unset DEST_ADDRESS
196 unset FDA
197
198 LINE_NUMBER="$(sed -r 's/^\s*([0-9]+)\s*.*/\1/' <<< "$LINE")"
199 LINE="$(sed -r 's/^\s*([0-9]+)\s*(.+)$/\2/' <<< "$LINE")"
200
201 if grep -qE '^@' <<< "$LINE"; then
202 FDA=true
203 fi
204
205 ALIAS="$(sed -r 's/(^[^: ]+):?\s.*/\1/' <<< "$LINE")"
206 DEST_STR="$(sed -r 's/(^[^: ]+):?\s+([^,]+)/\2/' <<< "$LINE")"
207
208 # GET LOCAL PART
209 ALIAS_LOCAL="${ALIAS/@*/}"
210 [ -z "$ALIAS_LOCAL" ] && ALIAS_LOCAL="NULL"
211
212 # GET DOMAIN PART
213 if grep -Eq '@[^@]+' <<< "${ALIAS}"; then
214 ALIAS_DOMAIN="${ALIAS/*@/}"
215 else
216 ALIAS_DOMAIN="NULL"
217 fi
218
219 ### bash4.4
220 #mapfile -d ';' -t LOCAL < <(printf '%s;' "${DEST/,\s+/,/}")
221
222 declare -a ADDRESS
223 DEST_ADDRESSES=( $(split "," "$DEST_STR") )
224
225 for DEST_ADDRESS in "${DEST_ADDRESSES[@]}"; do
226 ((ADDRESS_COUNT++))
227 unset ACTION
228
229 # GET LOCAL PART
230 DEST_LOCAL="${DEST_ADDRESS/@*/}"
231 [ -z "$DEST_LOCAL" ] && DEST_LOCAL="NULL"
232
233 # GET DOMAIN PART
234 if grep -Eq '@[^@]+' <<< "${DEST_ADDRESS}"; then
235 DEST_DOMAIN="${DEST_ADDRESS/*@/}"
236 else
237 DEST_DOMAIN="NULL"
238 fi
239
240 ### ANALYSE
241 if [ $FDA ]; then
242 ACTION="keep"
243 REASON="fda"
244 fi
245
246 if [ $BLACKLIST ] && \
247 [ "$ALIAS_LOCAL" == "$DEST_LOCAL" ] && \
248 [ "$ALIAS_DOMAIN" == "NULL" ] && \
249 grep -Eq "$DEST_DOMAIN" <<< "${DOMAIN_BLACKLIST[@]}"; then
250 ACTION="remove"
251 REASON="blacklist"
252 elif [ "$ALIAS_LOCAL" == "$DEST_LOCAL" ] && \
253 [ "$ALIAS_DOMAIN" == "$DEST_DOMAIN" ]; then
254 ACTION="remove"
255 REASON="redundant"
256 else
257 ACTION="keep"
258 REASON="purpose"
259 fi
260
261 case "$ACTION" in
262 "keep") ((KEEP++));;
263 "remove") ((REMOVE++));;
264 esac
265
266 case "$REASON" in
267 "fda") ((KEEP_FDA++));;
268 "purpose") ((KEEP_PURPOSE++));;
269 "blacklist") ((REMOVE_BLACKLIST++));;
270 "redundant") ((REMOVE_REDUNDANT++));;
271 esac
272
273
274 ### OUTPUT
275 if [ "$PRINT" == "ALL" ] || \
276 ([ "$PRINT" == "REMOVABLE" ] && [ "$ACTION" == "remove" ]) || \
277 ([ "$PRINT" == "KEEPABLE" ] && [ "$ACTION" == "keep" ]) ; then
278 [ ! $SHORT ] && echo
279 echo "Alias: $ALIAS"
280 if [ ! $SHORT ]; then
281 echo "Line: $LINE_NUMBER"
282 echo "Raw Line: $LINE"
283 echo "Alias local: $ALIAS_LOCAL"
284 echo "Alias domain: $ALIAS_DOMAIN"
285 echo "Dest Address: $DEST_ADDRESS"
286 echo "Dest Local: $DEST_LOCAL"
287 echo "Dest Domain: $DEST_DOMAIN"
288 echo "Action: $ACTION"
289 echo "Reason: $REASON"
290 [ $FDA ] && echo -e "Type:\t\tFull domain alias"
291 fi
292 fi
293 done
294 done <<< "$(cat -n "$FILE"| sed -r '/^\s*([0-9]+)?\s*(#.*)?$/d')"
295
296 REMOVE1=$((REMOVE_REDUNDANT+REMOVE_BLACKLIST))
297
298 cat <<-EOL
299
300 = Summary =
301
302 $ALIAS_COUNT aliases have been processed.
303 $ADDRESS_COUNT destination addresses have been compared.
304 $KEEP alias-destination pairs should be kept.
305 $KEEP_FDA alias-destination pairs are full domain aliases (catch all).
306 $KEEP_PURPOSE alias-destination pairs serve a purpuse.
307 $REMOVE_REDUNDANT alias-destination pairs are redundant.
308 $REMOVE_BLACKLIST alias-destination pairs are blacklisted.
309 $REMOVE alias-destination pairs should be removed.
310 EOL
Install
1 aptitude install postfix mailutils
Unix-Permissions
1 root@mail /etc/postfix # find /etc/postfix -type f -exec chmod o-rx {} \;
2 root@mail /etc/postfix # find /etc/postfix/ -type d -exec chmod -v 750 {} \;
3 der Modus von „/etc/postfix/“ wurde von 0755 (rwxr-xr-x) in 0750 (rwxr-x---) geändert
4 der Modus von „/etc/postfix/sasl“ wurde von 0755 (rwxr-xr-x) in 0750 (rwxr-x---) geändert
5 Modus von „/etc/postfix/ldap“ als 0750 (rwxr-x---) erhalten
6 root@mail /etc/postfix # find /etc/postfix/ -type d -exec chgrp -v postfix {} \;
7 die Gruppe von „/etc/postfix/“ wurde von root in postfix geändert
8 die Gruppe von „/etc/postfix/sasl“ wurde von root in postfix geändert
9 die Gruppe von „/etc/postfix/ldap“ wurde von root in postfix geändert
10 root@mail /etc/postfix # find /etc/postfix/ -exec chgrp -v postfix {} \;
11 die Gruppe von „/etc/postfix/“ wurde als postfix erhalten
12 die Gruppe von „/etc/postfix/sasl“ wurde als postfix erhalten
13 die Gruppe von „/etc/postfix/sasl/smtpd.conf“ wurde von root in postfix geändert
14 die Gruppe von „/etc/postfix/postfix-files“ wurde von root in postfix geändert
15 die Gruppe von „/etc/postfix/postfix-script“ wurde von root in postfix geändert
16 die Gruppe von „/etc/postfix/post-install“ wurde von root in postfix geändert
17 die Gruppe von „/etc/postfix/dynamicmaps.cf“ wurde von root in postfix geändert
18 die Gruppe von „/etc/postfix/master.cf“ wurde von root in postfix geändert
19 die Gruppe von „/etc/postfix/ldap“ wurde als postfix erhalten
20 die Gruppe von „/etc/postfix/ldap/mailenabled_distgroups.cf“ wurde von root in postfix geändert
21 die Gruppe von „/etc/postfix/ldap/virtual_alias_maps_mailforwarding.cf“ wurde von root in postfix geändert
22 die Gruppe von „/etc/postfix/ldap/transport_maps.cf“ wurde von root in postfix geändert
23 die Gruppe von „/etc/postfix/ldap/virtual_alias_maps_sharedfolders.cf“ wurde von root in postfix geändert
24 die Gruppe von „/etc/postfix/ldap/mailenabled_dynamic_distgroups.cf“ wurde von root in postfix geändert
25 die Gruppe von „/etc/postfix/ldap/local_recipient_maps.cf“ wurde von root in postfix geändert
26 die Gruppe von „/etc/postfix/ldap/virtual_alias_maps.cf“ wurde von root in postfix geändert
27 die Gruppe von „/etc/postfix/ldap/mydestination.cf“ wurde von root in postfix geändert
28 die Gruppe von „/etc/postfix/transport.db“ wurde von root in postfix geändert
29 die Gruppe von „/etc/postfix/header_checks.inbound“ wurde von root in postfix geändert
30 die Gruppe von „/etc/postfix/header_checks.inbound.db“ wurde von root in postfix geändert
31 die Gruppe von „/etc/postfix/header_checks.internal“ wurde von root in postfix geändert
32 die Gruppe von „/etc/postfix/header_checks.internal.db“ wurde von root in postfix geändert
33 die Gruppe von „/etc/postfix/header_checks.submission“ wurde von root in postfix geändert
34 die Gruppe von „/etc/postfix/header_checks.submission.db“ wurde von root in postfix geändert
35 die Gruppe von „/etc/postfix/transport“ wurde von root in postfix geändert
36 die Gruppe von „/etc/postfix/main.cf“ wurde von root in postfix geändert
Basics
1 aptitude install db-util
1 adduser postfix ssl-cert
Compatibility Level
Postfix 3.0 introduces a safety net that runs Postfix programs with backwards-compatible default settings after an upgrade. The safety net will log a warning whenever a "new" default setting could have an negative effect on your mail flow.
Postfix compares the build in compatibility_level (at compile time) to the one specified in main.cf compatibility_level (default: 0). It determines settings in default state and takes actions if compatibility_level in main.cf is less than compiled in.
Sources:
Backwards-compatible default settings that may kick in:
kept: append_dot_mydomain=yes - new (3.0): append_dot_mydomain=no
kept: chroot=y - new (3.0): chroot=n
kept: smtpd_relay_restrictions = (empty) new (2.10): smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, defer_unauth_destination
kept: mynetworks_style=subnet new (3.0): mynetworks_style=host
kept: relay_domains=$mydestination new (3.0): relay_domains= -> empty
kept: smtputf8_enable=no new (3.0): smtputf8_enable=yes
Restrictions
TODO
Choose your setup
Postfix:
- local ALIAS: shared domains, UNIX system accounts
- virtual MAILBOX: separate domains, non-UNIX accounts
- virtual ALIAS: separate domains, UNIX system accounts
vmail setup
Please prepare dovecot first by foolowing follow dovecot#vmail_setup and return here when done.
/etc/postfix/main.cf
1 ### ALIASED DOMAINS AND ADDRESSES
2 ### POINTING TO REMOTE DOMAINS
3 #virtual_maps =
4 virtual_maps = hash:/etc/postfix/virtual
5 virtual_alias_maps = $virtual_maps
6 #virtual_alias_domains = $virtual_alias_maps
7 virtual_alias_domains = hash:/etc/postfix/virtual_alias_domains
8
9 ### MAILBOXED DOMAINS AND ADDRESSES WHERE THIS
10 ### MTA IS FINAL TARGET
11
12 ### ENSURE virtual_mailbox_maps IS EMPTY
13 ### OR smtpd_reject_unlisted_recipient (default: yes)
14 ### WILL ENFORCE EVERY USER TO BE LISTED IN THIS DB
15 virtual_mailbox_maps =
16 #virtual_mailbox_domains = $virtual_mailbox_maps
17 virtual_mailbox_domains = hash:/etc/postfix/virtual_mailbox_domains
18
19 ### virtual_transport CAN BE OVERRIDDEN BY /etc/postfix/transports
20 #virtual_transport = virtual
21 virtual_transport = lmtp:unix:private/dovecot-lmtp
Please make sure virtual_mailbox_maps is null otherwise smtpd_reject_unlisted_recipient (default: yes) will enforce that every user is listed in this database.
This causes error Recipient address rejected: User unknown in virtual mailbox table; in the most cases.
Address verfication is performed by address_verify_virtual_transport = $virtual_transport which is default. And dovecot will answer this question in the lmtp-protocol.
Hint:
- Never list a domain or address in multiple of the following databases at the same time:
mydestination
relay_domains
virtual_alias_domains
virtual_mailbox_domains
- Never list a domain or address in multiple of the following databases at the same time:
/etc/postfix/virtual_mailbox_domains
1 rockstable.it WORD
Address verfiy cache
1 ### ADDRESS VERIFY CACHE
2 address_verify_map = btree:$data_directory/verify_cache
3 #address_verify_negative_cache = yes
4 address_verify_negative_cache = no
5 #address_verify_negative_expire_time = 3d
6 #address_verify_negative_refresh_time = 3h
7 #address_verify_positive_expire_time = 31d
8 #address_verify_positive_refresh_time = 7d
9 address_verify_virtual_transport = $virtual_transport
You can look inside into the verify cache with the following command:
1 db_dump -p /var/lib/postfix/verify_cache
Crypto
1 ### IF SYNTAX HIGHLIGHTING IS MISSING:
2 ## -> "make vim_syntax"
3
4 ciphers_insecure = RC4
5 cipher_suite_minimum = high
6 protocols_insecure = !SSLv2,!SSLv3,!TLSv1
7 tls_security_level = may
8
9
10 ### Cipherlists
11 ##tls_export_cipherlist = aNULL:-aNULL:ALL:+RC4:@STRENGTH
12 ##tls_high_cipherlist = aNULL:-aNULL:ALL:!EXPORT:!LOW:!MEDIUM:+RC4:@STRENGTH
13 ##tls_low_cipherlist = aNULL:-aNULL:ALL:!EXPORT:+RC4:@STRENGTH
14 ##tls_medium_cipherlist = aNULL:-aNULL:ALL:!EXPORT:!LOW:+RC4:@STRENGTH
15 ##tls_null_cipherlist = eNULL:!aNULL
16
17
18 ### LMTP Client
19 #lmtp_enforce_tls (default: no)
20 #lmtp_sasl_tls_security_options (default: $lmtp_sasl_security_options)
21 #lmtp_sasl_tls_verified_security_options (default: $lmtp_sasl_tls_security_options)
22 #lmtp_starttls_timeout (default: 300s)
23 #lmtp_tls_CAfile (default: empty)
24 #lmtp_tls_CApath (default: empty)
25 #lmtp_tls_block_early_mail_reply (default: empty)
26 #lmtp_tls_cert_file (default: empty)
27 #lmtp_tls_ciphers (default: export)
28 lmtp_tls_ciphers = $cipher_suite_minimum
29 #lmtp_tls_dcert_file (default: empty)
30 #lmtp_tls_dkey_file (default: $lmtp_tls_dcert_file)
31 #lmtp_tls_eccert_file (default: empty)
32 #lmtp_tls_eckey_file (default: empty)
33 #lmtp_tls_enforce_peername (default: yes)
34 #lmtp_tls_exclude_ciphers (default: empty)
35 lmtp_tls_exclude_ciphers = $ciphers_insecure
36 #lmtp_tls_fingerprint_cert_match (default: empty)
37 #lmtp_tls_fingerprint_digest (default: md5)
38 lmtp_tls_fingerprint_digest = sha1
39 #lmtp_tls_force_insecure_host_tlsa_lookup (default: no)
40 #lmtp_tls_key_file (default: $lmtp_tls_cert_file)
41 #lmtp_tls_loglevel (default: 0)
42 #lmtp_tls_mandatory_ciphers (default: empty)
43 lmtp_tls_mandatory_ciphers = $cipher_suite_minimum
44 #lmtp_tls_mandatory_exclude_ciphers (default: empty)
45 lmtp_tls_mandatory_exclude_ciphers = $ciphers_insecure
46 #lmtp_tls_mandatory_protocols (default: !SSLv2)
47 lmtp_tls_mandatory_protocols = $protocols_insecure
48 #lmtp_tls_note_starttls_offer (default: no)
49 #lmtp_tls_per_site (default: empty)
50 #lmtp_tls_policy_maps (default: empty)
51 #lmtp_tls_protocols (default: empty)
52 lmtp_tls_protocols = $protocols_insecure
53 #lmtp_tls_scert_verifydepth (default: 9)
54 #lmtp_tls_secure_cert_match (default: nexthop)
55 #lmtp_tls_security_level (default: empty)
56 # possible values: none, may, encrypt, dane, dane-only,
57 # fingerprint, verify, secure
58 lmtp_tls_security_level = $tls_security_level
59 #lmtp_tls_session_cache_database (default: empty)
60 #lmtp_tls_session_cache_timeout (default: 3600s)
61 #lmtp_tls_trust_anchor_file (default: empty)
62 #lmtp_tls_verify_cert_match (default: hostname)
63 #lmtp_use_tls (default: no) <- deprecaded with 2.3 -> smtpd_tls_security_level
64
65
66 ### SMTP Client
67 #smtp_enforce_tls (default: no)
68 #smtp_sasl_tls_security_options (default: $smtp_sasl_security_options)
69 #smtp_sasl_tls_verified_security_options (default: $smtp_sasl_tls_security_options)
70 #smtp_starttls_timeout (default: 300s)
71 #smtp_tls_CAfile (default: empty)
72 #smtp_tls_CApath (default: empty)
73 #smtp_tls_block_early_mail_reply (default: no)
74 #smtp_tls_cert_file (default: empty)
75 #smtp_tls_cipherlist (default: empty) <- obsolete
76 #smtp_tls_ciphers (default: export)
77 smtp_tls_ciphers = $cipher_suite_minimum
78 #smtp_tls_dcert_file (default: empty)
79 #smtp_tls_dkey_file (default: $smtp_tls_dcert_file)
80 #smtp_tls_eccert_file (default: empty)
81 #smtp_tls_eckey_file (default: $smtp_tls_eccert_file)
82 #smtp_tls_enforce_peername (default: yes)
83 #smtp_tls_exclude_ciphers (default: empty)
84 smtp_tls_exclude_ciphers = $ciphers_insecure
85 #smtp_tls_fingerprint_cert_match (default: empty)
86 #smtp_tls_fingerprint_digest (default: md5)
87 smtp_tls_fingerprint_digest = sha1
88 #smtp_tls_force_insecure_host_tlsa_lookup (default: no)
89 #smtp_tls_key_file (default: $smtp_tls_cert_file)
90 #smtp_tls_loglevel (default: 0)
91 #smtp_tls_mandatory_ciphers (default: medium)
92 smtp_tls_mandatory_ciphers = $cipher_suite_minimum
93 #smtp_tls_mandatory_exclude_ciphers (default: empty)
94 smtp_tls_mandatory_exclude_ciphers = $ciphers_insecure
95 #smtp_tls_mandatory_protocols (default: !SSLv2)
96 smtp_tls_mandatory_protocols = $protocols_insecure
97 #smtp_tls_note_starttls_offer (default: no)
98 #smtp_tls_per_site (default: empty)
99 #smtp_tls_policy_maps (default: empty)
100 #smtp_tls_protocols (default: !SSLv2)
101 smtp_tls_protocols = $protocols_insecure
102 #smtp_tls_scert_verifydepth (default: 9)
103 #smtp_tls_secure_cert_match (default: nexthop, dot-nexthop)
104 #smtp_tls_security_level (default: empty)
105 # possible values: none, may, encrypt, dane, dane-only,
106 # fingerprint, verify, secure
107 smtp_tls_security_level = $tls_security_level
108 #smtp_tls_session_cache_database (default: empty)
109 #smtp_tls_session_cache_timeout (default: 3600s)
110 #smtp_tls_trust_anchor_file (default: empty)
111 #smtp_tls_verify_cert_match (default: hostname)
112 #smtp_use_tls (default: no) <- deprecaded with 2.3 -> smtp_tls_security_level
113
114
115 ### SMTPD Server
116 #smtpd_client_new_tls_session_rate_limit (default: 0)
117 #smtpd_enforce_tls (default: no)
118 #smtpd_sasl_tls_security_options (default: $smtpd_sasl_security_options)
119 #smtpd_starttls_timeout (default: see postconf -d output)
120 #smtpd_tls_CAfile (default: empty)
121 #smtpd_tls_CApath (default: empty)
122 #smtpd_tls_always_issue_session_ids (default: yes)
123 #smtpd_tls_ask_ccert (default: no)
124 #smtpd_tls_auth_only (default: no)
125 #smtpd_tls_ccert_verifydepth (default: 9)
126 #smtpd_tls_cert_file (default: empty)
127 #smtpd_tls_cipherlist (default: empty) <- obsolete
128 #smtpd_tls_ciphers (default: export)
129 smtpd_tls_ciphers = $cipher_suite_minimum
130 #smtpd_tls_dcert_file (default: empty)
131 #smtpd_tls_dh1024_param_file (default: empty)
132 #smtpd_tls_dh512_param_file (default: empty)
133 #smtpd_tls_dkey_file (default: $smtpd_tls_dcert_file)
134 #smtpd_tls_eccert_file (default: empty)
135 #smtpd_tls_eckey_file (default: $smtpd_tls_eccert_file)
136 #smtpd_tls_eecdh_grade (default: see postconf -d output)
137 #smtpd_tls_exclude_ciphers (default: empty)
138 smtpd_tls_exclude_ciphers = $ciphers_insecure
139 #smtpd_tls_fingerprint_digest (default: md5)
140 smtpd_tls_fingerprint_digest = sha1
141 #smtpd_tls_key_file (default: $smtpd_tls_cert_file)
142 #smtpd_tls_loglevel (default: 0)
143 #smtpd_tls_mandatory_ciphers (default: medium)
144 smtpd_tls_mandatory_ciphers = $cipher_suite_minimum
145 #smtpd_tls_mandatory_exclude_ciphers (default: empty)
146 smtpd_tls_mandatory_exclude_ciphers = $ciphers_insecure
147 #smtpd_tls_mandatory_protocols (default: !SSLv2)
148 smtpd_tls_mandatory_protocols = $protocols_insecure
149 #smtpd_tls_protocols (default: none)
150 smtpd_tls_protocols=$protocols_insecure
151 #smtpd_tls_received_header (default: no)
152 #smtpd_tls_req_ccert (default: no)
153 #smtpd_tls_security_level (default: empty)
154 # possible values: none, may, encrypt
155 smtpd_tls_security_level = $tls_security_level
156 #smtpd_tls_session_cache_database (default: empty)
157 #smtpd_tls_session_cache_timeout (default: 3600s)
158 #smtpd_tls_wrappermode (default: no)
159 #smtpd_use_tls (default: no) <- deprecaded with 2.3 -> smtpd_tls_security_level
You can delete all these comments in vim to get a clean version by:
1 :g/^#[^#]/d
1 ### Customs
2 ciphers_insecure = RC4
3 cipher_suite_minimum = high
4 protocols_insecure = !SSLv2,!SSLv3,!TLSv1
5 tls_security_level = may
6
7
8 ### Cipherlists
9 ##tls_export_cipherlist = aNULL:-aNULL:ALL:+RC4:@STRENGTH
10 ##tls_high_cipherlist = aNULL:-aNULL:ALL:!EXPORT:!LOW:!MEDIUM:+RC4:@STRENGTH
11 ##tls_low_cipherlist = aNULL:-aNULL:ALL:!EXPORT:+RC4:@STRENGTH
12 ##tls_medium_cipherlist = aNULL:-aNULL:ALL:!EXPORT:!LOW:+RC4:@STRENGTH
13 ##tls_null_cipherlist = eNULL:!aNULL
14
15
16 ### LMTP Client
17 lmtp_tls_ciphers = $cipher_suite_minimum
18 lmtp_tls_exclude_ciphers = $ciphers_insecure
19 lmtp_tls_fingerprint_digest = sha1
20 lmtp_tls_mandatory_ciphers = $cipher_suite_minimum
21 lmtp_tls_mandatory_exclude_ciphers = $ciphers_insecure
22 lmtp_tls_mandatory_protocols = $protocols_insecure
23 lmtp_tls_protocols = $protocols_insecure
24 lmtp_tls_security_level = $tls_security_level
25
26
27 ### SMTP Client
28 smtp_tls_ciphers = $cipher_suite_minimum
29 smtp_tls_exclude_ciphers = $ciphers_insecure
30 smtp_tls_fingerprint_digest = sha1
31 smtp_tls_mandatory_ciphers = $cipher_suite_minimum
32 smtp_tls_mandatory_exclude_ciphers = $ciphers_insecure
33 smtp_tls_mandatory_protocols = $protocols_insecure
34 smtp_tls_protocols = $protocols_insecure
35 smtp_tls_security_level = $tls_security_level
36
37
38 ### SMTPD Server
39 smtpd_tls_ciphers = $cipher_suite_minimum
40 smtpd_tls_exclude_ciphers = $ciphers_insecure
41 smtpd_tls_fingerprint_digest = sha1
42 smtpd_tls_mandatory_ciphers = $cipher_suite_minimum
43 smtpd_tls_mandatory_exclude_ciphers = $ciphers_insecure
44 smtpd_tls_mandatory_protocols = $protocols_insecure
45 smtpd_tls_protocols=$protocols_insecure
46 smtpd_tls_security_level = $tls_security_level
Perfect forward secrecy (PFS)
First generate Diffie-Hellmann parameters and return here afterwards: OpenSSL#Generate or renew files with Diffie-Hellman-Parameters
Enable PFS in postfix
Defaults:
1 smtpd_tls_dh1024_param_file =
2 smtpd_tls_dh512_param_file =
3 smtpd_tls_eecdh_grade = auto
4 tls_eecdh_auto_curves = X25519 X448 prime256v1 secp521r1 secp384r1
5 tls_eecdh_strong_curve = prime256v1
6 tls_eecdh_ultra_curve = secp384r1
7 tlsproxy_tls_dh1024_param_file = $smtpd_tls_dh1024_param_file
8 tlsproxy_tls_dh512_param_file = $smtpd_tls_dh512_param_file
9 tlsproxy_tls_eecdh_grade = $smtpd_tls_eecdh_grade
Hardened:
Makefile
Nice trick to save some work - use a Makefile
/etc/postfix/Makefile
1 postmap:
2 postmap /etc/postfix/access_client
3 postmap /etc/postfix/access_helo
4 postmap /etc/postfix/access_sender
5 postmap /etc/postfix/access_recipient
6 postmap /etc/postfix/body_checks
7 postmap /etc/postfix/esmtp_access
8 postmap /etc/postfix/header_checks
9 postmap /etc/postfix/relay_domains
10 postmap /etc/postfix/virtual
11 postmap /etc/postfix/transport
12 newaliases
13
14 vim_syntax:
15 cat vim_syntax.vim >> /usr/share/vim/vim73/syntax/pfmain.vim
Define a syntax-file to be appended
/etc/postfix/vim_syntax.vim
1 syntax keyword pfmainConf ciphers_insecure
2 syntax keyword pfmainConf cipher_suite_minimum
3 syntax keyword pfmainConf protocols_insecure
4 syntax keyword pfmainConf tls_security_level
5
6 syntax match pfmainRef "$\<ciphers_insecure\>"
7 syntax match pfmainRef "$\<cipher_suite_minimum\>"
8 syntax match pfmainRef "$\<protocols_insecure\>"
9 syntax match pfmainRef "$\<tls_security_level\>"
1 make postmap
Submission
Prepare postfix for dovecot submission:
Because dovecot-submissiond binds to tcp/587 we need to add an alternate submission port to /etc/services.
Now we configure /etc/postfix/master.cf to fire up a submission-service bound to localhost.
Postgrey
Wenn eine Email an den Mail-Server versendet zugestellt wird, trägt "postgrey" ein Tripel aus (Client, Sender, Recipient) zusammen mit einem Timestamp in die Datenbank "/var/lib/postgrey/postgrey.db" ein, sollte dieses noch nicht dort zu finden sein. Postgrey versendet einem solchen unbestätigten Client dann ein Return-Code 450 "Try again later". Ist ein konfigurierbares Delay (Default: 300s) erreicht, so ist es dem Client erneut gestattet die Email einzuliefern. Die Datenbank wird standardmäßig von Triplets befreit, zu welchen es seit 35d keinen Kontakt mehr gab. Postgrey stellt Whitelists für clients und recipients bereit.
Ich halte postgrey im Produktivbetrieb für absolut einsetzbar, denn nur die erste Email eines Triplets wird um 5min verzögert.
Evtl. kann das Bereinigungsintervall auf einen höheren Wert gesetzt werden, um seltene Prozesse zu beschleunigen oder interne Server von denen ständig wechselnde Email-Adressen kommt, in die Whitelist eingetragen werden.
About Postgrey
Configuration
Database unter /var/lib/postgrey/postgrey.db
- Defaults
- delay: 300s
- max-age: 35d
- bind-socket: 127.0.0.1:10023
1 root@mail /etc/postgrey # cat /etc/default/postgrey
2 # postgrey startup options, created for Debian
3
4 # you may want to set
5 # --delay=N how long to greylist, seconds (default: 300)
6 # --max-age=N delete old entries after N days (default: 35)
7 # see also the postgrey(8) manpage
8
9 POSTGREY_OPTS="--inet=127.0.0.1:10023"
10
11 # the --greylist-text commandline argument can not be easily passed through
12 # POSTGREY_OPTS when it contains spaces. So, insert your text here:
13 #POSTGREY_TEXT="Your customized rejection message here"
14
Inclusion via restriction in /etc/postfix/main.cf
Whitelists
Whitelist format for recipient addresses
domain.addr "domain.addr" domain and subdomains. name@ "name@.*" and extended addresses "name+blabla@.*". name@domain.addr "name@domain.addr" and extended addresses. /regexp/ anything that matches "regexp" (the full address is matched).
Whitelist format for client addresses
domain.addr "domain.addr" domain and subdomains. IP1.IP2.IP3.IP4 IP address IP1.IP2.IP3.IP4. You can also leave off one number, in which case only the first specified numbers will be checked. IP1.IP2.IP3.IP4/MASK CIDR-syle network. Example: 192.168.1.0/24 /regexp/ anything that matches "regexp" (the full address is matched).
policy-weightd
policyd-weight(8) is a SMTP policy daemon written in perl(1) for postfix(1). It evaluates based on RBL/RHSBL results, HELO and MAIL FROM domain and subdomain arguments and the client IP address the possibility of forgery or SPAM. It is designed to be called before the SMTP DATA command at the RCPT TO stage. This way it is a) possible to reject a mail attempt before the body has been received and b) to keep multirecipient mail intact, i.e. provide the functionality of selective usage based on recipients.
Configuration
1 root@mail /etc (git)-[master] # cat /etc/policyd-weight.conf
2 #policyd-weight uses a perl(1) style configuration file which it reads
3 #on startup. The cache re-reads the configuration after $MAINTE‐
4 #NANCE_LEVEL (default: 5) queries. If -f is not specified, it searches
5 #for configuration files on following locations:
6
7
8 #CACHE SETTINGS
9 # $CACHESIZE (default: 2000)
10 # Set the minimum size of the SPAM cache.
11 # $CACHEMAXSIZE (default: 4000)
12 # Set the maximum size of the SPAM cache.
13 # $CACHEREJECTMSG
14 # (default: 550 temporarily blocked because of previous errors)"
15 # Set the SMTP status code and a explanatory message for rejected
16 # mails due to cached results
17 # $NTTL (default: 1)
18 # The client is penalized for that many retries.
19 $NTTL=10;
20 # $NTIME (default: 30)
21 # The $NTTL counter will only be decremented if the client waits
22 # at least $NTIME seconds.
23 $NTIME=5;
24 # $POSCACHESIZE (default: 1000)
25 # Set the minimum size of the HAM cache.
26 # $POSCACHEMAXSIZE (default: 2000)
27 # Set the maximum size of the HAM cache.
28 # $PTTL (default: 60)
29 # After that many queries the HAM entry must succeed one run
30 # through the RBL checks again.
31 # $PTIME (default: 3h)
32 # after $PTIME in HAM Cache the client must pass one time the RBL
33 # checks again. Values must be nonfractal. Accepted time-units:
34 # s(econds), m(inutes), h(ours), d(ays)
35 # $TEMP_PTIME (default: 1d)
36 # The client must pass this time the RBL checks in order to be
37 # listed as hard-HAM. After this time the client will pass immedi‐
38 # ately for PTTL within PTIME. Values must be non-fractal.
39 # Accepted time-units: s(econds), m(inutes), h(ours), d(ays)
40
41
42 #DEBUG SETTINGS
43 # $DEBUG (default: 0)
44 # Turn debugging on (1) or off (0)
45
46
47
48 #DNS SETTINGS
49 # $DNS_RETRIES (default: 2)
50 # How many times a single DNS query may be repeated
51 # $DNS_RETRY_IVAL (default: 2)
52 # Retry a query without response after that many seconds
53 # $MAXDNSERR (default: 3)
54 # If that many queries fail, the mail is accepted with $MAXDNSER‐
55 # RMSG.
56 # In total DNS queries this means: $MAXDNSERR * $DNS_RETRIES
57
58
59 #MISC SETTINGS
60 # $MAINTENANCE_LEVEL (default: 5)
61 # After that many policy requests the cache (and in daemon mode
62 # child processes) checks for configuration file changes
63 # $MAXIDLECACHE (default: 60)
64 # After that many seconds of being idle the cache checks for con‐
65 # figuration file changes.
66 # $PIDFILE (default: /var/run/policyd-weight.pid)
67 # Path and filename to store the master pid (daemon mode)
68 # $LOCKPATH (default: /tmp/.policyd-weight/)
69 # Directory where policyd-weight stores sockets and lock-
70 # files/directories. Its argument must contain a trailing slash.
71 # $SPATH (default: $LOCKPATH.'/polw.sock')
72 # Path and filename which the cache has to use for communication.
73 # $TCP_PORT (default: 12525)
74 # TCP port on which the policy server listens (daemon mode)
75 # $BIND_ADDRESS (default: '127.0.0.1')
76 # IP Address on which policyd-weight binds. Currently either only
77 # one or all IPs are supported. Specify 'all' if you want to lis‐
78 # ten on all IPs.
79 # $SOMAXCONN (default: 1024)
80 # Maximum connections which policyd-weight accepts. This is set
81 # high enough to cover most scenarios.
82 # $USER (default: polw)
83 # Set the user under which policyd-weight runs
84 # $GROUP (default: $USER)
85 # Set the group under which policyd-weight runs
86
87
88 #OUTPUT AND LOG SETTINGS
89 # $ADD_X_HEADER (default: 1)
90 # Insert a X-policyd-weight: header with evaluation messages.
91 # 1 = on, 0 = off
92 # $LOG_BAD_RBL_ONLY (default: 1)
93 # Insert only RBL results in logging strings if the RBL score
94 # changes the overall score. Thus RBLs with a GOOD SCORE of 0
95 # don't appear in logging strings if the RBL returned no BAD hit.
96 # 1 = on, 0 = off
97 # $MAXDNSBLMSG (default: 550 Your MTA is listed in too many DNSBLs)
98 # The message sent to the client if it was reject due to $MAXDNS‐
99 # BLHITS and/or $MAXDNSBLSCORE.
100 # $REJECTMSG (default: 550 Mail appeared to be SPAM or forged. Ask your
101 # Mail/DNS-Adminisrator to correct HELO and DNS MX settings or to get
102 # removed from DNSBLs)
103 # Set the SMTP status code for rejected mails and a message why
104 # the action was taken
105
106
107
108 #RESOURCE AND OPTIMIZATIONS
109 # $CHILDIDLE (default: 120)
110 # How many seconds a child may be idle before it dies (daemon
111 # mode)
112 # $MAX_PROC (default: 50)
113 # Process limit on how many processes policyd-weight will spawn
114 # (daemon mode)
115 # $MIN_PROC (default: 2)
116 # Minimum child processes which are kept alive in idle times (dae‐
117 # mon mode)
118 # $PUDP (default: 0)
119 # Set persistent UDP connections used for DNS queries on (1) or
120 # off (0).
121
122
123
124 #SCORE SETTINGS
125 # Positive values indicate a bad (SPAM) score, negative values indicate a
126 # good (HAM) score.
127 # @bogus_mx_score (2.1, 0)
128 # If the sender domain has neither MX nor A records or these
129 # records resolve to a bogus IP-Address (for instance private net‐
130 # works) then this check asigns the full score of bogus_mx_score.
131 # If there is no MX but an A record of the sender domain then it
132 # receives a penalty only if DNSBL-listed.
133 # Log Entries:
134 # BOGUS_MX
135 # The sender A and MX records are bogus or empty.
136 # BAD_MX
137 # The sender domain has an empty or bogus MX record and the
138 # client is DNSBL listed.
139 # Related RFCs:
140 # [1918] Address Allocation for Private Internets
141 # [2821] Simple Mail Transfer Protocol (Sect 3.6 and Sect 5)
142 # @client_ip_eq_helo_score (1.5, -1.25)
143 # Define scores for the match of the reverse record (hostname)
144 # against the HELO argument. Reverse lookups are done, if the for‐
145 # ward lookups failed and are not trusted.
146 # Log Entries:
147 # REV_IP_EQ_HELO
148 # The Client's PTR matched the HELO argument.
149 # REV_IP_EQ_HELO_DOMAIN
150 # Domain portions of Client PTR and HELO argument matched.
151 # RESOLVED_IP_IS_NOT_HELO
152 # Client PTRs found but did not match HELO argument.
153 # @helo_score (1.5, -2)
154 # Define scores for the match of the Client IP and its /24 subnet
155 # against the A records of HELO or MAIL FROM domain/host. It also
156 # holds the bad score for MX verifications.
157 # Log Entries:
158 # CL_IP_EQ_HELO_NUMERIC
159 # Client IP matches the [IPv4] HELO.
160 # CL_IP_EQ_FROM_IP
161 # Client IP matches the A record of the MAIL FROM sender
162 # domain/host.
163 # CL_IP_EQ_HELO_IP
164 # Client IP matches the A record of the HELO argument.
165 # CL_IP_NE_HELO
166 # The IP and the /24 subnet did not match A/MX records of
167 # HELO and MAIL FROM arguments and their subdomains.
168 # @helo_from_mx_eq_ip_score (1.5, -3.1)
169 # Define scores for the match of Client IP against MX records.
170 # Positive (SPAM) values are used in case the MAIL FROM matches
171 # not the HELO argument AND the client seems to be dynamic AND the
172 # client is no MX for HELO and MAIL FROM arguments. The total
173 # DNSBL score is added to its bad score.
174 # Log Entries:
175 # CL_IP_EQ_FROM_MX
176 # Client IP matches the MAIL FROM domain/host MX record
177 # CL_IP_EQ_HELO_MX
178 # Client IP matches the HELO domain/host MX record
179 # CLIENT_NOT_MX/A_FROM_DOMAIN
180 # Client is not a verified HELO and doesn't match A/MX records
181 # of MAIL FROM argument
182 # CLIENT/24_NOT_MX/A_FROM_DOMAIN
183 # Client's subnet does not match A/MX records of the MAIL FROM
184 # argument
185 # $dnsbl_checks_only (default: 0)
186 # Disable HELO/RHSBL verifications and the like. Do only RBL
187 # checks.
188 # 1 = on, 0 = off
189 # @dnsbl_score (default: see below)
190 # A list of RBLs to be checked. If you want that a host is not
191 # being evaluated any further if it is listed on several lists or
192 # a very trustworthy list you can control a immediate REJECT with
193 # $MAXDNSBLHITS and/or $MAXDNSBLSCORE. A list of RBLs must be
194 # build as follows:
195 # @dnsbl_score = (
196 # RBLHOST1, HIT SCORE, MISS SCORE, LOG NAME,
197 # RBLHOST2, HIT SCORE, MISS SCORE, LOG NAME,
198 # ...
199 # );
200 # The default is:
201 # @dnsbl_score = (
202 # "dynablock.njabl.org", 3.25, 0, "DYN_NJABL",
203 # "dnsbl.njabl.org", 4.25, -1.5, "BL_NJABL",
204 # "bl.spamcop.net", 1.75, -1.5, "SPAMCOP",
205 # "sbl-xbl.spamhaus.org", 4.35, -1.5, "SBL_XBL_SPAMHAUS",
206 # "list.dsbl.org", 4.35, 0, "DSBL_ORG",
207 # "ix.dnsbl.manitu.net", 4.35, 0, "IX_MANITU",
208 # "relays.ordb.org", 3.25, 0, "ORDB_ORG"
209 # );
210 # @rhsbl_score (default: see below)
211 # Define a list of RHSBL host which are queried for the sender
212 # domain. Results get additionally scores of 0.5 * DNSBL results
213 # and @rhsbl_penalty_score. A list of RHSBL hosts to be queried
214 # must be build as follows:
215 # @rhsbl_score = (
216 # RHSBLHOST1, HIT SCORE, MISS SCORE, LOG NAME,
217 # RHSBLHOST2, HIT SCORE, MISS SCORE, LOG NAME,
218 # ...
219 # );
220 # The default is:
221 # @rhsbl_score = (
222 # "rhsbl.ahbl.org", 1.8, 0, "AHBL",
223 # "dsn.rfc-ignorant.org", 3.2, 0, "DSN_RFCI",
224 # "postmaster.rfc-ignorant.org", 1 , 0, "PM_RFCI",
225 # "abuse.rfc-ignorant.org", 1, 0, "ABUSE_RFCI"
226 # );
227 # @rhsbl_penalty_score (3.1, 0)
228 # This score will be added to each RHSBL hit if following crite‐
229 # rias are met:
230 # Sender has a random local-part (i.e. yztrzgb@example.tld)
231 # or MX records of sender domain are bogus
232 # or FROM matches not HELO
233 # or HELO is untrusted (Forward record matched, reverse record
234 # did not match)
235 # $MAXDNSBLHITS (default: 2)
236 # If the client is listed in more than $MAXDNSBLHITS RBLs it will
237 # be rejected immediately with $MAXDNSBLMSG and without further
238 # evaluation. Results are cached by default.
239 # $MAXDNSBLSCORE (default: 8)
240 # If the BAD SCOREs of @dnsbl_score listed RBLs reach a level
241 # greater than $MAXDNSBLSCORE the client will be rejected immedi‐
242 # ately with $MAXDNSBLMSG and without further evaluation. Results
243 # are cached by default.
244 # $REJECTLEVEL (default: 1)
245 # Score results equal or greater than this level will be rejected
246 # with $REJECTMSG
247
Defaults
1 ## This is a POSIX shell fragment sourced by /etc/init.d/policyd-weight
2 ## variable: DAEMON_OPTS
3 ## daemon options to policyd-weight, possible options:
4 ##
5 ## Options
6 ## -D Don't detach master - run master in foreground
7 ## -d Debug, don't daemonize, log to STDOUT
8 ## -f /path/to/file Specify a configuration file
9 ## -h This help
10 ## -k Kill cache instance
11 ## -s Show cache entries and exit. With -d show debug
12 ## cache entries
13 ## -v Show version and exit
14 ##
15 ## default: unset
16 DAEMON_OPTS="-f /etc/policyd-weight.conf"
Inclusion via restriction in /etc/postfix/main.cf
rspamd
For installation see rspamd
/etc/postfix/main.cf
1 ### RSPAMD
2
3 #smtpd_milters = unix:/var/lib/rspamd/milter.sock
4 # or for TCP socket
5 smtpd_milters = inet:localhost:11332
6 non_smtpd_milters = inet:localhost:11332
7
8 # skip mail without checks if something goes wrong
9 milter_default_action = accept
10
11 # 6 is the default milter protocol version;
12 # prior to Postfix 2.6 the default protocol was 2.
13 # milter_protocol = 6
14
15 milter_default_action = accept
16 milter_mail_macros = i {auth_type} {auth_authen} {auth_author} {mail_addr} {mail_host} {mail_mailer}
17 #milter_mail_macros = i {auth_authen} {client_addr} {client_name} {mail_addr}
Sender Policy Framwork (SPF)
* www.spf-record.de * www.dmarcanalyzer.com: SPF Checker
Only the Server behind MX-Record may send email. v=spf1 mx -all