Compare commits
159 Commits
eed8497faa
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| b32555f66c | |||
| e3c2df0f3b | |||
| 2f3e513f04 | |||
| 876fae3364 | |||
| 3032337c7d | |||
| 4240bc3b14 | |||
| 14fc0b0578 | |||
| 6a827cba44 | |||
| 0ec563bb3c | |||
| 027930ae6e | |||
| 20da412413 | |||
| e829868645 | |||
| 5b853a26cb | |||
| cd39cb98b8 | |||
| b09baa144c | |||
| f0921f8669 | |||
| 548c4015e8 | |||
| e91c9f1b04 | |||
| 4bb27992d8 | |||
| 4360717cfe | |||
| 59488b9065 | |||
| fdd17790f6 | |||
| 50bc28dc2a | |||
| b87793cbad | |||
|
|
cc155c578a | ||
| b28b3a8316 | |||
| ecfd630612 | |||
| 68d2bd18b7 | |||
|
|
6521b03aa2 | ||
| 05723c0514 | |||
| 32b3c8b01e | |||
| f2f3797c1e | |||
| d8979faa06 | |||
| d407b2ecf0 | |||
| 13e1d575f9 | |||
| a246f5009f | |||
| 41f5f61d32 | |||
| eb18cf2a84 | |||
| 578db07b76 | |||
| 3b3652ec55 | |||
| 44c56d6083 | |||
| 8e9f35ed76 | |||
| 0303c79b03 | |||
| 20d4c95404 | |||
| 3b60d1b83e | |||
| cb9e958d39 | |||
| 761a3a3b34 | |||
| ae06305069 | |||
| e50851b519 | |||
| c82ff77bbe | |||
| f4c7453675 | |||
| 06914fcade | |||
| 230ab94ca6 | |||
| 7cc2369ea0 | |||
| 4aaeae3b1a | |||
| 692e76ad1d | |||
| 6f02a45023 | |||
| e971f26c75 | |||
| bbc3cf87f1 | |||
| 195e3f65ee | |||
| 0270997761 | |||
| 6e19d1a938 | |||
| 5a9dcc4b8f | |||
| 94a1895873 | |||
| e00ba6f4ce | |||
| 845325eac8 | |||
| ba20cb36fe | |||
| 83ad91f77d | |||
| 3a98ac15f7 | |||
| d811cbfbd1 | |||
| 5eebd200f4 | |||
| 14ae5a3ebf | |||
| e24fb4cad3 | |||
| cc06fe5cfa | |||
| 4442c6230e | |||
| 3f141499dc | |||
| 9b12e32853 | |||
| 894ff4eced | |||
| 99b1205d1b | |||
| ae2b6540af | |||
| 6cc1848e45 | |||
| 07231ac1c7 | |||
|
|
7b6e4c36d0 | ||
| ee41a335b1 | |||
| 0b410ad6d8 | |||
| aa092ea841 | |||
| da6c7fca0e | |||
| f1f56f48f6 | |||
| 765b16fd59 | |||
| 6a34a5b74c | |||
| ad1d844b54 | |||
| aa38ae7d76 | |||
|
|
f6482795c4 | ||
| 361ccefd9a | |||
| 307c47d4a5 | |||
|
|
8670eb3dba | ||
|
|
8a66f11f49 | ||
| 1d78a7e4b3 | |||
| 6c3c0c596b | |||
| b069fdac30 | |||
| 240dfbb54a | |||
| 3eb53b5463 | |||
| e976d0e3ef | |||
|
|
da37fc1938 | ||
|
|
d189d8c4e9 | ||
|
|
d0816ecf1c | ||
| 8a9ea4141b | |||
| 46ea239260 | |||
| f766e859f7 | |||
| 3785baa94a | |||
| a792c623bd | |||
| 2110953673 | |||
| aad56b6497 | |||
| 97898ca194 | |||
| 520a1c115d | |||
| e70949f6ec | |||
| 397c6304e8 | |||
| 5365eb8e18 | |||
| 0c5c9915f8 | |||
| 015cba6d05 | |||
| b4cbe3989c | |||
| ba486f22db | |||
| 44317f0b57 | |||
| 0f6fa53e6d | |||
| 0c4dd7b5e9 | |||
| e93a4783a2 | |||
| 5261828376 | |||
| 3f3ef95240 | |||
| cda7fb08da | |||
| 83a4e631b5 | |||
| b1f4cdc84d | |||
| 1f05685af9 | |||
| e48b35bdd1 | |||
|
|
e595f034d8 | ||
| d5d3bddb8c | |||
| b717e88130 | |||
| ccc527abc2 | |||
| 2291f6efa9 | |||
| bb464c1686 | |||
| 23165653f5 | |||
| ba988c63bc | |||
| 4dd9611151 | |||
| 0bde654616 | |||
| 190b0d0fcb | |||
| 30db99c91e | |||
| 25d24ccdfc | |||
| e50d23d9e8 | |||
| 2984da58c9 | |||
| 4a6d7034f2 | |||
| 0e9f2d739b | |||
| 58cd085f59 | |||
| a0f75035ad | |||
| db1c2fd72b | |||
| 058ea39ce7 | |||
| 225d8f83c6 | |||
| 93a7f2fe62 | |||
| 5f554c8bbd | |||
| cc146aa5fc | |||
| 1f34f1eaaa |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -3,6 +3,7 @@
|
|||||||
*.log
|
*.log
|
||||||
*.swp
|
*.swp
|
||||||
conf/*.conf
|
conf/*.conf
|
||||||
|
conf/*.env
|
||||||
|
|
||||||
# - Postfixadmin
|
# - Postfixadmin
|
||||||
postfixadmin-*
|
postfixadmin-*
|
||||||
|
|||||||
5297
BAK/install_amavis.sh.Pre-Queue.00
Executable file
5297
BAK/install_amavis.sh.Pre-Queue.00
Executable file
File diff suppressed because it is too large
Load Diff
684
BAK/install_opendkim.sh.Pre-Queue.00
Executable file
684
BAK/install_opendkim.sh.Pre-Queue.00
Executable file
@@ -0,0 +1,684 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
clear
|
||||||
|
echo -e "\n \033[32mStart Installation of OpenDKIM..\033[m"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# -------------
|
||||||
|
# - Settings
|
||||||
|
# -------------
|
||||||
|
|
||||||
|
#_src_base_dir="$(realpath $(dirname $0))"
|
||||||
|
#conf_file="${_src_base_dir}/conf/install_opendkim.conf"
|
||||||
|
|
||||||
|
log_file="$(mktemp)"
|
||||||
|
|
||||||
|
backup_date="$(date +%Y-%m-%d-%H%M)"
|
||||||
|
|
||||||
|
_opendkim_packages="opendkim opendkim-tools"
|
||||||
|
|
||||||
|
opendkim_base_dir="/etc/opendkim"
|
||||||
|
opendkim_key_dir="${opendkim_base_dir}/keys"
|
||||||
|
opendkim_conf_file="/etc/opendkim.conf"
|
||||||
|
|
||||||
|
postfix_spool_dir="/var/spool/postfix"
|
||||||
|
|
||||||
|
opendkim_socket_dir="${postfix_spool_dir}/opendkim"
|
||||||
|
opendkim_socket_file="${opendkim_socket_dir}/opendkim.sock"
|
||||||
|
|
||||||
|
postfix_needs_restart=false
|
||||||
|
opendkim_needs_restart=false
|
||||||
|
|
||||||
|
|
||||||
|
# -------------
|
||||||
|
# --- Some functions
|
||||||
|
# -------------
|
||||||
|
echononl(){
|
||||||
|
echo X\\c > /tmp/shprompt$$
|
||||||
|
if [ `wc -c /tmp/shprompt$$ | awk '{print $1}'` -eq 1 ]; then
|
||||||
|
echo -e -n "$*\\c" 1>&2
|
||||||
|
else
|
||||||
|
echo -e -n "$*" 1>&2
|
||||||
|
fi
|
||||||
|
rm /tmp/shprompt$$
|
||||||
|
}
|
||||||
|
|
||||||
|
fatal(){
|
||||||
|
echo ""
|
||||||
|
echo -e "fatal error: $*"
|
||||||
|
echo ""
|
||||||
|
echo -e "\t\033[31m\033[1mInstalllation will be interrupted\033[m\033[m"
|
||||||
|
echo ""
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
error(){
|
||||||
|
echo ""
|
||||||
|
echo -e "\t[ \033[31m\033[1mFehler\033[m ]: $*"
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
warn (){
|
||||||
|
echo ""
|
||||||
|
echo -e "\t[ \033[33m\033[1mWarning\033[m ]: $*"
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
info (){
|
||||||
|
echo ""
|
||||||
|
echo -e "\t[ \033[32m\033[1mInfo\033[m ]: $*"
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
echo_done() {
|
||||||
|
echo -e "\033[80G[ \033[32mdone\033[m ]"
|
||||||
|
}
|
||||||
|
echo_ok() {
|
||||||
|
echo -e "\033[80G[ \033[32mok\033[m ]"
|
||||||
|
}
|
||||||
|
echo_warning() {
|
||||||
|
echo -e "\033[80G[ \033[33m\033[1mwarn\033[m ]"
|
||||||
|
}
|
||||||
|
echo_failed(){
|
||||||
|
echo -e "\033[80G[ \033[1;31mfailed\033[m ]"
|
||||||
|
}
|
||||||
|
echo_skipped() {
|
||||||
|
echo -e "\033[80G[ \033[37mskipped\033[m ]"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# -------------
|
||||||
|
# - Some pre-installation tasks
|
||||||
|
# -------------
|
||||||
|
|
||||||
|
# - Is 'systemd' supported on this system
|
||||||
|
# -
|
||||||
|
SYSTEMD_EXISTS=false
|
||||||
|
systemd=$(which systemd)
|
||||||
|
systemctl=$(which systemctl)
|
||||||
|
|
||||||
|
if [[ -n "$systemd" ]] || [[ -n "$systemctl" ]] ; then
|
||||||
|
SYSTEMD_EXISTS=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# =============
|
||||||
|
# - Start Installation
|
||||||
|
# =============
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# - Synchronise package index files with the repository
|
||||||
|
# -
|
||||||
|
echononl " Synchronise package index files with the repository.."
|
||||||
|
apt-get update > "$log_file" 2>&1
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# - Install OpenDKIM
|
||||||
|
# -
|
||||||
|
echononl " Install needed debian packages.."
|
||||||
|
opendkim_packages=""
|
||||||
|
packages_installed=false
|
||||||
|
for _pkg in $_opendkim_packages ; do
|
||||||
|
if aptitude search "$_pkg" | grep " $_pkg " | grep -e "^i" > /dev/null 2>&1 ; then
|
||||||
|
continue
|
||||||
|
else
|
||||||
|
opendkim_packages="$opendkim_packages $_pkg"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [[ -n "$opendkim_packages" ]]; then
|
||||||
|
DEBIAN_FRONTEND=noninteractive apt-get -y install $opendkim_packages > /dev/null 2> "$log_file"
|
||||||
|
packages_installed=true
|
||||||
|
opendkim_needs_restart=true
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# - Add user 'postfix' to group 'opendkim'
|
||||||
|
# -
|
||||||
|
echononl " Add user 'postfix' to group 'opendkim'.."
|
||||||
|
if grep opendkim /etc/group | grep -q postfix 2> /dev/null ; then
|
||||||
|
echo_skipped
|
||||||
|
else
|
||||||
|
adduser postfix opendkim > "$log_file" 2>&1
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# - Save configuration file from distribution
|
||||||
|
# -
|
||||||
|
echononl " Save configuration file from distribution"
|
||||||
|
if $packages_installed ; then
|
||||||
|
cp -a $opendkim_conf_file $opendkim_conf_file.ORIG 2> "$log_file"
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
fi
|
||||||
|
|
||||||
|
echononl " Backup existing file '${opendkim_conf_file}'.."
|
||||||
|
if [[ -f "${opendkim_conf_file}" ]] ; then
|
||||||
|
mv "${opendkim_conf_file}" "${opendkim_conf_file}.${backup_date}"
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
fi
|
||||||
|
|
||||||
|
# - Create OpenDKIM configuration
|
||||||
|
# -
|
||||||
|
echononl " Create OpenDKIM configuration"
|
||||||
|
if [[ -f "$opendkim_conf_file" ]] \
|
||||||
|
&& grep -i -q -E "^\s*Socket\s+local:$opendkim_socket_file" "$opendkim_conf_file" \
|
||||||
|
&& grep -i -q -E "^\s*SigningTable.*${opendkim_base_dir}/signing.table" "$opendkim_conf_file" \
|
||||||
|
&& grep -i -q -E "^\s*KeyTable.*${opendkim_base_dir}/key.table" "$opendkim_conf_file" ; then
|
||||||
|
echo_skipped
|
||||||
|
warn "OpenDKIM seems already be configured."
|
||||||
|
else
|
||||||
|
cat <<EOF > $opendkim_conf_file 2> $log_file
|
||||||
|
# Datei $opendkim_conf_file
|
||||||
|
|
||||||
|
# Sets the "authserv-id" to use when generating the Authentication-Results:
|
||||||
|
# header field after verifying a message. The default is to use the name of
|
||||||
|
# the MTA processing the message. If the string "HOSTNAME" is provided, the
|
||||||
|
# name of the host running the filter (as returned by the gethostname(3)
|
||||||
|
# function) will be used.
|
||||||
|
AuthservID "DKIM check $(hostname -f)"
|
||||||
|
|
||||||
|
# OpenDKIM agiert als Mail Filter (= Milter) in den
|
||||||
|
# Modi signer (s) und verifier (v) und verwendet eine
|
||||||
|
# Socket-Datei zur Kommunikation (alternativ: lokaler Port)
|
||||||
|
Mode sv
|
||||||
|
|
||||||
|
# Socket local:/var/run/opendkim/opendkim.sock
|
||||||
|
# Socket local:$opendkim_socket_file
|
||||||
|
# Socket inet:12345@localhost
|
||||||
|
Socket local:$opendkim_socket_file
|
||||||
|
|
||||||
|
# OpenDKIM verwendet diesen Benutzer bzw.
|
||||||
|
# diese Gruppe
|
||||||
|
UserID opendkim:opendkim
|
||||||
|
UMask 002
|
||||||
|
PidFile /var/run/opendkim/opendkim.pid
|
||||||
|
|
||||||
|
# OpenDKIM bei Problemen neustarten,
|
||||||
|
# aber max. 10 mal pro Stunde
|
||||||
|
AutoRestart yes
|
||||||
|
AutoRestartRate 10/1h
|
||||||
|
|
||||||
|
# Logging (wenn alles funktioniert eventuell reduzieren)
|
||||||
|
Syslog yes
|
||||||
|
SyslogSuccess yes
|
||||||
|
LogWhy yes
|
||||||
|
|
||||||
|
# Verfahren, wie Header und Body durch
|
||||||
|
# OpenDKIM verarbeitet werden sollen.
|
||||||
|
Canonicalization relaxed/simple
|
||||||
|
|
||||||
|
# interne Mails nicht mit OpenDKIM verarbeiten
|
||||||
|
ExternalIgnoreList refile:${opendkim_base_dir}/trusted
|
||||||
|
InternalHosts refile:${opendkim_base_dir}/trusted
|
||||||
|
|
||||||
|
# welche Verschlüsselungs-Keys sollen für welche
|
||||||
|
# Domains verwendet werden
|
||||||
|
# (refile: für Dateien mit regulären Ausdrücke)
|
||||||
|
SigningTable refile:${opendkim_base_dir}/signing.table
|
||||||
|
KeyTable ${opendkim_base_dir}/key.table
|
||||||
|
|
||||||
|
# diesen Signatur-Algorithmus verwenden
|
||||||
|
SignatureAlgorithm rsa-sha256
|
||||||
|
|
||||||
|
# Always oversign From (sign using actual From and a null From to prevent
|
||||||
|
# malicious signatures header fields (From and/or others) between the signer
|
||||||
|
# and the verifier. From is oversigned by default in the Debian pacakge
|
||||||
|
# because it is often the identity key used by reputation systems and thus
|
||||||
|
# somewhat security sensitive.
|
||||||
|
OversignHeaders From
|
||||||
|
|
||||||
|
# Add an "Authentication-Results:" header field even to unsigned messages
|
||||||
|
# from domains with no "signs all" policy. The reported DKIM result will be
|
||||||
|
# "none" in such cases. Normally unsigned mail from non-strict domains does
|
||||||
|
# not cause the results header field to be added.
|
||||||
|
AlwaysAddARHeader yes
|
||||||
|
|
||||||
|
# Causes opendkim to fork and exits immediately, leaving the service running
|
||||||
|
# in the background. The default is "true".
|
||||||
|
Background yes
|
||||||
|
|
||||||
|
# Sets the DNS timeout in seconds. A value of 0 causes an infinite wait. The
|
||||||
|
# default is 5. Ignored if not using an asynchronous resolver package. See
|
||||||
|
# also the NOTES section below.
|
||||||
|
DNSTimeout 5
|
||||||
|
EOF
|
||||||
|
opendkim_needs_restart=true
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# - Assign ownership to the opendkim user and restrict tthe
|
||||||
|
# - file permissions:
|
||||||
|
# -
|
||||||
|
echononl " Assign ownership and file permissions.."
|
||||||
|
chmod u=rw,go=r $opendkim_conf_file 2> $log_file
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# - Create the directories to hold OpenDKIM’s data files, assign
|
||||||
|
# - ownership to the opendkim user, and restrict the file
|
||||||
|
# - permissions:
|
||||||
|
# -
|
||||||
|
echononl " Create directory '$opendkim_base_dir'"
|
||||||
|
if [[ -d "$opendkim_base_dir" ]] ; then
|
||||||
|
echo_skipped
|
||||||
|
else
|
||||||
|
opendkim_needs_restart=true
|
||||||
|
mkdir ${opendkim_base_dir} 2> $log_file
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echononl " Create directory '$opendkim_key_dir'"
|
||||||
|
if [[ -d "$opendkim_key_dir" ]] ; then
|
||||||
|
echo_skipped
|
||||||
|
else
|
||||||
|
opendkim_needs_restart=true
|
||||||
|
mkdir $opendkim_key_dir 2> $log_file
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echononl " Set ownership on directory '${opendkim_base_dir}' (recursive).."
|
||||||
|
chown -R opendkim:opendkim ${opendkim_base_dir} 2> $log_file
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
echononl " Set file-permission on $opendkim_key_dir"
|
||||||
|
chmod go-rw $opendkim_key_dir 2> $log_file
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# - Create empty files
|
||||||
|
# - ${opendkim_base_dir}/signing.table
|
||||||
|
# - ${opendkim_base_dir}/key.table
|
||||||
|
# -
|
||||||
|
echononl " Create empty file '${opendkim_base_dir}/signing.table'.."
|
||||||
|
if [[ -f "${opendkim_base_dir}/signing.table" ]] ; then
|
||||||
|
echo_skipped
|
||||||
|
else
|
||||||
|
touch ${opendkim_base_dir}/signing.table 2> $log_file
|
||||||
|
opendkim_needs_restart=true
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echononl " Create empty file '${opendkim_base_dir}/key.table'.."
|
||||||
|
if [[ -f "${opendkim_base_dir}/key.table" ]] ; then
|
||||||
|
echo_skipped
|
||||||
|
else
|
||||||
|
touch ${opendkim_base_dir}/key.table 2> $log_file
|
||||||
|
opendkim_needs_restart=true
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# - Create the trusted hosts file ${opendkim_base_dir}/trusted.hosts.
|
||||||
|
# -
|
||||||
|
echononl " Create trusted hosts file '${opendkim_base_dir}/trusted'.."
|
||||||
|
if [[ -f "${opendkim_base_dir}/trusted" ]] ; then
|
||||||
|
echo_skipped
|
||||||
|
else
|
||||||
|
cat <<EOF > ${opendkim_base_dir}/trusted 2> $log_file
|
||||||
|
127.0.0.1
|
||||||
|
::1
|
||||||
|
localhost
|
||||||
|
$(hostname -f)
|
||||||
|
EOF
|
||||||
|
opendkim_needs_restart=true
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# - Create the OpenDKIM socket directory in Postfix’s work area
|
||||||
|
# - and make sure it has the correct ownership:
|
||||||
|
# -
|
||||||
|
echononl " Create the OpenDKIM socket directory in Postfix’s work area.."
|
||||||
|
if [[ -d "${postfix_spool_dir}/opendkim" ]] ; then
|
||||||
|
echo_skipped
|
||||||
|
else
|
||||||
|
mkdir ${postfix_spool_dir}/opendkim 2> $log_file
|
||||||
|
opendkim_needs_restart=true
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
echononl " Set ownership on directory '${postfix_spool_dir}/opendkim'.."
|
||||||
|
chown opendkim:postfix ${postfix_spool_dir}/opendkim 2> $log_file
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# - Edit /etc/default/opendkim
|
||||||
|
# -
|
||||||
|
# - Set:
|
||||||
|
# - SOCKET="local:${postfix_spool_dir}/opendkim/opendkim.sock"
|
||||||
|
# -
|
||||||
|
echononl " Set 'SOCKET' at file /etc/default/opendkim.."
|
||||||
|
if grep -q -E "^\s*SOCKET" /etc/default/opendkim 2>/dev/null ; then
|
||||||
|
if grep -q -E "^\s*SOCKET.*local:$opendkim_socket_file" /etc/default/opendkim 2>/dev/null ; then
|
||||||
|
echo_skipped
|
||||||
|
else
|
||||||
|
perl -i -n -p -e "s#^\s*SOCKET=.*#SOCKET=\"local:$opendkim_socket_file\"#" /etc/default/opendkim 2> $log_file
|
||||||
|
opendkim_needs_restart=true
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
cat <<EOF >>/etc/default/opendkim 2> $log_file
|
||||||
|
SOCKET="local:$opendkim_socket_file"
|
||||||
|
EOF
|
||||||
|
opendkim_needs_restart=true
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# - Edit /etc/postfix/main.cf and add a section to activate
|
||||||
|
# - processing of e-mail through the OpenDKIM daemon:
|
||||||
|
# -
|
||||||
|
backup_date="$(date +%Y-%m-%d-%H%M)"
|
||||||
|
echononl " Backup existing postfix configuration (main.cf).."
|
||||||
|
cp -a /etc/postfix/main.cf /etc/postfix/main.cf.$backup_date 2> $log_file
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echononl " Activate processing of e-mail through the OpenDKIM daemon.."
|
||||||
|
if grep -q -E "milter_default_action\s*=\s*accept" /etc/postfix/main.cf ; then
|
||||||
|
echo_skipped
|
||||||
|
warn "Postfix (main.cf) seems already be configured for milters"
|
||||||
|
echononl " Delete previosly saved Postfix configuration.."
|
||||||
|
rm /etc/postfix/main.cf.$backup_date 2> $log_file
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
cat <<EOF >> /etc/postfix/main.cf 2> $log_file
|
||||||
|
|
||||||
|
# ======= Milter configuration =======
|
||||||
|
|
||||||
|
# OpenDKIM
|
||||||
|
|
||||||
|
milter_default_action = accept
|
||||||
|
|
||||||
|
# Postfix ≥ 2.6 milter_protocol = 6, Postfix ≤ 2.5 milter_protocol = 2
|
||||||
|
milter_protocol = 6
|
||||||
|
|
||||||
|
# Note:
|
||||||
|
# We will sign AFTER sending through AmaVIS, just befor sending out. So
|
||||||
|
# set 'smtpd_milters =' to an emty string here and add to localhost:10025
|
||||||
|
# section in master.cf: 'smtpd_milters=local:/opendkim/opendkim.sock'
|
||||||
|
#
|
||||||
|
# If you want sign mails before sending through AmaVIS, set
|
||||||
|
# 'smtpd_milters = local:/opendkim/opendkim.sock' here and add to
|
||||||
|
# localhost:10025 section in master.cf: 'smtpd_milters='
|
||||||
|
#
|
||||||
|
#smtpd_milters = local:/opendkim/opendkim.sock
|
||||||
|
smtpd_milters =
|
||||||
|
|
||||||
|
# Was sind non_smtpd_milters?
|
||||||
|
#
|
||||||
|
# non_smtpd_milters gilt für alle Postfix-Prozesse, die Mails verarbeiten, aber NICHT
|
||||||
|
# der smtpd-Daemon sind.
|
||||||
|
#
|
||||||
|
# Das betrifft z. B.:
|
||||||
|
#
|
||||||
|
# cleanup Header/Content-Bereinigung
|
||||||
|
# qmgr Queue-Manager
|
||||||
|
# lmtp / smtp Auslieferung nach extern
|
||||||
|
# local lokale Zustellung
|
||||||
|
#
|
||||||
|
# Das sind z. B.:
|
||||||
|
#
|
||||||
|
# - interne Bounces (MAILER-DAEMON)
|
||||||
|
#
|
||||||
|
# - Cron-Mails vom Server
|
||||||
|
#
|
||||||
|
# - Weiterleitungen, die Postfix selbst generiert
|
||||||
|
#
|
||||||
|
# - Mails, die über sendmail CLI gesendet werden
|
||||||
|
#
|
||||||
|
# - Mails, die Amavis über LMTP zurückgibt
|
||||||
|
#
|
||||||
|
# - etc.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# DKIM soll auch die ausgehenden Mails signieren, die nicht über smtpd daemon versendet werden.
|
||||||
|
non_smtpd_milters = local:/opendkim/opendkim.sock
|
||||||
|
EOF
|
||||||
|
postfix_needs_restart=true
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# - Prevent Postfix from setting the DKIM Header twice (one befor
|
||||||
|
# - and one after processing amavis
|
||||||
|
# -
|
||||||
|
# - To disable milter processing after amavis, add to your master.cf in
|
||||||
|
# - the after-amavis section:
|
||||||
|
# - 127.0.0.1:10025 inet n - - - - smtpd
|
||||||
|
# - [...]
|
||||||
|
# - -o smtpd_milters=
|
||||||
|
# -
|
||||||
|
# - If you want to run the milter after amavis, set in main.cf
|
||||||
|
# - smtpd_milters=
|
||||||
|
# - to an empty string and add the smtpd_milters configuration to master.cf
|
||||||
|
# - (after-section amavis) instead:
|
||||||
|
# - -o smtpd_milters=local:/opendkim/opendkim.sock
|
||||||
|
# -
|
||||||
|
echononl " Backup file '/etc/postfix/master.cf'.."
|
||||||
|
cp -a /etc/postfix/master.cf /etc/postfix/master.cf.$backup_date 2> $log_file
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
echononl " Adjust /etc/postfix/master.cf. Set DKIM after sending throuh AmaVIS.."
|
||||||
|
_found=false
|
||||||
|
_changed=false
|
||||||
|
tmp_master_file="/tmp/postfix_master.cf"
|
||||||
|
> $tmp_master_file
|
||||||
|
while IFS='' read -r _line || [[ -n $_line ]] ; do
|
||||||
|
|
||||||
|
if $_found && ! echo "$_line" | grep -i -q -E "^\s*-o" 2> /dev/null ; then
|
||||||
|
echo " -o smtpd_milters=local:/opendkim/opendkim.sock" >> "$tmp_master_file"
|
||||||
|
_changed=true
|
||||||
|
_found=false
|
||||||
|
fi
|
||||||
|
|
||||||
|
if $_found && echo "$_line" | grep -i -q -E "^\s*-o\s+smtpd_milters=\s*" ; then
|
||||||
|
_found=false
|
||||||
|
if ! echo "$_line" | grep -i -q -E "^\s*-o\s+smtpd_milters=\s*local:/opendkim/opendkim.sock\s*$" ; then
|
||||||
|
echo " -o smtpd_milters=local:/opendkim/opendkim.sock" >> "$tmp_master_file"
|
||||||
|
_changed=true
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if echo "$_line" | grep -i -q -E "^\s*(submission|smtps)\s+inet\s+" 2> /dev/null ; then
|
||||||
|
_found=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$_line" >> "$tmp_master_file"
|
||||||
|
|
||||||
|
done < "/etc/postfix/master.cf"
|
||||||
|
if $_changed ; then
|
||||||
|
cp $tmp_master_file /etc/postfix/master.cf 2> $log_file
|
||||||
|
postfix_needs_restart=true
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
info "Postfix (master.cf) was not changed - seems already be configured right."
|
||||||
|
echononl " Delete previosly saved file '/etc/postfix/master.cf'.."
|
||||||
|
rm /etc/postfix/master.cf.$backup_date 2> $log_file
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
rm -f $tmp_master_file
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# - Restart OpenDKIM
|
||||||
|
# -
|
||||||
|
echononl " Restart OpenDKIM.."
|
||||||
|
if $opendkim_needs_restart ; then
|
||||||
|
if $SYSTEMD_EXISTS ; then
|
||||||
|
systemctl restart opendkim > $log_file 2>&1
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
/etc/init.d/opendkim restart > $log_file 2>&1
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# - Restart Postfix so it starts using OpenDKIM when processing mail:
|
||||||
|
# -
|
||||||
|
echononl " Restart Postfix.."
|
||||||
|
if $postfix_needs_restart ; then
|
||||||
|
if $SYSTEMD_EXISTS ; then
|
||||||
|
systemctl restart postfix > $log_file 2>&1
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
/etc/init.d/postfix restart > $log_file 2>&1
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
rm -f "$log_file"
|
||||||
|
exit 0
|
||||||
936
BAK/install_opendmarc.sh.Pre-Queue.00
Executable file
936
BAK/install_opendmarc.sh.Pre-Queue.00
Executable file
@@ -0,0 +1,936 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
clear
|
||||||
|
echo -e "\n \033[32mStart Installation of OpenDMARC..\033[m"
|
||||||
|
|
||||||
|
overwrite_config_files=true
|
||||||
|
|
||||||
|
|
||||||
|
# -------------
|
||||||
|
# - Settings
|
||||||
|
# -------------
|
||||||
|
|
||||||
|
#_src_base_dir="$(realpath $(dirname $0))"
|
||||||
|
#conf_file="${_src_base_dir}/conf/install_opendmarc.conf"
|
||||||
|
|
||||||
|
_opendmarc_packages="opendmarc"
|
||||||
|
|
||||||
|
opendmarc_base_dir="/etc/opendmarc"
|
||||||
|
opendmarc_conf_file="/etc/opendmarc.conf"
|
||||||
|
|
||||||
|
postfix_spool_dir="/var/spool/postfix"
|
||||||
|
|
||||||
|
opendmarc_socket_dir="${postfix_spool_dir}/opendmarc"
|
||||||
|
opendmarc_socket_file="${opendmarc_socket_dir}/opendmarc.sock"
|
||||||
|
|
||||||
|
config_file_name_value_parameters="
|
||||||
|
AuthservID|$(hostname -f)
|
||||||
|
TrustedAuthservIDs|$(hostname -f)
|
||||||
|
PidFile|/run/opendmarc/opendmarc.pid
|
||||||
|
RejectFailures|true
|
||||||
|
Syslog|true
|
||||||
|
SyslogFacility|mail
|
||||||
|
IgnoreHosts|${opendmarc_base_dir}/ignore.hosts
|
||||||
|
IgnoreMailFrom|${opendmarc_base_dir}/ignore.mailfrom
|
||||||
|
IgnoreAuthenticatedClients|true
|
||||||
|
RequiredHeaders|false
|
||||||
|
UMask|002
|
||||||
|
FailureReports|false
|
||||||
|
AutoRestart|true
|
||||||
|
HistoryFile|/run/opendmarc/opendmarc.dat
|
||||||
|
SPFIgnoreResults|false
|
||||||
|
SPFSelfValidate|true
|
||||||
|
Socket|${opendmarc_socket_file}
|
||||||
|
"
|
||||||
|
declare -a config_file_name_value_parameter_arr=()
|
||||||
|
for _conf in $config_file_name_value_parameters ; do
|
||||||
|
config_file_name_value_parameter_arr+=("$_conf")
|
||||||
|
done
|
||||||
|
|
||||||
|
postfix_needs_restart=false
|
||||||
|
opendmarc_needs_restart=false
|
||||||
|
|
||||||
|
backup_date="$(date +%Y-%m-%d-%H%M)"
|
||||||
|
log_file="$(mktemp)"
|
||||||
|
|
||||||
|
# -------------
|
||||||
|
# --- Some functions
|
||||||
|
# -------------
|
||||||
|
echononl(){
|
||||||
|
echo X\\c > /tmp/shprompt$$
|
||||||
|
if [ `wc -c /tmp/shprompt$$ | awk '{print $1}'` -eq 1 ]; then
|
||||||
|
echo -e -n "$*\\c" 1>&2
|
||||||
|
else
|
||||||
|
echo -e -n "$*" 1>&2
|
||||||
|
fi
|
||||||
|
rm /tmp/shprompt$$
|
||||||
|
}
|
||||||
|
|
||||||
|
fatal(){
|
||||||
|
echo ""
|
||||||
|
echo -e "fatal error: $*"
|
||||||
|
echo ""
|
||||||
|
echo -e "\t\033[31m\033[1mInstalllation will be interrupted\033[m\033[m"
|
||||||
|
echo ""
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
error(){
|
||||||
|
echo ""
|
||||||
|
echo -e "\t[ \033[31m\033[1mFehler\033[m ]: $*"
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
warn (){
|
||||||
|
echo ""
|
||||||
|
echo -e "\t[ \033[33m\033[1mWarning\033[m ]: $*"
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
info (){
|
||||||
|
echo ""
|
||||||
|
echo -e "\t[ \033[32m\033[1mInfo\033[m ]: $*"
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
echo_done() {
|
||||||
|
echo -e "\033[80G[ \033[32mdone\033[m ]"
|
||||||
|
}
|
||||||
|
echo_ok() {
|
||||||
|
echo -e "\033[80G[ \033[32mok\033[m ]"
|
||||||
|
}
|
||||||
|
echo_warning() {
|
||||||
|
echo -e "\033[80G[ \033[33m\033[1mwarn\033[m ]"
|
||||||
|
}
|
||||||
|
echo_failed(){
|
||||||
|
echo -e "\033[80G[ \033[1;31mfailed\033[m ]"
|
||||||
|
}
|
||||||
|
echo_skipped() {
|
||||||
|
echo -e "\033[80G[ \033[37mskipped\033[m ]"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# -------------
|
||||||
|
# - Some pre-installation tasks
|
||||||
|
# -------------
|
||||||
|
|
||||||
|
# - Is 'systemd' supported on this system
|
||||||
|
# -
|
||||||
|
SYSTEMD_EXISTS=false
|
||||||
|
systemd=$(which systemd)
|
||||||
|
systemctl=$(which systemctl)
|
||||||
|
|
||||||
|
if [[ -n "$systemd" ]] || [[ -n "$systemctl" ]] ; then
|
||||||
|
SYSTEMD_EXISTS=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# =============
|
||||||
|
# - Start Installation
|
||||||
|
# =============
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# - Synchronise package index files with the repository
|
||||||
|
# -
|
||||||
|
echononl " Synchronise package index files with the repository.."
|
||||||
|
apt-get update > "$log_file" 2>&1
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# - Install opendmarc
|
||||||
|
# -
|
||||||
|
echononl " Install needed debian packages.."
|
||||||
|
opendmarc_packages=""
|
||||||
|
packages_installed=false
|
||||||
|
for _pkg in $_opendmarc_packages ; do
|
||||||
|
if aptitude search "$_pkg" | grep " $_pkg " | grep -e "^i" > /dev/null 2>&1 ; then
|
||||||
|
continue
|
||||||
|
else
|
||||||
|
opendmarc_packages="$opendmarc_packages $_pkg"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [[ -n "$opendmarc_packages" ]]; then
|
||||||
|
DEBIAN_FRONTEND=noninteractive apt-get -y install $opendmarc_packages > /dev/null 2> "$log_file"
|
||||||
|
packages_installed=true
|
||||||
|
opendmarc_needs_restart=true
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# - Add user 'postfix' to group 'opendmarc'
|
||||||
|
# -
|
||||||
|
echononl " Add user 'postfix' to group 'opendmarc'.."
|
||||||
|
if grep -E "^opendmarc" /etc/group | grep -q postfix 2> /dev/null ; then
|
||||||
|
echo_skipped
|
||||||
|
else
|
||||||
|
usermod -a -G opendmarc postfix > "$log_file" 2>&1
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# - Add 'IgnoreHosts' with default value to the original opendmarc.conf file
|
||||||
|
#
|
||||||
|
echononl " Add 'IgnoreHosts' with default value to the opendmarc.conf file.."
|
||||||
|
if ! $(grep -q -E "^IgnoreHosts\s+" ${opendmarc_conf_file} 2> /dev/null) ; then
|
||||||
|
cat << EOF >> ${opendmarc_conf_file}
|
||||||
|
|
||||||
|
## Specifies the path to a file that contains a list of hostnames, IP addresses,
|
||||||
|
## and/or CIDR expressions identifying hosts whose SMTP connections are to be
|
||||||
|
## ignored by the filter. If not specified, defaults to "127.0.0.1" only.
|
||||||
|
#
|
||||||
|
IgnoreHosts 127.0.0.1
|
||||||
|
|
||||||
|
# Optional - auch nach Absender-Domain ignorieren:
|
||||||
|
IgnoreMailFrom ${opendmarc_base_dir}/ignore.mailfrom
|
||||||
|
EOF
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# - Add 'IgnoreAuthenticatedClients' with default value to the original opendmarc.conf file
|
||||||
|
#
|
||||||
|
_param="IgnoreAuthenticatedClients"
|
||||||
|
echononl " Add '${_param}' with default value to the opendmarc.conf file.."
|
||||||
|
if ! $(grep -q -E "^${_param}\s+" ${opendmarc_conf_file} 2> /dev/null) ; then
|
||||||
|
cat << EOF >> ${opendmarc_conf_file}
|
||||||
|
|
||||||
|
## If set, causes mail from authenticated clients (i.e., those that used
|
||||||
|
## SMTP AUTH) to be ignored by the filter. The default is "false".
|
||||||
|
#
|
||||||
|
IgnoreAuthenticatedClients false
|
||||||
|
EOF
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# - Add 'TrustedAuthservIDs' with default value to the original opendmarc.conf file
|
||||||
|
#
|
||||||
|
_param="TrustedAuthservIDs"
|
||||||
|
echononl " Add '${_param}' with default value to the opendmarc.conf file.."
|
||||||
|
if ! $(grep -q -E "^${_param}\s+" ${opendmarc_conf_file} 2> /dev/null) ; then
|
||||||
|
cat << EOF >> ${opendmarc_conf_file}
|
||||||
|
|
||||||
|
# Provides a list of authserv-ids that are to be used to identify Authentication-Results
|
||||||
|
# header fields whose contents are to be assumed as valid input for the DMARC assessment.
|
||||||
|
# To provide a list, separate values by commas. If the string "HOSTNAME" is provided,
|
||||||
|
# the name of the host running the filter (as returned by the gethostname(3) function)
|
||||||
|
# will be used. Matching against this list is case-insensitive. The default is to use the
|
||||||
|
# value of AuthservID.
|
||||||
|
#
|
||||||
|
TrustedAuthservIDs OpenDMARC
|
||||||
|
EOF
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# - Add 'RequiredHeaders' with default value to the original opendmarc.conf file
|
||||||
|
#
|
||||||
|
_param="IgnoreAuthenticatedClients"
|
||||||
|
echononl " Add '${_param}' with default value to the opendmarc.conf file.."
|
||||||
|
if ! $(grep -q -E "^${_param}\s+" ${opendmarc_conf_file} 2> /dev/null) ; then
|
||||||
|
cat << EOF >> ${opendmarc_conf_file}
|
||||||
|
|
||||||
|
## If set, causes mail from authenticated clients (i.e., those that used
|
||||||
|
## SMTP AUTH) to be ignored by the filter. The default is "false".
|
||||||
|
#
|
||||||
|
IgnoreAuthenticatedClients false
|
||||||
|
EOF
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# - Add 'RequiredHeaders' with default value to the original opendmarc.conf file
|
||||||
|
#
|
||||||
|
_param="RequiredHeaders"
|
||||||
|
echononl " Add '${_param}' with default value to the opendmarc.conf file.."
|
||||||
|
if ! $(grep -q -E "^${_param}\s+" ${opendmarc_conf_file} 2> /dev/null) ; then
|
||||||
|
cat << EOF >> ${opendmarc_conf_file}
|
||||||
|
|
||||||
|
## If set, the filter will ensure the header of the message conforms to the basic
|
||||||
|
## header field count restrictions laid out in RFC5322, Section 3.6. Messages
|
||||||
|
## failing this test are rejected without further processing. A From: field from
|
||||||
|
## which no domain name could be extracted will also be rejected.
|
||||||
|
#
|
||||||
|
RequiredHeaders false
|
||||||
|
EOF
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# - Add 'AutoRestart' with default value to the original opendmarc.conf file
|
||||||
|
#
|
||||||
|
_param="AutoRestart"
|
||||||
|
echononl " Add '${_param}' with default value to the opendmarc.conf file.."
|
||||||
|
if ! $(grep -q -E "^${_param}\s+" ${opendmarc_conf_file} 2> /dev/null) ; then
|
||||||
|
cat << EOF >> ${opendmarc_conf_file}
|
||||||
|
|
||||||
|
## Automatically re-start on failures. Use with caution; if the filter fails
|
||||||
|
## instantly after it starts, this can cause a tight fork(2) loop.
|
||||||
|
#
|
||||||
|
AutoRestart false
|
||||||
|
EOF
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# - Add 'HistoryFile' with default value to the original opendmarc.conf file
|
||||||
|
#
|
||||||
|
_param="HistoryFile"
|
||||||
|
echononl " Add '${_param}' with default value to the opendmarc.conf file.."
|
||||||
|
if ! $(grep -q -E "^${_param}\s+" ${opendmarc_conf_file} 2> /dev/null) ; then
|
||||||
|
cat << EOF >> ${opendmarc_conf_file}
|
||||||
|
|
||||||
|
## If set, specifies the location of a text file to which records are written
|
||||||
|
## that can be used to generate DMARC aggregate reports. Records are batches of
|
||||||
|
## rows containing information about a single received message, and include all
|
||||||
|
## relevant information needed to generate a DMARC aggregate report. It is
|
||||||
|
## expected that this will not be used in its raw form, but rather periodically
|
||||||
|
## imported into a relational database from which the aggregate reports can be
|
||||||
|
## extracted using opendmarc-importstats(8).
|
||||||
|
#
|
||||||
|
HistoryFile /run/opendmarc/opendmarc.dat
|
||||||
|
EOF
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# - Add 'SPFIgnoreResults' with default value to the original opendmarc.conf file
|
||||||
|
#
|
||||||
|
_param="SPFIgnoreResults"
|
||||||
|
echononl " Add '${_param}' with default value to the opendmarc.conf file.."
|
||||||
|
if ! $(grep -q -E "^${_param}\s+" ${opendmarc_conf_file} 2> /dev/null) ; then
|
||||||
|
cat << EOF >> ${opendmarc_conf_file}
|
||||||
|
|
||||||
|
## Causes the filter to ignore any SPF results in the header of the message. This
|
||||||
|
## is useful if you want the filter to perform SPF checks itself, or because you
|
||||||
|
## don't trust the arriving header. The default is "false".
|
||||||
|
#
|
||||||
|
SPFIgnoreResults false
|
||||||
|
EOF
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# - Add 'SPFSelfValidate' with default value to the original opendmarc.conf file
|
||||||
|
#
|
||||||
|
_param="SPFSelfValidate"
|
||||||
|
echononl " Add '${_param}' with default value to the opendmarc.conf file.."
|
||||||
|
if ! $(grep -q -E "^${_param}\s+" ${opendmarc_conf_file} 2> /dev/null) ; then
|
||||||
|
cat << EOF >> ${opendmarc_conf_file}
|
||||||
|
|
||||||
|
## Causes the filter to perform a fallback SPF check itself when it can find no
|
||||||
|
## SPF results in the message header. If SPFIgnoreResults is also set, it never
|
||||||
|
## looks for SPF results in headers and always performs the SPF check itself when
|
||||||
|
## this is set. The default is "false".
|
||||||
|
#
|
||||||
|
SPFSelfValidate false
|
||||||
|
EOF
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# - Save configuration file from distribution
|
||||||
|
# -
|
||||||
|
echononl " Save configuration file from distribution"
|
||||||
|
if [[ -f "${opendmarc_conf_file}.ORIG" ]] ; then
|
||||||
|
echo_skipped
|
||||||
|
else
|
||||||
|
cp -a $opendmarc_conf_file $opendmarc_conf_file.ORIG 2> "$log_file"
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
for _val in "${config_file_name_value_parameter_arr[@]}" ; do
|
||||||
|
IFS='|' read -a _val_arr <<< "${_val}"
|
||||||
|
|
||||||
|
echononl " $opendmarc_conf_file: ${_val_arr[0]} -> ${_val_arr[1]}.."
|
||||||
|
if $(grep -E -q "^\s*${_val_arr[0]}\s+${_val_arr[1]}\s*$" $opendmarc_conf_file 2> /dev/null) ; then
|
||||||
|
echo_skipped
|
||||||
|
elif $(grep -E -q "^\s*#\s*${_val_arr[0]}\s+" $opendmarc_conf_file 2> /dev/null); then
|
||||||
|
perl -i -n -p -e "s&^(\s*#\s*${_val_arr[0]}.*)&\1\n${_val_arr[0]} ${_val_arr[1]}&" $opendmarc_conf_file > "$log_file" 2>&1
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
opendmarc_needs_restart=true
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
elif $(grep -E -q "^\s*${_val_arr[0]}\s+" $opendmarc_conf_file 2> /dev/null) ; then
|
||||||
|
perl -i -n -p -e "s#^(\s*${_val_arr[0]}.*)#\#\1\n${_val_arr[0]} ${_val_arr[1]}#" $opendmarc_conf_file > "$log_file" 2>&1
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
opendmarc_needs_restart=true
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
cat <<EOF >> $opendmarc_conf_file 2> "$log_file"
|
||||||
|
|
||||||
|
${_val_arr[0]} ${_val_arr[1]}
|
||||||
|
EOF
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
opendmarc_needs_restart=true
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
|
# - Assign ownership to the opendmarc user and restrict tthe
|
||||||
|
# - file permissions:
|
||||||
|
# -
|
||||||
|
echononl " Assign file permissions to '$opendmarc_conf_file'.."
|
||||||
|
chmod u=rw,go=r $opendmarc_conf_file 2> $log_file
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# - Create the directories to hold opendmarc's data files, assign
|
||||||
|
# - ownership to the opendmarc user, and restrict the file
|
||||||
|
# - permissions:
|
||||||
|
# -
|
||||||
|
echononl " Create directory '$opendmarc_base_dir'"
|
||||||
|
if [[ -d "$opendmarc_base_dir" ]] ; then
|
||||||
|
echo_skipped
|
||||||
|
else
|
||||||
|
opendmarc_needs_restart=true
|
||||||
|
mkdir ${opendmarc_base_dir} 2> $log_file
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echononl " Set ownership on directory '${opendmarc_base_dir}' (recursive).."
|
||||||
|
chown -R opendmarc:opendmarc ${opendmarc_base_dir} 2> $log_file
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
echononl " Backup existing file '${opendmarc_base_dir}/ignore.hosts'.."
|
||||||
|
if [[ -f "${opendmarc_base_dir}/ignore.hosts" ]] ; then
|
||||||
|
mv "${opendmarc_base_dir}/ignore.hosts" "${opendmarc_base_dir}/ignore.hosts.${backup_date}"
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
fi
|
||||||
|
|
||||||
|
# - Create the file ${opendmarc_base_dir}/ignore.hosts
|
||||||
|
# -
|
||||||
|
echononl " Create file '${opendmarc_base_dir}/ignore.hosts'.."
|
||||||
|
if [[ -f "${opendmarc_base_dir}/ignore.hosts" ]] ; then
|
||||||
|
echo_skipped
|
||||||
|
else
|
||||||
|
cat <<EOF > ${opendmarc_base_dir}/ignore.hosts 2> $log_file
|
||||||
|
# /etc/opendmarc/ignore.hosts
|
||||||
|
#
|
||||||
|
# Aktuell hat OpenDMARC seinen Milter nur am Dienst
|
||||||
|
# 'localhost:10025' hängen. Dort ist der Client
|
||||||
|
# immer 127.0.0.1, nicht die externe Gegenstelle.
|
||||||
|
#
|
||||||
|
# Deshalb macht es in diesem Setup keinen Sinn,
|
||||||
|
# hier IP-Adressen von externen Diensten (CRSend etc.)
|
||||||
|
# einzutragen – sie würden nie matchen.
|
||||||
|
#
|
||||||
|
# WICHTIG:
|
||||||
|
# - KEIN 127.0.0.1
|
||||||
|
# - KEIN localhost
|
||||||
|
# - KEIN ::1
|
||||||
|
#
|
||||||
|
# Eintrag dieser Adressen würde DMARC komplett deaktivieren.
|
||||||
|
#
|
||||||
|
# ==> Datei bleibt absichtlich leer.
|
||||||
|
EOF
|
||||||
|
opendmarc_needs_restart=true
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# - Create the file ${opendmarc_base_dir}/ignore.hosts
|
||||||
|
# -
|
||||||
|
|
||||||
|
echononl " Backup existing file '${opendmarc_base_dir}/ignore.mailfrom'.."
|
||||||
|
if [[ -f "${opendmarc_base_dir}/ignore.mailfrom" ]] ; then
|
||||||
|
mv "${opendmarc_base_dir}/ignore.mailfrom" "${opendmarc_base_dir}/ignore.mailfrom.${backup_date}"
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
fi
|
||||||
|
|
||||||
|
echononl " Create file '${opendmarc_base_dir}/ignore.mailfrom'.."
|
||||||
|
if [[ -f "${opendmarc_base_dir}/ignore.mailfrom" ]] ; then
|
||||||
|
echo_skipped
|
||||||
|
else
|
||||||
|
cat <<EOF > ${opendmarc_base_dir}/ignore.mailfrom 2> $log_file
|
||||||
|
# /etc/opendmarc/ignore.mailfrom
|
||||||
|
#
|
||||||
|
# Hier könnte man Absender-Domains von der DMARC-Prüfung
|
||||||
|
# ausnehmen (z. B. problematische Partner-Domains).
|
||||||
|
#
|
||||||
|
# Aktuell ist das für dein Setup nicht notwendig.
|
||||||
|
#
|
||||||
|
# Beispiele (NICHT aktiv!):
|
||||||
|
# @example.org
|
||||||
|
# example.org
|
||||||
|
#
|
||||||
|
# ==> Datei bleibt absichtlich leer.
|
||||||
|
EOF
|
||||||
|
opendmarc_needs_restart=true
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# - Edit /etc/default/opendmarc
|
||||||
|
# -
|
||||||
|
# - Set:
|
||||||
|
# - SOCKET="local:${postfix_spool_dir}/opendmarc/opendmarc.sock"
|
||||||
|
# -
|
||||||
|
echononl " Set 'SOCKET' at file /etc/default/opendmarc.."
|
||||||
|
if grep -q -E "^\s*SOCKET" /etc/default/opendmarc 2>/dev/null ; then
|
||||||
|
if grep -q -E "^\s*SOCKET\s*=\s*\"*local:$opendmarc_socket_file" /etc/default/opendmarc 2>/dev/null ; then
|
||||||
|
echo_skipped
|
||||||
|
else
|
||||||
|
perl -i -n -p -e "s#^\s*SOCKET=.*#SOCKET=\"local:$opendmarc_socket_file\"#" /etc/default/opendmarc 2> $log_file
|
||||||
|
opendmarc_needs_restart=true
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
cat <<EOF >>/etc/default/opendmarc 2> $log_file
|
||||||
|
SOCKET="local:$opendmarc_socket_file"
|
||||||
|
EOF
|
||||||
|
opendmarc_needs_restart=true
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# - Create the opendmarc socket directory in Postfix’s work area
|
||||||
|
# - and make sure it has the correct ownership:
|
||||||
|
# -
|
||||||
|
echononl " Create the opendmarc socket directory in Postfix's work area.."
|
||||||
|
if [[ -d "${postfix_spool_dir}/opendmarc" ]] ; then
|
||||||
|
echo_skipped
|
||||||
|
else
|
||||||
|
mkdir ${postfix_spool_dir}/opendmarc 2> $log_file
|
||||||
|
opendmarc_needs_restart=true
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
echononl " Set ownership on directory '${postfix_spool_dir}/opendmarc'.."
|
||||||
|
chown opendmarc:postfix ${postfix_spool_dir}/opendmarc 2> $log_file
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# - Edit /etc/postfix/main.cf and add a section to activate
|
||||||
|
# - processing of e-mail through the opendmarc daemon:
|
||||||
|
# -
|
||||||
|
echononl " Backup existing postfix configuration (main.cf).."
|
||||||
|
cp -a /etc/postfix/main.cf /etc/postfix/main.cf.$backup_date 2> $log_file
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echononl " Set Variable non_smtpd_milters at '/etc/postfix/main.cf'.."
|
||||||
|
if $(grep -q -E "^\s*non_smtpd_milters\s*=\s*.*opendkim.sock" /etc/postfix/main.cf 2> /dev/null) ; then
|
||||||
|
if $(grep -q -E "^\s*non_smtpd_milters\s*=\s*.*$(basename "${opendmarc_socket_file}")" /etc/postfix/main.cf); then
|
||||||
|
echo_skipped
|
||||||
|
else
|
||||||
|
perl -i -n -p -e "s&^\s*(non_smtpd_milters\s*=.*opendkim.sock)&\1,local:/$(basename "${opendmarc_socket_dir}")/$(basename "${opendmarc_socket_file}")&" \
|
||||||
|
/etc/postfix/main.cf > $log_file 2>&1
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
postfix_needs_restart=true
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
warn "Postfix is not adjusted. Complete Postfix configuration (main.cf) manually\!"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
|
||||||
|
# - Edit /etc/postfix/main.cf and add a section to activate
|
||||||
|
# - processing of e-mail through the OpenDKIM daemon:
|
||||||
|
# -
|
||||||
|
backup_date="$(date +%Y-%m-%d-%H%M)"
|
||||||
|
echononl " Backup existing postfix configuration (main.cf).."
|
||||||
|
cp -a /etc/postfix/main.cf /etc/postfix/main.cf.$backup_date 2> $log_file
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echononl " Activate processing of e-mail through the OpenDKIM daemon.."
|
||||||
|
if grep -q -E "milter_default_action\s*=\s*accept" /etc/postfix/main.cf ; then
|
||||||
|
echo_skipped
|
||||||
|
info "Postfix (main.cf) was not changed - seems already be configured right."
|
||||||
|
echononl " Delete previosly saved Postfix configuration.."
|
||||||
|
rm /etc/postfix/main.cf.$backup_date 2> $log_file
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
cat <<EOF >> /etc/postfix/main.cf 2> $log_file
|
||||||
|
|
||||||
|
# ======= Milter configuration =======
|
||||||
|
|
||||||
|
# OpenDKIM
|
||||||
|
|
||||||
|
milter_default_action = accept
|
||||||
|
|
||||||
|
# Postfix ≥ 2.6 milter_protocol = 6, Postfix ≤ 2.5 milter_protocol = 2
|
||||||
|
milter_protocol = 6
|
||||||
|
|
||||||
|
# Note:
|
||||||
|
# We will sign AFTER sending through AmaVIS, just befor sending out. So
|
||||||
|
# set 'smtpd_milters =' to an emty string here and add to localhost:10025
|
||||||
|
# section in master.cf: 'smtpd_milters=local:/opendkim/opendkim.sock'
|
||||||
|
#
|
||||||
|
# If you want sign mails before sending through AmaVIS, set
|
||||||
|
# 'smtpd_milters = local:/opendkim/opendkim.sock' here and add to
|
||||||
|
# localhost:10025 section in master.cf: 'smtpd_milters='
|
||||||
|
#
|
||||||
|
#smtpd_milters = local:/opendkim/opendkim.sock
|
||||||
|
smtpd_milters =
|
||||||
|
|
||||||
|
# Was sind non_smtpd_milters?
|
||||||
|
#
|
||||||
|
# non_smtpd_milters gilt für alle Postfix-Prozesse, die Mails verarbeiten, aber NICHT
|
||||||
|
# der smtpd-Daemon sind.
|
||||||
|
#
|
||||||
|
# Das betrifft z. B.:
|
||||||
|
#
|
||||||
|
# cleanup Header/Content-Bereinigung
|
||||||
|
# qmgr Queue-Manager
|
||||||
|
# lmtp / smtp Auslieferung nach extern
|
||||||
|
# local lokale Zustellung
|
||||||
|
#
|
||||||
|
# Das sind z. B.:
|
||||||
|
#
|
||||||
|
# - interne Bounces (MAILER-DAEMON)
|
||||||
|
#
|
||||||
|
# - Cron-Mails vom Server
|
||||||
|
#
|
||||||
|
# - Weiterleitungen, die Postfix selbst generiert
|
||||||
|
#
|
||||||
|
# - Mails, die über sendmail CLI gesendet werden
|
||||||
|
#
|
||||||
|
# - Mails, die Amavis über LMTP zurückgibt
|
||||||
|
#
|
||||||
|
# - etc.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# DKIM soll auch die ausgehenden Mails signieren, die nicht über smtpd daemon versendet werden.
|
||||||
|
non_smtpd_milters = local:/opendkim/opendkim.sock
|
||||||
|
EOF
|
||||||
|
postfix_needs_restart=true
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
|
||||||
|
# - Prevent Postfix from setting the DMARC Header twice (one befor
|
||||||
|
# - and one after processing amavis
|
||||||
|
# -
|
||||||
|
# - To disable milter processing after amavis, add to your master.cf in
|
||||||
|
# - the after-amavis section:
|
||||||
|
# - 127.0.0.1:10025 inet n - - - - smtpd
|
||||||
|
# - [...]
|
||||||
|
# - -o smtpd_milters=
|
||||||
|
# -
|
||||||
|
# - If you want to run the milter after amavis, set in main.cf
|
||||||
|
# - smtpd_milters=
|
||||||
|
# - to an empty string and add the smtpd_milters configuration to master.cf
|
||||||
|
# - (after-section amavis) instead:
|
||||||
|
# - -o smtpd_milters=local:/opendmarc/opendmarc.sock
|
||||||
|
# -
|
||||||
|
echononl " Backup file '/etc/postfix/master.cf'.."
|
||||||
|
cp -a /etc/postfix/master.cf /etc/postfix/master.cf.${backup_date} 2> $log_file
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echononl " Adjust /etc/postfix/master.cf. Set DMARC after sending throuh AmaVIS.."
|
||||||
|
_found=false
|
||||||
|
_changed=false
|
||||||
|
tmp_master_file="/tmp/postfix_master.cf"
|
||||||
|
> $tmp_master_file
|
||||||
|
while IFS='' read -r _line || [[ -n $_line ]] ; do
|
||||||
|
|
||||||
|
if $_found && ! echo "$_line" | grep -i -q -E "^\s*-o" 2> /dev/null ; then
|
||||||
|
echo " -o smtpd_milters=local:/opendmarc/opendmarc.sock" >> "$tmp_master_file"
|
||||||
|
_changed=true
|
||||||
|
_found=false
|
||||||
|
fi
|
||||||
|
|
||||||
|
if $_found && echo "$_line" | grep -i -q -E "^\s*-o\s+smtpd_milters=\s*" ; then
|
||||||
|
_found=false
|
||||||
|
if ! echo "$_line" | grep -i -q -E "^\s*-o\s+smtpd_milters=\s*local:/opendmarc/opendmarc.sock\s*$" ; then
|
||||||
|
echo " -o smtpd_milters=local:/opendmarc/opendmarc.sock" >> "$tmp_master_file"
|
||||||
|
_changed=true
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
if echo "$_line" | grep -i -q -E "^\s*(localhost|127.0.0.1):10025\s+inet\s+" 2> /dev/null ; then
|
||||||
|
_found=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$_line" >> "$tmp_master_file"
|
||||||
|
|
||||||
|
done < "/etc/postfix/master.cf"
|
||||||
|
|
||||||
|
if $_changed ; then
|
||||||
|
cp $tmp_master_file /etc/postfix/master.cf 2> $log_file
|
||||||
|
postfix_needs_restart=true
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
info "Postfix (master.cf) was not changed - seems already be configured right."
|
||||||
|
echononl " Delete previosly saved file '/etc/postfix/master.cf'.."
|
||||||
|
rm /etc/postfix/master.cf.$backup_date 2> $log_file
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
rm -f $tmp_master_file
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echononl " Enable OpenDMARC Service"
|
||||||
|
if $SYSTEMD_EXISTS ; then
|
||||||
|
systemctl enable opendmarc > $log_file 2>&1
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
warn "Maybe OpenDMARC Service is not enabled, because its an old non-systemd os.."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# - Restart opendmarc
|
||||||
|
# -
|
||||||
|
echononl " Restart opendmarc.."
|
||||||
|
if $opendmarc_needs_restart ; then
|
||||||
|
if $SYSTEMD_EXISTS ; then
|
||||||
|
systemctl restart opendmarc > $log_file 2>&1
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
/etc/init.d/opendmarc restart > $log_file 2>&1
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# - Restart Postfix so it starts using opendmarc when processing mail:
|
||||||
|
# -
|
||||||
|
echononl " Restart Postfix.."
|
||||||
|
if $postfix_needs_restart ; then
|
||||||
|
if $SYSTEMD_EXISTS ; then
|
||||||
|
systemctl restart postfix > $log_file 2>&1
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
/etc/init.d/postfix restart > $log_file 2>&1
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
rm -f "$log_file"
|
||||||
|
exit 0
|
||||||
4554
BAK/install_update_dovecot.sh.00
Executable file
4554
BAK/install_update_dovecot.sh.00
Executable file
File diff suppressed because it is too large
Load Diff
14
DOC/DMARC-Report/daily-run.sh
Executable file
14
DOC/DMARC-Report/daily-run.sh
Executable file
@@ -0,0 +1,14 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
BASE="/var/lib/dmarc"
|
||||||
|
TODAY_DIR="$BASE/reports/$(date -u +%Y/%m/%d)"
|
||||||
|
OUTDIR="$BASE/exports"
|
||||||
|
CSV="$OUTDIR/records.csv"
|
||||||
|
LOGF="$BASE/logs/scan-$(date -u +%F).log"
|
||||||
|
|
||||||
|
mkdir -p "$OUTDIR"
|
||||||
|
|
||||||
|
if [[ -d "$TODAY_DIR" ]]; then
|
||||||
|
/usr/local/bin/dmarc-scan.sh "$TODAY_DIR" --domain fluechtlingsrat-brandenburg.de --csv "$CSV" --append --top 25 --outdir "$OUTDIR" >> "$LOGF" 2>&1
|
||||||
|
fi
|
||||||
47
DOC/DMARC-Report/dmarc-collect.sh
Executable file
47
DOC/DMARC-Report/dmarc-collect.sh
Executable file
@@ -0,0 +1,47 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
BASE="/var/lib/dmarc"
|
||||||
|
INBOX="$BASE/reports"
|
||||||
|
PROC="$BASE/processed"
|
||||||
|
LOGF="$BASE/logs/collector.log"
|
||||||
|
|
||||||
|
umask 027
|
||||||
|
|
||||||
|
TMPDIR="$(mktemp -d)"
|
||||||
|
EML="$TMPDIR/mail.eml"
|
||||||
|
cat > "$EML"
|
||||||
|
|
||||||
|
ripmime --no-nameless --name-by-type --overwrite -i "$EML" -d "$TMPDIR" >>"$LOGF" 2>&1 || true
|
||||||
|
|
||||||
|
TODAY="$(date -u +%Y/%m/%d)"
|
||||||
|
OUTDIR="$INBOX/$TODAY"
|
||||||
|
mkdir -p "$OUTDIR"
|
||||||
|
|
||||||
|
moved=0
|
||||||
|
shopt -s nullglob
|
||||||
|
for f in "$TMPDIR"/*; do
|
||||||
|
case "$f" in
|
||||||
|
*.xml|*.XML|*.gz|*.zip)
|
||||||
|
sha="$(sha256sum "$f" | awk '{print $1}')"
|
||||||
|
base="$(basename "$f")"
|
||||||
|
dst="$OUTDIR/$(date -u +%Y%m%dT%H%M%SZ)_${sha:0:12}_$base"
|
||||||
|
mv "$f" "$dst"
|
||||||
|
echo "$(date -Is) stored $dst" >> "$LOGF"
|
||||||
|
moved=$((moved+1))
|
||||||
|
;;
|
||||||
|
*) : ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
mkdir -p "$PROC"
|
||||||
|
mv "$EML" "$PROC/$(date -u +%Y%m%dT%H%M%SZ)_mail.eml" || true
|
||||||
|
rm -rf "$TMPDIR"
|
||||||
|
|
||||||
|
if (( moved > 0 )); then
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
echo "$(date -Is) no usable attachment in message" >> "$LOGF"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
382
DOC/DMARC-Report/dmarc-scan-setup.md
Normal file
382
DOC/DMARC-Report/dmarc-scan-setup.md
Normal file
@@ -0,0 +1,382 @@
|
|||||||
|
|
||||||
|
# DMARC-Auswertungsskript `dmarc-scan.sh` – Installation, Beschreibung & Verwendung
|
||||||
|
|
||||||
|
## 📖 Zweck
|
||||||
|
|
||||||
|
`dmarc-scan.sh` analysiert DMARC-Aggregatberichte (XML, .zip, .gz) und erzeugt:
|
||||||
|
- gut lesbare Tabellen im Terminal,
|
||||||
|
- eine fortschreibbare Records-CSV (`--append`),
|
||||||
|
- Top-Listen nach IPs (gesamt und je Fail-Kategorie) als CSV.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚙️ Installation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apt install -y xmlstarlet unzip gzip
|
||||||
|
sudo tee /usr/local/bin/dmarc-scan.sh >/dev/null <<'EOF'
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
#
|
||||||
|
# dmarc-scan.sh — DMARC-XML-Reports (auch .gz/.zip) einlesen, tabellarisch anzeigen,
|
||||||
|
# Records als CSV exportieren (append optional), Top-IPs ermitteln
|
||||||
|
# und Top-Listen als CSV schreiben.
|
||||||
|
#
|
||||||
|
# Nutzung:
|
||||||
|
# ./dmarc-scan.sh /pfad/zu/reports \
|
||||||
|
# [--domain DOMAIN] \
|
||||||
|
# [--csv pfad/zur/records.csv] \
|
||||||
|
# [--append] \
|
||||||
|
# [--top N] \
|
||||||
|
# [--outdir pfad/zum/ordner]
|
||||||
|
#
|
||||||
|
# Beispiele:
|
||||||
|
# ./dmarc-scan.sh /var/mail/dmarc
|
||||||
|
# ./dmarc-scan.sh /var/mail/dmarc --domain fluechtlingsrat-brandenburg.de --csv dmarc.csv --append --top 15 --outdir ./export
|
||||||
|
#
|
||||||
|
# Voraussetzungen: xmlstarlet, unzip (für .zip), gzip (für .gz)
|
||||||
|
# Debian/Ubuntu: sudo apt-get install xmlstarlet unzip gzip
|
||||||
|
#
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
REPORT_DIR="${1:-}"
|
||||||
|
shift || true
|
||||||
|
|
||||||
|
# Defaults
|
||||||
|
WANT_DOMAIN=""
|
||||||
|
CSV_PATH="./dmarc-summary.csv"
|
||||||
|
APPEND=0
|
||||||
|
TOP_N=10
|
||||||
|
OUTDIR="."
|
||||||
|
|
||||||
|
# Arg-Parsing (einfach)
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "${1:-}" in
|
||||||
|
--domain)
|
||||||
|
WANT_DOMAIN="${2:-}"; shift 2 || true ;;
|
||||||
|
--csv)
|
||||||
|
CSV_PATH="${2:-}"; shift 2 || true ;;
|
||||||
|
--append)
|
||||||
|
APPEND=1; shift || true ;;
|
||||||
|
--top)
|
||||||
|
TOP_N="${2:-10}"; shift 2 || true ;;
|
||||||
|
--outdir)
|
||||||
|
OUTDIR="${2:-.}"; shift 2 || true ;;
|
||||||
|
*)
|
||||||
|
# Unbekannte Option ignorieren
|
||||||
|
shift || true ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ -z "$REPORT_DIR" || ! -d "$REPORT_DIR" ]]; then
|
||||||
|
echo "Fehler: Bitte ein Verzeichnis mit DMARC-Reports angeben."
|
||||||
|
echo "Beispiel: $0 /var/mail/dmarc --domain fluechtlingsrat-brandenburg.de --csv dmarc.csv --append --top 15 --outdir ./export"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! command -v xmlstarlet >/dev/null 2>&1; then
|
||||||
|
echo "Fehler: xmlstarlet nicht gefunden. Bitte installieren (z.B. 'sudo apt-get install xmlstarlet')."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "$OUTDIR"
|
||||||
|
|
||||||
|
# CSV-Header für Records; bei --append nur schreiben, wenn Datei noch nicht existiert
|
||||||
|
RECORDS_HEADER="report_org,policy_domain,begin_utc,end_utc,source_ip,count,disposition,spf,dkim,header_from"
|
||||||
|
ensure_records_header() {
|
||||||
|
if [[ "$APPEND" -eq 1 ]]; then
|
||||||
|
if [[ ! -f "$CSV_PATH" ]]; then
|
||||||
|
echo "$RECORDS_HEADER" > "$CSV_PATH"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "$RECORDS_HEADER" > "$CSV_PATH"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
ensure_records_header
|
||||||
|
|
||||||
|
# Zähler & Sets
|
||||||
|
declare -A SEEN_IPS=()
|
||||||
|
declare -A IP_COUNTS=() # Summe pro IP
|
||||||
|
declare -A SPF_ONLY_FAIL_IP=() # nur SPF fail pro IP
|
||||||
|
declare -A DKIM_ONLY_FAIL_IP=() # nur DKIM fail pro IP
|
||||||
|
declare -A BOTH_FAIL_IP=() # SPF+DKIM fail pro IP
|
||||||
|
|
||||||
|
total_msgs=0
|
||||||
|
pass_msgs=0
|
||||||
|
fail_msgs=0
|
||||||
|
spf_only_fail=0
|
||||||
|
dkim_only_fail=0
|
||||||
|
both_fail=0
|
||||||
|
|
||||||
|
# Hilfsfunktion: Epoch -> Datum (UTC)
|
||||||
|
epoch2date() {
|
||||||
|
local e="$1"
|
||||||
|
if [[ -z "$e" ]]; then printf "-"; return; fi
|
||||||
|
date -u -d @"$e" +"%Y-%m-%d %H:%M:%S UTC" 2>/dev/null || printf "%s" "$e"
|
||||||
|
}
|
||||||
|
|
||||||
|
# CSV-escape (Felder in Anführungszeichen, doppelte Anführungszeichen verdoppeln)
|
||||||
|
csv_escape() {
|
||||||
|
local s="${1:-}"
|
||||||
|
s="${s//\"/\"\"}"
|
||||||
|
printf "\"%s\"" "$s"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Eine einzelne XML-Datei parsen
|
||||||
|
parse_xml() {
|
||||||
|
local xml_input="$1"
|
||||||
|
|
||||||
|
# Domain aus policy_published, ggf. für Filter
|
||||||
|
local domain
|
||||||
|
domain=$(xmlstarlet sel -T -t -v "/feedback/policy_published/domain" "$xml_input" 2>/dev/null || true)
|
||||||
|
if [[ -n "$WANT_DOMAIN" && "$domain" != "$WANT_DOMAIN" ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
local org begin end pol sp aspf adkim
|
||||||
|
org=$(xmlstarlet sel -T -t -v "/feedback/report_metadata/org_name" "$xml_input" 2>/dev/null || printf "-")
|
||||||
|
begin=$(xmlstarlet sel -T -t -v "/feedback/report_metadata/date_range/begin" "$xml_input" 2>/dev/null || printf "")
|
||||||
|
end=$(xmlstarlet sel -T -t -v "/feedback/report_metadata/date_range/end" "$xml_input" 2>/dev/null || printf "")
|
||||||
|
pol=$(xmlstarlet sel -T -t -v "/feedback/policy_published/p" "$xml_input" 2>/dev/null || printf "-")
|
||||||
|
sp=$(xmlstarlet sel -T -t -v "/feedback/policy_published/sp" "$xml_input" 2>/dev/null || printf "-")
|
||||||
|
aspf=$(xmlstarlet sel -T -t -v "/feedback/policy_published/aspf" "$xml_input" 2>/dev/null || printf "-")
|
||||||
|
adkim=$(xmlstarlet sel -T -t -v "/feedback/policy_published/adkim" "$xml_input" 2>/dev/null || printf "-")
|
||||||
|
|
||||||
|
# Report-Header
|
||||||
|
echo "=============================================================================="
|
||||||
|
echo "Report von: ${org}"
|
||||||
|
echo "Domain (Policy): ${domain} (p=${pol}, sp=${sp}, aspf=${aspf}, adkim=${adkim})"
|
||||||
|
echo "Zeitraum: $(epoch2date "$begin") – $(epoch2date "$end")"
|
||||||
|
echo "------------------------------------------------------------------------------"
|
||||||
|
printf "%-16s %7s %-10s %-6s %-6s %s\n" "Source IP" "Count" "Disposition" "SPF" "DKIM" "Header-From"
|
||||||
|
echo "------------------------------------------------------------------------------"
|
||||||
|
|
||||||
|
# Alle <record>-Einträge tabellarisch ausgeben
|
||||||
|
while IFS='|' read -r ip cnt dispo spfres dkimres hfrom; do
|
||||||
|
[[ -z "$ip$cnt$dispo$spfres$dkimres$hfrom" ]] && continue
|
||||||
|
|
||||||
|
local n=0
|
||||||
|
if [[ -n "${cnt:-}" && "$cnt" =~ ^[0-9]+$ ]]; then n="$cnt"; fi
|
||||||
|
|
||||||
|
total_msgs=$(( total_msgs + n ))
|
||||||
|
[[ -n "$ip" ]] && SEEN_IPS["$ip"]=1
|
||||||
|
[[ -n "$ip" ]] && IP_COUNTS["$ip"]=$(( ${IP_COUNTS["$ip"]:-0} + n ))
|
||||||
|
|
||||||
|
if [[ "${spfres:-}" == "pass" && "${dkimres:-}" == "pass" ]]; then
|
||||||
|
pass_msgs=$(( pass_msgs + n ))
|
||||||
|
else
|
||||||
|
fail_msgs=$(( fail_msgs + n ))
|
||||||
|
if [[ "${spfres:-}" != "pass" && "${dkimres:-}" == "pass" ]]; then
|
||||||
|
spf_only_fail=$(( spf_only_fail + n ))
|
||||||
|
[[ -n "$ip" ]] && SPF_ONLY_FAIL_IP["$ip"]=$(( ${SPF_ONLY_FAIL_IP["$ip"]:-0} + n ))
|
||||||
|
elif [[ "${spfres:-}" == "pass" && "${dkimres:-}" != "pass" ]]; then
|
||||||
|
dkim_only_fail=$(( dkim_only_fail + n ))
|
||||||
|
[[ -n "$ip" ]] && DKIM_ONLY_FAIL_IP["$ip"]=$(( ${DKIM_ONLY_FAIL_IP["$ip"]:-0} + n ))
|
||||||
|
else
|
||||||
|
both_fail=$(( both_fail + n ))
|
||||||
|
[[ -n "$ip" ]] && BOTH_FAIL_IP["$ip"]=$(( ${BOTH_FAIL_IP["$ip"]:-0} + n ))
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf "%-16s %7s %-10s %-6s %-6s %s\n" "${ip:--}" "${n}" "${dispo:--}" "${spfres:--}" "${dkimres:--}" "${hfrom:--}"
|
||||||
|
|
||||||
|
local begin_human end_human
|
||||||
|
begin_human="$(epoch2date "$begin")"
|
||||||
|
end_human="$(epoch2date "$end")"
|
||||||
|
{
|
||||||
|
csv_escape "$org"; printf ","
|
||||||
|
csv_escape "$domain"; printf ","
|
||||||
|
csv_escape "$begin_human"; printf ","
|
||||||
|
csv_escape "$end_human"; printf ","
|
||||||
|
csv_escape "${ip:-}"; printf ","
|
||||||
|
printf "%s," "$n"
|
||||||
|
csv_escape "${dispo:-}"; printf ","
|
||||||
|
csv_escape "${spfres:-}"; printf ","
|
||||||
|
csv_escape "${dkimres:-}"; printf ","
|
||||||
|
csv_escape "${hfrom:-}"; printf "\n"
|
||||||
|
} >> "$CSV_PATH"
|
||||||
|
|
||||||
|
done < <(xmlstarlet sel -T -t \
|
||||||
|
-m "/feedback/record" \
|
||||||
|
-v "row/source_ip" -o "|" \
|
||||||
|
-v "row/count" -o "|" \
|
||||||
|
-v "row/policy_evaluated/disposition" -o "|" \
|
||||||
|
-v "row/policy_evaluated/spf" -o "|" \
|
||||||
|
-v "row/policy_evaluated/dkim" -o "|" \
|
||||||
|
-v "identifiers/header_from" -n \
|
||||||
|
"$xml_input" 2>/dev/null)
|
||||||
|
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
# Alle Dateien im Verzeichnis verarbeiten
|
||||||
|
shopt -s nullglob
|
||||||
|
for f in "$REPORT_DIR"/*; do
|
||||||
|
case "$f" in
|
||||||
|
*.xml)
|
||||||
|
parse_xml "$f"
|
||||||
|
;;
|
||||||
|
*.gz)
|
||||||
|
if command -v gzip >/dev/null 2>&1; then
|
||||||
|
tmp="$(mktemp)"
|
||||||
|
if gzip -cd "$f" > "$tmp"; then
|
||||||
|
parse_xml "$tmp"
|
||||||
|
else
|
||||||
|
echo "Warnung: Konnte $f nicht entpacken."
|
||||||
|
fi
|
||||||
|
rm -f "$tmp"
|
||||||
|
else
|
||||||
|
echo "Warnung: gzip nicht verfügbar, überspringe $f"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*.zip)
|
||||||
|
if command -v unzip >/dev/null 2>&1; then
|
||||||
|
tmpdir="$(mktemp -d)"
|
||||||
|
if unzip -qq -j "$f" '*.xml' -d "$tmpdir" >/dev/null 2>&1; then
|
||||||
|
for x in "$tmpdir"/*.xml; do
|
||||||
|
[[ -e "$x" ]] || continue
|
||||||
|
parse_xml "$x"
|
||||||
|
done
|
||||||
|
else
|
||||||
|
echo "Warnung: Konnte $f nicht entpacken (oder keine XML darin)."
|
||||||
|
fi
|
||||||
|
rm -rf "$tmpdir"
|
||||||
|
else
|
||||||
|
echo "Warnung: unzip nicht verfügbar, überspringe $f"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*) : ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# Zusammenfassung
|
||||||
|
unique_ips=${#SEEN_IPS[@]}
|
||||||
|
echo "=============================================================================="
|
||||||
|
echo "GESAMT-ZUSAMMENFASSUNG"
|
||||||
|
echo "Nachrichten gesamt: $total_msgs"
|
||||||
|
echo "Eindeutige Source-IPs: $unique_ips"
|
||||||
|
echo "Alle Auth PASS: $pass_msgs"
|
||||||
|
echo "SPF/DKIM Fehler gesamt: $fail_msgs"
|
||||||
|
echo " ├─ nur SPF-Fail: $spf_only_fail"
|
||||||
|
echo " ├─ nur DKIM-Fail: $dkim_only_fail"
|
||||||
|
echo " └─ SPF+DKIM-Fail: $both_fail"
|
||||||
|
[[ -n "$WANT_DOMAIN" ]] && echo "Gefilterte Domain: $WANT_DOMAIN"
|
||||||
|
echo "Records-CSV: $CSV_PATH"
|
||||||
|
echo "Hinweis: 'Fail' umfasst Records, bei denen SPF oder DKIM nicht 'pass' war."
|
||||||
|
|
||||||
|
# Top-Listen auf STDOUT
|
||||||
|
echo
|
||||||
|
echo "TOP $TOP_N IPs nach Anzahl (über alle Reports):"
|
||||||
|
{
|
||||||
|
for ip in "${!IP_COUNTS[@]}"; do
|
||||||
|
printf "%10d %s\n" "${IP_COUNTS[$ip]}" "$ip"
|
||||||
|
done
|
||||||
|
} | sort -rn | head -n "$TOP_N" | awk '{printf " %2d) %-16s %7s\n", NR, $2, $1}'
|
||||||
|
|
||||||
|
if (( fail_msgs > 0 )); then
|
||||||
|
echo
|
||||||
|
echo "Top-IPs nur SPF-Fail:"
|
||||||
|
{ for ip in "${!SPF_ONLY_FAIL_IP[@]}"; do printf "%10d %s\n" "${SPF_ONLY_FAIL_IP[$ip]}" "$ip"; done; } \
|
||||||
|
| sort -rn | head -n "$TOP_N" | awk '{printf " %2d) %-16s %7s\n", NR, $2, $1}'
|
||||||
|
echo
|
||||||
|
echo "Top-IPs nur DKIM-Fail:"
|
||||||
|
{ for ip in "${!DKIM_ONLY_FAIL_IP[@]}"; do printf "%10d %s\n" "${DKIM_ONLY_FAIL_IP[$ip]}" "$ip"; done; } \
|
||||||
|
| sort -rn | head -n "$TOP_N" | awk '{printf " %2d) %-16s %7s\n", NR, $2, $1}'
|
||||||
|
echo
|
||||||
|
echo "Top-IPs SPF+DKIM-Fail:"
|
||||||
|
{ for ip in "${!BOTH_FAIL_IP[@]}"; do printf "%10d %s\n" "${BOTH_FAIL_IP[$ip]}" "$ip"; done; } \
|
||||||
|
| sort -rn | head -n "$TOP_N" | awk '{printf " %2d) %-16s %7s\n", NR, $2, $1}'
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ---- CSV-Exporte der Top-Listen ---------------------------------------------
|
||||||
|
|
||||||
|
write_top_csv () {
|
||||||
|
local outfile="$1"; shift
|
||||||
|
local -n assoc="$1" # name reference auf assoziatives Array
|
||||||
|
echo "ip,count" > "$outfile"
|
||||||
|
if [[ "${#assoc[@]}" -eq 0 ]]; then
|
||||||
|
: # leer
|
||||||
|
else
|
||||||
|
for ip in "${!assoc[@]}"; do
|
||||||
|
printf "%s,%s\n" "$ip" "${assoc[$ip]}"
|
||||||
|
done | sort -t, -k2,2nr > "$outfile"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Gesamt-Top-IPs
|
||||||
|
write_top_csv "$OUTDIR/top_ips.csv" IP_COUNTS
|
||||||
|
|
||||||
|
# Top-Listen nach Fail-Kategorien
|
||||||
|
write_top_csv "$OUTDIR/top_spf_fail_ips.csv" SPF_ONLY_FAIL_IP
|
||||||
|
write_top_csv "$OUTDIR/top_dkim_fail_ips.csv" DKIM_ONLY_FAIL_IP
|
||||||
|
write_top_csv "$OUTDIR/top_both_fail_ips.csv" BOTH_FAIL_IP
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "Exportierte Top-CSV-Dateien:"
|
||||||
|
echo " $OUTDIR/top_ips.csv"
|
||||||
|
echo " $OUTDIR/top_spf_fail_ips.csv"
|
||||||
|
echo " $OUTDIR/top_dkim_fail_ips.csv"
|
||||||
|
echo " $OUTDIR/top_both_fail_ips.csv"
|
||||||
|
|
||||||
|
EOF
|
||||||
|
sudo chmod 750 /usr/local/bin/dmarc-scan.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🧩 Verwendung
|
||||||
|
|
||||||
|
Grundbeispiel:
|
||||||
|
```bash
|
||||||
|
dmarc-scan.sh /var/lib/dmarc/reports/2025/11/12
|
||||||
|
```
|
||||||
|
|
||||||
|
Mit Optionen:
|
||||||
|
```bash
|
||||||
|
dmarc-scan.sh /var/lib/dmarc/reports/2025/11/12 --domain fluechtlingsrat-brandenburg.de --csv /var/lib/dmarc/exports/records.csv --append --top 25 --outdir /var/lib/dmarc/exports/
|
||||||
|
```
|
||||||
|
|
||||||
|
### Parameterübersicht
|
||||||
|
|
||||||
|
| Parameter | Bedeutung |
|
||||||
|
|------------|------------|
|
||||||
|
| `--domain <domain>` | Filtert Berichte auf bestimmte Domain |
|
||||||
|
| `--csv <pfad>` | Pfad zur Ausgabedatei (Records-CSV) |
|
||||||
|
| `--append` | Bestehende CSV fortschreiben statt überschreiben |
|
||||||
|
| `--top <N>` | Anzahl der angezeigten Top-IPs |
|
||||||
|
| `--outdir <pfad>` | Zielverzeichnis für Top-Listen (CSV) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 Ausgabedateien
|
||||||
|
|
||||||
|
| Datei | Inhalt |
|
||||||
|
|-------|---------|
|
||||||
|
| `records.csv` | Alle Einzel-Records |
|
||||||
|
| `top_ips.csv` | IPs mit den meisten Mails |
|
||||||
|
| `top_spf_fail_ips.csv` | IPs mit nur SPF-Fails |
|
||||||
|
| `top_dkim_fail_ips.csv` | IPs mit nur DKIM-Fails |
|
||||||
|
| `top_both_fail_ips.csv` | IPs mit SPF+DKIM-Fails |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔁 Integration in den Serverbetrieb
|
||||||
|
|
||||||
|
Das Skript wird typischerweise durch den täglichen Job `/usr/local/lib/dmarc/daily-run.sh` aufgerufen.
|
||||||
|
Manuelle Nutzung ist jederzeit möglich.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🧩 Kontext – Verzeichnisstruktur (empfohlen)
|
||||||
|
|
||||||
|
```
|
||||||
|
/var/lib/dmarc/
|
||||||
|
├── reports/ # Eingehende Rohdaten (XML, ZIP, GZ) – nach Datum
|
||||||
|
├── exports/ # CSV- und Top-Dateien
|
||||||
|
└── logs/ # Logausgaben der täglichen Auswertung
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Autor:** oopen.de / Systemkonfiguration
|
||||||
|
**Stand:** November 2025
|
||||||
|
**Version:** 1.2
|
||||||
301
DOC/DMARC-Report/dmarc-scan.sh
Executable file
301
DOC/DMARC-Report/dmarc-scan.sh
Executable file
@@ -0,0 +1,301 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
#
|
||||||
|
# dmarc-scan.sh — DMARC-XML-Reports (auch .gz/.zip) einlesen, tabellarisch anzeigen,
|
||||||
|
# Records als CSV exportieren (append optional), Top-IPs ermitteln
|
||||||
|
# und Top-Listen als CSV schreiben.
|
||||||
|
#
|
||||||
|
# Nutzung:
|
||||||
|
# ./dmarc-scan.sh /pfad/zu/reports \
|
||||||
|
# [--domain DOMAIN] \
|
||||||
|
# [--csv pfad/zur/records.csv] \
|
||||||
|
# [--append] \
|
||||||
|
# [--top N] \
|
||||||
|
# [--outdir pfad/zum/ordner]
|
||||||
|
#
|
||||||
|
# Beispiele:
|
||||||
|
# ./dmarc-scan.sh /var/mail/dmarc
|
||||||
|
# ./dmarc-scan.sh /var/mail/dmarc --domain fluechtlingsrat-brandenburg.de --csv dmarc.csv --append --top 15 --outdir ./export
|
||||||
|
#
|
||||||
|
# Voraussetzungen: xmlstarlet, unzip (für .zip), gzip (für .gz)
|
||||||
|
# Debian/Ubuntu: sudo apt-get install xmlstarlet unzip gzip
|
||||||
|
#
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
REPORT_DIR="${1:-}"
|
||||||
|
shift || true
|
||||||
|
|
||||||
|
# Defaults
|
||||||
|
WANT_DOMAIN=""
|
||||||
|
CSV_PATH="./dmarc-summary.csv"
|
||||||
|
APPEND=0
|
||||||
|
TOP_N=10
|
||||||
|
OUTDIR="."
|
||||||
|
|
||||||
|
# Arg-Parsing (einfach)
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "${1:-}" in
|
||||||
|
--domain)
|
||||||
|
WANT_DOMAIN="${2:-}"; shift 2 || true ;;
|
||||||
|
--csv)
|
||||||
|
CSV_PATH="${2:-}"; shift 2 || true ;;
|
||||||
|
--append)
|
||||||
|
APPEND=1; shift || true ;;
|
||||||
|
--top)
|
||||||
|
TOP_N="${2:-10}"; shift 2 || true ;;
|
||||||
|
--outdir)
|
||||||
|
OUTDIR="${2:-.}"; shift 2 || true ;;
|
||||||
|
*)
|
||||||
|
# Unbekannte Option ignorieren
|
||||||
|
shift || true ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ -z "$REPORT_DIR" || ! -d "$REPORT_DIR" ]]; then
|
||||||
|
echo "Fehler: Bitte ein Verzeichnis mit DMARC-Reports angeben."
|
||||||
|
echo "Beispiel: $0 /var/mail/dmarc --domain fluechtlingsrat-brandenburg.de --csv dmarc.csv --append --top 15 --outdir ./export"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! command -v xmlstarlet >/dev/null 2>&1; then
|
||||||
|
echo "Fehler: xmlstarlet nicht gefunden. Bitte installieren (z.B. 'sudo apt-get install xmlstarlet')."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "$OUTDIR"
|
||||||
|
|
||||||
|
# CSV-Header für Records; bei --append nur schreiben, wenn Datei noch nicht existiert
|
||||||
|
RECORDS_HEADER="report_org,policy_domain,begin_utc,end_utc,source_ip,count,disposition,spf,dkim,header_from"
|
||||||
|
ensure_records_header() {
|
||||||
|
if [[ "$APPEND" -eq 1 ]]; then
|
||||||
|
if [[ ! -f "$CSV_PATH" ]]; then
|
||||||
|
echo "$RECORDS_HEADER" > "$CSV_PATH"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "$RECORDS_HEADER" > "$CSV_PATH"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
ensure_records_header
|
||||||
|
|
||||||
|
# Zähler & Sets
|
||||||
|
declare -A SEEN_IPS=()
|
||||||
|
declare -A IP_COUNTS=() # Summe pro IP
|
||||||
|
declare -A SPF_ONLY_FAIL_IP=() # nur SPF fail pro IP
|
||||||
|
declare -A DKIM_ONLY_FAIL_IP=() # nur DKIM fail pro IP
|
||||||
|
declare -A BOTH_FAIL_IP=() # SPF+DKIM fail pro IP
|
||||||
|
|
||||||
|
total_msgs=0
|
||||||
|
pass_msgs=0
|
||||||
|
fail_msgs=0
|
||||||
|
spf_only_fail=0
|
||||||
|
dkim_only_fail=0
|
||||||
|
both_fail=0
|
||||||
|
|
||||||
|
# Hilfsfunktion: Epoch -> Datum (UTC)
|
||||||
|
epoch2date() {
|
||||||
|
local e="$1"
|
||||||
|
if [[ -z "$e" ]]; then printf "-"; return; fi
|
||||||
|
date -u -d @"$e" +"%Y-%m-%d %H:%M:%S UTC" 2>/dev/null || printf "%s" "$e"
|
||||||
|
}
|
||||||
|
|
||||||
|
# CSV-escape (Felder in Anführungszeichen, doppelte Anführungszeichen verdoppeln)
|
||||||
|
csv_escape() {
|
||||||
|
local s="${1:-}"
|
||||||
|
s="${s//\"/\"\"}"
|
||||||
|
printf "\"%s\"" "$s"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Eine einzelne XML-Datei parsen
|
||||||
|
parse_xml() {
|
||||||
|
local xml_input="$1"
|
||||||
|
|
||||||
|
# Domain aus policy_published, ggf. für Filter
|
||||||
|
local domain
|
||||||
|
domain=$(xmlstarlet sel -T -t -v "/feedback/policy_published/domain" "$xml_input" 2>/dev/null || true)
|
||||||
|
if [[ -n "$WANT_DOMAIN" && "$domain" != "$WANT_DOMAIN" ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
local org begin end pol sp aspf adkim
|
||||||
|
org=$(xmlstarlet sel -T -t -v "/feedback/report_metadata/org_name" "$xml_input" 2>/dev/null || printf "-")
|
||||||
|
begin=$(xmlstarlet sel -T -t -v "/feedback/report_metadata/date_range/begin" "$xml_input" 2>/dev/null || printf "")
|
||||||
|
end=$(xmlstarlet sel -T -t -v "/feedback/report_metadata/date_range/end" "$xml_input" 2>/dev/null || printf "")
|
||||||
|
pol=$(xmlstarlet sel -T -t -v "/feedback/policy_published/p" "$xml_input" 2>/dev/null || printf "-")
|
||||||
|
sp=$(xmlstarlet sel -T -t -v "/feedback/policy_published/sp" "$xml_input" 2>/dev/null || printf "-")
|
||||||
|
aspf=$(xmlstarlet sel -T -t -v "/feedback/policy_published/aspf" "$xml_input" 2>/dev/null || printf "-")
|
||||||
|
adkim=$(xmlstarlet sel -T -t -v "/feedback/policy_published/adkim" "$xml_input" 2>/dev/null || printf "-")
|
||||||
|
|
||||||
|
# Report-Header
|
||||||
|
echo "=============================================================================="
|
||||||
|
echo "Report von: ${org}"
|
||||||
|
echo "Domain (Policy): ${domain} (p=${pol}, sp=${sp}, aspf=${aspf}, adkim=${adkim})"
|
||||||
|
echo "Zeitraum: $(epoch2date "$begin") – $(epoch2date "$end")"
|
||||||
|
echo "------------------------------------------------------------------------------"
|
||||||
|
printf "%-16s %7s %-10s %-6s %-6s %s\n" "Source IP" "Count" "Disposition" "SPF" "DKIM" "Header-From"
|
||||||
|
echo "------------------------------------------------------------------------------"
|
||||||
|
|
||||||
|
# Alle <record>-Einträge tabellarisch ausgeben
|
||||||
|
while IFS='|' read -r ip cnt dispo spfres dkimres hfrom; do
|
||||||
|
[[ -z "$ip$cnt$dispo$spfres$dkimres$hfrom" ]] && continue
|
||||||
|
|
||||||
|
local n=0
|
||||||
|
if [[ -n "${cnt:-}" && "$cnt" =~ ^[0-9]+$ ]]; then n="$cnt"; fi
|
||||||
|
|
||||||
|
total_msgs=$(( total_msgs + n ))
|
||||||
|
[[ -n "$ip" ]] && SEEN_IPS["$ip"]=1
|
||||||
|
[[ -n "$ip" ]] && IP_COUNTS["$ip"]=$(( ${IP_COUNTS["$ip"]:-0} + n ))
|
||||||
|
|
||||||
|
if [[ "${spfres:-}" == "pass" && "${dkimres:-}" == "pass" ]]; then
|
||||||
|
pass_msgs=$(( pass_msgs + n ))
|
||||||
|
else
|
||||||
|
fail_msgs=$(( fail_msgs + n ))
|
||||||
|
if [[ "${spfres:-}" != "pass" && "${dkimres:-}" == "pass" ]]; then
|
||||||
|
spf_only_fail=$(( spf_only_fail + n ))
|
||||||
|
[[ -n "$ip" ]] && SPF_ONLY_FAIL_IP["$ip"]=$(( ${SPF_ONLY_FAIL_IP["$ip"]:-0} + n ))
|
||||||
|
elif [[ "${spfres:-}" == "pass" && "${dkimres:-}" != "pass" ]]; then
|
||||||
|
dkim_only_fail=$(( dkim_only_fail + n ))
|
||||||
|
[[ -n "$ip" ]] && DKIM_ONLY_FAIL_IP["$ip"]=$(( ${DKIM_ONLY_FAIL_IP["$ip"]:-0} + n ))
|
||||||
|
else
|
||||||
|
both_fail=$(( both_fail + n ))
|
||||||
|
[[ -n "$ip" ]] && BOTH_FAIL_IP["$ip"]=$(( ${BOTH_FAIL_IP["$ip"]:-0} + n ))
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf "%-16s %7s %-10s %-6s %-6s %s\n" "${ip:--}" "${n}" "${dispo:--}" "${spfres:--}" "${dkimres:--}" "${hfrom:--}"
|
||||||
|
|
||||||
|
local begin_human end_human
|
||||||
|
begin_human="$(epoch2date "$begin")"
|
||||||
|
end_human="$(epoch2date "$end")"
|
||||||
|
{
|
||||||
|
csv_escape "$org"; printf ","
|
||||||
|
csv_escape "$domain"; printf ","
|
||||||
|
csv_escape "$begin_human"; printf ","
|
||||||
|
csv_escape "$end_human"; printf ","
|
||||||
|
csv_escape "${ip:-}"; printf ","
|
||||||
|
printf "%s," "$n"
|
||||||
|
csv_escape "${dispo:-}"; printf ","
|
||||||
|
csv_escape "${spfres:-}"; printf ","
|
||||||
|
csv_escape "${dkimres:-}"; printf ","
|
||||||
|
csv_escape "${hfrom:-}"; printf "\n"
|
||||||
|
} >> "$CSV_PATH"
|
||||||
|
|
||||||
|
done < <(xmlstarlet sel -T -t \
|
||||||
|
-m "/feedback/record" \
|
||||||
|
-v "row/source_ip" -o "|" \
|
||||||
|
-v "row/count" -o "|" \
|
||||||
|
-v "row/policy_evaluated/disposition" -o "|" \
|
||||||
|
-v "row/policy_evaluated/spf" -o "|" \
|
||||||
|
-v "row/policy_evaluated/dkim" -o "|" \
|
||||||
|
-v "identifiers/header_from" -n \
|
||||||
|
"$xml_input" 2>/dev/null)
|
||||||
|
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
# Alle Dateien im Verzeichnis verarbeiten
|
||||||
|
shopt -s nullglob
|
||||||
|
for f in "$REPORT_DIR"/*; do
|
||||||
|
case "$f" in
|
||||||
|
*.xml)
|
||||||
|
parse_xml "$f"
|
||||||
|
;;
|
||||||
|
*.gz)
|
||||||
|
if command -v gzip >/dev/null 2>&1; then
|
||||||
|
tmp="$(mktemp)"
|
||||||
|
if gzip -cd "$f" > "$tmp"; then
|
||||||
|
parse_xml "$tmp"
|
||||||
|
else
|
||||||
|
echo "Warnung: Konnte $f nicht entpacken."
|
||||||
|
fi
|
||||||
|
rm -f "$tmp"
|
||||||
|
else
|
||||||
|
echo "Warnung: gzip nicht verfügbar, überspringe $f"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*.zip)
|
||||||
|
if command -v unzip >/dev/null 2>&1; then
|
||||||
|
tmpdir="$(mktemp -d)"
|
||||||
|
if unzip -qq -j "$f" '*.xml' -d "$tmpdir" >/dev/null 2>&1; then
|
||||||
|
for x in "$tmpdir"/*.xml; do
|
||||||
|
[[ -e "$x" ]] || continue
|
||||||
|
parse_xml "$x"
|
||||||
|
done
|
||||||
|
else
|
||||||
|
echo "Warnung: Konnte $f nicht entpacken (oder keine XML darin)."
|
||||||
|
fi
|
||||||
|
rm -rf "$tmpdir"
|
||||||
|
else
|
||||||
|
echo "Warnung: unzip nicht verfügbar, überspringe $f"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*) : ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# Zusammenfassung
|
||||||
|
unique_ips=${#SEEN_IPS[@]}
|
||||||
|
echo "=============================================================================="
|
||||||
|
echo "GESAMT-ZUSAMMENFASSUNG"
|
||||||
|
echo "Nachrichten gesamt: $total_msgs"
|
||||||
|
echo "Eindeutige Source-IPs: $unique_ips"
|
||||||
|
echo "Alle Auth PASS: $pass_msgs"
|
||||||
|
echo "SPF/DKIM Fehler gesamt: $fail_msgs"
|
||||||
|
echo " ├─ nur SPF-Fail: $spf_only_fail"
|
||||||
|
echo " ├─ nur DKIM-Fail: $dkim_only_fail"
|
||||||
|
echo " └─ SPF+DKIM-Fail: $both_fail"
|
||||||
|
[[ -n "$WANT_DOMAIN" ]] && echo "Gefilterte Domain: $WANT_DOMAIN"
|
||||||
|
echo "Records-CSV: $CSV_PATH"
|
||||||
|
echo "Hinweis: 'Fail' umfasst Records, bei denen SPF oder DKIM nicht 'pass' war."
|
||||||
|
|
||||||
|
# Top-Listen auf STDOUT
|
||||||
|
echo
|
||||||
|
echo "TOP $TOP_N IPs nach Anzahl (über alle Reports):"
|
||||||
|
{
|
||||||
|
for ip in "${!IP_COUNTS[@]}"; do
|
||||||
|
printf "%10d %s\n" "${IP_COUNTS[$ip]}" "$ip"
|
||||||
|
done
|
||||||
|
} | sort -rn | head -n "$TOP_N" | awk '{printf " %2d) %-16s %7s\n", NR, $2, $1}'
|
||||||
|
|
||||||
|
if (( fail_msgs > 0 )); then
|
||||||
|
echo
|
||||||
|
echo "Top-IPs nur SPF-Fail:"
|
||||||
|
{ for ip in "${!SPF_ONLY_FAIL_IP[@]}"; do printf "%10d %s\n" "${SPF_ONLY_FAIL_IP[$ip]}" "$ip"; done; } \
|
||||||
|
| sort -rn | head -n "$TOP_N" | awk '{printf " %2d) %-16s %7s\n", NR, $2, $1}'
|
||||||
|
echo
|
||||||
|
echo "Top-IPs nur DKIM-Fail:"
|
||||||
|
{ for ip in "${!DKIM_ONLY_FAIL_IP[@]}"; do printf "%10d %s\n" "${DKIM_ONLY_FAIL_IP[$ip]}" "$ip"; done; } \
|
||||||
|
| sort -rn | head -n "$TOP_N" | awk '{printf " %2d) %-16s %7s\n", NR, $2, $1}'
|
||||||
|
echo
|
||||||
|
echo "Top-IPs SPF+DKIM-Fail:"
|
||||||
|
{ for ip in "${!BOTH_FAIL_IP[@]}"; do printf "%10d %s\n" "${BOTH_FAIL_IP[$ip]}" "$ip"; done; } \
|
||||||
|
| sort -rn | head -n "$TOP_N" | awk '{printf " %2d) %-16s %7s\n", NR, $2, $1}'
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ---- CSV-Exporte der Top-Listen ---------------------------------------------
|
||||||
|
|
||||||
|
write_top_csv () {
|
||||||
|
local outfile="$1"; shift
|
||||||
|
local -n assoc="$1" # name reference auf assoziatives Array
|
||||||
|
echo "ip,count" > "$outfile"
|
||||||
|
if [[ "${#assoc[@]}" -eq 0 ]]; then
|
||||||
|
: # leer
|
||||||
|
else
|
||||||
|
for ip in "${!assoc[@]}"; do
|
||||||
|
printf "%s,%s\n" "$ip" "${assoc[$ip]}"
|
||||||
|
done | sort -t, -k2,2nr > "$outfile"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Gesamt-Top-IPs
|
||||||
|
write_top_csv "$OUTDIR/top_ips.csv" IP_COUNTS
|
||||||
|
|
||||||
|
# Top-Listen nach Fail-Kategorien
|
||||||
|
write_top_csv "$OUTDIR/top_spf_fail_ips.csv" SPF_ONLY_FAIL_IP
|
||||||
|
write_top_csv "$OUTDIR/top_dkim_fail_ips.csv" DKIM_ONLY_FAIL_IP
|
||||||
|
write_top_csv "$OUTDIR/top_both_fail_ips.csv" BOTH_FAIL_IP
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "Exportierte Top-CSV-Dateien:"
|
||||||
|
echo " $OUTDIR/top_ips.csv"
|
||||||
|
echo " $OUTDIR/top_spf_fail_ips.csv"
|
||||||
|
echo " $OUTDIR/top_dkim_fail_ips.csv"
|
||||||
|
echo " $OUTDIR/top_both_fail_ips.csv"
|
||||||
621
DOC/DMARC-Report/dmarc-server-setup.md
Normal file
621
DOC/DMARC-Report/dmarc-server-setup.md
Normal file
@@ -0,0 +1,621 @@
|
|||||||
|
# DMARC-Server-Sammelsystem – Einrichtung und Betrieb
|
||||||
|
|
||||||
|
## 📖 Präambel
|
||||||
|
|
||||||
|
Dieses Dokument beschreibt die vollständige Einrichtung eines automatisierten DMARC-Report-Sammelsystems auf einem Linux-Mailserver mit **Postfix**, **Amavis** und **Dovecot (LMTP)**.
|
||||||
|
Ziel: DMARC-Aggregatberichte (XML, .gz, .zip) serverseitig empfangen, speichern und regelmäßig auswerten.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 Ziel
|
||||||
|
|
||||||
|
- DMARC-Reports zentral über `dmarc-reports@oopen.de` empfangen.
|
||||||
|
- Reports automatisch extrahieren und datumsbasiert speichern.
|
||||||
|
- Regelmäßige automatische Auswertung mit `dmarc-scan.sh`.
|
||||||
|
- Speicherung der Ergebnisse in CSV-Dateien.
|
||||||
|
- Wartungsarm, sicher und robust.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📁 Verzeichnisstruktur
|
||||||
|
|
||||||
|
Alle Dateien werden unter `/var/lib/dmarc` abgelegt:
|
||||||
|
|
||||||
|
```
|
||||||
|
/var/lib/dmarc/
|
||||||
|
├── reports/ # Eingegangene XML-, GZ-, ZIP-Dateien
|
||||||
|
│ └── YYYY/MM/DD/ # Datumsbasierte Ablage
|
||||||
|
├── processed/ # Originalmails (Archiv)
|
||||||
|
├── exports/ # CSV- und Top-Auswertungen
|
||||||
|
└── logs/ # Logdateien
|
||||||
|
```
|
||||||
|
|
||||||
|
Verzeichnisse anlegen:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo install -d -o vmail -g vmail -m 750 /var/lib/dmarc/{reports,processed,exports,logs}
|
||||||
|
sudo install -d -o root -g root -m 750 /usr/local/lib/dmarc
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚙️ 1. Postfix-Integration
|
||||||
|
|
||||||
|
### 1.1 Transport und Master-Konfiguration
|
||||||
|
|
||||||
|
In `/etc/postfix/master.cf` **am Ende einfügen:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dmarc-pipe unix - n n - - pipe
|
||||||
|
flags=Rq user=vmail argv=/usr/local/bin/dmarc-collect.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
> Passe `user=` an, falls dein Mailbenutzer anders heißt (z. B. `mail` oder `amavis`).
|
||||||
|
|
||||||
|
### 1.2 Transportregel definieren
|
||||||
|
|
||||||
|
In `/etc/postfix/transport`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dmarc-reports@oopen.de dmarc-pipe:
|
||||||
|
```
|
||||||
|
|
||||||
|
Aktivieren:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo postmap /etc/postfix/transport
|
||||||
|
sudo systemctl reload postfix
|
||||||
|
```
|
||||||
|
|
||||||
|
Damit weiß Postfix, dass Mails an diese Adresse an das Skript weitergegeben werden.
|
||||||
|
|
||||||
|
### 1.3 (Optional) Kopie der Mail behalten
|
||||||
|
|
||||||
|
Wenn du zusätzlich eine Kopie im IMAP-Postfach haben willst:
|
||||||
|
|
||||||
|
In `/etc/postfix/virtual_alias_maps`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dmarc-reports@oopen.de dmarc-reports-mbox@oopen.de
|
||||||
|
```
|
||||||
|
|
||||||
|
Dann:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo postmap btree:/etc/postfix/virtual_alias_maps
|
||||||
|
sudo systemctl reload postfix
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Merke:** `/etc/postfix/transport` = ZustellWEG, `/etc/postfix/virtual_alias_maps` = EmpfängerALIAS.
|
||||||
|
> Nur Skript? → Nur `transport`-Eintrag.
|
||||||
|
> Skript + Kopie? → `virtual`-Alias **zusätzlich**.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📨 2. DNS-Einträge (DMARC + External Reporting)
|
||||||
|
|
||||||
|
### Beispiel für eine Domain
|
||||||
|
|
||||||
|
```dns
|
||||||
|
_dmarc.fluechtlingsrat-brandenburg.de. IN TXT "v=DMARC1; p=none; rua=mailto:dmarc-reports@oopen.de; ruf=mailto:dmarc-reports@oopen.de; fo=1; aspf=r; adkim=r"
|
||||||
|
```
|
||||||
|
|
||||||
|
### External Reporting (oopen.de)
|
||||||
|
|
||||||
|
Wenn du Berichte für mehrere Domains auf `@oopen.de` empfängst, erlaube externes Reporting:
|
||||||
|
|
||||||
|
```dns
|
||||||
|
oopen.de._report._dmarc.oopen.de. IN TXT "v=DMARC1"
|
||||||
|
*.oopen.de._report._dmarc.oopen.de. IN TXT "v=DMARC1"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🧰 3. Sammelskript `/usr/local/bin/dmarc-collect.sh`
|
||||||
|
|
||||||
|
**Datei anlegen:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo tee /usr/local/bin/dmarc-collect.sh >/dev/null <<'EOF'
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
BASE="/var/lib/dmarc"
|
||||||
|
INBOX="$BASE/reports"
|
||||||
|
PROC="$BASE/processed"
|
||||||
|
LOGF="$BASE/logs/collector.log"
|
||||||
|
|
||||||
|
umask 027
|
||||||
|
|
||||||
|
TMPDIR="$(mktemp -d)"
|
||||||
|
EML="$TMPDIR/mail.eml"
|
||||||
|
cat > "$EML"
|
||||||
|
|
||||||
|
ripmime --no-nameless --name-by-type --overwrite -i "$EML" -d "$TMPDIR" >>"$LOGF" 2>&1 || true
|
||||||
|
|
||||||
|
TODAY="$(date -u +%Y/%m/%d)"
|
||||||
|
OUTDIR="$INBOX/$TODAY"
|
||||||
|
mkdir -p "$OUTDIR"
|
||||||
|
|
||||||
|
moved=0
|
||||||
|
shopt -s nullglob
|
||||||
|
for f in "$TMPDIR"/*; do
|
||||||
|
case "$f" in
|
||||||
|
*.xml|*.XML|*.gz|*.zip)
|
||||||
|
sha="$(sha256sum "$f" | awk '{print $1}')"
|
||||||
|
base="$(basename "$f")"
|
||||||
|
dst="$OUTDIR/$(date -u +%Y%m%dT%H%M%SZ)_${sha:0:12}_$base"
|
||||||
|
mv "$f" "$dst"
|
||||||
|
echo "$(date -Is) stored $dst" >> "$LOGF"
|
||||||
|
moved=$((moved+1))
|
||||||
|
;;
|
||||||
|
*) : ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
mkdir -p "$PROC"
|
||||||
|
mv "$EML" "$PROC/$(date -u +%Y%m%dT%H%M%SZ)_mail.eml" || true
|
||||||
|
rm -rf "$TMPDIR"
|
||||||
|
|
||||||
|
if (( moved > 0 )); then
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
echo "$(date -Is) no usable attachment in message" >> "$LOGF"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
EOF
|
||||||
|
sudo apt install -y ripmime
|
||||||
|
sudo chown vmail:vmail /usr/local/bin/dmarc-collect.sh
|
||||||
|
sudo chmod 750 /usr/local/bin/dmarc-collect.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Inhalt von `dmarc-collect.sh`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
BASE="/var/lib/dmarc"
|
||||||
|
INBOX="$BASE/reports"
|
||||||
|
PROC="$BASE/processed"
|
||||||
|
LOGF="$BASE/logs/collector.log"
|
||||||
|
|
||||||
|
umask 027
|
||||||
|
|
||||||
|
TMPDIR="$(mktemp -d)"
|
||||||
|
EML="$TMPDIR/mail.eml"
|
||||||
|
cat > "$EML"
|
||||||
|
|
||||||
|
ripmime --no-nameless --name-by-type --overwrite -i "$EML" -d "$TMPDIR" >>"$LOGF" 2>&1 || true
|
||||||
|
|
||||||
|
TODAY="$(date -u +%Y/%m/%d)"
|
||||||
|
OUTDIR="$INBOX/$TODAY"
|
||||||
|
mkdir -p "$OUTDIR"
|
||||||
|
|
||||||
|
moved=0
|
||||||
|
shopt -s nullglob
|
||||||
|
for f in "$TMPDIR"/*; do
|
||||||
|
case "$f" in
|
||||||
|
*.xml|*.XML|*.gz|*.zip)
|
||||||
|
sha="$(sha256sum "$f" | awk '{print $1}')"
|
||||||
|
base="$(basename "$f")"
|
||||||
|
dst="$OUTDIR/$(date -u +%Y%m%dT%H%M%SZ)_${sha:0:12}_$base"
|
||||||
|
mv "$f" "$dst"
|
||||||
|
echo "$(date -Is) stored $dst" >> "$LOGF"
|
||||||
|
moved=$((moved+1))
|
||||||
|
;;
|
||||||
|
*) : ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
mkdir -p "$PROC"
|
||||||
|
mv "$EML" "$PROC/$(date -u +%Y%m%dT%H%M%SZ)_mail.eml" || true
|
||||||
|
rm -rf "$TMPDIR"
|
||||||
|
|
||||||
|
if (( moved > 0 )); then
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
echo "$(date -Is) no usable attachment in message" >> "$LOGF"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⏱️ 4. Automatische tägliche Auswertung
|
||||||
|
|
||||||
|
**Datei:** `/usr/local/lib/dmarc/daily-run.sh`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo tee /usr/local/lib/dmarc/daily-run.sh >/dev/null <<'EOF'
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
BASE="/var/lib/dmarc"
|
||||||
|
TODAY_DIR="$BASE/reports/$(date -u +%Y/%m/%d)"
|
||||||
|
OUTDIR="$BASE/exports"
|
||||||
|
CSV="$OUTDIR/records.csv"
|
||||||
|
LOGF="$BASE/logs/scan-$(date -u +%F).log"
|
||||||
|
|
||||||
|
mkdir -p "$OUTDIR"
|
||||||
|
|
||||||
|
if [[ -d "$TODAY_DIR" ]]; then
|
||||||
|
/usr/local/bin/dmarc-scan.sh "$TODAY_DIR" --domain fluechtlingsrat-brandenburg.de --csv "$CSV" --append --top 25 --outdir "$OUTDIR" >> "$LOGF" 2>&1
|
||||||
|
fi
|
||||||
|
EOF
|
||||||
|
sudo chmod 750 /usr/local/lib/dmarc/daily-run.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Cronjob anlegen:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
echo '17 3 * * * root /usr/local/lib/dmarc/daily-run.sh' | sudo tee /etc/cron.d/dmarc-daily >/dev/null
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🧮 5. Auswertungsskript `/usr/local/bin/dmarc-scan.sh`
|
||||||
|
|
||||||
|
Installation:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apt install -y xmlstarlet unzip gzip
|
||||||
|
sudo tee /usr/local/bin/dmarc-scan.sh >/dev/null <<'EOF'
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
#
|
||||||
|
# dmarc-scan.sh — DMARC-XML-Reports (auch .gz/.zip) einlesen, tabellarisch anzeigen,
|
||||||
|
# Records als CSV exportieren (append optional), Top-IPs ermitteln
|
||||||
|
# und Top-Listen als CSV schreiben.
|
||||||
|
#
|
||||||
|
# Nutzung:
|
||||||
|
# ./dmarc-scan.sh /pfad/zu/reports \
|
||||||
|
# [--domain DOMAIN] \
|
||||||
|
# [--csv pfad/zur/records.csv] \
|
||||||
|
# [--append] \
|
||||||
|
# [--top N] \
|
||||||
|
# [--outdir pfad/zum/ordner]
|
||||||
|
#
|
||||||
|
# Beispiele:
|
||||||
|
# ./dmarc-scan.sh /var/mail/dmarc
|
||||||
|
# ./dmarc-scan.sh /var/mail/dmarc --domain fluechtlingsrat-brandenburg.de --csv dmarc.csv --append --top 15 --outdir ./export
|
||||||
|
#
|
||||||
|
# Voraussetzungen: xmlstarlet, unzip (für .zip), gzip (für .gz)
|
||||||
|
# Debian/Ubuntu: sudo apt-get install xmlstarlet unzip gzip
|
||||||
|
#
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
REPORT_DIR="${1:-}"
|
||||||
|
shift || true
|
||||||
|
|
||||||
|
# Defaults
|
||||||
|
WANT_DOMAIN=""
|
||||||
|
CSV_PATH="./dmarc-summary.csv"
|
||||||
|
APPEND=0
|
||||||
|
TOP_N=10
|
||||||
|
OUTDIR="."
|
||||||
|
|
||||||
|
# Arg-Parsing (einfach)
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "${1:-}" in
|
||||||
|
--domain)
|
||||||
|
WANT_DOMAIN="${2:-}"; shift 2 || true ;;
|
||||||
|
--csv)
|
||||||
|
CSV_PATH="${2:-}"; shift 2 || true ;;
|
||||||
|
--append)
|
||||||
|
APPEND=1; shift || true ;;
|
||||||
|
--top)
|
||||||
|
TOP_N="${2:-10}"; shift 2 || true ;;
|
||||||
|
--outdir)
|
||||||
|
OUTDIR="${2:-.}"; shift 2 || true ;;
|
||||||
|
*)
|
||||||
|
# Unbekannte Option ignorieren
|
||||||
|
shift || true ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ -z "$REPORT_DIR" || ! -d "$REPORT_DIR" ]]; then
|
||||||
|
echo "Fehler: Bitte ein Verzeichnis mit DMARC-Reports angeben."
|
||||||
|
echo "Beispiel: $0 /var/mail/dmarc --domain fluechtlingsrat-brandenburg.de --csv dmarc.csv --append --top 15 --outdir ./export"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! command -v xmlstarlet >/dev/null 2>&1; then
|
||||||
|
echo "Fehler: xmlstarlet nicht gefunden. Bitte installieren (z.B. 'sudo apt-get install xmlstarlet')."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "$OUTDIR"
|
||||||
|
|
||||||
|
# CSV-Header für Records; bei --append nur schreiben, wenn Datei noch nicht existiert
|
||||||
|
RECORDS_HEADER="report_org,policy_domain,begin_utc,end_utc,source_ip,count,disposition,spf,dkim,header_from"
|
||||||
|
ensure_records_header() {
|
||||||
|
if [[ "$APPEND" -eq 1 ]]; then
|
||||||
|
if [[ ! -f "$CSV_PATH" ]]; then
|
||||||
|
echo "$RECORDS_HEADER" > "$CSV_PATH"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "$RECORDS_HEADER" > "$CSV_PATH"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
ensure_records_header
|
||||||
|
|
||||||
|
# Zähler & Sets
|
||||||
|
declare -A SEEN_IPS=()
|
||||||
|
declare -A IP_COUNTS=() # Summe pro IP
|
||||||
|
declare -A SPF_ONLY_FAIL_IP=() # nur SPF fail pro IP
|
||||||
|
declare -A DKIM_ONLY_FAIL_IP=() # nur DKIM fail pro IP
|
||||||
|
declare -A BOTH_FAIL_IP=() # SPF+DKIM fail pro IP
|
||||||
|
|
||||||
|
total_msgs=0
|
||||||
|
pass_msgs=0
|
||||||
|
fail_msgs=0
|
||||||
|
spf_only_fail=0
|
||||||
|
dkim_only_fail=0
|
||||||
|
both_fail=0
|
||||||
|
|
||||||
|
# Hilfsfunktion: Epoch -> Datum (UTC)
|
||||||
|
epoch2date() {
|
||||||
|
local e="$1"
|
||||||
|
if [[ -z "$e" ]]; then printf "-"; return; fi
|
||||||
|
date -u -d @"$e" +"%Y-%m-%d %H:%M:%S UTC" 2>/dev/null || printf "%s" "$e"
|
||||||
|
}
|
||||||
|
|
||||||
|
# CSV-escape (Felder in Anführungszeichen, doppelte Anführungszeichen verdoppeln)
|
||||||
|
csv_escape() {
|
||||||
|
local s="${1:-}"
|
||||||
|
s="${s//\"/\"\"}"
|
||||||
|
printf "\"%s\"" "$s"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Eine einzelne XML-Datei parsen
|
||||||
|
parse_xml() {
|
||||||
|
local xml_input="$1"
|
||||||
|
|
||||||
|
# Domain aus policy_published, ggf. für Filter
|
||||||
|
local domain
|
||||||
|
domain=$(xmlstarlet sel -T -t -v "/feedback/policy_published/domain" "$xml_input" 2>/dev/null || true)
|
||||||
|
if [[ -n "$WANT_DOMAIN" && "$domain" != "$WANT_DOMAIN" ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
local org begin end pol sp aspf adkim
|
||||||
|
org=$(xmlstarlet sel -T -t -v "/feedback/report_metadata/org_name" "$xml_input" 2>/dev/null || printf "-")
|
||||||
|
begin=$(xmlstarlet sel -T -t -v "/feedback/report_metadata/date_range/begin" "$xml_input" 2>/dev/null || printf "")
|
||||||
|
end=$(xmlstarlet sel -T -t -v "/feedback/report_metadata/date_range/end" "$xml_input" 2>/dev/null || printf "")
|
||||||
|
pol=$(xmlstarlet sel -T -t -v "/feedback/policy_published/p" "$xml_input" 2>/dev/null || printf "-")
|
||||||
|
sp=$(xmlstarlet sel -T -t -v "/feedback/policy_published/sp" "$xml_input" 2>/dev/null || printf "-")
|
||||||
|
aspf=$(xmlstarlet sel -T -t -v "/feedback/policy_published/aspf" "$xml_input" 2>/dev/null || printf "-")
|
||||||
|
adkim=$(xmlstarlet sel -T -t -v "/feedback/policy_published/adkim" "$xml_input" 2>/dev/null || printf "-")
|
||||||
|
|
||||||
|
# Report-Header
|
||||||
|
echo "=============================================================================="
|
||||||
|
echo "Report von: ${org}"
|
||||||
|
echo "Domain (Policy): ${domain} (p=${pol}, sp=${sp}, aspf=${aspf}, adkim=${adkim})"
|
||||||
|
echo "Zeitraum: $(epoch2date "$begin") – $(epoch2date "$end")"
|
||||||
|
echo "------------------------------------------------------------------------------"
|
||||||
|
printf "%-16s %7s %-10s %-6s %-6s %s\n" "Source IP" "Count" "Disposition" "SPF" "DKIM" "Header-From"
|
||||||
|
echo "------------------------------------------------------------------------------"
|
||||||
|
|
||||||
|
# Alle <record>-Einträge tabellarisch ausgeben
|
||||||
|
while IFS='|' read -r ip cnt dispo spfres dkimres hfrom; do
|
||||||
|
[[ -z "$ip$cnt$dispo$spfres$dkimres$hfrom" ]] && continue
|
||||||
|
|
||||||
|
local n=0
|
||||||
|
if [[ -n "${cnt:-}" && "$cnt" =~ ^[0-9]+$ ]]; then n="$cnt"; fi
|
||||||
|
|
||||||
|
total_msgs=$(( total_msgs + n ))
|
||||||
|
[[ -n "$ip" ]] && SEEN_IPS["$ip"]=1
|
||||||
|
[[ -n "$ip" ]] && IP_COUNTS["$ip"]=$(( ${IP_COUNTS["$ip"]:-0} + n ))
|
||||||
|
|
||||||
|
if [[ "${spfres:-}" == "pass" && "${dkimres:-}" == "pass" ]]; then
|
||||||
|
pass_msgs=$(( pass_msgs + n ))
|
||||||
|
else
|
||||||
|
fail_msgs=$(( fail_msgs + n ))
|
||||||
|
if [[ "${spfres:-}" != "pass" && "${dkimres:-}" == "pass" ]]; then
|
||||||
|
spf_only_fail=$(( spf_only_fail + n ))
|
||||||
|
[[ -n "$ip" ]] && SPF_ONLY_FAIL_IP["$ip"]=$(( ${SPF_ONLY_FAIL_IP["$ip"]:-0} + n ))
|
||||||
|
elif [[ "${spfres:-}" == "pass" && "${dkimres:-}" != "pass" ]]; then
|
||||||
|
dkim_only_fail=$(( dkim_only_fail + n ))
|
||||||
|
[[ -n "$ip" ]] && DKIM_ONLY_FAIL_IP["$ip"]=$(( ${DKIM_ONLY_FAIL_IP["$ip"]:-0} + n ))
|
||||||
|
else
|
||||||
|
both_fail=$(( both_fail + n ))
|
||||||
|
[[ -n "$ip" ]] && BOTH_FAIL_IP["$ip"]=$(( ${BOTH_FAIL_IP["$ip"]:-0} + n ))
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf "%-16s %7s %-10s %-6s %-6s %s\n" "${ip:--}" "${n}" "${dispo:--}" "${spfres:--}" "${dkimres:--}" "${hfrom:--}"
|
||||||
|
|
||||||
|
local begin_human end_human
|
||||||
|
begin_human="$(epoch2date "$begin")"
|
||||||
|
end_human="$(epoch2date "$end")"
|
||||||
|
{
|
||||||
|
csv_escape "$org"; printf ","
|
||||||
|
csv_escape "$domain"; printf ","
|
||||||
|
csv_escape "$begin_human"; printf ","
|
||||||
|
csv_escape "$end_human"; printf ","
|
||||||
|
csv_escape "${ip:-}"; printf ","
|
||||||
|
printf "%s," "$n"
|
||||||
|
csv_escape "${dispo:-}"; printf ","
|
||||||
|
csv_escape "${spfres:-}"; printf ","
|
||||||
|
csv_escape "${dkimres:-}"; printf ","
|
||||||
|
csv_escape "${hfrom:-}"; printf "\n"
|
||||||
|
} >> "$CSV_PATH"
|
||||||
|
|
||||||
|
done < <(xmlstarlet sel -T -t \
|
||||||
|
-m "/feedback/record" \
|
||||||
|
-v "row/source_ip" -o "|" \
|
||||||
|
-v "row/count" -o "|" \
|
||||||
|
-v "row/policy_evaluated/disposition" -o "|" \
|
||||||
|
-v "row/policy_evaluated/spf" -o "|" \
|
||||||
|
-v "row/policy_evaluated/dkim" -o "|" \
|
||||||
|
-v "identifiers/header_from" -n \
|
||||||
|
"$xml_input" 2>/dev/null)
|
||||||
|
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
|
||||||
|
# Alle Dateien im Verzeichnis verarbeiten
|
||||||
|
shopt -s nullglob
|
||||||
|
for f in "$REPORT_DIR"/*; do
|
||||||
|
case "$f" in
|
||||||
|
*.xml)
|
||||||
|
parse_xml "$f"
|
||||||
|
;;
|
||||||
|
*.gz)
|
||||||
|
if command -v gzip >/dev/null 2>&1; then
|
||||||
|
tmp="$(mktemp)"
|
||||||
|
if gzip -cd "$f" > "$tmp"; then
|
||||||
|
parse_xml "$tmp"
|
||||||
|
else
|
||||||
|
echo "Warnung: Konnte $f nicht entpacken."
|
||||||
|
fi
|
||||||
|
rm -f "$tmp"
|
||||||
|
else
|
||||||
|
echo "Warnung: gzip nicht verfügbar, überspringe $f"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*.zip)
|
||||||
|
if command -v unzip >/dev/null 2>&1; then
|
||||||
|
tmpdir="$(mktemp -d)"
|
||||||
|
if unzip -qq -j "$f" '*.xml' -d "$tmpdir" >/dev/null 2>&1; then
|
||||||
|
for x in "$tmpdir"/*.xml; do
|
||||||
|
[[ -e "$x" ]] || continue
|
||||||
|
parse_xml "$x"
|
||||||
|
done
|
||||||
|
else
|
||||||
|
echo "Warnung: Konnte $f nicht entpacken (oder keine XML darin)."
|
||||||
|
fi
|
||||||
|
rm -rf "$tmpdir"
|
||||||
|
else
|
||||||
|
echo "Warnung: unzip nicht verfügbar, überspringe $f"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*) : ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# Zusammenfassung
|
||||||
|
unique_ips=${#SEEN_IPS[@]}
|
||||||
|
echo "=============================================================================="
|
||||||
|
echo "GESAMT-ZUSAMMENFASSUNG"
|
||||||
|
echo "Nachrichten gesamt: $total_msgs"
|
||||||
|
echo "Eindeutige Source-IPs: $unique_ips"
|
||||||
|
echo "Alle Auth PASS: $pass_msgs"
|
||||||
|
echo "SPF/DKIM Fehler gesamt: $fail_msgs"
|
||||||
|
echo " ├─ nur SPF-Fail: $spf_only_fail"
|
||||||
|
echo " ├─ nur DKIM-Fail: $dkim_only_fail"
|
||||||
|
echo " └─ SPF+DKIM-Fail: $both_fail"
|
||||||
|
[[ -n "$WANT_DOMAIN" ]] && echo "Gefilterte Domain: $WANT_DOMAIN"
|
||||||
|
echo "Records-CSV: $CSV_PATH"
|
||||||
|
echo "Hinweis: 'Fail' umfasst Records, bei denen SPF oder DKIM nicht 'pass' war."
|
||||||
|
|
||||||
|
# Top-Listen auf STDOUT
|
||||||
|
echo
|
||||||
|
echo "TOP $TOP_N IPs nach Anzahl (über alle Reports):"
|
||||||
|
{
|
||||||
|
for ip in "${!IP_COUNTS[@]}"; do
|
||||||
|
printf "%10d %s\n" "${IP_COUNTS[$ip]}" "$ip"
|
||||||
|
done
|
||||||
|
} | sort -rn | head -n "$TOP_N" | awk '{printf " %2d) %-16s %7s\n", NR, $2, $1}'
|
||||||
|
|
||||||
|
if (( fail_msgs > 0 )); then
|
||||||
|
echo
|
||||||
|
echo "Top-IPs nur SPF-Fail:"
|
||||||
|
{ for ip in "${!SPF_ONLY_FAIL_IP[@]}"; do printf "%10d %s\n" "${SPF_ONLY_FAIL_IP[$ip]}" "$ip"; done; } \
|
||||||
|
| sort -rn | head -n "$TOP_N" | awk '{printf " %2d) %-16s %7s\n", NR, $2, $1}'
|
||||||
|
echo
|
||||||
|
echo "Top-IPs nur DKIM-Fail:"
|
||||||
|
{ for ip in "${!DKIM_ONLY_FAIL_IP[@]}"; do printf "%10d %s\n" "${DKIM_ONLY_FAIL_IP[$ip]}" "$ip"; done; } \
|
||||||
|
| sort -rn | head -n "$TOP_N" | awk '{printf " %2d) %-16s %7s\n", NR, $2, $1}'
|
||||||
|
echo
|
||||||
|
echo "Top-IPs SPF+DKIM-Fail:"
|
||||||
|
{ for ip in "${!BOTH_FAIL_IP[@]}"; do printf "%10d %s\n" "${BOTH_FAIL_IP[$ip]}" "$ip"; done; } \
|
||||||
|
| sort -rn | head -n "$TOP_N" | awk '{printf " %2d) %-16s %7s\n", NR, $2, $1}'
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ---- CSV-Exporte der Top-Listen ---------------------------------------------
|
||||||
|
|
||||||
|
write_top_csv () {
|
||||||
|
local outfile="$1"; shift
|
||||||
|
local -n assoc="$1" # name reference auf assoziatives Array
|
||||||
|
echo "ip,count" > "$outfile"
|
||||||
|
if [[ "${#assoc[@]}" -eq 0 ]]; then
|
||||||
|
: # leer
|
||||||
|
else
|
||||||
|
for ip in "${!assoc[@]}"; do
|
||||||
|
printf "%s,%s\n" "$ip" "${assoc[$ip]}"
|
||||||
|
done | sort -t, -k2,2nr > "$outfile"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Gesamt-Top-IPs
|
||||||
|
write_top_csv "$OUTDIR/top_ips.csv" IP_COUNTS
|
||||||
|
|
||||||
|
# Top-Listen nach Fail-Kategorien
|
||||||
|
write_top_csv "$OUTDIR/top_spf_fail_ips.csv" SPF_ONLY_FAIL_IP
|
||||||
|
write_top_csv "$OUTDIR/top_dkim_fail_ips.csv" DKIM_ONLY_FAIL_IP
|
||||||
|
write_top_csv "$OUTDIR/top_both_fail_ips.csv" BOTH_FAIL_IP
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "Exportierte Top-CSV-Dateien:"
|
||||||
|
echo " $OUTDIR/top_ips.csv"
|
||||||
|
echo " $OUTDIR/top_spf_fail_ips.csv"
|
||||||
|
echo " $OUTDIR/top_dkim_fail_ips.csv"
|
||||||
|
echo " $OUTDIR/top_both_fail_ips.csv"
|
||||||
|
|
||||||
|
EOF
|
||||||
|
sudo chmod 750 /usr/local/bin/dmarc-scan.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Beschreibung: Das Skript liest XML/ZIP/GZ-Reports, zeigt eine Tabelle pro Report, schreibt eine Records-CSV (mit `--append` fortsetzbar) und exportiert Top-Listen als CSV in `--outdir`.
|
||||||
|
|
||||||
|
**Wichtige Parameter:**
|
||||||
|
|
||||||
|
- `--domain DOMAIN` (Filter)
|
||||||
|
- `--csv PFAD` (Records-CSV)
|
||||||
|
- `--append` (anhängen statt überschreiben)
|
||||||
|
- `--top N` (Top-Liste Größe)
|
||||||
|
- `--outdir PFAD` (Top-CSV Ziel)
|
||||||
|
|
||||||
|
**Beispiel:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dmarc-scan.sh /var/lib/dmarc/reports/2025/11/12 --domain fluechtlingsrat-brandenburg.de --csv /var/lib/dmarc/exports/records.csv --append --top 25 --outdir /var/lib/dmarc/exports/
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔁 6. Logrotate
|
||||||
|
|
||||||
|
**Datei:** `/etc/logrotate.d/dmarc`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
/var/lib/dmarc/logs/*.log {
|
||||||
|
weekly
|
||||||
|
rotate 12
|
||||||
|
compress
|
||||||
|
delaycompress
|
||||||
|
missingok
|
||||||
|
notifempty
|
||||||
|
create 640 vmail vmail
|
||||||
|
sharedscripts
|
||||||
|
postrotate
|
||||||
|
systemctl reload postfix >/dev/null 2>&1 || true
|
||||||
|
endscript
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✅ 7. Test
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo -u vmail /usr/local/bin/dmarc-collect.sh < testmail.eml
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Autor:** oopen.de / Systemkonfiguration
|
||||||
|
**Stand:** November 2025
|
||||||
|
**Version:** 1.2
|
||||||
36
DOC/DMARC_Rejections_SOP.md
Normal file
36
DOC/DMARC_Rejections_SOP.md
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
# Analyse und Begründung von DMARC-Rejects
|
||||||
|
## (Postfix + OpenDMARC 1.4.2)
|
||||||
|
|
||||||
|
### 1. Zweck
|
||||||
|
Diese SOP beschreibt, wie DMARC-Rejects auf dem Mailserver revisionssicher analysiert und begründet werden, ohne die betroffene E-Mail anzunehmen oder erneut senden zu lassen.
|
||||||
|
|
||||||
|
### 2. Systemkontext
|
||||||
|
- MTA: Postfix
|
||||||
|
- DMARC-Filter: OpenDMARC 1.4.2
|
||||||
|
- SPF-Prüfung: policyd-spf
|
||||||
|
- DKIM-Prüfung: OpenDKIM
|
||||||
|
- Entscheidungspunkt: SMTP END-OF-MESSAGE
|
||||||
|
|
||||||
|
### 3. Grundprinzip
|
||||||
|
OpenDMARC loggt nur das Endergebnis der DMARC-Evaluation, nicht die Detailursachen. Die Ursache eines Rejects wird durch Log-Korrelation ermittelt.
|
||||||
|
|
||||||
|
### 4. Relevante Logquellen
|
||||||
|
- Postfix (SMTP-Rejects)
|
||||||
|
- policyd-spf (SPF-Ergebnis, identity)
|
||||||
|
- OpenDMARC (pass/fail/none pro Domain)
|
||||||
|
|
||||||
|
### 5. Entscheidungslogik
|
||||||
|
DMARC besteht nur, wenn mindestens ein Mechanismus DMARC-konform erfolgreich ist:
|
||||||
|
- SPF(mailfrom) aligned
|
||||||
|
- DKIM valid + aligned
|
||||||
|
|
||||||
|
SPF über HELO ist für DMARC nicht verwertbar.
|
||||||
|
|
||||||
|
### 6. Ableitungsregel
|
||||||
|
Wenn SPF nur über HELO erfolgreich war und DMARC fail meldet, muss DKIM fehlgeschlagen sein.
|
||||||
|
|
||||||
|
### 7. Revisionssichere Begründung
|
||||||
|
Die E-Mail wurde gemäß der DMARC-Policy der Absenderdomain abgelehnt, da keine DMARC-konforme Authentifizierung vorlag.
|
||||||
|
|
||||||
|
### 8. Referenzen
|
||||||
|
RFC 7489 (DMARC), RFC 7208 (SPF), RFC 6376 (DKIM)
|
||||||
BIN
DOC/DMARC_Rejections_SOP.pdf
Normal file
BIN
DOC/DMARC_Rejections_SOP.pdf
Normal file
Binary file not shown.
@@ -1,16 +0,0 @@
|
|||||||
|
|
||||||
## -------------------------------------- ##
|
|
||||||
## - some litle tests ##
|
|
||||||
## -------------------------------------- ##
|
|
||||||
|
|
||||||
## - test smtp (STARTTLS), submission (587) (STARTTLS), smtp (SSL),
|
|
||||||
## - pop3 (SSL), pop3 (STARTTLS), imap (SSL) and imap (STARTTLS)
|
|
||||||
## -
|
|
||||||
openssl s_client -crlf -starttls smtp -connect localhost:25 [-state -debug]
|
|
||||||
openssl s_client -crlf -starttls smtp -connect localhost:587
|
|
||||||
openssl s_client -crlf -connect localhost:465
|
|
||||||
openssl s_client -crlf -connect localhost:995
|
|
||||||
openssl s_client -crlf -starttls pop3 -connect localhost:110
|
|
||||||
openssl s_client -crlf -connect localhost:993
|
|
||||||
openssl s_client -crlf -starttls imap -connect localhost:143
|
|
||||||
|
|
||||||
44
DOC/README.test_mailprotocols
Normal file
44
DOC/README.test_mailprotocols
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
|
||||||
|
## -------------------------------------- ##
|
||||||
|
## - some litle tests ##
|
||||||
|
## -------------------------------------- ##
|
||||||
|
|
||||||
|
## -
|
||||||
|
## - test smtp (STARTTLS), submission (587) (STARTTLS), smtp (SSL),
|
||||||
|
## - pop3 (SSL), pop3 (STARTTLS), imap (SSL) and imap (STARTTLS)
|
||||||
|
## -
|
||||||
|
|
||||||
|
# ---
|
||||||
|
# test - localhost
|
||||||
|
# ---
|
||||||
|
|
||||||
|
openssl s_client -crlf -starttls smtp -connect localhost:25 [-state -debug]
|
||||||
|
openssl s_client -crlf -starttls smtp -connect localhost:587
|
||||||
|
openssl s_client -crlf -connect localhost:465
|
||||||
|
openssl s_client -crlf -connect localhost:995
|
||||||
|
openssl s_client -crlf -starttls pop3 -connect localhost:110
|
||||||
|
openssl s_client -crlf -connect localhost:993
|
||||||
|
openssl s_client -crlf -starttls imap -connect localhost:143
|
||||||
|
|
||||||
|
|
||||||
|
# ---
|
||||||
|
# tests - remote mailserver
|
||||||
|
# ---
|
||||||
|
|
||||||
|
mailserver="mx.gemeinschaft-altenschlirf.de"
|
||||||
|
|
||||||
|
openssl s_client -crlf -starttls smtp -connect ${mailserver}:25 [-state -debug]
|
||||||
|
openssl s_client -crlf -starttls smtp -connect ${mailserver}:587
|
||||||
|
openssl s_client -crlf -connect ${mailserver}:465
|
||||||
|
openssl s_client -crlf -connect ${mailserver}:995
|
||||||
|
openssl s_client -crlf -starttls pop3 -connect ${mailserver}:110
|
||||||
|
openssl s_client -crlf -connect ${mailserver}:993
|
||||||
|
openssl s_client -crlf -starttls imap -connect ${mailserver}:143
|
||||||
|
|
||||||
|
|
||||||
|
# Test RSA based TLS connection
|
||||||
|
#
|
||||||
|
echo "quit" | openssl s_client -connect ${mailserver}:25 -starttls smtp -tls1_2 -cipher ECDHE-RSA-AES256-GCM-SHA384
|
||||||
|
|
||||||
|
echo "quit" | openssl s_client -connect ${mailserver}:25 -starttls smtp -tls1_2
|
||||||
|
echo "quit" | openssl s_client -connect ${mailserver}:25 -starttls smtp
|
||||||
@@ -19,3 +19,19 @@ doveadm index -A INBOX
|
|||||||
# -the storage files will be also checked.
|
# -the storage files will be also checked.
|
||||||
# -
|
# -
|
||||||
doveadm force-resync -A INBOX
|
doveadm force-resync -A INBOX
|
||||||
|
|
||||||
|
|
||||||
|
# - Index users .Sent Folder
|
||||||
|
# -
|
||||||
|
doveadm index -u <user@domain.ltd> .Sent
|
||||||
|
|
||||||
|
|
||||||
|
# - oder alternativ und etwas allgemeiner für egal welchen Unterordner
|
||||||
|
# - ==================================================================
|
||||||
|
# -
|
||||||
|
# - Index eines Unterverzeichnisses einer Mailbox löschen
|
||||||
|
# -
|
||||||
|
# - z.Bsp. für den 'gesendet' Ordner der Mailbox presse@mbr-berlin.de
|
||||||
|
# -
|
||||||
|
# - rm /var/vmail/mbr-berlin.de/presse/Maildir/.Sent/dovecot.index*
|
||||||
|
# - systemctl restart dovecot.service
|
||||||
|
|||||||
61
DOC/dovecot/README.maildir-size-fix.pl
Normal file
61
DOC/dovecot/README.maildir-size-fix.pl
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
# ----------
|
||||||
|
# Fix Maildir Size
|
||||||
|
#
|
||||||
|
# falls sich die tatsächliche Größe einer E-mail im Maildir Format
|
||||||
|
# von der Größenangabe im Dateinamen unterscheidet, dann läuft
|
||||||
|
# dovecot auf fehler.
|
||||||
|
#
|
||||||
|
# Es gibt 2 Möglichekeiten das zu verhindern:
|
||||||
|
#
|
||||||
|
# 1. in der dovecot.conf (z.Bsp. in 10-mail.conf deb Parameter
|
||||||
|
# 'maildir_broken_filename_sizes' auf 'yes' setzen
|
||||||
|
#
|
||||||
|
# maildir_broken_filename_sizes = yes
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# 2. Die Größenangaben im Dateinamen korrigieren. Dafür gint es ein Skript
|
||||||
|
# namens 'maildir-size-fix.pl'. Dieses Skript steht bei Githup's
|
||||||
|
# 'dovecot/tools' zur Verfügung:
|
||||||
|
#
|
||||||
|
# https://github.com/dovecot/tools
|
||||||
|
#
|
||||||
|
# Das Perl-Skript maildir-size-fix.pl ist ein Werkzeug, das im Dovecot-Projekt
|
||||||
|
# verwendet wird, um Probleme mit der Größe von Maildir-Dateien zu beheben.
|
||||||
|
#
|
||||||
|
# Nützliche Optionen
|
||||||
|
#
|
||||||
|
# - add_missing_size: Fügt die Größeninformation hinzu, wenn sie fehlt.
|
||||||
|
#
|
||||||
|
# - fix_existing_size: Überprüft und korrigiert bestehende Größeninformationen.
|
||||||
|
#
|
||||||
|
# - recursive: Scannt das Maildir rekursiv, um auch Unterordner zu berücksichtigen.
|
||||||
|
#
|
||||||
|
# - verbose: Ermöglicht detaillierte Protokollierung der Vorgänge.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# ---------------------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Jede E.Mail in einem Maildir Ordner ist eine eigene Datei, dess dateiname üblicherweise
|
||||||
|
# die Größe der datei selbst enthält (..,S=<dateigrösse>,W=..)
|
||||||
|
#
|
||||||
|
# ein typische Datei innerhalb eines Maildirordners sieht so aus:
|
||||||
|
#
|
||||||
|
# 1755713024.M837247P2624513.rage,S=38568,W=39101:2,Sc
|
||||||
|
# | | |
|
||||||
|
# Zeitstempel | Hostname
|
||||||
|
# eind. ID
|
||||||
|
#
|
||||||
|
# S= und ,W=: Dateigröße und "Weighted size" (für IMAP/Quota).
|
||||||
|
#
|
||||||
|
# wobei die flags folgende bedeitung haben:
|
||||||
|
#
|
||||||
|
# +-------+-----------------------------+
|
||||||
|
# | Flag | Bedeutung |
|
||||||
|
# +-------+-----------------------------+
|
||||||
|
# | S | Seen (gelesen) |
|
||||||
|
# | R | Replied (beantwortet) |
|
||||||
|
# | F | Flagged (markiert / wichtig)|
|
||||||
|
# | T | Trashed (zum Löschen mark.) |
|
||||||
|
# | D | Draft (Entwurf) |
|
||||||
|
# | P | Passed (weitergeleitet) |
|
||||||
|
# +-------+-----------------------------+
|
||||||
18
DOC/postfwd/README.default-rate-limits
Normal file
18
DOC/postfwd/README.default-rate-limits
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
default rate limits
|
||||||
|
===================
|
||||||
|
|
||||||
|
- von unbekannten Server 5 Empfänger pro 5 Minuten
|
||||||
|
Message: only 5 recipients per 5 minutes allowed
|
||||||
|
|
||||||
|
- von einer IP-Adresse nicht mehr als 50 Nachrichten pro Minute
|
||||||
|
Message: Too many connections from <IP-Adress>
|
||||||
|
|
||||||
|
- Pro Nachricht nicht mehr als 50 Empfänger
|
||||||
|
Message: Too many recipients, please reduce to less than 50 or consider using a mailing list
|
||||||
|
|
||||||
|
- von einem User (also z.Bsp. cloud@oopen.de) nicht mehr 50 Nachrichten/Stunde
|
||||||
|
Message: Number messages per hour exceeded
|
||||||
|
|
||||||
|
- von einem User (also z.Bsp. cloud@oopen.de) nicht mehr 250 Empfänger/Stunde
|
||||||
|
Message: Number recipients per hour exceeded
|
||||||
|
|
||||||
10
README.disable-milter-mail-filter
Normal file
10
README.disable-milter-mail-filter
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# ----------
|
||||||
|
# Disable Milter (mail filter) for (remote) SMTP client IP address(es).
|
||||||
|
|
||||||
|
# see:
|
||||||
|
# https://www.postfix.org/MILTER_README.html
|
||||||
|
# https://www.postfix.org/MILTER_README.html#per-client
|
||||||
|
#
|
||||||
|
# https://www.postfix.org/postconf.5.html#smtpd_milter_maps
|
||||||
|
|
||||||
|
|
||||||
@@ -58,7 +58,7 @@
|
|||||||
- create configuration file 'install_update_dovecot.conf'
|
- create configuration file 'install_update_dovecot.conf'
|
||||||
cp -a conf install_update_dovecot.conf.sample install_update_dovecot.conf
|
cp -a conf install_update_dovecot.conf.sample install_update_dovecot.conf
|
||||||
- adjust configuration file 'install_update_dovecot.conf' to your needs
|
- adjust configuration file 'install_update_dovecot.conf' to your needs
|
||||||
- run script 'install_update_dovecot.sh'
|
- run script 'install_update_dovecot-2.4.sh' # the old one was: 'install_update_dovecot.sh'
|
||||||
|
|
||||||
Note:
|
Note:
|
||||||
Maybe you have to finish installing postfixadmin, i.e creating admin account(s).
|
Maybe you have to finish installing postfixadmin, i.e creating admin account(s).
|
||||||
|
|||||||
3
README.smtp-over-tor-hidden-services
Normal file
3
README.smtp-over-tor-hidden-services
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
#
|
||||||
|
# see: https://www.void.gr/kargig/blog/2014/05/10/smtp-over-hidden-services-with-postfix/
|
||||||
|
#
|
||||||
159
README.virtual-do-not-reply
Normal file
159
README.virtual-do-not-reply
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
# ====================
|
||||||
|
# Forward E-Mails to 'do-not-reply@..' address to (file) /dev/null
|
||||||
|
# ====================
|
||||||
|
|
||||||
|
# ---
|
||||||
|
# Example for this readme:
|
||||||
|
#
|
||||||
|
# Create a forwarding to /dev/null for the address no-reply@cloud-01.oopen.de
|
||||||
|
# ---
|
||||||
|
|
||||||
|
DOMAIN=""cloud-01.oopen.de
|
||||||
|
E_MAIL="no-reply@cloud-01.oopen.de"
|
||||||
|
|
||||||
|
# see also:
|
||||||
|
# https://www.postfix.org/VIRTUAL_README.html
|
||||||
|
#
|
||||||
|
# https://think.unblog.ch/weiterleiten-von-postfix-alias-an-dev-null/
|
||||||
|
# https://think.unblog.ch/en/forward-postfix-alias-to-dev-null/
|
||||||
|
#
|
||||||
|
# https://www.serverwatch.com/guides/forwarding-a-postfix-virtual-alias-to-dev-null/
|
||||||
|
|
||||||
|
|
||||||
|
# Notice:
|
||||||
|
# the usual solution is to forward to (file) /dev/null. In a local-only setup you could do
|
||||||
|
# that in /etc/aliases.
|
||||||
|
#
|
||||||
|
# However, if your're using Postfix virtual domains, it gets a little more complicated. With
|
||||||
|
# virtual domains/users, you can't forward mail to a file (like /dev/null).
|
||||||
|
|
||||||
|
|
||||||
|
# ---
|
||||||
|
# 1. Set up an alias user 'do-not-reply'that forwards incoming e-mails to /dev/null.
|
||||||
|
# ---
|
||||||
|
|
||||||
|
# Add to file '/etc/aliases' a line like:
|
||||||
|
# do-not-reply: /dev/null
|
||||||
|
|
||||||
|
if ! $(grep -q -E "^\s*do-not-reply:" /etc/aliases 2>/devnull) ; then
|
||||||
|
cat <<EOF >> /etc/aliases
|
||||||
|
|
||||||
|
do-not-reply: /dev/null
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Renew alias database:
|
||||||
|
#
|
||||||
|
newaliases
|
||||||
|
|
||||||
|
|
||||||
|
# ---
|
||||||
|
# 2. Set up the domain (domain part of not-reply address)
|
||||||
|
# ---
|
||||||
|
|
||||||
|
# Create file '/etc/postfix/virtual_alias_domains' and add your domain '@cloud-01.oopen.de'
|
||||||
|
#
|
||||||
|
# ${DOMAIN} OK
|
||||||
|
#
|
||||||
|
if [[ ! -f "/etc/postfix/virtual_alias_domains" ]] ; then
|
||||||
|
|
||||||
|
cat <<EOF >> /etc/postfix/virtual_alias_domains
|
||||||
|
# - File: /etc/postfix/virtual_alias_domains
|
||||||
|
# -
|
||||||
|
# - Note:
|
||||||
|
# - a mapping file always has two columns. In such a 'one-dimensional' mapping (list of domains)
|
||||||
|
# - Postfix does not care about your second column. It does not even have to be 'OK', it can be
|
||||||
|
# - anything.
|
||||||
|
# -
|
||||||
|
# - Example:
|
||||||
|
# - <domain> OK
|
||||||
|
|
||||||
|
${DOMAIN} OK
|
||||||
|
EOF
|
||||||
|
else
|
||||||
|
if ! $(grep -q -E "^\s*${DOMAIN}" /etc/postfix/virtual_alias_domains 2> /dev/null) ; then
|
||||||
|
cat <<EOF >> /etc/postfix/virtual_alias_domains
|
||||||
|
|
||||||
|
${DOMAIN} OK
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# Create Postfix lookup table (database file) from '/etc/postfix/virtual_alias_domains'
|
||||||
|
#
|
||||||
|
postmap btree:/etc/postfix/virtual_alias_domains
|
||||||
|
|
||||||
|
|
||||||
|
# Add virtual_alias_domains to Postfix main Configuration
|
||||||
|
#
|
||||||
|
# ...
|
||||||
|
# virtual_alias_domains =
|
||||||
|
# btree:/etc/postfix/virtual_alias_domains
|
||||||
|
# ...
|
||||||
|
#
|
||||||
|
if ! $(grep -q -E "^\s*virtual_alias_domains\s*=\s*btree:/etc/postfix/virtual_alias_domains" /etc/postfix/main.cf) \
|
||||||
|
&& ! $(grep -q -E "^\s*btree:/etc/postfix/virtual_alias_domains" /etc/postfix/main.cf); then
|
||||||
|
perl -i -n -p -e "s#^(\s*virtual_alias_domains\s*=.*)#\1\n btree:/etc/postfix/virtual_alias_domains#" /etc/postfix/main.cf
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# ---
|
||||||
|
# 3. Set up adress mapping
|
||||||
|
# ---
|
||||||
|
|
||||||
|
# - Create file '/etc/postfix/virtual_alias_maps' and add your address mapping
|
||||||
|
# -
|
||||||
|
# - ${E_MAIL} do-not-reply
|
||||||
|
# -
|
||||||
|
if [[ ! -f "/etc/postfix/virtual_alias_maps" ]] ; then
|
||||||
|
|
||||||
|
cat <<EOF >> /etc/postfix/virtual_alias_maps
|
||||||
|
# - File: /etc/postfix/virtual_alias_maps
|
||||||
|
# -
|
||||||
|
# - Redirect mail for one address to one or more addresses.
|
||||||
|
# -
|
||||||
|
# - Example:
|
||||||
|
# - # incomming address 'no-reply@cloud-01.oopen.de' to local 'do-not-reply' address
|
||||||
|
# - no-reply@cloud-01.oopen.de do-not-reply
|
||||||
|
# -
|
||||||
|
|
||||||
|
${E_MAIL} do-not-reply
|
||||||
|
EOF
|
||||||
|
else
|
||||||
|
if ! $(grep -q -E "^\s*${E_MAIL}" /etc/postfix/virtual_alias_maps 2> /dev/null) ; then
|
||||||
|
cat <<EOF >> /etc/postfix/virtual_alias_maps
|
||||||
|
|
||||||
|
${E_MAIL} do-not-reply
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# Create Postfix lookup table (database file) from '/etc/postfix/virtual_alias_maps'
|
||||||
|
#
|
||||||
|
postmap btree:/etc/postfix/virtual_alias_maps
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Add virtual_alias_maps to Postfix main Configuration
|
||||||
|
#
|
||||||
|
# ...
|
||||||
|
# virtual_alias_maps =
|
||||||
|
# btree:/etc/postfix/virtual_alias_maps
|
||||||
|
# ...
|
||||||
|
#
|
||||||
|
if ! $(grep -q -E "^\s*virtual_alias_maps\s*=\s*btree:/etc/postfix/virtual_alias_maps" /etc/postfix/main.cf) \
|
||||||
|
&& ! $(grep -q -E "^\s*btree:/etc/postfix/virtual_alias_maps" /etc/postfix/main.cf); then
|
||||||
|
perl -i -n -p -e "s#^(\s*virtual_alias_maps\s*=.*)#\1\n btree:/etc/postfix/virtual_alias_maps#" /etc/postfix/main.cf
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# ---
|
||||||
|
# 4. Reload Postfix
|
||||||
|
# ---
|
||||||
|
|
||||||
|
systemctl reload postfix
|
||||||
|
|
||||||
@@ -6,6 +6,8 @@ _HOSTNAME=
|
|||||||
_IPV4=
|
_IPV4=
|
||||||
_IPV6=
|
_IPV6=
|
||||||
|
|
||||||
|
_SASL_AUTH_ENABLED=no
|
||||||
|
|
||||||
_QUARANTINE_DIR=/var/QUARANTINE
|
_QUARANTINE_DIR=/var/QUARANTINE
|
||||||
_QUARANTINE_ADMIN=postmaster\@$mydomain
|
_QUARANTINE_ADMIN=postmaster\@$mydomain
|
||||||
|
|
||||||
|
|||||||
@@ -165,8 +165,16 @@ max_userip_connections=24
|
|||||||
#auth_mechanisms="plain login digest-md5 cram-md5"
|
#auth_mechanisms="plain login digest-md5 cram-md5"
|
||||||
auth_mechanisms="plain login"
|
auth_mechanisms="plain login"
|
||||||
|
|
||||||
|
|
||||||
|
# ---
|
||||||
# - Settings for quota warning sript
|
# - Settings for quota warning sript
|
||||||
# -
|
# ---
|
||||||
|
|
||||||
|
# msg_language
|
||||||
|
#
|
||||||
|
# possible Vallues are 'en' or 'de'
|
||||||
|
#
|
||||||
|
msg_language=de
|
||||||
from_address="o.open <oo@oopen.de>"
|
from_address="o.open <oo@oopen.de>"
|
||||||
reply_to="oo@oopen.de"
|
reply_to="oo@oopen.de"
|
||||||
webmailer="https://webmail.oopen.de"
|
webmailer="https://webmail.oopen.de"
|
||||||
|
|||||||
@@ -115,9 +115,11 @@ DEFAULT_ADMIN_EMAIL="argus@oopen.de"
|
|||||||
|
|
||||||
# - Is this a systemd system?
|
# - Is this a systemd system?
|
||||||
# -
|
# -
|
||||||
if [[ "X`which systemd`" = "X" ]]; then
|
systemd_exists=false
|
||||||
systemd_exists=false
|
systemd=$(which systemd)
|
||||||
else
|
systemctl=$(which systemctl)
|
||||||
|
|
||||||
|
if [[ -n "$systemd" ]] || [[ -n "$systemctl" ]] ; then
|
||||||
systemd_exists=true
|
systemd_exists=true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
1234
install_amavis.sh
1234
install_amavis.sh
File diff suppressed because it is too large
Load Diff
@@ -14,6 +14,8 @@ echo -e "\n \033[32mStart Installation of OpenDKIM..\033[m"
|
|||||||
|
|
||||||
log_file="$(mktemp)"
|
log_file="$(mktemp)"
|
||||||
|
|
||||||
|
backup_date="$(date +%Y-%m-%d-%H%M)"
|
||||||
|
|
||||||
_opendkim_packages="opendkim opendkim-tools"
|
_opendkim_packages="opendkim opendkim-tools"
|
||||||
|
|
||||||
opendkim_base_dir="/etc/opendkim"
|
opendkim_base_dir="/etc/opendkim"
|
||||||
@@ -28,6 +30,7 @@ opendkim_socket_file="${opendkim_socket_dir}/opendkim.sock"
|
|||||||
postfix_needs_restart=false
|
postfix_needs_restart=false
|
||||||
opendkim_needs_restart=false
|
opendkim_needs_restart=false
|
||||||
|
|
||||||
|
|
||||||
# -------------
|
# -------------
|
||||||
# --- Some functions
|
# --- Some functions
|
||||||
# -------------
|
# -------------
|
||||||
@@ -91,9 +94,11 @@ echo_skipped() {
|
|||||||
|
|
||||||
# - Is 'systemd' supported on this system
|
# - Is 'systemd' supported on this system
|
||||||
# -
|
# -
|
||||||
if [ "X`which systemd`" = "X" ]; then
|
SYSTEMD_EXISTS=false
|
||||||
SYSTEMD_EXISTS=false
|
systemd=$(which systemd)
|
||||||
else
|
systemctl=$(which systemctl)
|
||||||
|
|
||||||
|
if [[ -n "$systemd" ]] || [[ -n "$systemctl" ]] ; then
|
||||||
SYSTEMD_EXISTS=true
|
SYSTEMD_EXISTS=true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -175,6 +180,18 @@ else
|
|||||||
echo_skipped
|
echo_skipped
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
echononl " Backup existing file '${opendkim_conf_file}'.."
|
||||||
|
if [[ -f "${opendkim_conf_file}" ]] ; then
|
||||||
|
mv "${opendkim_conf_file}" "${opendkim_conf_file}.${backup_date}"
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
fi
|
||||||
|
|
||||||
# - Create OpenDKIM configuration
|
# - Create OpenDKIM configuration
|
||||||
# -
|
# -
|
||||||
@@ -189,54 +206,212 @@ else
|
|||||||
cat <<EOF > $opendkim_conf_file 2> $log_file
|
cat <<EOF > $opendkim_conf_file 2> $log_file
|
||||||
# Datei $opendkim_conf_file
|
# Datei $opendkim_conf_file
|
||||||
|
|
||||||
|
# AuthservID (string)
|
||||||
|
#
|
||||||
|
# Sets the "authserv-id" to use when generating the Authentication-Results:
|
||||||
|
# header field after verifying a message. The default is to use the name of
|
||||||
|
# the MTA processing the message. If the string "HOSTNAME" is provided, the
|
||||||
|
# name of the host running the filter (as returned by the gethostname(3)
|
||||||
|
# function) will be used.
|
||||||
|
AuthservID HOSTNAME
|
||||||
|
|
||||||
|
# Mode (string)
|
||||||
|
#
|
||||||
# OpenDKIM agiert als Mail Filter (= Milter) in den
|
# OpenDKIM agiert als Mail Filter (= Milter) in den
|
||||||
# Modi signer (s) und verifier (v) und verwendet eine
|
# Modi signer (s) und verifier (v) und verwendet eine
|
||||||
# Socket-Datei zur Kommunikation (alternativ: lokaler Port)
|
# Socket-Datei zur Kommunikation (alternativ: lokaler Port)
|
||||||
Mode sv
|
Mode sv
|
||||||
|
|
||||||
|
# Socket (string)
|
||||||
|
#
|
||||||
|
# Specifies the socket that should be established by the filter to receive
|
||||||
|
# connections from sendmail(8) in order to provide service. socketspec is
|
||||||
|
# in one of two forms: local:path, which creates a UNIX domain socket at
|
||||||
|
# the specified path, or inet:port[@host] or inet6:port[@host] which
|
||||||
|
# creates a TCP socket on the specified port and in the specified protocol
|
||||||
|
# family. If the host is not given as either a hostname or an IP address,
|
||||||
|
# the socket will be listening on all interfaces. A literal IP address must
|
||||||
|
# be enclosed in square brackets. This option is mandatory either in the
|
||||||
|
# configuration file or on the command line.
|
||||||
|
#
|
||||||
# Socket local:/var/run/opendkim/opendkim.sock
|
# Socket local:/var/run/opendkim/opendkim.sock
|
||||||
# Socket local:$opendkim_socket_file
|
# Socket local:$opendkim_socket_file
|
||||||
# Socket inet:12345@localhost
|
# Socket inet:12345@localhost
|
||||||
Socket local:$opendkim_socket_file
|
Socket local:$opendkim_socket_file
|
||||||
|
|
||||||
# OpenDKIM verwendet diesen Benutzer bzw.
|
# UserID (string)
|
||||||
# diese Gruppe
|
#
|
||||||
|
# Attempts to become the specified userid before starting operations. The
|
||||||
|
# value is of the form userid[:group]. The process will be assigned all of
|
||||||
|
# the groups and primary group ID of the named userid unless an alternate
|
||||||
|
# group is specified.
|
||||||
UserID opendkim:opendkim
|
UserID opendkim:opendkim
|
||||||
|
|
||||||
|
# UMask (integer)
|
||||||
|
#
|
||||||
|
#Requests a specific permissions mask to be used for file creation. This
|
||||||
|
# only really applies to creation of the socket when Socket specifies a UNIX
|
||||||
|
# domain socket, and to the PidFile (if any); temporary files are created by
|
||||||
|
# the mkstemp(3) function that enforces a specific file mode on creation
|
||||||
|
# regardless of the process umask. See umask(2) for more information.
|
||||||
|
#
|
||||||
UMask 002
|
UMask 002
|
||||||
|
|
||||||
|
# PidFile (string)
|
||||||
|
#
|
||||||
|
# Specifies the path to a file that should be created at process start
|
||||||
|
# containing the process ID.
|
||||||
PidFile /var/run/opendkim/opendkim.pid
|
PidFile /var/run/opendkim/opendkim.pid
|
||||||
|
|
||||||
# OpenDKIM bei Problemen neustarten,
|
# AutoRestart (Boolean)
|
||||||
# aber max. 10 mal pro Stunde
|
#
|
||||||
|
# Automatically re-start on failures. Use with caution; if the filter fails
|
||||||
|
# instantly after it starts, this can cause a tight fork(2) loop.
|
||||||
AutoRestart yes
|
AutoRestart yes
|
||||||
|
|
||||||
|
# AutoRestartRate (string)
|
||||||
|
#
|
||||||
|
# Sets the maximum automatic restart rate. If the filter begins restarting
|
||||||
|
# faster than the rate defined here, it will give up and terminate. This is
|
||||||
|
# a string of the form n/t[u] where n is an integer limiting the count of
|
||||||
|
# restarts in the given interval and t[u] defines the time interval through
|
||||||
|
# which the rate is calculated; t is an integer and u defines the units thus
|
||||||
|
# represented ("s" or "S" for seconds, the default; "m" or "M" for minutes;
|
||||||
|
# "h" or "H" for hours; "d" or "D" for days). For example, a value of "10/1h"
|
||||||
|
# limits the restarts to 10 in one hour. There is no default, meaning restart
|
||||||
|
# rate is not limited.
|
||||||
AutoRestartRate 10/1h
|
AutoRestartRate 10/1h
|
||||||
|
|
||||||
# Logging (wenn alles funktioniert eventuell reduzieren)
|
# Syslog (Boolean)
|
||||||
|
#
|
||||||
|
# Log via calls to syslog(3) any interesting activity.
|
||||||
Syslog yes
|
Syslog yes
|
||||||
|
|
||||||
|
# SyslogSuccess (Boolean)
|
||||||
|
#
|
||||||
|
# Log via calls to syslog(3) additional entries indicating successful signing
|
||||||
|
# or verification of messages.
|
||||||
SyslogSuccess yes
|
SyslogSuccess yes
|
||||||
|
|
||||||
|
# LogWhy (boolean)
|
||||||
|
#
|
||||||
|
# If logging is enabled (see Syslog below), issues very detailed logging
|
||||||
|
# about the logic behind the filter’s decision to either sign a message or
|
||||||
|
# verify it. The logic behind the decision is non-trivial and can be confusing
|
||||||
|
# to administrators not familiar with its operation. A description of how the
|
||||||
|
# decision is made can be found in the OPERATIONS section of the opendkim(8)
|
||||||
|
# man page. This causes a large increase in the amount of log data generated
|
||||||
|
# for each message, so it should be limited to debugging use and not enabled
|
||||||
|
# for general operation.
|
||||||
LogWhy yes
|
LogWhy yes
|
||||||
|
|
||||||
# Verfahren, wie Header und Body durch
|
# Verfahren, wie Header und Body durch
|
||||||
# OpenDKIM verarbeitet werden sollen.
|
# OpenDKIM verarbeitet werden sollen.
|
||||||
Canonicalization relaxed/simple
|
Canonicalization relaxed/simple
|
||||||
|
|
||||||
# interne Mails nicht mit OpenDKIM verarbeiten
|
# ExternalIgnoreList (dataset)
|
||||||
|
#
|
||||||
|
# Identifies a set of "external" hosts that may send mail through the server
|
||||||
|
# as one of the signing domains without credentials as such. This has the
|
||||||
|
# effect of suppressing the "external host (hostname) tried to send mail as
|
||||||
|
# (domain)" log messages. Entries in the data set should be of the same form
|
||||||
|
# as those of the PeerList option below. The set is empty by default.
|
||||||
ExternalIgnoreList refile:${opendkim_base_dir}/trusted
|
ExternalIgnoreList refile:${opendkim_base_dir}/trusted
|
||||||
|
|
||||||
|
# InternalHosts (dataset)
|
||||||
|
#
|
||||||
|
# Identifies a set internal hosts whose mail should be signed rather than
|
||||||
|
# verified. Entries in this data set follow the same form as those of the
|
||||||
|
# PeerList option below. If not specified, the default of "127.0.0.1" is applied.
|
||||||
|
# Naturally, providing a value here overrides the default, so if mail from
|
||||||
|
# 127.0.0.1 should be signed, the list provided here should include that address
|
||||||
|
# explicitly.
|
||||||
InternalHosts refile:${opendkim_base_dir}/trusted
|
InternalHosts refile:${opendkim_base_dir}/trusted
|
||||||
|
|
||||||
# welche Verschlüsselungs-Keys sollen für welche
|
# SigningTable (dataset)
|
||||||
# Domains verwendet werden
|
#
|
||||||
# (refile: für Dateien mit regulären Ausdrücke)
|
# Defines a table used to select one or more signatures to apply to a message
|
||||||
|
# based on the address found in the From: header field. Keys in this table vary
|
||||||
|
# depending on the type of table used; values in this data set should include
|
||||||
|
# one field that contains a name found in the KeyTable (see above) that
|
||||||
|
# identifies which key should be used in generating the signature, and an
|
||||||
|
# optional second field naming the signer of the message that will be included
|
||||||
|
# in the "i=" tag in the generated signature. Note that the "i=" value will not
|
||||||
|
# be included in the signature if it conflicts with the signing domain
|
||||||
|
# (the "d=" value).
|
||||||
|
#
|
||||||
|
# If the first field contains only a "%" character, it will be replaced by the
|
||||||
|
# domain found in the From: header field. Similarly, within the optional second
|
||||||
|
# field, any "%" character will be replaced by the domain found in the From:
|
||||||
|
# header field.
|
||||||
|
#
|
||||||
|
# If this table specifies a regular expression file ("refile"), then the keys are
|
||||||
|
# wildcard patterns that are matched against the address found in the From:
|
||||||
|
# header field. Entries are checked in the order in which they appear in the file.
|
||||||
|
#
|
||||||
|
# For all other database types, the full user@host is checked first, then simply
|
||||||
|
# host, then user@.domain (with all superdomains checked in sequence, so
|
||||||
|
# "foo.example.com" would first check "user@foo.example.com", then "user@.example.com",
|
||||||
|
# then "user@.com"), then .domain, then user@*, and finally *.
|
||||||
SigningTable refile:${opendkim_base_dir}/signing.table
|
SigningTable refile:${opendkim_base_dir}/signing.table
|
||||||
|
|
||||||
|
# KeyTable (dataset)
|
||||||
|
#
|
||||||
|
# Gives the location of a file mapping key names to signing keys. If present,
|
||||||
|
# overrides any KeyFile setting in the configuration file. The data set named here
|
||||||
|
# maps each key name to three values: (a) the name of the domain to use in the
|
||||||
|
# signature's "d=" value; (b) the name of the selector to use in the signature's
|
||||||
|
# "s=" value; and (c) either a private key or a path to a file containing a private
|
||||||
|
# key. If the first value consists solely of a percent sign ("%") character, it
|
||||||
|
# will be replaced by the apparent domain of the sender when generating a signature.
|
||||||
|
# If the third value starts with a slash ("/") character, or "./" or "../", then it
|
||||||
|
# is presumed to refer to a file from which the private key should be read, otherwise
|
||||||
|
# it is itself a PEM-encoded private key or a base64-encoded DER private key; a "%"
|
||||||
|
# in the third value in this case will be replaced by the apparent domain name of
|
||||||
|
# the sender. The SigningTable (see below) is used to select records from this table
|
||||||
|
# to be used to add signatures based on the message sender.
|
||||||
KeyTable ${opendkim_base_dir}/key.table
|
KeyTable ${opendkim_base_dir}/key.table
|
||||||
|
|
||||||
# diesen Signatur-Algorithmus verwenden
|
# SignatureAlgorithm (string)
|
||||||
|
#
|
||||||
|
# Selects the signing algorithm to use when generating signatures. Use 'opendkim -V'
|
||||||
|
# to see the list of supported algorithms. The default is rsa-sha256 if it is
|
||||||
|
# available, otherwise it will be rsa-sha1.
|
||||||
SignatureAlgorithm rsa-sha256
|
SignatureAlgorithm rsa-sha256
|
||||||
|
|
||||||
# Always oversign From (sign using actual From and a null From to prevent
|
# OversignHeaders (dataset)
|
||||||
# malicious signatures header fields (From and/or others) between the signer
|
#
|
||||||
# and the verifier. From is oversigned by default in the Debian pacakge
|
# Specifies a set of header fields that should be included in all signature header
|
||||||
# because it is often the identity key used by reputation systems and thus
|
# lists (the "h=" tag) once more than the number of times they were actually present
|
||||||
# somewhat security sensitive.
|
# in the signed message. The set is empty by default. The purpose of this, and
|
||||||
|
# especially of listing an absent header field, is to prevent the addition of
|
||||||
|
# important fields between the signer and the verifier. Since the verifier would
|
||||||
|
# include that header field when performing verification if it had been added by an
|
||||||
|
# intermediary, the signed message and the verified message were different and the
|
||||||
|
# verification would fail. Note that listing a field name here and not listing it in
|
||||||
|
# the SignHeaders list is likely to generate invalid signatures.
|
||||||
OversignHeaders From
|
OversignHeaders From
|
||||||
|
|
||||||
|
# AlwaysAddARHeader (Boolean)
|
||||||
|
#
|
||||||
|
# Add an "Authentication-Results:" header field even to unsigned messages
|
||||||
|
# from domains with no "signs all" policy. The reported DKIM result will be
|
||||||
|
# "none" in such cases. Normally unsigned mail from non-strict domains does
|
||||||
|
# not cause the results header field to be added.
|
||||||
|
AlwaysAddARHeader yes
|
||||||
|
|
||||||
|
# Background (Boolean)
|
||||||
|
#
|
||||||
|
# Causes opendkim to fork and exits immediately, leaving the service running
|
||||||
|
# in the background. The default is "true".
|
||||||
|
Background yes
|
||||||
|
|
||||||
|
# DNSTimeout (integer)
|
||||||
|
#
|
||||||
|
# Sets the DNS timeout in seconds. A value of 0 causes an infinite wait. The
|
||||||
|
# default is 5. Ignored if not using an asynchronous resolver package. See
|
||||||
|
# also the NOTES section below.
|
||||||
|
DNSTimeout 5
|
||||||
EOF
|
EOF
|
||||||
opendkim_needs_restart=true
|
opendkim_needs_restart=true
|
||||||
if [[ $? -eq 0 ]] ; then
|
if [[ $? -eq 0 ]] ; then
|
||||||
@@ -351,7 +526,6 @@ else
|
|||||||
127.0.0.1
|
127.0.0.1
|
||||||
::1
|
::1
|
||||||
localhost
|
localhost
|
||||||
$(hostname -f)
|
|
||||||
EOF
|
EOF
|
||||||
opendkim_needs_restart=true
|
opendkim_needs_restart=true
|
||||||
if [[ $? -eq 0 ]] ; then
|
if [[ $? -eq 0 ]] ; then
|
||||||
@@ -469,7 +643,36 @@ milter_protocol = 6
|
|||||||
# localhost:10025 section in master.cf: 'smtpd_milters='
|
# localhost:10025 section in master.cf: 'smtpd_milters='
|
||||||
#
|
#
|
||||||
#smtpd_milters = local:/opendkim/opendkim.sock
|
#smtpd_milters = local:/opendkim/opendkim.sock
|
||||||
smtpd_milters =
|
smtpd_milters = local:/opendkim/opendkim.sock
|
||||||
|
|
||||||
|
# Was sind non_smtpd_milters?
|
||||||
|
#
|
||||||
|
# non_smtpd_milters gilt für alle Postfix-Prozesse, die Mails verarbeiten, aber NICHT
|
||||||
|
# der smtpd-Daemon sind.
|
||||||
|
#
|
||||||
|
# Das betrifft z. B.:
|
||||||
|
#
|
||||||
|
# cleanup Header/Content-Bereinigung
|
||||||
|
# qmgr Queue-Manager
|
||||||
|
# lmtp / smtp Auslieferung nach extern
|
||||||
|
# local lokale Zustellung
|
||||||
|
#
|
||||||
|
# Das sind z. B.:
|
||||||
|
#
|
||||||
|
# - interne Bounces (MAILER-DAEMON)
|
||||||
|
#
|
||||||
|
# - Cron-Mails vom Server
|
||||||
|
#
|
||||||
|
# - Weiterleitungen, die Postfix selbst generiert
|
||||||
|
#
|
||||||
|
# - Mails, die über sendmail CLI gesendet werden
|
||||||
|
#
|
||||||
|
# - Mails, die Amavis über LMTP zurückgibt
|
||||||
|
#
|
||||||
|
# - etc.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# DKIM soll auch die ausgehenden Mails signieren, die nicht über smtpd daemon versendet werden.
|
||||||
non_smtpd_milters = local:/opendkim/opendkim.sock
|
non_smtpd_milters = local:/opendkim/opendkim.sock
|
||||||
EOF
|
EOF
|
||||||
postfix_needs_restart=true
|
postfix_needs_restart=true
|
||||||
@@ -520,9 +723,15 @@ while IFS='' read -r _line || [[ -n $_line ]] ; do
|
|||||||
|
|
||||||
if $_found && echo "$_line" | grep -i -q -E "^\s*-o\s+smtpd_milters=\s*" ; then
|
if $_found && echo "$_line" | grep -i -q -E "^\s*-o\s+smtpd_milters=\s*" ; then
|
||||||
_found=false
|
_found=false
|
||||||
|
if ! echo "$_line" | grep -i -q -E "^\s*-o\s+smtpd_milters=\s*local:/opendkim/opendkim.sock\s*$" ; then
|
||||||
|
echo " -o smtpd_milters=local:/opendkim/opendkim.sock" >> "$tmp_master_file"
|
||||||
|
echo " -o milter_macro_daemon_name=ORIGINATING" >> "$tmp_master_file"
|
||||||
|
_changed=true
|
||||||
|
continue
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if echo "$_line" | grep -i -q -E "^\s*(127.0.0.1|localhost):10025\s+inet\s+" 2> /dev/null ; then
|
if echo "$_line" | grep -i -q -E "^\s*(submission|smtps)\s+inet\s+" 2> /dev/null ; then
|
||||||
_found=true
|
_found=true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -540,7 +749,7 @@ if $_changed ; then
|
|||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo_skipped
|
echo_skipped
|
||||||
warn "Postfix (master.cf) seems already be configured."
|
info "Postfix (master.cf) was not changed - seems already be configured right."
|
||||||
echononl " Delete previosly saved file '/etc/postfix/master.cf'.."
|
echononl " Delete previosly saved file '/etc/postfix/master.cf'.."
|
||||||
rm /etc/postfix/master.cf.$backup_date 2> $log_file
|
rm /etc/postfix/master.cf.$backup_date 2> $log_file
|
||||||
if [[ $? -eq 0 ]] ; then
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
clear
|
clear
|
||||||
echo -e "\n \033[32mStart Installation of OpenDMARC..\033[m"
|
echo -e "\n \033[32mStart Installation of OpenDMARC..\033[m"
|
||||||
|
|
||||||
|
overwrite_config_files=true
|
||||||
|
|
||||||
|
|
||||||
# -------------
|
# -------------
|
||||||
@@ -23,22 +24,26 @@ opendmarc_socket_dir="${postfix_spool_dir}/opendmarc"
|
|||||||
opendmarc_socket_file="${opendmarc_socket_dir}/opendmarc.sock"
|
opendmarc_socket_file="${opendmarc_socket_dir}/opendmarc.sock"
|
||||||
|
|
||||||
config_file_name_value_parameters="
|
config_file_name_value_parameters="
|
||||||
AuthservID|OpenDMARC
|
AuthservID|HOSTNAME
|
||||||
|
TrustedAuthservIDs|HOSTNAME
|
||||||
PidFile|/run/opendmarc/opendmarc.pid
|
PidFile|/run/opendmarc/opendmarc.pid
|
||||||
RejectFailures|true
|
RejectFailures|true
|
||||||
Syslog|true
|
Syslog|true
|
||||||
SyslogFacility|mail
|
SyslogFacility|mail
|
||||||
TrustedAuthservIDs|$(hostname -f)
|
IgnoreHosts|${opendmarc_base_dir}/ignore.hosts
|
||||||
IgnoreHosts|/etc/opendmarc/ignore.hosts
|
IgnoreMailFrom|${opendmarc_base_dir}/ignore.mailfrom
|
||||||
IgnoreAuthenticatedClients|true
|
IgnoreAuthenticatedClients|true
|
||||||
RequiredHeaders|true
|
RequiredHeaders|false
|
||||||
UMask|002
|
UMask|002
|
||||||
FailureReports|false
|
FailureReports|false
|
||||||
AutoRestart|true
|
AutoRestart|true
|
||||||
HistoryFile|/run/opendmarc/opendmarc.dat
|
HistoryFile|/run/opendmarc/opendmarc.dat
|
||||||
|
SPFIgnoreResults|false
|
||||||
SPFSelfValidate|true
|
SPFSelfValidate|true
|
||||||
Socket|${opendmarc_socket_file}
|
Socket|${opendmarc_socket_file}
|
||||||
"
|
"
|
||||||
|
|
||||||
|
|
||||||
declare -a config_file_name_value_parameter_arr=()
|
declare -a config_file_name_value_parameter_arr=()
|
||||||
for _conf in $config_file_name_value_parameters ; do
|
for _conf in $config_file_name_value_parameters ; do
|
||||||
config_file_name_value_parameter_arr+=("$_conf")
|
config_file_name_value_parameter_arr+=("$_conf")
|
||||||
@@ -113,9 +118,11 @@ echo_skipped() {
|
|||||||
|
|
||||||
# - Is 'systemd' supported on this system
|
# - Is 'systemd' supported on this system
|
||||||
# -
|
# -
|
||||||
if [ "X`which systemd`" = "X" ]; then
|
SYSTEMD_EXISTS=false
|
||||||
SYSTEMD_EXISTS=false
|
systemd=$(which systemd)
|
||||||
else
|
systemctl=$(which systemctl)
|
||||||
|
|
||||||
|
if [[ -n "$systemd" ]] || [[ -n "$systemctl" ]] ; then
|
||||||
SYSTEMD_EXISTS=true
|
SYSTEMD_EXISTS=true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -182,6 +189,240 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# - Add 'IgnoreHosts' with default value to the original opendmarc.conf file
|
||||||
|
#
|
||||||
|
echononl " Add 'IgnoreHosts' with default value to the opendmarc.conf file.."
|
||||||
|
if ! $(grep -q -E "^IgnoreHosts\s+" ${opendmarc_conf_file} 2> /dev/null) ; then
|
||||||
|
cat << EOF >> ${opendmarc_conf_file}
|
||||||
|
|
||||||
|
## IgnoreHosts (string)
|
||||||
|
##
|
||||||
|
## Specifies the path to a file that contains a list of hostnames, IP addresses,
|
||||||
|
## and/or CIDR expressions identifying hosts whose SMTP connections are to be
|
||||||
|
## ignored by the filter. If not specified, defaults to "127.0.0.1" only.
|
||||||
|
#
|
||||||
|
IgnoreHosts /etc/opendmarc/ignore.hosts
|
||||||
|
EOF
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# - Add 'IgnoreMailFrom' with default value to the original opendmarc.conf file
|
||||||
|
#
|
||||||
|
echononl " Add 'IgnoreMailFrom' with default value to the opendmarc.conf file.."
|
||||||
|
if ! $(grep -q -E "^IgnoreMailFrom\s+" ${opendmarc_conf_file} 2> /dev/null) ; then
|
||||||
|
cat << EOF >> ${opendmarc_conf_file}
|
||||||
|
|
||||||
|
## IgnoreMailFrom (string)
|
||||||
|
##
|
||||||
|
## Gives a list of domain names whose mail (based on the From: domain)
|
||||||
|
## is to be ignored by the filter. The list should be comma-separated.
|
||||||
|
## Matching against this list is case-insensitive. The default is an
|
||||||
|
## empty list, meaning no mail is ignored.
|
||||||
|
#
|
||||||
|
IgnoreMailFrom /etc/opendmarc/ignore.mailfrom
|
||||||
|
EOF
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# - Add 'IgnoreAuthenticatedClients' with default value to the original opendmarc.conf file
|
||||||
|
#
|
||||||
|
_param="IgnoreAuthenticatedClients"
|
||||||
|
echononl " Add '${_param}' with default value to the opendmarc.conf file.."
|
||||||
|
if ! $(grep -q -E "^${_param}\s+" ${opendmarc_conf_file} 2> /dev/null) ; then
|
||||||
|
cat << EOF >> ${opendmarc_conf_file}
|
||||||
|
|
||||||
|
## IgnoreAuthenticatedClients (Boolean)
|
||||||
|
##
|
||||||
|
## If set, causes mail from authenticated clients (i.e., those that used
|
||||||
|
## SMTP AUTH) to be ignored by the filter. The default is "false".
|
||||||
|
#
|
||||||
|
IgnoreAuthenticatedClients true
|
||||||
|
EOF
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# - Add 'TrustedAuthservIDs' with default value to the original opendmarc.conf file
|
||||||
|
#
|
||||||
|
_param="TrustedAuthservIDs"
|
||||||
|
echononl " Add '${_param}' with default value to the opendmarc.conf file.."
|
||||||
|
if ! $(grep -q -E "^${_param}\s+" ${opendmarc_conf_file} 2> /dev/null) ; then
|
||||||
|
cat << EOF >> ${opendmarc_conf_file}
|
||||||
|
|
||||||
|
# Provides a list of authserv-ids that are to be used to identify Authentication-Results
|
||||||
|
# header fields whose contents are to be assumed as valid input for the DMARC assessment.
|
||||||
|
# To provide a list, separate values by commas. If the string "HOSTNAME" is provided,
|
||||||
|
# the name of the host running the filter (as returned by the gethostname(3) function)
|
||||||
|
# will be used. Matching against this list is case-insensitive. The default is to use the
|
||||||
|
# value of AuthservID.
|
||||||
|
#
|
||||||
|
TrustedAuthservIDs HOSTNAME
|
||||||
|
EOF
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# - Add 'RequiredHeaders' with default value to the original opendmarc.conf file
|
||||||
|
#
|
||||||
|
_param="RequiredHeaders"
|
||||||
|
echononl " Add '${_param}' with default value to the opendmarc.conf file.."
|
||||||
|
if ! $(grep -q -E "^${_param}\s+" ${opendmarc_conf_file} 2> /dev/null) ; then
|
||||||
|
cat << EOF >> ${opendmarc_conf_file}
|
||||||
|
|
||||||
|
## RequiredHeaders (Boolean)
|
||||||
|
##
|
||||||
|
## If set, the filter will ensure the header of the message conforms to the basic
|
||||||
|
## header field count restrictions laid out in RFC5322, Section 3.6. Messages
|
||||||
|
## failing this test are rejected without further processing. A From: field from
|
||||||
|
## which no domain name could be extracted will also be rejected.
|
||||||
|
#
|
||||||
|
RequiredHeaders false
|
||||||
|
EOF
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# - Add 'AutoRestart' with default value to the original opendmarc.conf file
|
||||||
|
#
|
||||||
|
_param="AutoRestart"
|
||||||
|
echononl " Add '${_param}' with default value to the opendmarc.conf file.."
|
||||||
|
if ! $(grep -q -E "^${_param}\s+" ${opendmarc_conf_file} 2> /dev/null) ; then
|
||||||
|
cat << EOF >> ${opendmarc_conf_file}
|
||||||
|
|
||||||
|
## AutoRestart (Boolean)
|
||||||
|
##
|
||||||
|
## Automatically re-start on failures. Use with caution; if the filter fails
|
||||||
|
## instantly after it starts, this can cause a tight fork(2) loop.
|
||||||
|
#
|
||||||
|
AutoRestart true
|
||||||
|
EOF
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# - Add 'HistoryFile' with default value to the original opendmarc.conf file
|
||||||
|
#
|
||||||
|
_param="HistoryFile"
|
||||||
|
echononl " Add '${_param}' with default value to the opendmarc.conf file.."
|
||||||
|
if ! $(grep -q -E "^${_param}\s+" ${opendmarc_conf_file} 2> /dev/null) ; then
|
||||||
|
cat << EOF >> ${opendmarc_conf_file}
|
||||||
|
|
||||||
|
## HistoryFile (string)
|
||||||
|
##
|
||||||
|
## If set, specifies the location of a text file to which records are written
|
||||||
|
## that can be used to generate DMARC aggregate reports. Records are batches of
|
||||||
|
## rows containing information about a single received message, and include all
|
||||||
|
## relevant information needed to generate a DMARC aggregate report. It is
|
||||||
|
## expected that this will not be used in its raw form, but rather periodically
|
||||||
|
## imported into a relational database from which the aggregate reports can be
|
||||||
|
## extracted using opendmarc-importstats(8).
|
||||||
|
#
|
||||||
|
#HistoryFile /run/opendmarc/opendmarc.dat
|
||||||
|
EOF
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# - Add 'SPFIgnoreResults' with default value to the original opendmarc.conf file
|
||||||
|
#
|
||||||
|
_param="SPFIgnoreResults"
|
||||||
|
echononl " Add '${_param}' with default value to the opendmarc.conf file.."
|
||||||
|
if ! $(grep -q -E "^${_param}\s+" ${opendmarc_conf_file} 2> /dev/null) ; then
|
||||||
|
cat << EOF >> ${opendmarc_conf_file}
|
||||||
|
|
||||||
|
## Causes the filter to ignore any SPF results in the header of the message. This
|
||||||
|
## is useful if you want the filter to perform SPF checks itself, or because you
|
||||||
|
## don't trust the arriving header. The default is "false".
|
||||||
|
#
|
||||||
|
SPFIgnoreResults false
|
||||||
|
EOF
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# - Add 'SPFSelfValidate' with default value to the original opendmarc.conf file
|
||||||
|
#
|
||||||
|
_param="SPFSelfValidate"
|
||||||
|
echononl " Add '${_param}' with default value to the opendmarc.conf file.."
|
||||||
|
if ! $(grep -q -E "^${_param}\s+" ${opendmarc_conf_file} 2> /dev/null) ; then
|
||||||
|
cat << EOF >> ${opendmarc_conf_file}
|
||||||
|
|
||||||
|
## Causes the filter to perform a fallback SPF check itself when it can find no
|
||||||
|
## SPF results in the message header. If SPFIgnoreResults is also set, it never
|
||||||
|
## looks for SPF results in headers and always performs the SPF check itself when
|
||||||
|
## this is set. The default is "false".
|
||||||
|
#
|
||||||
|
SPFSelfValidate true
|
||||||
|
EOF
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
# - Save configuration file from distribution
|
# - Save configuration file from distribution
|
||||||
# -
|
# -
|
||||||
echononl " Save configuration file from distribution"
|
echononl " Save configuration file from distribution"
|
||||||
@@ -203,15 +444,6 @@ for _val in "${config_file_name_value_parameter_arr[@]}" ; do
|
|||||||
echononl " $opendmarc_conf_file: ${_val_arr[0]} -> ${_val_arr[1]}.."
|
echononl " $opendmarc_conf_file: ${_val_arr[0]} -> ${_val_arr[1]}.."
|
||||||
if $(grep -E -q "^\s*${_val_arr[0]}\s+${_val_arr[1]}\s*$" $opendmarc_conf_file 2> /dev/null) ; then
|
if $(grep -E -q "^\s*${_val_arr[0]}\s+${_val_arr[1]}\s*$" $opendmarc_conf_file 2> /dev/null) ; then
|
||||||
echo_skipped
|
echo_skipped
|
||||||
elif $(grep -E -q "^\s*#\s*${_val_arr[0]}\s+" $opendmarc_conf_file 2> /dev/null); then
|
|
||||||
perl -i -n -p -e "s&^(\s*#\s*${_val_arr[0]}.*)&\1\n${_val_arr[0]} ${_val_arr[1]}&" $opendmarc_conf_file > "$log_file" 2>&1
|
|
||||||
if [[ $? -eq 0 ]] ; then
|
|
||||||
echo_ok
|
|
||||||
opendmarc_needs_restart=true
|
|
||||||
else
|
|
||||||
echo_failed
|
|
||||||
error "$(cat $log_file)"
|
|
||||||
fi
|
|
||||||
elif $(grep -E -q "^\s*${_val_arr[0]}\s+" $opendmarc_conf_file 2> /dev/null) ; then
|
elif $(grep -E -q "^\s*${_val_arr[0]}\s+" $opendmarc_conf_file 2> /dev/null) ; then
|
||||||
perl -i -n -p -e "s#^(\s*${_val_arr[0]}.*)#\#\1\n${_val_arr[0]} ${_val_arr[1]}#" $opendmarc_conf_file > "$log_file" 2>&1
|
perl -i -n -p -e "s#^(\s*${_val_arr[0]}.*)#\#\1\n${_val_arr[0]} ${_val_arr[1]}#" $opendmarc_conf_file > "$log_file" 2>&1
|
||||||
if [[ $? -eq 0 ]] ; then
|
if [[ $? -eq 0 ]] ; then
|
||||||
@@ -221,11 +453,8 @@ for _val in "${config_file_name_value_parameter_arr[@]}" ; do
|
|||||||
echo_failed
|
echo_failed
|
||||||
error "$(cat $log_file)"
|
error "$(cat $log_file)"
|
||||||
fi
|
fi
|
||||||
else
|
elif $(grep -E -q "^\s*#\s*${_val_arr[0]}\s+" $opendmarc_conf_file 2> /dev/null); then
|
||||||
cat <<EOF >> $opendmarc_conf_file 2> "$log_file"
|
perl -i -n -p -e "s&^(\s*#\s*${_val_arr[0]}.*)&\1\n${_val_arr[0]} ${_val_arr[1]}&" $opendmarc_conf_file > "$log_file" 2>&1
|
||||||
|
|
||||||
${_val_arr[0]} ${_val_arr[1]}
|
|
||||||
EOF
|
|
||||||
if [[ $? -eq 0 ]] ; then
|
if [[ $? -eq 0 ]] ; then
|
||||||
echo_ok
|
echo_ok
|
||||||
opendmarc_needs_restart=true
|
opendmarc_needs_restart=true
|
||||||
@@ -233,6 +462,100 @@ EOF
|
|||||||
echo_failed
|
echo_failed
|
||||||
error "$(cat $log_file)"
|
error "$(cat $log_file)"
|
||||||
fi
|
fi
|
||||||
|
else
|
||||||
|
if [[ "${_val_arr[0]}" == "IgnoreHosts" ]]; then
|
||||||
|
cat <<EOF >> $opendmarc_conf_file 2> "$log_file"
|
||||||
|
|
||||||
|
## IgnoreHosts (string)
|
||||||
|
##
|
||||||
|
## Specifies the path to a file that contains a list of hostnames, IP
|
||||||
|
## addresses, and/or CIDR expressions identifying hosts whose SMTP
|
||||||
|
## connections are to be ignored by the filter. If not specified,
|
||||||
|
## defaults to "127.0.0.1" only.
|
||||||
|
#
|
||||||
|
${_val_arr[0]} ${_val_arr[1]}
|
||||||
|
EOF
|
||||||
|
elif [[ "${_val_arr[0]}" == "IgnoreMailFrom" ]]; then
|
||||||
|
cat <<EOF >> $opendmarc_conf_file 2> "$log_file"
|
||||||
|
|
||||||
|
## IgnoreMailFrom (string)
|
||||||
|
##
|
||||||
|
## Gives a list of domain names whose mail (based on the From: domain)
|
||||||
|
## is to be ignored by the filter. The list should be comma-separated.
|
||||||
|
## Matching against this list is case-insensitive. The default is an
|
||||||
|
## empty list, meaning no mail is ignored.
|
||||||
|
#
|
||||||
|
${_val_arr[0]} ${_val_arr[1]}
|
||||||
|
EOF
|
||||||
|
elif [[ "${_val_arr[0]}" == "IgnoreAuthenticatedClients" ]]; then
|
||||||
|
cat <<EOF >> $opendmarc_conf_file 2> "$log_file"
|
||||||
|
|
||||||
|
## IgnoreAuthenticatedClients (Boolean)
|
||||||
|
##
|
||||||
|
## If set, causes mail from authenticated clients (i.e., those that used
|
||||||
|
## SMTP AUTH) to be ignored by the filter. The default is "false".
|
||||||
|
#
|
||||||
|
${_val_arr[0]} ${_val_arr[1]}
|
||||||
|
EOF
|
||||||
|
elif [[ "${_val_arr[0]}" == "AutoRestart" ]]; then
|
||||||
|
cat <<EOF >> $opendmarc_conf_file 2> "$log_file"
|
||||||
|
## AutoRestart (Boolean)
|
||||||
|
##
|
||||||
|
## Automatically re-start on failures. Use with caution; if the filter
|
||||||
|
## fails instantly after it starts, this can cause a tight fork(2)
|
||||||
|
## loop.
|
||||||
|
#
|
||||||
|
${_val_arr[0]} ${_val_arr[1]}
|
||||||
|
EOF
|
||||||
|
elif [[ "${_val_arr[0]}" == "RequiredHeaders" ]]; then
|
||||||
|
cat <<EOF >> $opendmarc_conf_file 2> "$log_file"
|
||||||
|
|
||||||
|
## RequiredHeaders (Boolean)
|
||||||
|
##
|
||||||
|
## If set, the filter will ensure the header of the message conforms to
|
||||||
|
## the basic header field count restrictions laid out in RFC5322,
|
||||||
|
## Section 3.6. Messages failing this test are rejected without further
|
||||||
|
## processing. A From: field from which no domain name could be
|
||||||
|
## extracted will also be rejected.
|
||||||
|
#
|
||||||
|
${_val_arr[0]} ${_val_arr[1]}
|
||||||
|
EOF
|
||||||
|
elif [[ "${_val_arr[0]}" == "SPFSelfValidate" ]]; then
|
||||||
|
cat <<EOF >> $opendmarc_conf_file 2> "$log_file"
|
||||||
|
## SPFSelfValidate (Boolean)
|
||||||
|
##
|
||||||
|
## Causes the filter to perform a fallback SPF check itself when it can
|
||||||
|
## find no SPF results in the message header. If SPFIgnoreResults is
|
||||||
|
## also set, it never looks for SPF results in headers and always
|
||||||
|
## performs the SPF check itself when this is set. The default is
|
||||||
|
## "false".
|
||||||
|
#
|
||||||
|
${_val_arr[0]} ${_val_arr[1]}
|
||||||
|
EOF
|
||||||
|
elif [[ "${_val_arr[0]}" == "SPFIgnoreResults" ]]; then
|
||||||
|
cat <<EOF >> $opendmarc_conf_file 2> "$log_file"
|
||||||
|
## SPFIgnoreResults (Boolean)
|
||||||
|
##
|
||||||
|
## Causes the filter to ignore any SPF results in the header of the
|
||||||
|
## message. This is useful if you want the filter to perform SPF checks
|
||||||
|
## itself, or because you don't trust the arriving header. The default
|
||||||
|
## is "false".
|
||||||
|
#
|
||||||
|
${_val_arr[0]} ${_val_arr[1]}
|
||||||
|
EOF
|
||||||
|
else
|
||||||
|
cat <<EOF >> $opendmarc_conf_file 2> "$log_file"
|
||||||
|
|
||||||
|
${_val_arr[0]} ${_val_arr[1]}
|
||||||
|
EOF
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
opendmarc_needs_restart=true
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
@@ -277,6 +600,18 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
echononl " Backup existing file '${opendmarc_base_dir}/ignore.hosts'.."
|
||||||
|
if [[ -f "${opendmarc_base_dir}/ignore.hosts" ]] ; then
|
||||||
|
mv "${opendmarc_base_dir}/ignore.hosts" "${opendmarc_base_dir}/ignore.hosts.${backup_date}"
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
fi
|
||||||
|
|
||||||
# - Create the file ${opendmarc_base_dir}/ignore.hosts
|
# - Create the file ${opendmarc_base_dir}/ignore.hosts
|
||||||
# -
|
# -
|
||||||
@@ -285,11 +620,68 @@ if [[ -f "${opendmarc_base_dir}/ignore.hosts" ]] ; then
|
|||||||
echo_skipped
|
echo_skipped
|
||||||
else
|
else
|
||||||
cat <<EOF > ${opendmarc_base_dir}/ignore.hosts 2> $log_file
|
cat <<EOF > ${opendmarc_base_dir}/ignore.hosts 2> $log_file
|
||||||
# We are using AmaViS at 'localhost 127.0.0.1 . So we cannot bypass them
|
# /etc/opendmarc/ignore.hosts
|
||||||
#
|
#
|
||||||
# 127.0.0.1
|
# Aktuell hat OpenDMARC seinen Milter nur am Dienst
|
||||||
# localhost
|
# 'localhost:10025' hängen. Dort ist der Client
|
||||||
$(hostname -f)
|
# immer 127.0.0.1, nicht die externe Gegenstelle.
|
||||||
|
#
|
||||||
|
# Deshalb macht es in diesem Setup keinen Sinn,
|
||||||
|
# hier IP-Adressen von externen Diensten (CRSend etc.)
|
||||||
|
# einzutragen – sie würden nie matchen.
|
||||||
|
#
|
||||||
|
# WICHTIG:
|
||||||
|
# - KEIN 127.0.0.1
|
||||||
|
# - KEIN localhost
|
||||||
|
# - KEIN ::1
|
||||||
|
#
|
||||||
|
# Eintrag dieser Adressen würde DMARC komplett deaktivieren.
|
||||||
|
#
|
||||||
|
# ==> Datei bleibt absichtlich leer.
|
||||||
|
EOF
|
||||||
|
opendmarc_needs_restart=true
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# - Create the file ${opendmarc_base_dir}/ignore.hosts
|
||||||
|
# -
|
||||||
|
|
||||||
|
echononl " Backup existing file '${opendmarc_base_dir}/ignore.mailfrom'.."
|
||||||
|
if [[ -f "${opendmarc_base_dir}/ignore.mailfrom" ]] ; then
|
||||||
|
mv "${opendmarc_base_dir}/ignore.mailfrom" "${opendmarc_base_dir}/ignore.mailfrom.${backup_date}"
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
fi
|
||||||
|
|
||||||
|
echononl " Create file '${opendmarc_base_dir}/ignore.mailfrom'.."
|
||||||
|
if [[ -f "${opendmarc_base_dir}/ignore.mailfrom" ]] ; then
|
||||||
|
echo_skipped
|
||||||
|
else
|
||||||
|
cat <<EOF > ${opendmarc_base_dir}/ignore.mailfrom 2> $log_file
|
||||||
|
# /etc/opendmarc/ignore.mailfrom
|
||||||
|
#
|
||||||
|
# Hier könnte man Absender-Domains von der DMARC-Prüfung
|
||||||
|
# ausnehmen (z. B. problematische Partner-Domains).
|
||||||
|
#
|
||||||
|
# Aktuell ist das für dein Setup nicht notwendig.
|
||||||
|
#
|
||||||
|
# Beispiele (NICHT aktiv!):
|
||||||
|
# @example.org
|
||||||
|
# example.org
|
||||||
|
#
|
||||||
|
# ==> Datei bleibt absichtlich leer.
|
||||||
EOF
|
EOF
|
||||||
opendmarc_needs_restart=true
|
opendmarc_needs_restart=true
|
||||||
if [[ $? -eq 0 ]] ; then
|
if [[ $? -eq 0 ]] ; then
|
||||||
@@ -388,42 +780,19 @@ if $(grep -q -E "^\s*non_smtpd_milters\s*=\s*.*opendkim.sock" /etc/postfix/main.
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
|
|
||||||
echo_skipped
|
echo_skipped
|
||||||
warn "Postfix is not adjusted. Complete Postfix configuration (main.cf) manually\!"
|
warn "non_smtpd_milters is not adjusted. Complete Postfix configuration (main.cf) manually\!"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
# - Prevent Postfix from setting the DMARC Header twice (one befor
|
echononl " Set Variable smtpd_milters at '/etc/postfix/main.cf'.."
|
||||||
# - and one after processing amavis
|
if $(grep -q -E "^\s*smtpd_milters\s*=\s*.*opendkim.sock" /etc/postfix/main.cf 2> /dev/null) ; then
|
||||||
# -
|
if $(grep -q -E "^\s*smtpd_milters\s*=\s*.*$(basename "${opendmarc_socket_file}")" /etc/postfix/main.cf); then
|
||||||
# - To disable milter processing after amavis, add to your master.cf in
|
|
||||||
# - the after-amavis section:
|
|
||||||
# - 127.0.0.1:10025 inet n - - - - smtpd
|
|
||||||
# - [...]
|
|
||||||
# - -o smtpd_milters=
|
|
||||||
# -
|
|
||||||
# - If you want to run the milter after amavis, set in main.cf
|
|
||||||
# - smtpd_milters=
|
|
||||||
# - to an empty string and add the smtpd_milters configuration to master.cf
|
|
||||||
# - (after-section amavis) instead:
|
|
||||||
# - -o smtpd_milters=local:/opendmarc/opendmarc.sock
|
|
||||||
# -
|
|
||||||
echononl " Backup file '/etc/postfix/master.cf'.."
|
|
||||||
cp -a /etc/postfix/master.cf /etc/postfix/master.cf.${backup_date} 2> $log_file
|
|
||||||
if [[ $? -eq 0 ]] ; then
|
|
||||||
echo_ok
|
|
||||||
else
|
|
||||||
echo_failed
|
|
||||||
error "$(cat $log_file)"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echononl " Adjust /etc/postfix/master.cf. Set DMARC after sending throuh AmaVIS.."
|
|
||||||
if $(grep -q -E "^\s*-o\s+smtpd_milters\s*=\s*.*opendkim.sock" /etc/postfix/master.cf 2> /dev/null) ; then
|
|
||||||
if $(grep -q -E "^\s*-o\s+smtpd_milters\s*=\s*.*$(basename ${opendmarc_socket_file})" /etc/postfix/master.cf); then
|
|
||||||
echo_skipped
|
echo_skipped
|
||||||
else
|
else
|
||||||
perl -i -n -p -e "s&(^\s*-o\s+smtpd_milters\s*=.*)&\1,local:/$(basename "${opendmarc_socket_dir}")/$(basename "${opendmarc_socket_file}")&" \
|
perl -i -n -p -e "s&^\s*(smtpd_milters\s*=.*opendkim.sock)&\1,local:/$(basename "${opendmarc_socket_dir}")/$(basename "${opendmarc_socket_file}")&" \
|
||||||
/etc/postfix/master.cf > $log_file 2>&1
|
/etc/postfix/main.cf > $log_file 2>&1
|
||||||
if [[ $? -eq 0 ]] ; then
|
if [[ $? -eq 0 ]] ; then
|
||||||
echo_ok
|
echo_ok
|
||||||
postfix_needs_restart=true
|
postfix_needs_restart=true
|
||||||
@@ -434,9 +803,101 @@ if $(grep -q -E "^\s*-o\s+smtpd_milters\s*=\s*.*opendkim.sock" /etc/postfix/mast
|
|||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo_skipped
|
echo_skipped
|
||||||
warn "Postfix is not adjusted. Complete Postfix configuration (master.cf) manually\!"
|
warn "smtpd_milters was not adjusted. Complete Postfix configuration (main.cf) manually\!"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
|
||||||
|
# - Edit /etc/postfix/main.cf and add a section to activate
|
||||||
|
# - processing of e-mail through the OpenDKIM daemon:
|
||||||
|
# -
|
||||||
|
backup_date="$(date +%Y-%m-%d-%H%M)"
|
||||||
|
echononl " Backup existing postfix configuration (main.cf).."
|
||||||
|
cp -a /etc/postfix/main.cf /etc/postfix/main.cf.$backup_date 2> $log_file
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echononl " Activate processing of e-mail through the OpenDKIM daemon.."
|
||||||
|
if grep -q -E "milter_default_action\s*=\s*accept" /etc/postfix/main.cf ; then
|
||||||
|
echo_skipped
|
||||||
|
info "Postfix (main.cf) was not changed - seems already be configured right."
|
||||||
|
echononl " Delete previosly saved Postfix configuration.."
|
||||||
|
rm /etc/postfix/main.cf.$backup_date 2> $log_file
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
cat <<EOF >> /etc/postfix/main.cf 2> $log_file
|
||||||
|
|
||||||
|
# ======= Milter configuration =======
|
||||||
|
|
||||||
|
# OpenDKIM, OpenDMARC
|
||||||
|
|
||||||
|
milter_default_action = accept
|
||||||
|
|
||||||
|
# Postfix ≥ 2.6 milter_protocol = 6, Postfix ≤ 2.5 milter_protocol = 2
|
||||||
|
milter_protocol = 6
|
||||||
|
|
||||||
|
# Note:
|
||||||
|
# We will sign AFTER sending through AmaVIS, just befor sending out. So
|
||||||
|
# set 'smtpd_milters =' to an emty string here and add to localhost:10025
|
||||||
|
# section in master.cf: 'smtpd_milters=local:/opendkim/opendkim.sock'
|
||||||
|
#
|
||||||
|
# If you want sign mails before sending through AmaVIS, set
|
||||||
|
# 'smtpd_milters = local:/opendkim/opendkim.sock' here and add to
|
||||||
|
# localhost:10025 section in master.cf: 'smtpd_milters='
|
||||||
|
#
|
||||||
|
smtpd_milters = local:/opendkim/opendkim.sock, local:/opendmarc/opendmarc.sock
|
||||||
|
|
||||||
|
# Was sind non_smtpd_milters?
|
||||||
|
#
|
||||||
|
# non_smtpd_milters gilt für alle Postfix-Prozesse, die Mails verarbeiten, aber NICHT
|
||||||
|
# der smtpd-Daemon sind.
|
||||||
|
#
|
||||||
|
# Das betrifft z. B.:
|
||||||
|
#
|
||||||
|
# cleanup Header/Content-Bereinigung
|
||||||
|
# qmgr Queue-Manager
|
||||||
|
# lmtp / smtp Auslieferung nach extern
|
||||||
|
# local lokale Zustellung
|
||||||
|
#
|
||||||
|
# Das sind z. B.:
|
||||||
|
#
|
||||||
|
# - interne Bounces (MAILER-DAEMON)
|
||||||
|
#
|
||||||
|
# - Cron-Mails vom Server
|
||||||
|
#
|
||||||
|
# - Weiterleitungen, die Postfix selbst generiert
|
||||||
|
#
|
||||||
|
# - Mails, die über sendmail CLI gesendet werden
|
||||||
|
#
|
||||||
|
# - Mails, die Amavis über LMTP zurückgibt
|
||||||
|
#
|
||||||
|
# - etc.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# DKIM soll auch die ausgehenden Mails signieren, die nicht über smtpd daemon versendet werden.
|
||||||
|
non_smtpd_milters = local:/opendkim/opendkim.sock, local:/opendmarc/opendmarc.sock
|
||||||
|
EOF
|
||||||
|
postfix_needs_restart=true
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
echononl " Enable OpenDMARC Service"
|
echononl " Enable OpenDMARC Service"
|
||||||
@@ -503,20 +964,6 @@ else
|
|||||||
echo_skipped
|
echo_skipped
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo ""
|
|
||||||
if [[ -f "/etc/postfix/master.cf.${backup_date}" ]] ; then
|
|
||||||
if $(diff "/etc/postfix/master.cf" "/etc/postfix/master.cf.${backup_date}"> /dev/null 2>&1) ; then
|
|
||||||
info "File \033[1m/etc/postfix/master.cf\033[m has not changed.\n\t Removing previos created backup.."
|
|
||||||
rm "/etc/postfix/master.cf.${backup_date}"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
if [[ -f "/etc/postfix/main.cf.${backup_date}" ]] ; then
|
|
||||||
if $(diff "/etc/postfix/main.cf" "/etc/postfix/main.cf.${backup_date}"> /dev/null 2>&1) ; then
|
|
||||||
info "File \033[1m/etc/postfix/main.cf\033[m has not changed.\n\t Removing previos created backup.."
|
|
||||||
rm "/etc/postfix/main.cf.${backup_date}"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
rm -f "$log_file"
|
rm -f "$log_file"
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -78,6 +78,50 @@ echo_skipped() {
|
|||||||
echo -e "\033[80G[ \033[33m\033[1mskipped\033[m ]"
|
echo -e "\033[80G[ \033[33m\033[1mskipped\033[m ]"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
blank_line() {
|
||||||
|
if $terminal ; then
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
trim() {
|
||||||
|
local var="$*"
|
||||||
|
var="${var#"${var%%[![:space:]]*}"}" # remove leading whitespace characters
|
||||||
|
var="${var%"${var##*[![:space:]]}"}" # remove trailing whitespace characters
|
||||||
|
echo -n "$var"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
detect_os_1 () {
|
||||||
|
|
||||||
|
if $(which lsb_release > /dev/null 2>&1) ; then
|
||||||
|
|
||||||
|
os_dist="$(lsb_release -i | awk '{print tolower($3)}')"
|
||||||
|
os_version="$(lsb_release -r | awk '{print tolower($2)}')"
|
||||||
|
os_codename="$(lsb_release -c | awk '{print tolower($2)}')"
|
||||||
|
|
||||||
|
if [[ "$os_dist" = "debian" ]]; then
|
||||||
|
if $(echo "$os_version" | grep -q '\.') ; then
|
||||||
|
os_version=$(echo "$os_version" | cut --delimiter='.' -f1)
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
elif [[ -e "/etc/os-release" ]]; then
|
||||||
|
|
||||||
|
. /etc/os-release
|
||||||
|
|
||||||
|
os_dist=$ID
|
||||||
|
os_version=${VERSION_ID}
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
# remove whitespace from os_dist and os_version
|
||||||
|
os_dist="${os_dist// /}"
|
||||||
|
os_version="${os_version// /}"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# -------------
|
# -------------
|
||||||
# --- Some default settings
|
# --- Some default settings
|
||||||
@@ -85,14 +129,18 @@ echo_skipped() {
|
|||||||
|
|
||||||
DEFAULT_ADMIN_EMAIL="argus@oopen.de"
|
DEFAULT_ADMIN_EMAIL="argus@oopen.de"
|
||||||
DEFAULT_RELAY_HOST="b.mx.oopen.de"
|
DEFAULT_RELAY_HOST="b.mx.oopen.de"
|
||||||
|
DEFAULT_RELAY_PORT=25
|
||||||
DEFAULT_SASL_AUTH=false
|
DEFAULT_SASL_AUTH=false
|
||||||
|
DEFAULT_REWRITE_SENDER_DOMAIN=None
|
||||||
|
|
||||||
|
|
||||||
# - Is this a systemd system?
|
# - Is this a systemd system?
|
||||||
# -
|
# -
|
||||||
if [[ "X`which systemd`" = "X" ]]; then
|
systemd_exists=false
|
||||||
systemd_exists=false
|
systemd=$(which systemd)
|
||||||
else
|
systemctl=$(which systemctl)
|
||||||
|
|
||||||
|
if [[ -n "$systemd" ]] || [[ -n "$systemctl" ]] ; then
|
||||||
systemd_exists=true
|
systemd_exists=true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -118,8 +166,19 @@ if [[ -z "$_HOSTNAME" ]] ; then
|
|||||||
[[ "$_HOSTNAME" = "$_HOSTNAME_SHORT" ]] && _HOSTNAME=""
|
[[ "$_HOSTNAME" = "$_HOSTNAME_SHORT" ]] && _HOSTNAME=""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
blank_line
|
||||||
|
echononl "Detect distribution/release of running OS.."
|
||||||
|
detect_os_1 > /dev/null 2>&1
|
||||||
|
if [[ $? -ne 0 ]]; then
|
||||||
|
echo_failed
|
||||||
|
else
|
||||||
|
echo_ok
|
||||||
|
fi
|
||||||
|
blank_line
|
||||||
|
blank_line
|
||||||
|
|
||||||
clear
|
|
||||||
|
#clear
|
||||||
echo -e "\033[21G\033[32mInstallation script for Postfix basic mailsystem \033[m"
|
echo -e "\033[21G\033[32mInstallation script for Postfix basic mailsystem \033[m"
|
||||||
echo
|
echo
|
||||||
|
|
||||||
@@ -284,13 +343,17 @@ fi
|
|||||||
# --- Some further default values depending on sasl authentification
|
# --- Some further default values depending on sasl authentification
|
||||||
# -------------
|
# -------------
|
||||||
|
|
||||||
# - Set default value for relay host if sasl authentification should be
|
# - Set default value for relay host / relay port if sasl authentification should be
|
||||||
# - supported and value for _RELAY_HOST not given
|
# - supported and value for _RELAY_HOST / _RELAY_PORT not given
|
||||||
# -
|
# -
|
||||||
if [[ "$SASL_AUTH" = "yes" ]] || $SASL_AUTH ; then
|
if [[ "$SASL_AUTH" = "yes" ]] || $SASL_AUTH ; then
|
||||||
[[ -z "$_RELAY_HOST" ]] && _RELAY_HOST="$DEFAULT_RELAY_HOST"
|
[[ -z "$_RELAY_HOST" ]] && _RELAY_HOST="$DEFAULT_RELAY_HOST"
|
||||||
|
[[ -z "$_RELAY_PORT" ]] && _RELAY_PORT="$DEFAULT_RELAY_PORT"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ -z ${_REWRITE_SENDER_DOMAIN} ]] ; then
|
||||||
|
_REWRITE_SENDER_DOMAIN="${DEFAULT_REWRITE_SENDER_DOMAIN}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
if [[ "$SASL_AUTH" = "yes" ]] || $SASL_AUTH ; then
|
if [[ "$SASL_AUTH" = "yes" ]] || $SASL_AUTH ; then
|
||||||
@@ -357,11 +420,57 @@ if [[ "$SASL_AUTH" = "yes" ]] || $SASL_AUTH ; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
RELAY_PORT=
|
||||||
|
echo ""
|
||||||
|
echo "Insert the target port to connect to ${RELAY_HOST}"
|
||||||
|
echo ""
|
||||||
|
if [[ -n "$_RELAY_PORT" ]];then
|
||||||
|
echononl "(target) Port on ${RELAY_HOST} [$_RELAY_PORT]: "
|
||||||
|
read RELAY_PORT
|
||||||
|
if [[ "X${RELAY_PORT}" = "X" ]]; then
|
||||||
|
RELAY_PORT=$_RELAY_PORT
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
while [[ "X${RELAY_PORT}" = "X" ]]; do
|
||||||
|
echononl "(target) Port on ${RELAY_HOST}: "
|
||||||
|
read RELAY_PORT
|
||||||
|
if [[ "X${RELAY_PORT}" = "X" ]]; then
|
||||||
|
echo -e "\n\t\033[33m\033[1mi(target) Port of ${RELAY_HOST} is reqired\033[m\n"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
else
|
else
|
||||||
SASL_AUTH=false
|
SASL_AUTH=false
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
REWRITE_SENDER_DOMAIN=
|
||||||
|
echo ""
|
||||||
|
echo ""
|
||||||
|
echo -e "\033[33m** \033[32m-- \033[33m**\033[m"
|
||||||
|
echo ""
|
||||||
|
echo "Change the sender domain"
|
||||||
|
echo ""
|
||||||
|
echo -e "\t'\033[33mNone\033[m' if no change is desired"
|
||||||
|
echo ""
|
||||||
|
if [[ -n "${_REWRITE_SENDER_DOMAIN}" ]] ; then
|
||||||
|
echononl "New sender domain [${_REWRITE_SENDER_DOMAIN}]: "
|
||||||
|
read REWRITE_SENDER_DOMAIN
|
||||||
|
if [[ "X${REWRITE_SENDER_DOMAIN}" = "X" ]]; then
|
||||||
|
REWRITE_SENDER_DOMAIN="${_REWRITE_SENDER_DOMAIN}"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
while [[ "X${IPV6}" = "X" ]]; do
|
||||||
|
echononl "New sender domain: "
|
||||||
|
read REWRITE_SENDER_DOMAIN
|
||||||
|
if [[ "X${REWRITE_SENDER_DOMAIN}" = "X" ]]; then
|
||||||
|
REWRITE_SENDER_DOMAIN="None"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo -e "\033[33m** \033[32m-- \033[33m**\033[m"
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo ""
|
echo ""
|
||||||
@@ -372,11 +481,18 @@ echo -e "\tIPv4 address.............: $IPV4"
|
|||||||
echo -e "\tIPv6 address.............: $IPV6"
|
echo -e "\tIPv6 address.............: $IPV6"
|
||||||
echo -e "\tAdmin e-mail.............: $ADMIN_EMAIL"
|
echo -e "\tAdmin e-mail.............: $ADMIN_EMAIL"
|
||||||
echo ""
|
echo ""
|
||||||
|
if [[ "$(trim ${REWRITE_SENDER_DOMAIN,,})" = 'none' ]] ; then
|
||||||
|
echo -e "\trewrite sender domain....: \033[33mNone\033[m"
|
||||||
|
else
|
||||||
|
echo -e "\trewrite sender domain....: $REWRITE_SENDER_DOMAIN"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
echo -e "\tRelay using sasl auth....: $SASL_AUTH"
|
echo -e "\tRelay using sasl auth....: $SASL_AUTH"
|
||||||
if $SASL_AUTH ; then
|
if $SASL_AUTH ; then
|
||||||
echo -e "\t sasl user.............: $SASL_USER"
|
echo -e "\t sasl user.............: $SASL_USER"
|
||||||
echo -e "\t sasl password.........: $SASL_PASS"
|
echo -e "\t sasl password.........: $SASL_PASS"
|
||||||
echo -e "\t Relayhost.............: $RELAY_HOST"
|
echo -e "\t Relayhost.............: $RELAY_HOST"
|
||||||
|
echo -e "\t Port on Relayhost.....: $RELAY_PORT"
|
||||||
fi
|
fi
|
||||||
echo ""
|
echo ""
|
||||||
echononl "einverstanden (yes/no): "
|
echononl "einverstanden (yes/no): "
|
||||||
@@ -408,6 +524,8 @@ _SASL_AUTH=$SASL_AUTH
|
|||||||
_SASL_USER=$SASL_USER
|
_SASL_USER=$SASL_USER
|
||||||
_SASL_PASS=$SASL_PASS
|
_SASL_PASS=$SASL_PASS
|
||||||
_RELAY_HOST=$RELAY_HOST
|
_RELAY_HOST=$RELAY_HOST
|
||||||
|
_RELAY_PORT=$RELAY_PORT
|
||||||
|
_REWRITE_SENDER_DOMAIN=$REWRITE_SENDER_DOMAIN
|
||||||
EOF
|
EOF
|
||||||
if [[ $? -eq 0 ]] ; then
|
if [[ $? -eq 0 ]] ; then
|
||||||
echo_ok
|
echo_ok
|
||||||
@@ -583,12 +701,25 @@ mydestination =
|
|||||||
## -
|
## -
|
||||||
mynetworks =
|
mynetworks =
|
||||||
127.0.0.0/8
|
127.0.0.0/8
|
||||||
${IPV4}/32
|
EOF
|
||||||
|
|
||||||
smtp_bind_address = $IPV4
|
if [[ ${IPV4} =~ ^127 ]] ; then
|
||||||
smtp_bind_address6 = $IPV6
|
|
||||||
|
cat <<EOF >> /etc/postfix/main.cf
|
||||||
|
|
||||||
|
smtp_bind_address =
|
||||||
|
smtp_bind_address6 =
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
|
else
|
||||||
|
cat <<EOF >> /etc/postfix/main.cf
|
||||||
|
${IPV4}/32
|
||||||
|
|
||||||
|
smtp_bind_address = $IPV4
|
||||||
|
#smtp_bind_address6 =
|
||||||
|
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cat <<EOF >> /etc/postfix/main.cf
|
cat <<EOF >> /etc/postfix/main.cf
|
||||||
@@ -641,9 +772,21 @@ alias_database =
|
|||||||
## -
|
## -
|
||||||
## - Note: \$sender_canonical_maps is processed before \$canonical_maps.
|
## - Note: \$sender_canonical_maps is processed before \$canonical_maps.
|
||||||
## -
|
## -
|
||||||
sender_canonical_maps = btree:/etc/postfix/sender_canonical
|
sender_canonical_maps =
|
||||||
|
btree:/etc/postfix/sender_canonical
|
||||||
|
|
||||||
|
|
||||||
|
## - smtp_generic_maps (default: empty)
|
||||||
|
## -
|
||||||
|
## - Optional lookup tables that perform address rewriting in the Postfix
|
||||||
|
## - SMTP client, typically to transform a locally valid address into a
|
||||||
|
## - globally valid address when sending mail across the Internet. This is
|
||||||
|
## - needed when the local machine does not have its own Internet domain name,
|
||||||
|
## -but uses something like localdomain.local instead.
|
||||||
|
## -
|
||||||
|
smtp_generic_maps =
|
||||||
|
btree:/etc/postfix/generic
|
||||||
|
|
||||||
## - The maximal time a message is queued before it is sent back as
|
## - The maximal time a message is queued before it is sent back as
|
||||||
## - undeliverable. Defaults to 5d (5 days)
|
## - undeliverable. Defaults to 5d (5 days)
|
||||||
## - Specify 0 when mail delivery should be tried only once.
|
## - Specify 0 when mail delivery should be tried only once.
|
||||||
@@ -685,9 +828,24 @@ smtp_sasl_auth_enable = yes
|
|||||||
|
|
||||||
# Only offer SMTP AUTH when talking over an encrypted connection
|
# Only offer SMTP AUTH when talking over an encrypted connection
|
||||||
smtpd_tls_auth_only = yes
|
smtpd_tls_auth_only = yes
|
||||||
|
EOF
|
||||||
|
|
||||||
|
if [[ ${RELAY_PORT} -ne 25 ]] ; then
|
||||||
|
cat <<EOF >> /etc/postfix/main.cf
|
||||||
|
|
||||||
|
# Forwarding to the ip-adress of host b.mx.oopen.de
|
||||||
|
relayhost = [${RELAY_HOST}]:${RELAY_PORT}
|
||||||
|
EOF
|
||||||
|
else
|
||||||
|
cat <<EOF >> /etc/postfix/main.cf
|
||||||
|
|
||||||
# Forwarding to the ip-adress of host b.mx.oopen.de
|
# Forwarding to the ip-adress of host b.mx.oopen.de
|
||||||
relayhost = [${RELAY_HOST}]
|
relayhost = [${RELAY_HOST}]
|
||||||
|
EOF
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
cat <<EOF >> /etc/postfix/main.cf
|
||||||
|
|
||||||
# File including login data
|
# File including login data
|
||||||
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
|
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
|
||||||
@@ -771,7 +929,9 @@ smtpd_tls_key_file = $_TLS_KEY_FILE
|
|||||||
#smtpd_tls_dh1024_param_file = /etc/postfix/ssl/dh_1024.pem
|
#smtpd_tls_dh1024_param_file = /etc/postfix/ssl/dh_1024.pem
|
||||||
## - also possible to use 2048 key with that parameter
|
## - also possible to use 2048 key with that parameter
|
||||||
## -
|
## -
|
||||||
smtpd_tls_dh1024_param_file = /etc/postfix/ssl/dh_2048.pem
|
## - DEPRECATED parameter-
|
||||||
|
## -
|
||||||
|
#smtpd_tls_dh1024_param_file = /etc/postfix/ssl/dh_2048.pem
|
||||||
|
|
||||||
## - File with DH parameters that the Postfix SMTP server should use with EDH ciphers.
|
## - File with DH parameters that the Postfix SMTP server should use with EDH ciphers.
|
||||||
## -
|
## -
|
||||||
@@ -806,59 +966,103 @@ smtp_tls_CAfile = $_TLS_CA_FILE
|
|||||||
#
|
#
|
||||||
# List of TLS protocols that the Postfix SMTP server will exclude or
|
# List of TLS protocols that the Postfix SMTP server will exclude or
|
||||||
# include with opportunistic TLS encryption.
|
# include with opportunistic TLS encryption.
|
||||||
smtpd_tls_protocols = !SSLv2, !SSLv3
|
#smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1
|
||||||
|
|
||||||
|
# TLS protocols accepted by the Postfix SMTP server with opportunistic TLS encryption.
|
||||||
#
|
#
|
||||||
# The SSL/TLS protocols accepted by the Postfix SMTP server
|
#smtpd_tls_protocols = >=TLSv1
|
||||||
# with mandatory TLS encryption.
|
|
||||||
smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3
|
|
||||||
|
|
||||||
|
# TLS protocols accepted by the Postfix SMTP server with mandatory TLS encryption.
|
||||||
# Disable SSLv2 SSLv3 - Postfix SMTP client
|
|
||||||
#
|
#
|
||||||
# List of TLS protocols that the Postfix SMTP client will exclude or
|
#smtpd_tls_mandatory_protocols = >=TLSv1
|
||||||
# include with opportunistic TLS encryption.
|
|
||||||
smtp_tls_protocols = !SSLv2, !SSLv3
|
# TLS protocols that the Postfix SMTP client will use with opportunistic TLS encryption.
|
||||||
#
|
#
|
||||||
# List of SSL/TLS protocols that the Postfix SMTP client will use
|
#smtp_tls_protocols = >=TLSv1
|
||||||
# with mandatory TLS encryption
|
|
||||||
smtp_tls_mandatory_protocols = !SSLv2, !SSLv3
|
|
||||||
|
|
||||||
|
# The minimum TLS cipher grade that the Postfix SMTP server will use with mandatory TLS encryption.
|
||||||
## - Activate des "Ephemeral Elliptic Curve Diffie-Hellman" (EECDH) key exchange
|
|
||||||
## - openssl > 1.0
|
|
||||||
## -
|
|
||||||
smtpd_tls_eecdh_grade = strong
|
|
||||||
|
|
||||||
# standard list cryptographic algorithm
|
|
||||||
tls_preempt_cipherlist = yes
|
|
||||||
|
|
||||||
# Disable ciphers which are less than 256-bit:
|
|
||||||
#
|
#
|
||||||
#smtpd_tls_mandatory_ciphers = high
|
smtp_tls_mandatory_protocols = >=TLSv1.2
|
||||||
|
|
||||||
|
|
||||||
|
# The Postfix SMTP server security grade for ephemeral elliptic-curve
|
||||||
|
# Diffie-Hellman (EECDH) key exchange. As of Postfix 3.6, the value of this
|
||||||
|
# parameter is always ignored, and Postfix behaves as though the auto value
|
||||||
|
# (described below) was chosen.
|
||||||
#
|
#
|
||||||
# opportunistic
|
# auto
|
||||||
smtpd_tls_ciphers = high
|
# Use the most preferred curve that is supported by both the client and the server.
|
||||||
|
# This setting requires Postfix ≥ 3.2 compiled and linked with OpenSSL ≥ 1.0.2. This
|
||||||
|
# is the default setting under the above conditions (and the only setting used with
|
||||||
|
# Postfix ≥ 3.6).
|
||||||
|
#
|
||||||
|
# none
|
||||||
|
# Don't use EECDH. Ciphers based on EECDH key exchange will be disabled. This is the
|
||||||
|
# default in Postfix versions 2.6 and 2.7.
|
||||||
|
#
|
||||||
|
# strong
|
||||||
|
# Use EECDH with approximately 128 bits of security at a reasonable computational cost.
|
||||||
|
# This is the default in Postfix versions 2.8-3.5.
|
||||||
|
#
|
||||||
|
# ultra
|
||||||
|
# Use EECDH with approximately 192 bits of security at computational cost that is
|
||||||
|
# approximately twice as high as 128 bit strength ECC.
|
||||||
|
#
|
||||||
|
smtpd_tls_eecdh_grade = auto
|
||||||
|
|
||||||
|
|
||||||
# Exclude ciphers
|
# With SSLv3 and later, use the Postfix SMTP server's cipher preference order instead
|
||||||
|
# of the remote client's cipher preference order.
|
||||||
|
#
|
||||||
|
# By default, the OpenSSL server selects the client's most preferred cipher that the
|
||||||
|
# server supports. With SSLv3 and later, the server may choose its own most preferred
|
||||||
|
# cipher that is supported (offered) by the client.
|
||||||
|
#
|
||||||
|
# Setting "tls_preempt_cipherlist = yes" enables server cipher preferences.
|
||||||
|
#
|
||||||
|
# default: no
|
||||||
|
#
|
||||||
|
#tls_preempt_cipherlist = no
|
||||||
|
|
||||||
|
|
||||||
|
# The minimum TLS cipher grade that the Postfix SMTP server will use with mandatory
|
||||||
|
# TLS encryption. The default grade ("medium") is sufficiently strong that any benefit
|
||||||
|
# from globally restricting TLS sessions to a more stringent grade is likely negligible,
|
||||||
|
# especially given the fact that many implementations still do not offer any stronger
|
||||||
|
# ("high" grade) ciphers, while those that do, will always use "high" grade ciphers.
|
||||||
|
# So insisting on "high" grade ciphers is generally counter-productive. Allowing "export"
|
||||||
|
# or "low" ciphers is typically not a good idea, as systems limited to just these are
|
||||||
|
# limited to obsolete browsers. No known SMTP clients fail to support at least one
|
||||||
|
# "medium" or "high" grade cipher.
|
||||||
|
#
|
||||||
|
# default: medium
|
||||||
|
#
|
||||||
|
#smtpd_tls_mandatory_ciphers = medium
|
||||||
|
|
||||||
|
# The minimum TLS cipher grade that the Postfix SMTP server will use with opportunistic
|
||||||
|
# TLS encryption. Cipher types listed in smtpd_tls_exclude_ciphers are excluded from the
|
||||||
|
# base definition of the selected cipher grade.
|
||||||
|
#
|
||||||
|
# default: medium
|
||||||
|
#
|
||||||
|
#smtpd_tls_ciphers = medium
|
||||||
|
|
||||||
|
|
||||||
|
# List of ciphers or cipher types to exclude from the SMTP server cipher list at all
|
||||||
|
# TLS security levels.
|
||||||
|
#
|
||||||
|
# DO NOT exclude ciphers unless it is essential to do so. This is not an OpenSSL cipherlist;
|
||||||
|
# it is a simple list separated by whitespace and/or commas. The elements are a single cipher,
|
||||||
|
# or one or more "+" separated cipher properties, in which case only ciphers matching all the
|
||||||
|
# properties are excluded.
|
||||||
|
#
|
||||||
#smtpd_tls_exclude_ciphers =
|
#smtpd_tls_exclude_ciphers =
|
||||||
# RC4
|
|
||||||
# aNULL
|
# Additional list of ciphers or cipher types to exclude from the Postfix SMTP client cipher
|
||||||
# SEED-SHA
|
# list at mandatory TLS security levels. This list works in addition to the exclusions listed
|
||||||
# EXP
|
# with smtp_tls_exclude_ciphers
|
||||||
# MD5
|
#
|
||||||
smtpd_tls_exclude_ciphers =
|
#smtp_tls_mandatory_exclude_ciphers =
|
||||||
aNULL
|
|
||||||
eNULL
|
|
||||||
EXPORT
|
|
||||||
DES
|
|
||||||
RC4
|
|
||||||
MD5
|
|
||||||
PSK
|
|
||||||
aECDH
|
|
||||||
EDH-DSS-DES-CBC3-SHA
|
|
||||||
EDH-RSA-DES-CDC3-SHA
|
|
||||||
KRB5-DE5, CBC3-SHA
|
|
||||||
|
|
||||||
|
|
||||||
smtpd_tls_session_cache_database = btree:\${data_directory}/smtpd_scache
|
smtpd_tls_session_cache_database = btree:\${data_directory}/smtpd_scache
|
||||||
@@ -903,8 +1107,21 @@ echo_ok
|
|||||||
echononl " Configure SASL authentification"
|
echononl " Configure SASL authentification"
|
||||||
if $SASL_AUTH ; then
|
if $SASL_AUTH ; then
|
||||||
|
|
||||||
|
_sasl_pw_file="/etc/postfix/sasl_passwd"
|
||||||
|
if [[ -f "${_sasl_pw_file}" ]] && $(grep -q -E "^\[${RELAY_HOST}\]" ${_sasl_pw_file} 2> /dev/null); then
|
||||||
|
sed -i "/^\[${RELAY_HOST}/d" ${_sasl_pw_file}
|
||||||
|
if [[ "$?" != "0" ]]; then
|
||||||
|
error "Setting \"/etc/postfix/sasl_passwd\" failed! "
|
||||||
|
_failed=true
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
_failed=false
|
_failed=false
|
||||||
echo "[$RELAY_HOST] ${SASL_USER}@${RELAY_HOST}:$SASL_PASS" > /etc/postfix/sasl_passwd
|
if [[ ${RELAY_PORT} -ne 25 ]] ; then
|
||||||
|
echo "[$RELAY_HOST]:${RELAY_PORT} ${SASL_USER}@${RELAY_HOST}:$SASL_PASS" >> /etc/postfix/sasl_passwd
|
||||||
|
else
|
||||||
|
echo "[$RELAY_HOST] ${SASL_USER}@${RELAY_HOST}:$SASL_PASS" >> /etc/postfix/sasl_passwd
|
||||||
|
fi
|
||||||
if [[ "$?" != "0" ]]; then
|
if [[ "$?" != "0" ]]; then
|
||||||
error "Setting \"/etc/postfix/sasl_passwd\" failed! "
|
error "Setting \"/etc/postfix/sasl_passwd\" failed! "
|
||||||
_failed=true
|
_failed=true
|
||||||
@@ -998,41 +1215,91 @@ fi
|
|||||||
## - with EDH ciphers (length 512 and 1024
|
## - with EDH ciphers (length 512 and 1024
|
||||||
## -
|
## -
|
||||||
echononl " Generate DH key length=512 \"/etc/postfix/ssl/dh_512.pem\""
|
echononl " Generate DH key length=512 \"/etc/postfix/ssl/dh_512.pem\""
|
||||||
if [ ! -f /etc/postfix/ssl/dh_512.pem ]; then
|
if [[ ! -f /etc/postfix/ssl/dh_512.pem ]]; then
|
||||||
#openssl dhparam -out /etc/postfix/ssl/dh_512.pem -2 512 > /dev/null 2>&1
|
if [[ "$os_dist" = "debian" ]] && [[ $os_version -gt 11 ]] ; then
|
||||||
openssl dhparam -dsaparam -out /etc/postfix/ssl/dh_512.pem 512 > /dev/null 2>&1
|
openssl dhparam -out /etc/postfix/ssl/dh_512.pem 512 > /dev/null 2>&1
|
||||||
|
else
|
||||||
|
openssl dhparam -dsaparam -out /etc/postfix/ssl/dh_512.pem 512 > /dev/null 2>&1
|
||||||
|
fi
|
||||||
if [[ $? -eq 0 ]] ; then
|
if [[ $? -eq 0 ]] ; then
|
||||||
echo_ok
|
echo_ok
|
||||||
else
|
else
|
||||||
echo_failed
|
echo_failed
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo_skipped
|
if [[ "$os_dist" = "debian" ]] && [[ $os_version -gt 11 ]] ; then
|
||||||
|
if $(grep -q -E "X9.42" /etc/postfix/ssl/dh_512.pem 2> /dev/null); then
|
||||||
|
openssl dhparam -out /etc/postfix/ssl/dh_512.pem 512 > /dev/null 2>&1
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
echononl " Generate DH key length=1024 \"/etc/postfix/ssl/dh_1024.pem\""
|
echononl " Generate DH key length=1024 \"/etc/postfix/ssl/dh_1024.pem\""
|
||||||
if [ ! -f /etc/postfix/ssl/dh_1024.pem ]; then
|
if [[ ! -f /etc/postfix/ssl/dh_1024.pem ]]; then
|
||||||
#openssl dhparam -out /etc/postfix/ssl/dh_1024.pem -2 1024 > /dev/null 2>&1
|
if [[ "$os_dist" = "debian" ]] && [[ $os_version -gt 11 ]] ; then
|
||||||
openssl dhparam -dsaparam -out /etc/postfix/ssl/dh_1024.pem 1024 > /dev/null 2>&1
|
openssl dhparam -out /etc/postfix/ssl/dh_1024.pem 1024 > /dev/null 2>&1
|
||||||
|
else
|
||||||
|
openssl dhparam -dsaparam -out /etc/postfix/ssl/dh_1024.pem 1024 > /dev/null 2>&1
|
||||||
|
fi
|
||||||
if [[ $? -eq 0 ]] ; then
|
if [[ $? -eq 0 ]] ; then
|
||||||
echo_ok
|
echo_ok
|
||||||
else
|
else
|
||||||
echo_failed
|
echo_failed
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo_skipped
|
if [[ "$os_dist" = "debian" ]] && [[ $os_version -gt 11 ]] ; then
|
||||||
|
if $(grep -q -E "X9.42" /etc/postfix/ssl/dh_1024.pem 2> /dev/null); then
|
||||||
|
openssl dhparam -out /etc/postfix/ssl/dh_1024.pem 1024 > /dev/null 2>&1
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
echononl " Generate DH key length=2048 \"/etc/postfix/ssl/dh_2048.pem\""
|
echononl " Generate DH key length=2048 \"/etc/postfix/ssl/dh_2048.pem\""
|
||||||
if [ ! -f /etc/postfix/ssl/dh_2048.pem ]; then
|
if [[ ! -f /etc/postfix/ssl/dh_2048.pem ]]; then
|
||||||
#openssl dhparam -out /etc/postfix/ssl/dh_2048.pem -2 2048 > /dev/null 2>&1
|
if [[ "$os_dist" = "debian" ]] && [[ $os_version -gt 11 ]] ; then
|
||||||
openssl dhparam -dsaparam -out /etc/postfix/ssl/dh_2048.pem 2048 > /dev/null 2>&1
|
openssl dhparam -out /etc/postfix/ssl/dh_2048.pem 2048 > /dev/null 2>&1
|
||||||
|
else
|
||||||
|
openssl dhparam -dsaparam -out /etc/postfix/ssl/dh_2048.pem 2048 > /dev/null 2>&1
|
||||||
|
fi
|
||||||
if [[ $? -eq 0 ]] ; then
|
if [[ $? -eq 0 ]] ; then
|
||||||
echo_ok
|
echo_ok
|
||||||
else
|
else
|
||||||
echo_failed
|
echo_failed
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo_skipped
|
if [[ "$os_dist" = "debian" ]] && [[ $os_version -gt 11 ]] ; then
|
||||||
|
if $(grep -q -E "X9.42" /etc/postfix/ssl/dh_2048.pem 2> /dev/null); then
|
||||||
|
openssl dhparam -out /etc/postfix/ssl/dh_2048.pem 2048 > /dev/null 2>&1
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
echononl " Create Symlink \"$_TLS_CERT_FILE\""
|
echononl " Create Symlink \"$_TLS_CERT_FILE\""
|
||||||
if [ ! -h "$_TLS_CERT_FILE" ]; then
|
if [ ! -h "$_TLS_CERT_FILE" ]; then
|
||||||
ln -s /etc/ssl/certs/ssl-cert-snakeoil.pem $_TLS_CERT_FILE
|
ln -s /etc/ssl/certs/ssl-cert-snakeoil.pem $_TLS_CERT_FILE
|
||||||
@@ -1121,6 +1388,21 @@ else
|
|||||||
echo_failed
|
echo_failed
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
echononl " Create file \"generic\""
|
||||||
|
if [[ "$(trim ${REWRITE_SENDER_DOMAIN,,})" = 'none' ]] ; then
|
||||||
|
touch /etc/postfix/generic
|
||||||
|
else
|
||||||
|
cat <<EOF > /etc/postfix/generic
|
||||||
|
@$(cat cat /etc/mailname) $(hostname)@$(trim ${REWRITE_SENDER_DOMAIN,,})
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
postmap btree:/etc/postfix/generic
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
## - restart postfix
|
## - restart postfix
|
||||||
## -
|
## -
|
||||||
@@ -1145,15 +1427,19 @@ fi
|
|||||||
## - Omitt logging into system.log
|
## - Omitt logging into system.log
|
||||||
## -
|
## -
|
||||||
echononl " Create \"/etc/rsyslog.d/postfix.conf\""
|
echononl " Create \"/etc/rsyslog.d/postfix.conf\""
|
||||||
cat << EOF >> /etc/rsyslog.d/postfix.conf
|
cat << EOF > /etc/rsyslog.d/postfix.conf
|
||||||
|
# Create an additional socket in postfix's chroot in order not to break
|
||||||
|
# mail logging when rsyslog is restarted. If the directory is missing,
|
||||||
|
# rsyslog will silently skip creating the socket.
|
||||||
|
\$AddUnixListenSocket /var/spool/postfix/dev/log
|
||||||
|
|
||||||
#
|
#
|
||||||
# Logging for the mail system. Split it up so that
|
# Logging for the mail system. Split it up so that
|
||||||
# it is easy to write scripts to parse these files.
|
# it is easy to write scripts to parse these files.
|
||||||
#
|
#
|
||||||
mail.info -/var/log/mail.info
|
#mail.info -/var/log/mail.info
|
||||||
mail.warn -/var/log/mail.warn
|
#mail.warn -/var/log/mail.warn
|
||||||
mail.err /var/log/mail.err
|
#mail.err /var/log/mail.err
|
||||||
|
|
||||||
mail.* -/var/log/mail.log
|
mail.* -/var/log/mail.log
|
||||||
& stop
|
& stop
|
||||||
@@ -1181,6 +1467,12 @@ else
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ ${RELAY_PORT} -ne 25 ]] ; then
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
warn "Please do not forget to allow port \033[1m${RELAY_PORT}\033[m on both sides, outgoing
|
||||||
|
on this host here and incoming on the relay host '${RELAY_HOST}'."
|
||||||
|
fi
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
clean_up 0
|
clean_up 0
|
||||||
|
|||||||
@@ -126,6 +126,61 @@ detect_os_1 () {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
detect_mysql_version () {
|
||||||
|
|
||||||
|
_MYSQLD_VERSION="$(mysqld -V 2>/dev/null)"
|
||||||
|
|
||||||
|
if [[ -z "$_MYSQLD_VERSION" ]]; then
|
||||||
|
fatal "No installed MySQL server or distribution found!"
|
||||||
|
elif [[ -d "/usr/local/mysql" ]] && [[ "$(basename "$(realpath "/usr/local/mysql")")" =~ percona- ]]; then
|
||||||
|
MYSQL_CUR_DISTRIBUTION="Percona"
|
||||||
|
elif [[ "$_MYSQLD_VERSION" =~ MariaDB ]]; then
|
||||||
|
MYSQL_CUR_DISTRIBUTION="MariaDB"
|
||||||
|
elif [[ "$_MYSQLD_VERSION" =~ MySQL ]]; then
|
||||||
|
MYSQL_CUR_DISTRIBUTION="MySQL"
|
||||||
|
elif [[ -d "/usr/local/mysql" ]] && [[ "$(basename "$(realpath "/usr/local/mysql")")" =~ mysql- ]]; then
|
||||||
|
MYSQL_CUR_DISTRIBUTION="MySQL"
|
||||||
|
elif [[ -d "/usr/local/mysql" ]] && [[ "$(basename "$(realpath "/usr/local/mysql")")" =~ mariadb- ]]; then
|
||||||
|
MYSQL_CUR_DISTRIBUTION="MariaDB"
|
||||||
|
else
|
||||||
|
error "MySQL Instalation found, but cannot determin the distribution!"
|
||||||
|
|
||||||
|
MYSQL_CUR_DISTRIBUTION=
|
||||||
|
echo ""
|
||||||
|
echo " Select the installed MySQL distribution."
|
||||||
|
echo ""
|
||||||
|
echo " [1] MySQL (the original community edition)"
|
||||||
|
echo " [2] Percona Server for MySQL"
|
||||||
|
echo " [3] MariaDB"
|
||||||
|
echo ""
|
||||||
|
echononl " Eingabe [1/2/3]: "
|
||||||
|
|
||||||
|
while [ "$MYSQL_CUR_DISTRIBUTION" != "MySQL" -a "$MYSQL_CUR_DISTRIBUTION" != "MariaDB" -a "$MYSQL_CUR_DISTRIBUTION" != "Percona" ];do
|
||||||
|
read OPTION
|
||||||
|
case $OPTION in
|
||||||
|
1) MYSQL_CUR_DISTRIBUTION="MySQL"
|
||||||
|
;;
|
||||||
|
2) MYSQL_CUR_DISTRIBUTION="Percona"
|
||||||
|
;;
|
||||||
|
3) MYSQL_CUR_DISTRIBUTION="MariaDB"
|
||||||
|
;;
|
||||||
|
*) echo ""
|
||||||
|
echo -e "\tFalsche Eingabe ! [ 1 = MySQL ; 2 = Percona ; 3 = MariaDB ]"
|
||||||
|
echo ""
|
||||||
|
echononl " Eingabe:"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
MYSQL_VERSION="$(echo $_MYSQLD_VERSION | grep -o -E "[0-9]+\.[0-9]+\.[0-9]+(-[0-9]+)?" | head -n 1)"
|
||||||
|
MYSQL_MAJOR_VERSION="$(echo $MYSQL_VERSION | cut -d '.' -f1)"
|
||||||
|
MYSQL_MINOR_VERSION="$(echo $MYSQL_VERSION | cut -d '.' -f2)"
|
||||||
|
MYSQL_PATCH_LEVEL="$(echo $MYSQL_VERSION | cut -d '.' -f3)"
|
||||||
|
MYSQL_MAIN_VERSION="$(echo $MYSQL_VERSION | cut -d '.' -f1,2)"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# - Is 'systemd' supported on this system
|
# - Is 'systemd' supported on this system
|
||||||
@@ -228,14 +283,14 @@ else
|
|||||||
fi
|
fi
|
||||||
DEFAULT_POSTFIX_DB_NAME="postfix"
|
DEFAULT_POSTFIX_DB_NAME="postfix"
|
||||||
DEFAULT_POSTFIX_DB_USER="postfix"
|
DEFAULT_POSTFIX_DB_USER="postfix"
|
||||||
if [[ -f "/usr/local/mysql/sys-maint.cnf" ]] ; then
|
#if [[ -f "/usr/local/mysql/sys-maint.cnf" ]] ; then
|
||||||
DEFAULT_MYSQL_CREDENTIALS="--defaults-file=/usr/local/mysql/sys-maint.cnf"
|
# DEFAULT_MYSQL_CREDENTIALS="--defaults-file=/usr/local/mysql/sys-maint.cnf"
|
||||||
elif [[ -f "/etc/mysql/debian.cnf" ]] ; then
|
#elif [[ -f "/etc/mysql/debian.cnf" ]] ; then
|
||||||
DEFAULT_MYSQL_CREDENTIALS="--defaults-file=/etc/mysql/debian.cnf"
|
# DEFAULT_MYSQL_CREDENTIALS="--defaults-file=/etc/mysql/debian.cnf"
|
||||||
else
|
#else
|
||||||
DEFAULT_MYSQL_CREDENTIALS=""
|
# DEFAULT_MYSQL_CREDENTIALS=""
|
||||||
fi
|
#fi
|
||||||
DEFAULT_DEBIAN_MYSQL_CREDENTIALS="/etc/mysql/debian.cnf"
|
#DEFAULT_DEBIAN_MYSQL_CREDENTIALS="/etc/mysql/debian.cnf"
|
||||||
|
|
||||||
DEFAULT_DOVEADM_PW="/usr/local/dovecot/bin/doveadm pw"
|
DEFAULT_DOVEADM_PW="/usr/local/dovecot/bin/doveadm pw"
|
||||||
DEFAULT_DELETED_MAILBOX_DIR="/var/deleted-maildirs"
|
DEFAULT_DELETED_MAILBOX_DIR="/var/deleted-maildirs"
|
||||||
@@ -341,11 +396,64 @@ fi
|
|||||||
|
|
||||||
[[ -n "$MYSQL_DEBIAN_INSTALLATION" ]] || MYSQL_DEBIAN_INSTALLATION=false
|
[[ -n "$MYSQL_DEBIAN_INSTALLATION" ]] || MYSQL_DEBIAN_INSTALLATION=false
|
||||||
|
|
||||||
if [[ "$POSTFIX_DB_TYPE" = "mysql" ]]; then
|
if [[ "$POSTFIX_DB_TYPE" = "mysql" ]] ; then
|
||||||
if $MYSQL_DEBIAN_INSTALLATION ; then
|
|
||||||
[[ -n "$MYSQL_CREDENTIALS" ]] || MYSQL_CREDENTIALS="$DEFAULT_DEBIAN_MYSQL_CREDENTIALS"
|
if [[ -z ${MYSQL_CREDENTIALS} ]] ; then
|
||||||
else
|
|
||||||
[[ -n "$MYSQL_CREDENTIALS" ]] || MYSQL_CREDENTIALS="$DEFAULT_MYSQL_CREDENTIALS"
|
detect_mysql_version
|
||||||
|
|
||||||
|
if [[ "$MYSQL_CUR_DISTRIBUTION" = "MariaDB" ]] && ([[ $MYSQL_MAJOR_VERSION -gt 10 ]] \
|
||||||
|
|| ( [[ $MYSQL_MAJOR_VERSION -eq 10 ]] && [[ $MYSQL_MINOR_VERSION -gt 3 ]] )) ; then
|
||||||
|
if [[ -S "/tmp/mysql.sock" ]]; then
|
||||||
|
MYSQL_CREDENTIALS="-u root -S /tmp/mysql.sock"
|
||||||
|
elif [[ -S "/run/mysqld/mysqld.sock" ]]; then
|
||||||
|
MYSQL_CREDENTIALS="-u root -S /run/mysqld/mysqld.sock"
|
||||||
|
elif [[ -S "/var/run/mysqld/mysqld.sock" ]]; then
|
||||||
|
MYSQL_CREDENTIALS="-u root -S /var/run/mysqld/mysqld.sock"
|
||||||
|
else
|
||||||
|
fatal "Parameter 'MYSQL_CREDENTIALS' cannot be determined automated.
|
||||||
|
|
||||||
|
Use configuration file "$conf_file" to set
|
||||||
|
parameter manually."
|
||||||
|
fi
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
echononl "\tGet MySQL command.."
|
||||||
|
mysql_command="$(which mysql)"
|
||||||
|
if [[ $? -eq 0 ]]; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
|
||||||
|
if [[ -x "/usr/local/mysql/bin/mysql" ]]; then
|
||||||
|
mysql_command="/usr/local/mysql/bin/mysql"
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
fatal "$(cat $tmp_log_file)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if $(${mysql_command} --login-path=local -e ";" > /dev/null 2>&1) ; then
|
||||||
|
MYSQL_CREDENTIALS="--login-path=local"
|
||||||
|
elif [[ -f "/usr/local/mysql/sys-maint.cnf" ]] ; then
|
||||||
|
MYSQL_CREDENTIALS="--defaults-file=/usr/local/mysql/sys-maint.cnf"
|
||||||
|
elif [[ -f "/etc/mysql/debian.cnf" ]] ; then
|
||||||
|
MYSQL_CREDENTIALS="--defaults-file=/etc/mysql/debian.cnf"
|
||||||
|
else
|
||||||
|
fatal "Parameter 'MYSQL_CREDENTIALS' cannot be determined automated.
|
||||||
|
|
||||||
|
Use configuration file "$conf_file" to set
|
||||||
|
parameter manually."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
#if $MYSQL_DEBIAN_INSTALLATION ; then
|
||||||
|
# [[ -n "$MYSQL_CREDENTIALS" ]] || MYSQL_CREDENTIALS="$DEFAULT_DEBIAN_MYSQL_CREDENTIALS"
|
||||||
|
#else
|
||||||
|
# [[ -n "$MYSQL_CREDENTIALS" ]] || MYSQL_CREDENTIALS="$DEFAULT_MYSQL_CREDENTIALS"
|
||||||
|
#fi
|
||||||
|
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
[[ "$POSTFIX_DB_TYPE" = "pgsql" ]] || fatal "Unknown Database Type '$POSTFIX_DB_TYPE' (POSTFIX_DB_TYPE)"
|
[[ "$POSTFIX_DB_TYPE" = "pgsql" ]] || fatal "Unknown Database Type '$POSTFIX_DB_TYPE' (POSTFIX_DB_TYPE)"
|
||||||
@@ -406,12 +514,103 @@ else
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# - Get activ PHP version, means that on which is part of $PATH environment
|
||||||
|
# -
|
||||||
|
echononl "\tGet PHP version in PATH environment.."
|
||||||
|
if $(which php > /dev/null 2>&1) ; then
|
||||||
|
php_version_in_path="$(php --version 2> /dev/null | head -1 | cut -d' ' -f2 | cut -d '-' -f1 2> /dev/null)"
|
||||||
|
if [[ $? -eq 0 ]] && [[ -n "${php_version_in_path}" ]]; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
|
||||||
|
fatal "Failed getting PHP Version.."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
|
||||||
|
fatal "No PHP binary found in PATH environment.."
|
||||||
|
fi
|
||||||
|
|
||||||
|
_actual_config_file=""
|
||||||
|
_actual_password_hash=""
|
||||||
|
_actual_pfa_dir=""
|
||||||
|
_actual_pfa_documentroot=""
|
||||||
|
if [[ -d "${WEBSITE_BASEDIR}/htdocs" ]] ; then
|
||||||
|
PFA_UPDATE=true
|
||||||
|
_actual_pfa_documentroot="$(realpath "${WEBSITE_BASEDIR}/htdocs")"
|
||||||
|
if [[ "$(basename "$(dirname "${_actual_pfa_documentroot}")")" =~ ^postfixadmin ]]; then
|
||||||
|
_actual_pfa_dir="$(dirname "${_actual_pfa_documentroot}")"
|
||||||
|
else
|
||||||
|
_actual_pfa_dir="${_actual_pfa_documentroot}"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
PFA_UPDATE=false
|
||||||
|
fi
|
||||||
|
|
||||||
|
echononl "\tKeep passwordhasch from actual installation in mind.."
|
||||||
|
if [[ -n "$_actual_pfa_dir" && -d "$_actual_pfa_dir" ]] ; then
|
||||||
|
if [[ -f "${_actual_pfa_dir}/config.local.php" ]]; then
|
||||||
|
_actual_config_file="${_actual_pfa_dir}/config.local.php"
|
||||||
|
else
|
||||||
|
_actual_config_file="${_actual_pfa_dir}/config.inc.php"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
if [[ -f "$_actual_config_file" ]]; then
|
||||||
|
_actual_password_hash="$(grep -E "^\s*\\\$CONF\['setup_password'\]" $_actual_config_file 2> /dev/null \
|
||||||
|
| grep -v changeme \
|
||||||
|
| awk -F '=' '{print$2}'\
|
||||||
|
| awk -F ';' '{print$1}')"
|
||||||
|
|
||||||
|
_actual_password_hash="${_actual_password_hash#"${_actual_password_hash%%[![:space:]]*}"}"
|
||||||
|
# - Remove trailing whitespace characters
|
||||||
|
_actual_password_hash="${_actual_password_hash%"${_actual_password_hash##*[![:space:]]}"}"
|
||||||
|
# - Remove leading single quote
|
||||||
|
_actual_password_hash="${_actual_password_hash#"${_actual_password_hash%%[!\']*}"}"
|
||||||
|
# - Remove trailing single quote
|
||||||
|
_actual_password_hash="${_actual_password_hash%"${_actual_password_hash##*[!\']}"}"
|
||||||
|
# - Remove leading double quote
|
||||||
|
_actual_password_hash="${_actual_password_hash#"${_actual_password_hash%%[!\"]*}"}"
|
||||||
|
# - Remove trailing double quote
|
||||||
|
_actual_password_hash="${_actual_password_hash%"${_actual_password_hash##*[!\"]}"}"
|
||||||
|
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
fi
|
||||||
|
|
||||||
|
_installed_version=""
|
||||||
|
if $PFA_UPDATE ; then
|
||||||
|
echononl "\tDetermine installed version of PFA .."
|
||||||
|
_installed_version="$(echo "$(basename "${_actual_pfa_dir}")" | cut -d'-' -f2)"
|
||||||
|
echo_ok
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "\033[1;32mSettings for installation of \033[1;37mPostfix Admin / Vacation\033[m"
|
echo -e "\033[1;32mSettings for installation of \033[1;37mPostfix Admin / Vacation\033[m"
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "\tPostfix Admin Version................: $PF_ADMIN_VERSION"
|
if $PFA_UPDATE ; then
|
||||||
|
echo -e "\tUpdate Postfixadmin..................: YES"
|
||||||
|
if [[ -n "${_installed_version}" ]] ; then
|
||||||
|
echo -e "\tinstalled PFA verion.................: $_installed_version"
|
||||||
|
else
|
||||||
|
echo -e "\tinstalled PFA verion.................: "** \033[33mnot detected\033[m **
|
||||||
|
fi
|
||||||
|
if [[ -n "$_actual_password_hash" ]]; then
|
||||||
|
echo -e "\tactual Passwordhash..................: $_actual_password_hash"
|
||||||
|
else
|
||||||
|
echo -e "\tactual Passwordhash..................: ** \033[33mnot found\033[m **"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo -e "\tInstall Postfixadmin first time......: YES"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
echo -e "\tPostfix Admin new Version............: $PF_ADMIN_VERSION"
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "\tName of the Website..................: $WEBSITE_NAME"
|
echo -e "\tName of the Website..................: $WEBSITE_NAME"
|
||||||
echo ""
|
echo ""
|
||||||
@@ -439,8 +638,18 @@ echo ""
|
|||||||
if $PHP_DEBIAN_INSTALLATION ; then
|
if $PHP_DEBIAN_INSTALLATION ; then
|
||||||
echo -e "\tInstalled PHP version................: $php_major_version"
|
echo -e "\tInstalled PHP version................: $php_major_version"
|
||||||
else
|
else
|
||||||
echo -e "\tInstalled PHP versions...............: $php_major_versions"
|
declare -i index=1
|
||||||
|
for _ver in $php_major_versions ; do
|
||||||
|
if [[ $index -eq 1 ]] ; then
|
||||||
|
echo -en "\tInstalled PHP versions...............: $_ver"
|
||||||
|
else
|
||||||
|
echo -en " $_ver"
|
||||||
|
fi
|
||||||
|
((index++))
|
||||||
|
done
|
||||||
|
echo ""
|
||||||
echo -e "\tNewest PHP Version...................: $php_latest_ver"
|
echo -e "\tNewest PHP Version...................: $php_latest_ver"
|
||||||
|
echo -e "\tPHP Version of php binary in PATH....: $php_version_in_path"
|
||||||
fi
|
fi
|
||||||
echo ""
|
echo ""
|
||||||
if [[ "$POSTFIX_DB_TYPE" = "mysql" ]]; then
|
if [[ "$POSTFIX_DB_TYPE" = "mysql" ]]; then
|
||||||
@@ -509,45 +718,6 @@ _failed=false
|
|||||||
> $log_file
|
> $log_file
|
||||||
|
|
||||||
|
|
||||||
_actual_config_file=""
|
|
||||||
_actual_password_hash=""
|
|
||||||
_actual_pfa_dir=""
|
|
||||||
if [[ -d "${WEBSITE_BASEDIR}/htdocs" ]] ; then
|
|
||||||
_actual_pfa_dir="$(realpath "${WEBSITE_BASEDIR}/htdocs")"
|
|
||||||
fi
|
|
||||||
echononl "\tKeep passwordhasch from actual installation in mind.."
|
|
||||||
if [[ -n "$_actual_pfa_dir" && -d "$_actual_pfa_dir" ]] ; then
|
|
||||||
if [[ -f "${_actual_pfa_dir}/config.local.php" ]]; then
|
|
||||||
_actual_config_file="${_actual_pfa_dir}/config.local.php"
|
|
||||||
else
|
|
||||||
_actual_config_file="${_actual_pfa_dir}/config.inc.php"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
if [[ -f "$_actual_config_file" ]]; then
|
|
||||||
_actual_password_hash="$(grep -E "^\s*\\\$CONF\['setup_password'\]" $_actual_config_file 2> /dev/null \
|
|
||||||
| grep -v changeme \
|
|
||||||
| awk -F '=' '{print$2}'\
|
|
||||||
| awk -F ';' '{print$1}')"
|
|
||||||
|
|
||||||
_actual_password_hash="${_actual_password_hash#"${_actual_password_hash%%[![:space:]]*}"}"
|
|
||||||
# - Remove trailing whitespace characters
|
|
||||||
_actual_password_hash="${_actual_password_hash%"${_actual_password_hash##*[![:space:]]}"}"
|
|
||||||
# - Remove leading single quote
|
|
||||||
_actual_password_hash="${_actual_password_hash#"${_actual_password_hash%%[!\']*}"}"
|
|
||||||
# - Remove trailing single quote
|
|
||||||
_actual_password_hash="${_actual_password_hash%"${_actual_password_hash##*[!\']}"}"
|
|
||||||
# - Remove leading double quote
|
|
||||||
_actual_password_hash="${_actual_password_hash#"${_actual_password_hash%%[!\"]*}"}"
|
|
||||||
# - Remove trailing double quote
|
|
||||||
_actual_password_hash="${_actual_password_hash%"${_actual_password_hash##*[!\"]}"}"
|
|
||||||
|
|
||||||
echo_ok
|
|
||||||
else
|
|
||||||
echo_skipped
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "$POSTFIX_DB_TYPE" = "mysql" ]] ; then
|
if [[ "$POSTFIX_DB_TYPE" = "mysql" ]] ; then
|
||||||
echononl "\tCheck if database '$POSTFIX_DB_NAME' already exists.."
|
echononl "\tCheck if database '$POSTFIX_DB_NAME' already exists.."
|
||||||
_db_response="$(mysql $MYSQL_CREDENTIALS -N -s -e \
|
_db_response="$(mysql $MYSQL_CREDENTIALS -N -s -e \
|
||||||
@@ -630,9 +800,14 @@ else
|
|||||||
if [[ ! -d "${WEBSITE_BASEDIR}" ]] ; then
|
if [[ ! -d "${WEBSITE_BASEDIR}" ]] ; then
|
||||||
echo_skipped
|
echo_skipped
|
||||||
else
|
else
|
||||||
|
if [[ -n "$_installed_version" ]] ; then
|
||||||
|
_db_backup_file_name="${POSTFIX_DB_NAME}-pfa-${_installed_version}.${backup_date}.sql"
|
||||||
|
else
|
||||||
|
_db_backup_file_name="${POSTFIX_DB_NAME}-pfa.${backup_date}.sql"
|
||||||
|
fi
|
||||||
if [[ "$POSTFIX_DB_TYPE" = "mysql" ]]; then
|
if [[ "$POSTFIX_DB_TYPE" = "mysql" ]]; then
|
||||||
echo -n " (MySQL).."
|
echo -n " (MySQL).."
|
||||||
mysqldump $MYSQL_CREDENTIALS --opt $POSTFIX_DB_NAME > ${WEBSITE_BASEDIR}/${POSTFIX_DB_NAME}.${backup_date}.sql 2> $log_file
|
mysqldump $MYSQL_CREDENTIALS --opt $POSTFIX_DB_NAME > ${WEBSITE_BASEDIR}/${_db_backup_file_name} 2> $log_file
|
||||||
if [[ $? -eq 0 ]]; then
|
if [[ $? -eq 0 ]]; then
|
||||||
echo_ok
|
echo_ok
|
||||||
else
|
else
|
||||||
@@ -646,7 +821,7 @@ else
|
|||||||
fi
|
fi
|
||||||
elif [[ "$POSTFIX_DB_TYPE" = "pgsql" ]]; then
|
elif [[ "$POSTFIX_DB_TYPE" = "pgsql" ]]; then
|
||||||
echo -n " (PostgreSQL).."
|
echo -n " (PostgreSQL).."
|
||||||
su - postgres -c "pg_dump -c $POSTFIX_DB_NAME" >> ${WEBSITE_BASEDIR}/${POSTFIX_DB_NAME}.${backup_date}.sql 2> $log_file
|
su - postgres -c "pg_dump -c $POSTFIX_DB_NAME" >> ${WEBSITE_BASEDIR}/${_db_backup_file_name} 2> $log_file
|
||||||
if [[ $? -eq 0 ]]; then
|
if [[ $? -eq 0 ]]; then
|
||||||
echo_ok
|
echo_ok
|
||||||
else
|
else
|
||||||
@@ -1377,22 +1552,22 @@ EOF
|
|||||||
cat <<EOF >> ${APACHE_VHOST_DIR}/${WEBSITE_NAME}.conf 2>> $log_file
|
cat <<EOF >> ${APACHE_VHOST_DIR}/${WEBSITE_NAME}.conf 2>> $log_file
|
||||||
DocumentRoot "${WEBSITE_BASEDIR}/htdocs/"
|
DocumentRoot "${WEBSITE_BASEDIR}/htdocs/"
|
||||||
|
|
||||||
<FilesMatch \.php$>
|
|
||||||
EOF
|
EOF
|
||||||
if $PHP_DEBIAN_INSTALLATION ; then
|
if $PHP_DEBIAN_INSTALLATION ; then
|
||||||
php_socket_file="/run/php/php${php_major_version}-fpm.sock"
|
php_socket_file="/run/php/php${php_major_version}-fpm.sock"
|
||||||
if [[ -S "/run/php$(echo $php_major_version | cut -d'.' -f1)-fpm.sock" ]]; then
|
if [[ -S "/run/php$(echo $php_major_version | cut -d'.' -f1)-fpm.sock" ]]; then
|
||||||
php_socket_file="/run/php$(echo $php_major_version | cut -d'.' -f1)-fpm.sock"
|
php_socket_file="/run/php$(echo $php_major_version | cut -d'.' -f1)-fpm.sock"
|
||||||
fi
|
fi
|
||||||
cat <<EOF >> ${APACHE_VHOST_DIR}/${WEBSITE_NAME}.conf 2>> $log_file
|
|
||||||
SetHandler "proxy:unix:${php_socket_file}|fcgi://127.0.0.1"
|
|
||||||
EOF
|
|
||||||
else
|
else
|
||||||
cat <<EOF >> ${APACHE_VHOST_DIR}/${WEBSITE_NAME}.conf 2>> $log_file
|
php_socket_file="/run/php/php-${php_latest_ver}-fpm.www.sock"
|
||||||
SetHandler "proxy:unix:/tmp/php-${php_latest_ver}-fpm.www.sock|fcgi://127.0.0.1"
|
if [[ -S "/tmp/php-${php_latest_ver}-fpm.www.sock" ]]; then
|
||||||
EOF
|
php_socket_file="/run/php/php-${php_latest_ver}-fpm.www.sock"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cat <<EOF >> ${APACHE_VHOST_DIR}/${WEBSITE_NAME}.conf 2>> $log_file
|
cat <<EOF >> ${APACHE_VHOST_DIR}/${WEBSITE_NAME}.conf 2>> $log_file
|
||||||
|
<FilesMatch \.php$>
|
||||||
|
SetHandler "proxy:unix:${php_socket_file}|fcgi://127.0.0.1"
|
||||||
</FilesMatch>
|
</FilesMatch>
|
||||||
|
|
||||||
<IfModule dir_module>
|
<IfModule dir_module>
|
||||||
@@ -1667,23 +1842,25 @@ fi
|
|||||||
|
|
||||||
# - Encoding does not work as exspected.
|
# - Encoding does not work as exspected.
|
||||||
# -
|
# -
|
||||||
|
# - Update: Encoding seems to works now
|
||||||
|
# -
|
||||||
# - NOTE:
|
# - NOTE:
|
||||||
# - this IS NOT a fix, but a workaround
|
# - this IS NOT a fix, but a workaround
|
||||||
# -
|
# -
|
||||||
echononl "\tWorkaround, because encoding does not work as exspected."
|
#echononl "\tWorkaround, because encoding does not work as exspected."
|
||||||
# - Vacation script changed. Since Version 3.2 we need another perl regexp.
|
## - Vacation script changed. Since Version 3.2 we need another perl regexp.
|
||||||
# - The old one was:
|
## - The old one was:
|
||||||
# - perl -i -n -p -e "s/(\s*\'ctype\'\s* =>\s*)\'text\/plain.*$/\1\'text\/plain; charset=iso-8859-1\',/" \
|
## - perl -i -n -p -e "s/(\s*\'ctype\'\s* =>\s*)\'text\/plain.*$/\1\'text\/plain; charset=iso-8859-1\',/" \
|
||||||
# -
|
## -
|
||||||
perl -i -n -p -e "s/(\s*\'Content-Type\'\s* =>\s*)\"text\/plain.*$/\1\"text\/plain; charset=iso-8859-1\",/" \
|
##perl -i -n -p -e "s/(\s*\'Content-Type\'\s* =>\s*)\"text\/plain.*$/\1\"text\/plain; charset=iso-8859-1\",/" \
|
||||||
/var/spool/vacation/vacation.pl > "$log_file" 2>&1
|
## /var/spool/vacation/vacation.pl > "$log_file" 2>&1
|
||||||
if [[ $? -eq 0 ]];then
|
#if [[ $? -eq 0 ]];then
|
||||||
echo_ok
|
# echo_ok
|
||||||
info "This IS NOT a fix, but a workaround."
|
# info "This IS NOT a fix, but a workaround."
|
||||||
else
|
#else
|
||||||
echo_failed
|
# echo_failed
|
||||||
error "$(cat $log_file)"
|
# error "$(cat $log_file)"
|
||||||
fi
|
#fi
|
||||||
|
|
||||||
echononl "\tSet Permission on vacation script"
|
echononl "\tSet Permission on vacation script"
|
||||||
_failed=false
|
_failed=false
|
||||||
@@ -2187,8 +2364,9 @@ fi
|
|||||||
## - 'relay' // for backup mx
|
## - 'relay' // for backup mx
|
||||||
## - );
|
## - );
|
||||||
## - $CONF['transport_default'] = 'lmtp:unix:private/dovecot-lmtp';
|
## - $CONF['transport_default'] = 'lmtp:unix:private/dovecot-lmtp';
|
||||||
## - $CONF['vacation'] = 'YES';
|
## - $CONF['vacation'] = 'NO';
|
||||||
## - $CONF['vacation_domain'] = '$AUTOREPLY_HOSTNAME';
|
## - $CONF['vacation_domain'] = '$AUTOREPLY_HOSTNAME';
|
||||||
|
## - $CONF['password_expiration'] = 'NO';
|
||||||
## -
|
## -
|
||||||
echononl "\tAdjust Postfix Admin's Configuration - Part 3"
|
echononl "\tAdjust Postfix Admin's Configuration - Part 3"
|
||||||
_failed=false
|
_failed=false
|
||||||
@@ -2213,10 +2391,12 @@ cat <<EOF >> $pfa_conf_file 2> $log_file
|
|||||||
\$CONF['transport_default'] = 'lmtp:unix:private/dovecot-lmtp';
|
\$CONF['transport_default'] = 'lmtp:unix:private/dovecot-lmtp';
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
perl -i -n -p -e "s#^(\s*\\\$CONF\['vacation'\]\s*=.*)#//!\1\n\\\$CONF['vacation'] = 'YES';#" \
|
perl -i -n -p -e "s#^(\s*\\\$CONF\['vacation'\]\s*=.*)#//!\1\n\\\$CONF['vacation'] = 'NO';#" \
|
||||||
$pfa_conf_file >> $log_file 2>&1 || _failed=true
|
$pfa_conf_file >> $log_file 2>&1 || _failed=true
|
||||||
perl -i -n -p -e "s#^(\s*\\\$CONF\['vacation_domain'\]\s*=.*)#//!\1\n\\\$CONF['vacation_domain'] = '$AUTOREPLY_HOSTNAME';#" \
|
perl -i -n -p -e "s#^(\s*\\\$CONF\['vacation_domain'\]\s*=.*)#//!\1\n\\\$CONF['vacation_domain'] = '$AUTOREPLY_HOSTNAME';#" \
|
||||||
$pfa_conf_file >> $log_file 2>&1 || _failed=true
|
$pfa_conf_file >> $log_file 2>&1 || _failed=true
|
||||||
|
perl -i -n -p -e "s#^(\s*\\\$CONF\['password_expiration'\]\s*=.*)#//!\1\n\\\$CONF['password_expiration'] = 'NO';#" \
|
||||||
|
$pfa_conf_file >> $log_file 2>&1 || _failed=true
|
||||||
if $_failed ; then
|
if $_failed ; then
|
||||||
echo_failed
|
echo_failed
|
||||||
error "$(cat $log_file)"
|
error "$(cat $log_file)"
|
||||||
@@ -2316,7 +2496,7 @@ fi
|
|||||||
## - $CONF['show_undeliverable']='NO';
|
## - $CONF['show_undeliverable']='NO';
|
||||||
## - $CONF['show_popimap']='NO';
|
## - $CONF['show_popimap']='NO';
|
||||||
## -
|
## -
|
||||||
## - $CONF['used_quotas'] = 'YES';
|
## - $CONF['used_quotas'] = 'NO';
|
||||||
## - $CONF['new_quota_table'] = 'YES';
|
## - $CONF['new_quota_table'] = 'YES';
|
||||||
## -
|
## -
|
||||||
echononl "\tAdjust Postfix Admin's Configuration - Part 5"
|
echononl "\tAdjust Postfix Admin's Configuration - Part 5"
|
||||||
@@ -2348,7 +2528,7 @@ perl -i -n -p -e "s#^(\s*\\\$CONF\['show_undeliverable'\]\s*=.*)#//!\1\n\\\$CONF
|
|||||||
$pfa_conf_file >> $log_file 2>&1 || _failed=true
|
$pfa_conf_file >> $log_file 2>&1 || _failed=true
|
||||||
perl -i -n -p -e "s#^(\s*\\\$CONF\['show_popimap'\]\s*=.*)#//!\1\n\\\$CONF['show_popimap'] = 'NO';#" \
|
perl -i -n -p -e "s#^(\s*\\\$CONF\['show_popimap'\]\s*=.*)#//!\1\n\\\$CONF['show_popimap'] = 'NO';#" \
|
||||||
$pfa_conf_file >> $log_file 2>&1 || _failed=true
|
$pfa_conf_file >> $log_file 2>&1 || _failed=true
|
||||||
perl -i -n -p -e "s#^(\s*\\\$CONF\['used_quotas'\]\s*=.*)#//!\1\n\\\$CONF['used_quotas'] = 'YES';#" \
|
perl -i -n -p -e "s#^(\s*\\\$CONF\['used_quotas'\]\s*=.*)#//!\1\n\\\$CONF['used_quotas'] = 'NO';#" \
|
||||||
$pfa_conf_file >> $log_file 2>&1 || _failed=true
|
$pfa_conf_file >> $log_file 2>&1 || _failed=true
|
||||||
perl -i -n -p -e "s#^(\s*\\\$CONF\['new_quota_table'\]\s*=.*)#//!\1\n\\\$CONF['new_quota_table'] = 'YES';#" \
|
perl -i -n -p -e "s#^(\s*\\\$CONF\['new_quota_table'\]\s*=.*)#//!\1\n\\\$CONF['new_quota_table'] = 'YES';#" \
|
||||||
$pfa_conf_file >> $log_file 2>&1 || _failed=true
|
$pfa_conf_file >> $log_file 2>&1 || _failed=true
|
||||||
@@ -2396,13 +2576,47 @@ fi
|
|||||||
# -
|
# -
|
||||||
echononl "\tTake passwordhash from previosly installation.."
|
echononl "\tTake passwordhash from previosly installation.."
|
||||||
if [[ -n "$_actual_password_hash" ]] ; then
|
if [[ -n "$_actual_password_hash" ]] ; then
|
||||||
perl -i -n -p -e "s#^(\s*\\\$CONF\['setup_password'\]\s*=.*)#//!\1\n\\\$CONF['setup_password'] = '$_actual_password_hash';#" \
|
|
||||||
$pfa_conf_file >> $log_file 2>&1
|
_failed=false
|
||||||
if [[ $? -eq 0 ]] ; then
|
_backup_file="/tmp/$(basename "${pfa_conf_file}")"
|
||||||
echo_ok
|
mv "$pfa_conf_file" "$_backup_file" > $log_file 2>&1
|
||||||
else
|
if [[ $? -ne 0 ]] ; then
|
||||||
echo_failed
|
_failed=true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
> $pfa_conf_file
|
||||||
|
_found=false
|
||||||
|
while IFS='' read -r _line || [[ -n $_line ]] ; do
|
||||||
|
if echo "$_line" | grep -i -E "^\s*\\\$CONF\['setup_password'\]\s*=.*;" > /dev/null 2>&1 ; then
|
||||||
|
echo -n '//!' >> $pfa_conf_file
|
||||||
|
echo "$_line" >> $pfa_conf_file
|
||||||
|
if ! $_found ; then
|
||||||
|
echo "\$CONF['setup_password'] = '$_actual_password_hash';" >> $pfa_conf_file
|
||||||
|
_found=true
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "$_line" >> $pfa_conf_file
|
||||||
|
fi
|
||||||
|
done < $_backup_file
|
||||||
|
|
||||||
|
if [[ $? -ne 0 ]] ; then
|
||||||
|
_failed=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
if $_failed ; then
|
||||||
|
echo_failed
|
||||||
|
else
|
||||||
|
echo_ok
|
||||||
|
fi
|
||||||
|
|
||||||
|
#perl -i -n -p -e "s#^(\s*\\\$CONF\['setup_password'\]\s*=.*)#//!\1\n\\\$CONF['setup_password'] = '$_actual_password_hash';#" \
|
||||||
|
# $pfa_conf_file > $log_file 2>&1
|
||||||
|
#if [[ $? -eq 0 ]] ; then
|
||||||
|
# echo_ok
|
||||||
|
#else
|
||||||
|
# echo_failed
|
||||||
|
#fi
|
||||||
|
|
||||||
else
|
else
|
||||||
echo_skipped
|
echo_skipped
|
||||||
fi
|
fi
|
||||||
@@ -3331,6 +3545,11 @@ fi
|
|||||||
echo ""
|
echo ""
|
||||||
info "Browse to \033[1mhttp://${WEBSITE_NAME}/setup.php\033[m to create a 'setup password'\n$(cat <<EOF
|
info "Browse to \033[1mhttp://${WEBSITE_NAME}/setup.php\033[m to create a 'setup password'\n$(cat <<EOF
|
||||||
|
|
||||||
|
\t \033[33mIn caes of updating postfix.admin browse this URL and \033[1mlogin with your
|
||||||
|
\t setup_password\033[m\033[33m, because only after that the database '${POSTFIX_DB_NAME}'
|
||||||
|
\t will be updated. If you don't know this password, create a new one. This is also
|
||||||
|
\t done within this interface.\033[m
|
||||||
|
|
||||||
\t If this is a fresh new installation, you have also to ceate one (ore more)
|
\t If this is a fresh new installation, you have also to ceate one (ore more)
|
||||||
\t superadmin account(s).
|
\t superadmin account(s).
|
||||||
|
|
||||||
@@ -3354,6 +3573,14 @@ info "Browse to \033[1mhttp://${WEBSITE_NAME}/setup.php\033[m to create a 'setup
|
|||||||
EOF
|
EOF
|
||||||
)"
|
)"
|
||||||
|
|
||||||
|
if [[ -n "$_actual_password_hash" ]] ; then
|
||||||
|
info "The Parameter \$CONF['setup_password'] was set as follows:\n$(cat <<EOF
|
||||||
|
|
||||||
|
\t \$CONF['setup_password'] = '${_actual_password_hash}';
|
||||||
|
EOF
|
||||||
|
)"
|
||||||
|
fi
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
clean_up 0
|
clean_up 0
|
||||||
|
|
||||||
|
|||||||
@@ -65,6 +65,14 @@ echo_skipped() {
|
|||||||
echo -e "\033[80G[ \033[33m\033[1mskipped\033[m ]"
|
echo -e "\033[80G[ \033[33m\033[1mskipped\033[m ]"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
systemd_exists=false
|
||||||
|
systemd=$(which systemd)
|
||||||
|
systemctl=$(which systemctl)
|
||||||
|
|
||||||
|
if [[ -n "$systemd" ]] || [[ -n "$systemctl" ]] ; then
|
||||||
|
systemd_exists=true
|
||||||
|
fi
|
||||||
|
|
||||||
## - Install Postfix Firewall Daemon from debian packages system
|
## - Install Postfix Firewall Daemon from debian packages system
|
||||||
## -
|
## -
|
||||||
echononl " Install Postfix Firewall Daemon from debian packages system"
|
echononl " Install Postfix Firewall Daemon from debian packages system"
|
||||||
|
|||||||
@@ -108,6 +108,62 @@ is_number() {
|
|||||||
#return $([[ ! -z "${1##*[!0-9]*}" ]])
|
#return $([[ ! -z "${1##*[!0-9]*}" ]])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
detect_mysql_version () {
|
||||||
|
|
||||||
|
_MYSQLD_VERSION="$(mysqld -V 2>/dev/null)"
|
||||||
|
|
||||||
|
if [[ -z "$_MYSQLD_VERSION" ]]; then
|
||||||
|
fatal "No installed MySQL server or distribution found!"
|
||||||
|
elif [[ -d "/usr/local/mysql" ]] && [[ "$(basename "$(realpath "/usr/local/mysql")")" =~ percona- ]]; then
|
||||||
|
MYSQL_CUR_DISTRIBUTION="Percona"
|
||||||
|
elif [[ "$_MYSQLD_VERSION" =~ MariaDB ]]; then
|
||||||
|
MYSQL_CUR_DISTRIBUTION="MariaDB"
|
||||||
|
elif [[ "$_MYSQLD_VERSION" =~ MySQL ]]; then
|
||||||
|
MYSQL_CUR_DISTRIBUTION="MySQL"
|
||||||
|
elif [[ -d "/usr/local/mysql" ]] && [[ "$(basename "$(realpath "/usr/local/mysql")")" =~ mysql- ]]; then
|
||||||
|
MYSQL_CUR_DISTRIBUTION="MySQL"
|
||||||
|
elif [[ -d "/usr/local/mysql" ]] && [[ "$(basename "$(realpath "/usr/local/mysql")")" =~ mariadb- ]]; then
|
||||||
|
MYSQL_CUR_DISTRIBUTION="MariaDB"
|
||||||
|
else
|
||||||
|
error "MySQL Instalation found, but cannot determin the distribution!"
|
||||||
|
|
||||||
|
MYSQL_CUR_DISTRIBUTION=
|
||||||
|
echo ""
|
||||||
|
echo " Select the installed MySQL distribution."
|
||||||
|
echo ""
|
||||||
|
echo " [1] MySQL (the original community edition)"
|
||||||
|
echo " [2] Percona Server for MySQL"
|
||||||
|
echo " [3] MariaDB"
|
||||||
|
echo ""
|
||||||
|
echononl " Eingabe [1/2/3]: "
|
||||||
|
|
||||||
|
while [ "$MYSQL_CUR_DISTRIBUTION" != "MySQL" -a "$MYSQL_CUR_DISTRIBUTION" != "MariaDB" -a "$MYSQL_CUR_DISTRIBUTION" != "Percona" ];do
|
||||||
|
read OPTION
|
||||||
|
case $OPTION in
|
||||||
|
1) MYSQL_CUR_DISTRIBUTION="MySQL"
|
||||||
|
;;
|
||||||
|
2) MYSQL_CUR_DISTRIBUTION="Percona"
|
||||||
|
;;
|
||||||
|
3) MYSQL_CUR_DISTRIBUTION="MariaDB"
|
||||||
|
;;
|
||||||
|
*) echo ""
|
||||||
|
echo -e "\tFalsche Eingabe ! [ 1 = MySQL ; 2 = Percona ; 3 = MariaDB ]"
|
||||||
|
echo ""
|
||||||
|
echononl " Eingabe:"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
MYSQL_VERSION="$(echo $_MYSQLD_VERSION | grep -o -E "[0-9]+\.[0-9]+\.[0-9]+(-[0-9]+)?" | head -n 1)"
|
||||||
|
MYSQL_MAJOR_VERSION="$(echo $MYSQL_VERSION | cut -d '.' -f1)"
|
||||||
|
MYSQL_MINOR_VERSION="$(echo $MYSQL_VERSION | cut -d '.' -f2)"
|
||||||
|
MYSQL_PATCH_LEVEL="$(echo $MYSQL_VERSION | cut -d '.' -f3)"
|
||||||
|
MYSQL_MAIN_VERSION="$(echo $MYSQL_VERSION | cut -d '.' -f1,2)"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
trim() {
|
trim() {
|
||||||
local var="$*"
|
local var="$*"
|
||||||
var="${var#"${var%%[![:space:]]*}"}" # remove leading whitespace characters
|
var="${var#"${var%%[![:space:]]*}"}" # remove leading whitespace characters
|
||||||
@@ -296,14 +352,6 @@ DEFAULT_APACHE_VHOST_DIR="/usr/local/apache2/conf/vhosts"
|
|||||||
DEFAULT_DB_HOST="localhost"
|
DEFAULT_DB_HOST="localhost"
|
||||||
DEFAULT_DB_NAME="roundcubemail"
|
DEFAULT_DB_NAME="roundcubemail"
|
||||||
DEFAULT_DB_USER="roundcube"
|
DEFAULT_DB_USER="roundcube"
|
||||||
if [[ -f "/usr/local/mysql/sys-maint.cnf" ]] ; then
|
|
||||||
DEFAULT_MYSQL_CREDENTIALS="--defaults-file=/usr/local/mysql/sys-maint.cnf"
|
|
||||||
elif [[ -f "/etc/mysql/debian.cnf" ]] ; then
|
|
||||||
DEFAULT_MYSQL_CREDENTIALS="--defaults-file=/etc/mysql/debian.cnf"
|
|
||||||
else
|
|
||||||
DEFAULT_MYSQL_CREDENTIALS=""
|
|
||||||
fi
|
|
||||||
DEFAULT_DEBIAN_MYSQL_CREDENTIALS="--defaults-file=/etc/mysql/debian.cnf"
|
|
||||||
|
|
||||||
[[ -n "$ROUNDCUBE_VERSION" ]] || fatal "Roundcube Version (ROUNDCUBE_VERSION) not present!"
|
[[ -n "$ROUNDCUBE_VERSION" ]] || fatal "Roundcube Version (ROUNDCUBE_VERSION) not present!"
|
||||||
[[ -n "$WEBSITE_NAME" ]] || fatal "Website's name (WEBSITE_NAME) not present!"
|
[[ -n "$WEBSITE_NAME" ]] || fatal "Website's name (WEBSITE_NAME) not present!"
|
||||||
@@ -401,16 +449,76 @@ fi
|
|||||||
|
|
||||||
[[ -n "$MYSQL_DEBIAN_INSTALLATION" ]] || MYSQL_DEBIAN_INSTALLATION=false
|
[[ -n "$MYSQL_DEBIAN_INSTALLATION" ]] || MYSQL_DEBIAN_INSTALLATION=false
|
||||||
|
|
||||||
if [[ "$DB_TYPE" = "mysql" ]]; then
|
|
||||||
if $MYSQL_DEBIAN_INSTALLATION ; then
|
if [ "$DB_TYPE" = "postgres" -o "$DB_TYPE" = "postgresql" -o "$DB_TYPE" = "pgsql" -o "$DB_TYPE" = "psql" ];then
|
||||||
[[ -n "$MYSQL_CREDENTIALS" ]] || MYSQL_CREDENTIALS="$DEFAULT_DEBIAN_MYSQL_CREDENTIALS"
|
DB_TYPE="pgsql"
|
||||||
else
|
fi
|
||||||
[[ -n "$MYSQL_CREDENTIALS" ]] || MYSQL_CREDENTIALS="$DEFAULT_MYSQL_CREDENTIALS"
|
|
||||||
|
|
||||||
|
if [[ "$DB_TYPE" = "mysql" ]] ; then
|
||||||
|
|
||||||
|
if [[ -z ${MYSQL_CREDENTIALS} ]] ; then
|
||||||
|
|
||||||
|
detect_mysql_version
|
||||||
|
|
||||||
|
if [[ "$MYSQL_CUR_DISTRIBUTION" = "MariaDB" ]] && ([[ $MYSQL_MAJOR_VERSION -gt 10 ]] \
|
||||||
|
|| ( [[ $MYSQL_MAJOR_VERSION -eq 10 ]] && [[ $MYSQL_MINOR_VERSION -gt 3 ]] )) ; then
|
||||||
|
if [[ -S "/tmp/mysql.sock" ]]; then
|
||||||
|
MYSQL_CREDENTIALS="-u root -S /tmp/mysql.sock"
|
||||||
|
elif [[ -S "/run/mysqld/mysqld.sock" ]]; then
|
||||||
|
MYSQL_CREDENTIALS="-u root -S /run/mysqld/mysqld.sock"
|
||||||
|
elif [[ -S "/var/run/mysqld/mysqld.sock" ]]; then
|
||||||
|
MYSQL_CREDENTIALS="-u root -S /var/run/mysqld/mysqld.sock"
|
||||||
|
else
|
||||||
|
fatal "Parameter 'MYSQL_CREDENTIALS' cannot be determined automated.
|
||||||
|
|
||||||
|
Use configuration file "$conf_file" to set
|
||||||
|
parameter manually."
|
||||||
|
fi
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
echononl "\tGet MySQL command.."
|
||||||
|
mysql_command="$(which mysql)"
|
||||||
|
if [[ $? -eq 0 ]]; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
|
||||||
|
if [[ -x "/usr/local/mysql/bin/mysql" ]]; then
|
||||||
|
mysql_command="/usr/local/mysql/bin/mysql"
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
fatal "$(cat $tmp_log_file)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if $(${mysql_command} --login-path=local -e ";" > /dev/null 2>&1) ; then
|
||||||
|
MYSQL_CREDENTIALS="--login-path=local"
|
||||||
|
elif [[ -f "/usr/local/mysql/sys-maint.cnf" ]] ; then
|
||||||
|
MYSQL_CREDENTIALS="--defaults-file=/usr/local/mysql/sys-maint.cnf"
|
||||||
|
elif [[ -f "/etc/mysql/debian.cnf" ]] ; then
|
||||||
|
MYSQL_CREDENTIALS="--defaults-file=/etc/mysql/debian.cnf"
|
||||||
|
else
|
||||||
|
fatal "Parameter 'MYSQL_CREDENTIALS' cannot be determined automated.
|
||||||
|
|
||||||
|
Use configuration file "$conf_file" to set
|
||||||
|
parameter manually."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
#if $MYSQL_DEBIAN_INSTALLATION ; then
|
||||||
|
# [[ -n "$MYSQL_CREDENTIALS" ]] || MYSQL_CREDENTIALS="$DEFAULT_DEBIAN_MYSQL_CREDENTIALS"
|
||||||
|
#else
|
||||||
|
# [[ -n "$MYSQL_CREDENTIALS" ]] || MYSQL_CREDENTIALS="$DEFAULT_MYSQL_CREDENTIALS"
|
||||||
|
#fi
|
||||||
|
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
[[ "$DB_TYPE" = "pgsql" ]] || fatal "Unknown Database Type '$DB_TYPE' (DB_TYPE)"
|
[[ "$DB_TYPE" = "pgsql" ]] || fatal "Unknown Database Type '$DB_TYPE' (DB_TYPE)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
[[ -n "$SPAM_FOLDER_NAME" ]] || SPAM_FOLDER_NAME=$DEFAULT_SPAM_FOLDER_NAME
|
[[ -n "$SPAM_FOLDER_NAME" ]] || SPAM_FOLDER_NAME=$DEFAULT_SPAM_FOLDER_NAME
|
||||||
|
|
||||||
[[ -n "$SUPPORT_URL" ]] || SUPPORT_URL="http://www.${MAIN_DOMAIN}.$TLD"
|
[[ -n "$SUPPORT_URL" ]] || SUPPORT_URL="http://www.${MAIN_DOMAIN}.$TLD"
|
||||||
@@ -1480,7 +1588,7 @@ EOF
|
|||||||
EOF
|
EOF
|
||||||
else
|
else
|
||||||
cat <<EOF >> ${APACHE_VHOST_DIR}/${WEBSITE_NAME}.conf 2>> $log_file
|
cat <<EOF >> ${APACHE_VHOST_DIR}/${WEBSITE_NAME}.conf 2>> $log_file
|
||||||
SetHandler "proxy:unix:/tmp/php-${php_latest_ver}-fpm.www.sock|fcgi://127.0.0.1"
|
SetHandler "proxy:unix:/run/php/php-${php_latest_ver}-fpm.www.sock|fcgi://127.0.0.1"
|
||||||
EOF
|
EOF
|
||||||
fi
|
fi
|
||||||
cat <<EOF >> ${APACHE_VHOST_DIR}/${WEBSITE_NAME}.conf 2>> $log_file
|
cat <<EOF >> ${APACHE_VHOST_DIR}/${WEBSITE_NAME}.conf 2>> $log_file
|
||||||
@@ -1856,8 +1964,7 @@ info "Now browse to the intaller site and continue installation.\n$(cat <<EOF
|
|||||||
junk_mbox..............: $SPAM_FOLDER_NAME
|
junk_mbox..............: $SPAM_FOLDER_NAME
|
||||||
|
|
||||||
SMTP Settings:
|
SMTP Settings:
|
||||||
smtp_server............: tls://$(hostname -f)
|
smtp_host..............: tls://$(hostname -f):587
|
||||||
smtp_port..............: 587
|
|
||||||
|
|
||||||
smtp_user/smtp_pass....:
|
smtp_user/smtp_pass....:
|
||||||
[x] Use the current IMAP username and password for SMTP authentication
|
[x] Use the current IMAP username and password for SMTP authentication
|
||||||
@@ -1972,9 +2079,10 @@ cat <<EOF >>$WEBSITE_BASEDIR/roundcubemail-${ROUNDCUBE_VERSION}/config/config.in
|
|||||||
// SMTP
|
// SMTP
|
||||||
// ----------------------------------
|
// ----------------------------------
|
||||||
|
|
||||||
// SMTP server host (for sending mails).
|
// SMTP server host (and optional port number) for sending mails.
|
||||||
// Enter hostname with prefix tls:// to use STARTTLS, or use
|
// Enter hostname with prefix ssl:// to use Implicit TLS, or use
|
||||||
// prefix ssl:// to use the deprecated SSL over SMTP (aka SMTPS)
|
// prefix tls:// to use STARTTLS.
|
||||||
|
// If port number is omitted it will be set to 465 (for ssl://) or 587 otherwise.
|
||||||
// Supported replacement variables:
|
// Supported replacement variables:
|
||||||
// %h - user's IMAP hostname
|
// %h - user's IMAP hostname
|
||||||
// %n - hostname (\$_SERVER['SERVER_NAME'])
|
// %n - hostname (\$_SERVER['SERVER_NAME'])
|
||||||
@@ -1982,11 +2090,9 @@ cat <<EOF >>$WEBSITE_BASEDIR/roundcubemail-${ROUNDCUBE_VERSION}/config/config.in
|
|||||||
// %d - domain (http hostname \$_SERVER['HTTP_HOST'] without the first part)
|
// %d - domain (http hostname \$_SERVER['HTTP_HOST'] without the first part)
|
||||||
// %z - IMAP domain (IMAP hostname without the first part)
|
// %z - IMAP domain (IMAP hostname without the first part)
|
||||||
// For example %n = mail.domain.tld, %t = domain.tld
|
// For example %n = mail.domain.tld, %t = domain.tld
|
||||||
\$config['smtp_server'] = 'tls://$(hostname -f)';
|
// To specify different SMTP servers for different IMAP hosts provide an array
|
||||||
|
// of IMAP host (no prefix or port) and SMTP server e.g. ['imap.example.com' => 'smtp.example.net']
|
||||||
// SMTP port (default is 25; use 587 for STARTTLS or 465 for the
|
\$config['smtp_host'] = 'tls://$(hostname -f):587';
|
||||||
// deprecated SSL over SMTP (aka SMTPS))
|
|
||||||
\$config['smtp_port'] = 587;
|
|
||||||
|
|
||||||
// SMTP username (if required) if you use %u as the username Roundcube
|
// SMTP username (if required) if you use %u as the username Roundcube
|
||||||
// will use the current username for login
|
// will use the current username for login
|
||||||
|
|||||||
11289
install_update_dovecot-2.4.sh
Executable file
11289
install_update_dovecot-2.4.sh
Executable file
File diff suppressed because it is too large
Load Diff
@@ -115,13 +115,44 @@ echo_skipped() {
|
|||||||
echo -e "\033[71G[ \033[33m\033[1mskipped\033[m ]"
|
echo -e "\033[71G[ \033[33m\033[1mskipped\033[m ]"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
detect_os_1 () {
|
||||||
|
|
||||||
|
if $(which lsb_release > /dev/null 2>&1) ; then
|
||||||
|
|
||||||
|
os_dist="$(lsb_release -i | awk '{print tolower($3)}')"
|
||||||
|
os_version="$(lsb_release -r | awk '{print tolower($2)}')"
|
||||||
|
os_codename="$(lsb_release -c | awk '{print tolower($2)}')"
|
||||||
|
|
||||||
|
if [[ "$os_dist" = "debian" ]]; then
|
||||||
|
if $(echo "$os_version" | grep -q '\.') ; then
|
||||||
|
os_version=$(echo "$os_version" | cut --delimiter='.' -f1)
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
elif [[ -e "/etc/os-release" ]]; then
|
||||||
|
|
||||||
|
. /etc/os-release
|
||||||
|
|
||||||
|
os_dist=$ID
|
||||||
|
os_version=${VERSION_ID}
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
# remove whitespace from os_dist and os_version
|
||||||
|
os_dist="${os_dist// /}"
|
||||||
|
os_version="${os_version// /}"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# - Support systemd ?
|
# - Support systemd ?
|
||||||
# -
|
# -
|
||||||
if [[ "X$(which systemd)" = "X" ]]; then
|
SYSTEMD_EXISTS=false
|
||||||
SYSTEMD_EXISTS=false
|
systemd=$(which systemd)
|
||||||
else
|
systemctl=$(which systemctl)
|
||||||
|
|
||||||
|
if [[ -n "$systemd" ]] || [[ -n "$systemctl" ]] ; then
|
||||||
SYSTEMD_EXISTS=true
|
SYSTEMD_EXISTS=true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -134,6 +165,14 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# - Detect OS - Set variable
|
||||||
|
# - os_dist
|
||||||
|
# - os_version
|
||||||
|
# - os_codename
|
||||||
|
# -
|
||||||
|
detect_os_1
|
||||||
|
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echononl "\tInclude Configuration file.."
|
echononl "\tInclude Configuration file.."
|
||||||
if [[ ! -f $conf_file ]]; then
|
if [[ ! -f $conf_file ]]; then
|
||||||
@@ -250,14 +289,21 @@ dovecot_main_version="$(echo $_version | cut -d '.' -f1,2)"
|
|||||||
dovecot_major_version="$(echo $_version | cut -d '.' -f1)"
|
dovecot_major_version="$(echo $_version | cut -d '.' -f1)"
|
||||||
dovecot_minor_version="$(echo $_version | cut -d '.' -f2)"
|
dovecot_minor_version="$(echo $_version | cut -d '.' -f2)"
|
||||||
dovecot_patch_level="$(echo $_version | cut -d '.' -f3)"
|
dovecot_patch_level="$(echo $_version | cut -d '.' -f3)"
|
||||||
|
dovecot_minor_patch_level="$(echo $_version | cut -d '.' -f4)"
|
||||||
|
|
||||||
|
_version_short="${_version%-*}"
|
||||||
|
|
||||||
#echo ""
|
#echo ""
|
||||||
#echo "_version: $_version"
|
#echo "_version: $_version"
|
||||||
#echo "dovecot_main_version $dovecot_main_version"
|
#echo "dovecot_main_version $dovecot_main_version"
|
||||||
#echo "dovecot_major_version $dovecot_major_version"
|
#echo "dovecot_major_version $dovecot_major_version"
|
||||||
#echo "dovecot_minor_version $dovecot_minor_version"
|
#echo "dovecot_minor_version $dovecot_minor_version"
|
||||||
#echo "dovecot_patch_level $dovecot_patch_level"
|
#echo "dovecot_patch_level $dovecot_patch_level"
|
||||||
|
#echo "dovecot_minor_patch_level $dovecot_minor_patch_level"
|
||||||
#echo ""
|
#echo ""
|
||||||
|
#
|
||||||
|
#clean_up 0
|
||||||
|
|
||||||
|
|
||||||
# 'expire plugin'was rRemoved in version 2.3.14: This plugin is not needed.
|
# 'expire plugin'was rRemoved in version 2.3.14: This plugin is not needed.
|
||||||
# Use mailbox { autoexpunge } Mailbox settings instead.
|
# Use mailbox { autoexpunge } Mailbox settings instead.
|
||||||
@@ -673,32 +719,72 @@ fi
|
|||||||
|
|
||||||
## - Download Pigeonhole for Dovecot v2.2
|
## - Download Pigeonhole for Dovecot v2.2
|
||||||
## -
|
## -
|
||||||
echononl "\tDownload dovecot-${dovecot_main_version}-pigeonhole-${_pigeonhole}.tar.gz.."
|
if [[ ${dovecot_major_version} -eq 2 ]] && [[ ${dovecot_minor_version} -lt 4 ]] ; then
|
||||||
if [ ! -f "${_src_base_dir}/dovecot-${dovecot_main_version}-pigeonhole-${_pigeonhole}.tar.gz" ]; then
|
|
||||||
wget --no-check-certificate https://pigeonhole.dovecot.org/releases/${dovecot_main_version}/dovecot-${dovecot_main_version}-pigeonhole-${_pigeonhole}.tar.gz > /dev/null 2>&1
|
echononl "\tDownload dovecot-${dovecot_main_version}-pigeonhole-${_pigeonhole}.tar.gz.."
|
||||||
if [ "$?" = 0 ]; then
|
if [ ! -f "${_src_base_dir}/dovecot-${dovecot_main_version}-pigeonhole-${_pigeonhole}.tar.gz" ]; then
|
||||||
echo -e "$rc_done"
|
wget --no-check-certificate https://pigeonhole.dovecot.org/releases/${dovecot_main_version}/dovecot-${dovecot_main_version}-pigeonhole-${_pigeonhole}.tar.gz > /dev/null 2>&1
|
||||||
|
if [ "$?" = 0 ]; then
|
||||||
|
echo -e "$rc_done"
|
||||||
|
else
|
||||||
|
echo -e "$rc_failed"
|
||||||
|
error "Direct download of 'dovecot-${dovecot_main_version}-pigeonhole-${_pigeonhole}.tar.gz' failed
|
||||||
|
|
||||||
|
Download \033[1mdovecot-${dovecot_main_version}-pigeonhole-${_pigeonhole}.tar.gz\033[m manually
|
||||||
|
and proceed instllation."
|
||||||
|
|
||||||
|
echononl "\tProceed instllation [yes/no]: "
|
||||||
|
read OK
|
||||||
|
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||||||
|
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||||||
|
echononl "Wrong entry! - repeat [yes/no]: "
|
||||||
|
read OK
|
||||||
|
done
|
||||||
|
[[ $OK = "yes" ]] || fatal "Abbruch durch User"
|
||||||
|
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo -e "$rc_failed"
|
echo -e "$rc_skipped"
|
||||||
error "Direct download of 'dovecot-${dovecot_main_version}-pigeonhole-${_pigeonhole}.tar.gz' failed
|
|
||||||
|
|
||||||
Download \033[1mdovecot-${dovecot_main_version}-pigeonhole-${_pigeonhole}.tar.gz\033[m manually
|
|
||||||
and proceed instllation."
|
|
||||||
|
|
||||||
echononl "\tProceed instllation [yes/no]: "
|
|
||||||
read OK
|
|
||||||
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
|
||||||
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
|
||||||
echononl "Wrong entry! - repeat [yes/no]: "
|
|
||||||
read OK
|
|
||||||
done
|
|
||||||
[[ $OK = "yes" ]] || fatal "Abbruch durch User"
|
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
dovecot_pigeonhole_archiv="dovecot-${dovecot_main_version}-pigeonhole-${_pigeonhole}.tar.gz"
|
||||||
|
|
||||||
else
|
else
|
||||||
echo -e "$rc_skipped"
|
|
||||||
|
echononl "\tDownload dovecot-pigeonhole-${_pigeonhole}.tar.gz.."
|
||||||
|
if [ ! -f "${_src_base_dir}/dovecot-pigeonhole-${_pigeonhole}.tar.gz" ]; then
|
||||||
|
wget --no-check-certificate https://pigeonhole.dovecot.org/releases/${dovecot_main_version}/dovecot-pigeonhole-${_pigeonhole}.tar.gz > /dev/null 2>&1
|
||||||
|
if [ "$?" = 0 ]; then
|
||||||
|
echo -e "$rc_done"
|
||||||
|
dovecot_pigeonhole_archiv="dovecot-pigeonhole-${_pigeonhole}.tar.gz"
|
||||||
|
else
|
||||||
|
echo -e "$rc_failed"
|
||||||
|
|
||||||
|
error "Direct download of 'Pigeonhole Sieve and ManageSieve' source archiv failed
|
||||||
|
|
||||||
|
Download Pigeonhole Sieve and ManageSieve manually and name it to
|
||||||
|
|
||||||
|
\033[1mdovecot-pigeonhole-${_pigeonhole}.tar.gz\033[m\n"
|
||||||
|
|
||||||
|
|
||||||
|
echononl "\tProceed instllation [yes/no]: "
|
||||||
|
read OK
|
||||||
|
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||||||
|
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||||||
|
echononl "Wrong entry! - repeat [yes/no]: "
|
||||||
|
read OK
|
||||||
|
done
|
||||||
|
[[ $OK = "yes" ]] || fatal "Abbruch durch User"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo -e "$rc_skipped"
|
||||||
|
fi
|
||||||
|
|
||||||
|
dovecot_pigeonhole_archiv="dovecot-pigeonhole-${_pigeonhole}.tar.gz"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
dovecot_pigeonhole_archiv_prefix="${dovecot_pigeonhole_archiv%.tar.gz}"
|
||||||
|
dovecot_pigeonhole_archiv_dir="${dovecot_pigeonhole_archiv%.tar.gz}"
|
||||||
|
|
||||||
|
|
||||||
if $_new ; then
|
if $_new ; then
|
||||||
@@ -864,6 +950,7 @@ config_params="
|
|||||||
--prefix=/usr/local/dovecot-${_version} \
|
--prefix=/usr/local/dovecot-${_version} \
|
||||||
--with-${db_driver} \
|
--with-${db_driver} \
|
||||||
--with-gssapi=yes
|
--with-gssapi=yes
|
||||||
|
--with-ldap=yes
|
||||||
--with-rundir=/run/dovecot"
|
--with-rundir=/run/dovecot"
|
||||||
if $systemd_support ; then
|
if $systemd_support ; then
|
||||||
config_params="$config_params \
|
config_params="$config_params \
|
||||||
@@ -1018,20 +1105,20 @@ fi
|
|||||||
cd ${_src_base_dir}
|
cd ${_src_base_dir}
|
||||||
echo ""
|
echo ""
|
||||||
echononl "\tExtracting dovecot-${dovecot_main_version}-pigeonhole-${_pigeonhole}.tar.gz.."
|
echononl "\tExtracting dovecot-${dovecot_main_version}-pigeonhole-${_pigeonhole}.tar.gz.."
|
||||||
gunzip < dovecot-${dovecot_main_version}-pigeonhole-${_pigeonhole}.tar.gz | tar -xf -
|
gunzip < ${_src_base_dir}/${dovecot_pigeonhole_archiv} | tar -C ${_src_base_dir} -xf -
|
||||||
if [ "$?" = 0 ]; then
|
if [ "$?" = 0 ]; then
|
||||||
echo -e "$rc_done"
|
echo -e "$rc_done"
|
||||||
else
|
else
|
||||||
echo -e "$rc_failed"
|
echo -e "$rc_failed"
|
||||||
fatal Extracting dovecot-${dovecot_main_version}-pigeonhole-${_pigeonhole}.tar.gz failed
|
fatal Extracting ${dovecot_pigeonhole_archiv} failed
|
||||||
fi
|
fi
|
||||||
cd dovecot-${dovecot_main_version}-pigeonhole-${_pigeonhole}
|
cd ${dovecot_pigeonhole_archiv_dir}
|
||||||
|
|
||||||
|
|
||||||
echononl "\tConfigure Pigeonhole ManageSieve.."
|
echononl "\tConfigure Pigeonhole ManageSieve.."
|
||||||
./configure \
|
./configure \
|
||||||
--prefix=/usr/local/dovecot-${_version} \
|
--prefix=/usr/local/dovecot-${_version} \
|
||||||
--with-dovecot=/usr/local/dovecot-${_version}/lib/dovecot > ${_log_dir}/dovecot-${dovecot_main_version}-pigeonhole-${_pigeonhole}-configure.log 2<&1
|
--with-dovecot=/usr/local/dovecot-${_version}/lib/dovecot > ${_log_dir}/${dovecot_pigeonhole_archiv_prefix}-configure.log 2<&1
|
||||||
if [ "$?" = 0 ]; then
|
if [ "$?" = 0 ]; then
|
||||||
echo -e "$rc_done"
|
echo -e "$rc_done"
|
||||||
else
|
else
|
||||||
@@ -1040,7 +1127,7 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
echononl "\tCompile Pigeonhole ManageSieve.."
|
echononl "\tCompile Pigeonhole ManageSieve.."
|
||||||
make > ${_log_dir}/dovecot-${dovecot_main_version}-pigeonhole-${_pigeonhole}-make.log 2<&1
|
make > ${_log_dir}/${dovecot_pigeonhole_archiv_prefix}-make.log 2<&1
|
||||||
if [ "$?" = 0 ]; then
|
if [ "$?" = 0 ]; then
|
||||||
echo -e "$rc_done"
|
echo -e "$rc_done"
|
||||||
else
|
else
|
||||||
@@ -1049,7 +1136,7 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
echononl "\tInstall Pigeonhole ManageSieve.."
|
echononl "\tInstall Pigeonhole ManageSieve.."
|
||||||
make install > ${_log_dir}/dovecot-${dovecot_main_version}-pigeonhole-${_pigeonhole}-install.log 2<&1
|
make install > ${_log_dir}/${dovecot_pigeonhole_archiv_prefix}-install.log 2<&1
|
||||||
if [ "$?" = 0 ]; then
|
if [ "$?" = 0 ]; then
|
||||||
echo -e "$rc_done"
|
echo -e "$rc_done"
|
||||||
else
|
else
|
||||||
@@ -1058,6 +1145,7 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## -----------------
|
## -----------------
|
||||||
## --- Configure dovecot services
|
## --- Configure dovecot services
|
||||||
|
|
||||||
@@ -1597,7 +1685,11 @@ if [[ $dovecot_major_version -ge 3 ]] \
|
|||||||
if [[ ! -f "$dh_pem_file" ]] ; then
|
if [[ ! -f "$dh_pem_file" ]] ; then
|
||||||
echononl "\tCreate SSL DH parameters '$dh_pem_file'.."
|
echononl "\tCreate SSL DH parameters '$dh_pem_file'.."
|
||||||
echo -en "$rc_wait"
|
echo -en "$rc_wait"
|
||||||
openssl dhparam -dsaparam -out "$dh_pem_file" 4096 > /dev/null 2>&1
|
if [[ "$os_dist" = "debian" ]] && [[ $os_version -gt 11 ]] ; then
|
||||||
|
openssl dhparam -out "$dh_pem_file" 4096 > /dev/null 2>&1
|
||||||
|
else
|
||||||
|
openssl dhparam -dsaparam -out "$dh_pem_file" 4096 > /dev/null 2>&1
|
||||||
|
fi
|
||||||
if [[ $? -eq 0 ]]; then
|
if [[ $? -eq 0 ]]; then
|
||||||
echo -e "$rc_done"
|
echo -e "$rc_done"
|
||||||
else
|
else
|
||||||
@@ -2164,7 +2256,12 @@ EOF
|
|||||||
fatal "Creating file /etc/rsyslog.d/dovecot.conf failed"
|
fatal "Creating file /etc/rsyslog.d/dovecot.conf failed"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
/etc/init.d/rsyslog restart > /dev/null 2>&1
|
echononl "\tRestart rsyslog Servive"
|
||||||
|
if $systemd_support ; then
|
||||||
|
systemctl restart rsyslog.service > /dev/null 2>&1
|
||||||
|
else
|
||||||
|
/etc/init.d/rsyslog restart > /dev/null 2>&1
|
||||||
|
fi
|
||||||
if [ "$?" = 0 ]; then
|
if [ "$?" = 0 ]; then
|
||||||
echo -e "$rc_done"
|
echo -e "$rc_done"
|
||||||
else
|
else
|
||||||
@@ -3610,8 +3707,8 @@ fi
|
|||||||
## - quota_rule = *:storage=1g
|
## - quota_rule = *:storage=1g
|
||||||
## - quota_rule2 = trash:storage=+100m
|
## - quota_rule2 = trash:storage=+100m
|
||||||
## -
|
## -
|
||||||
## - quota_warning = storage=95%% quota-warning 95 %u
|
## - quota_warning = storage=80%% quota-warning 80 %u
|
||||||
## - quota_warning2 = storage=80%% quota-warning 80 %u
|
## - quota_warning2 = storage=95%% quota-warning 95 %u
|
||||||
## - }
|
## - }
|
||||||
## -
|
## -
|
||||||
## - service quota-warning {
|
## - service quota-warning {
|
||||||
@@ -3636,8 +3733,8 @@ plugin {
|
|||||||
quota_rule = *:storage=1G
|
quota_rule = *:storage=1G
|
||||||
quota_rule2 = Trash:storage=+200M
|
quota_rule2 = Trash:storage=+200M
|
||||||
|
|
||||||
quota_warning = storage=95%% quota-warning 95 %u
|
quota_warning = storage=80%% quota-warning 80 %u
|
||||||
quota_warning2 = storage=80%% quota-warning 80 %u
|
quota_warning2 = storage=95%% quota-warning 95 %u
|
||||||
}
|
}
|
||||||
|
|
||||||
service quota-warning {
|
service quota-warning {
|
||||||
@@ -4393,6 +4490,16 @@ if [[ -x "/root/bin/monitoring/check_cert_for_dovecot.sh" ]] ; then
|
|||||||
else
|
else
|
||||||
echo -e "$rc_failed"
|
echo -e "$rc_failed"
|
||||||
error "$(cat "$log_file")"
|
error "$(cat "$log_file")"
|
||||||
|
|
||||||
|
echononl "\tcontinue anyway [yes/no]: "
|
||||||
|
read OK
|
||||||
|
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||||||
|
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||||||
|
echononl "Wrong entry! - repeat [yes/no]: "
|
||||||
|
read OK
|
||||||
|
done
|
||||||
|
[[ $OK = "yes" ]] || fatal "Abbruch durch User"
|
||||||
|
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo -e "$rc_skipped"
|
echo -e "$rc_skipped"
|
||||||
|
|||||||
@@ -95,6 +95,16 @@ echo_skipped() {
|
|||||||
echo -e "\033[75G[ \033[30m\033[1mskipped\033[m ]"
|
echo -e "\033[75G[ \033[30m\033[1mskipped\033[m ]"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# -Is systemd supported on this system?
|
||||||
|
# -
|
||||||
|
systemd_supported=false
|
||||||
|
systemd=$(which systemd)
|
||||||
|
systemctl=$(which systemctl)
|
||||||
|
|
||||||
|
if [[ -n "$systemd" ]] || [[ -n "$systemctl" ]] ; then
|
||||||
|
systemd_supported=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
if [ "$POSTFIX_DB_TYPE" = "postgres" -o "$POSTFIX_DB_TYPE" = "postgresql" -o "$POSTFIX_DB_TYPE" = "pgsql" -o "$POSTFIX_DB_TYPE" = "psql" ];then
|
if [ "$POSTFIX_DB_TYPE" = "postgres" -o "$POSTFIX_DB_TYPE" = "postgresql" -o "$POSTFIX_DB_TYPE" = "pgsql" -o "$POSTFIX_DB_TYPE" = "psql" ];then
|
||||||
POSTFIX_DB_TYPE=pgsql
|
POSTFIX_DB_TYPE=pgsql
|
||||||
|
|||||||
@@ -182,9 +182,11 @@ fi
|
|||||||
|
|
||||||
# - Is this a systemd system?
|
# - Is this a systemd system?
|
||||||
# -
|
# -
|
||||||
if [[ "X`which systemd`" = "X" ]]; then
|
systemd_exists=false
|
||||||
systemd_exists=false
|
systemd=$(which systemd)
|
||||||
else
|
systemctl=$(which systemctl)
|
||||||
|
|
||||||
|
if [[ -n "$systemd" ]] || [[ -n "$systemctl" ]] ; then
|
||||||
systemd_exists=true
|
systemd_exists=true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
287
update_postfix_dh_parameters.sh
Executable file
287
update_postfix_dh_parameters.sh
Executable file
@@ -0,0 +1,287 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
script_dir="$(dirname $(realpath $0))"
|
||||||
|
script_name="$(basename "$0")"
|
||||||
|
|
||||||
|
conf_dir=$(dirname $0)/conf
|
||||||
|
conf_file="${conf_dir}/install_postfix_base.conf"
|
||||||
|
|
||||||
|
_TLS_CERT_DIR=/etc/postfix/ssl
|
||||||
|
_TLS_CERT_FILE="${_TLS_CERT_DIR}/mailserver.crt"
|
||||||
|
_TLS_KEY_FILE="${_TLS_CERT_DIR}/mailserver.key"
|
||||||
|
_TLS_CA_FILE=/etc/ssl/certs/ca-certificates.crt
|
||||||
|
|
||||||
|
|
||||||
|
log_file=$(mktemp)
|
||||||
|
|
||||||
|
|
||||||
|
# -------------
|
||||||
|
# --- Some functions
|
||||||
|
# -------------
|
||||||
|
clean_up() {
|
||||||
|
|
||||||
|
# Perform program exit housekeeping
|
||||||
|
rm -f $log_file
|
||||||
|
exit $1
|
||||||
|
}
|
||||||
|
|
||||||
|
echononl(){
|
||||||
|
echo X\\c > /tmp/shprompt$$
|
||||||
|
if [ `wc -c /tmp/shprompt$$ | awk '{print $1}'` -eq 1 ]; then
|
||||||
|
echo -e -n "$*\\c" 1>&2
|
||||||
|
else
|
||||||
|
echo -e -n "$*" 1>&2
|
||||||
|
fi
|
||||||
|
rm /tmp/shprompt$$
|
||||||
|
}
|
||||||
|
|
||||||
|
fatal(){
|
||||||
|
echo ""
|
||||||
|
echo -e "fatal error: $*"
|
||||||
|
echo ""
|
||||||
|
echo -e "\t\033[31m\033[1mInstalllation will be interrupted\033[m\033[m"
|
||||||
|
echo ""
|
||||||
|
clean_up 1
|
||||||
|
}
|
||||||
|
|
||||||
|
error(){
|
||||||
|
echo ""
|
||||||
|
echo -e "\t[ \033[31m\033[1mFehler\033[m ]: $*"
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
warn (){
|
||||||
|
echo ""
|
||||||
|
echo -e "\t[ \033[33m\033[1mWarning\033[m ]: $*"
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
info (){
|
||||||
|
echo ""
|
||||||
|
echo -e "\t[ \033[32m\033[1mInfo\033[m ]: $*"
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
echo_done() {
|
||||||
|
echo -e "\033[80G[ \033[32mdone\033[m ]"
|
||||||
|
}
|
||||||
|
echo_ok() {
|
||||||
|
echo -e "\033[80G[ \033[32mok\033[m ]"
|
||||||
|
}
|
||||||
|
echo_warning() {
|
||||||
|
echo -e "\033[80G[ \033[33m\033[1mwarn\033[m ]"
|
||||||
|
}
|
||||||
|
echo_failed(){
|
||||||
|
echo -e "\033[80G[ \033[1;31mfailed\033[m ]"
|
||||||
|
}
|
||||||
|
echo_skipped() {
|
||||||
|
echo -e "\033[80G[ \033[33m\033[1mskipped\033[m ]"
|
||||||
|
}
|
||||||
|
|
||||||
|
blank_line() {
|
||||||
|
if $terminal ; then
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
detect_os_1 () {
|
||||||
|
|
||||||
|
if $(which lsb_release > /dev/null 2>&1) ; then
|
||||||
|
|
||||||
|
os_dist="$(lsb_release -i | awk '{print tolower($3)}')"
|
||||||
|
os_version="$(lsb_release -r | awk '{print tolower($2)}')"
|
||||||
|
os_codename="$(lsb_release -c | awk '{print tolower($2)}')"
|
||||||
|
|
||||||
|
if [[ "$os_dist" = "debian" ]]; then
|
||||||
|
if $(echo "$os_version" | grep -q '\.') ; then
|
||||||
|
os_version=$(echo "$os_version" | cut --delimiter='.' -f1)
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
elif [[ -e "/etc/os-release" ]]; then
|
||||||
|
|
||||||
|
. /etc/os-release
|
||||||
|
|
||||||
|
os_dist=$ID
|
||||||
|
os_version=${VERSION_ID}
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
# remove whitespace from os_dist and os_version
|
||||||
|
os_dist="${os_dist// /}"
|
||||||
|
os_version="${os_version// /}"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# -------------
|
||||||
|
# --- Some default settings
|
||||||
|
# -------------
|
||||||
|
|
||||||
|
DEFAULT_ADMIN_EMAIL="argus@oopen.de"
|
||||||
|
DEFAULT_RELAY_HOST="b.mx.oopen.de"
|
||||||
|
DEFAULT_SASL_AUTH=false
|
||||||
|
|
||||||
|
|
||||||
|
# - Is this a systemd system?
|
||||||
|
# -
|
||||||
|
systemd_exists=false
|
||||||
|
systemd=$(which systemd)
|
||||||
|
systemctl=$(which systemctl)
|
||||||
|
|
||||||
|
if [[ -n "$systemd" ]] || [[ -n "$systemctl" ]] ; then
|
||||||
|
systemd_exists=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# - Read Configuration File if exists
|
||||||
|
# -
|
||||||
|
if [[ -f "$conf_file" ]]; then
|
||||||
|
source $conf_file
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# -------------
|
||||||
|
# --- Set default values for some non existent variables (i.e. no configuration file is present)
|
||||||
|
# -------------
|
||||||
|
|
||||||
|
[[ -z "$_ADMIN_EMAIL" ]] && _ADMIN_EMAIL="$DEFAULT_ADMIN_EMAIL"
|
||||||
|
[[ -z "$_SASL_AUTH" ]] && _SASL_AUTH="$DEFAULT_SASL_AUTH"
|
||||||
|
|
||||||
|
if [[ -z "$_HOSTNAME" ]] ; then
|
||||||
|
_HOSTNAME="$(hostname -f)"
|
||||||
|
_HOSTNAME_SHORT="$(hostname)"
|
||||||
|
[[ "$_HOSTNAME" = "$_HOSTNAME_SHORT" ]] && _HOSTNAME=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
blank_line
|
||||||
|
echononl "Detect distribution/release of running OS.."
|
||||||
|
detect_os_1 > /dev/null 2>&1
|
||||||
|
if [[ $? -ne 0 ]]; then
|
||||||
|
echo_failed
|
||||||
|
else
|
||||||
|
echo_ok
|
||||||
|
fi
|
||||||
|
blank_line
|
||||||
|
blank_line
|
||||||
|
|
||||||
|
## - create directory for certificates and copy certificates
|
||||||
|
## - and coresponding keys to /etc/postfix/ssl/
|
||||||
|
## -
|
||||||
|
if [[ ! -d "/etc/postfix/ssl" ]] ; then
|
||||||
|
fatal "Certification directory \033[1m/etc/postfix/ssl\033[m not found!"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
## - generate DH parameters that the Postfix SMTP server should use
|
||||||
|
## - with EDH ciphers (length 512 and 1024
|
||||||
|
## -
|
||||||
|
echononl " Generate DH key length=512 \"/etc/postfix/ssl/dh_512.pem\""
|
||||||
|
if [[ ! -f /etc/postfix/ssl/dh_512.pem ]]; then
|
||||||
|
if [[ "$os_dist" = "debian" ]] && [[ $os_version -gt 11 ]] ; then
|
||||||
|
openssl dhparam -out /etc/postfix/ssl/dh_512.pem 512 > /dev/null 2>&1
|
||||||
|
else
|
||||||
|
openssl dhparam -dsaparam -out /etc/postfix/ssl/dh_512.pem 512 > /dev/null 2>&1
|
||||||
|
fi
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if [[ "$os_dist" = "debian" ]] && [[ $os_version -gt 11 ]] ; then
|
||||||
|
if $(grep -q -E "X9.42" /etc/postfix/ssl/dh_512.pem 2> /dev/null); then
|
||||||
|
openssl dhparam -out /etc/postfix/ssl/dh_512.pem 512 > /dev/null 2>&1
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echononl " Generate DH key length=1024 \"/etc/postfix/ssl/dh_1024.pem\""
|
||||||
|
if [[ ! -f /etc/postfix/ssl/dh_1024.pem ]]; then
|
||||||
|
if [[ "$os_dist" = "debian" ]] && [[ $os_version -gt 11 ]] ; then
|
||||||
|
openssl dhparam -out /etc/postfix/ssl/dh_1024.pem 1024 > /dev/null 2>&1
|
||||||
|
else
|
||||||
|
openssl dhparam -dsaparam -out /etc/postfix/ssl/dh_1024.pem 1024 > /dev/null 2>&1
|
||||||
|
fi
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if [[ "$os_dist" = "debian" ]] && [[ $os_version -gt 11 ]] ; then
|
||||||
|
if $(grep -q -E "X9.42" /etc/postfix/ssl/dh_1024.pem 2> /dev/null); then
|
||||||
|
openssl dhparam -out /etc/postfix/ssl/dh_1024.pem 1024 > /dev/null 2>&1
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echononl " Generate DH key length=2048 \"/etc/postfix/ssl/dh_2048.pem\""
|
||||||
|
if [[ ! -f /etc/postfix/ssl/dh_2048.pem ]]; then
|
||||||
|
if [[ "$os_dist" = "debian" ]] && [[ $os_version -gt 11 ]] ; then
|
||||||
|
openssl dhparam -out /etc/postfix/ssl/dh_2048.pem 2048 > /dev/null 2>&1
|
||||||
|
else
|
||||||
|
openssl dhparam -dsaparam -out /etc/postfix/ssl/dh_2048.pem 2048 > /dev/null 2>&1
|
||||||
|
fi
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if [[ "$os_dist" = "debian" ]] && [[ $os_version -gt 11 ]] ; then
|
||||||
|
if $(grep -q -E "X9.42" /etc/postfix/ssl/dh_2048.pem 2> /dev/null); then
|
||||||
|
openssl dhparam -out /etc/postfix/ssl/dh_2048.pem 2048 > /dev/null 2>&1
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
## - restart postfix
|
||||||
|
## -
|
||||||
|
echononl " Restart postfix"
|
||||||
|
if $systemd_exists ; then
|
||||||
|
systemctl restart postfix > /dev/null 2>&1
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
/etc/init.d/postfix restart > /dev/null 2>&1
|
||||||
|
if [[ $? -eq 0 ]] ; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
clean_up 0
|
||||||
@@ -3,6 +3,8 @@
|
|||||||
clear
|
clear
|
||||||
echo -e "\n \033[32mStart script for upgrading Roundcube Webmailer..\033[m"
|
echo -e "\n \033[32mStart script for upgrading Roundcube Webmailer..\033[m"
|
||||||
|
|
||||||
|
CUR_IFS="$IFS"
|
||||||
|
|
||||||
## -----------------------------------------------------------------
|
## -----------------------------------------------------------------
|
||||||
## ----------------------------------------------------------------
|
## ----------------------------------------------------------------
|
||||||
## ---
|
## ---
|
||||||
@@ -18,7 +20,7 @@ echo -e "\n \033[32mStart script for upgrading Roundcube Webmailer..\033[m"
|
|||||||
# - Settings
|
# - Settings
|
||||||
# -------------
|
# -------------
|
||||||
|
|
||||||
#_src_base_dir="$(realpath $(dirname $0))"
|
_src_base_dir="$(realpath $(dirname $0))"
|
||||||
#conf_file="${_src_base_dir}/conf/install_upgrade_roundcube.conf"
|
#conf_file="${_src_base_dir}/conf/install_upgrade_roundcube.conf"
|
||||||
|
|
||||||
script_name="$(basename $(realpath $0))"
|
script_name="$(basename $(realpath $0))"
|
||||||
@@ -110,6 +112,62 @@ echo_not_yet_implemented(){
|
|||||||
echo -e "\033[85G[ \033[30m\033[1mnot yet implemented\033[m ]"
|
echo -e "\033[85G[ \033[30m\033[1mnot yet implemented\033[m ]"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
detect_mysql_version () {
|
||||||
|
|
||||||
|
_MYSQLD_VERSION="$(mysqld -V 2>/dev/null)"
|
||||||
|
|
||||||
|
if [[ -z "$_MYSQLD_VERSION" ]]; then
|
||||||
|
fatal "No installed MySQL server or distribution found!"
|
||||||
|
elif [[ -d "/usr/local/mysql" ]] && [[ "$(basename "$(realpath "/usr/local/mysql")")" =~ percona- ]]; then
|
||||||
|
MYSQL_CUR_DISTRIBUTION="Percona"
|
||||||
|
elif [[ "$_MYSQLD_VERSION" =~ MariaDB ]]; then
|
||||||
|
MYSQL_CUR_DISTRIBUTION="MariaDB"
|
||||||
|
elif [[ "$_MYSQLD_VERSION" =~ MySQL ]]; then
|
||||||
|
MYSQL_CUR_DISTRIBUTION="MySQL"
|
||||||
|
elif [[ -d "/usr/local/mysql" ]] && [[ "$(basename "$(realpath "/usr/local/mysql")")" =~ mysql- ]]; then
|
||||||
|
MYSQL_CUR_DISTRIBUTION="MySQL"
|
||||||
|
elif [[ -d "/usr/local/mysql" ]] && [[ "$(basename "$(realpath "/usr/local/mysql")")" =~ mariadb- ]]; then
|
||||||
|
MYSQL_CUR_DISTRIBUTION="MariaDB"
|
||||||
|
else
|
||||||
|
error "MySQL Instalation found, but cannot determin the distribution!"
|
||||||
|
|
||||||
|
MYSQL_CUR_DISTRIBUTION=
|
||||||
|
echo ""
|
||||||
|
echo " Select the installed MySQL distribution."
|
||||||
|
echo ""
|
||||||
|
echo " [1] MySQL (the original community edition)"
|
||||||
|
echo " [2] Percona Server for MySQL"
|
||||||
|
echo " [3] MariaDB"
|
||||||
|
echo ""
|
||||||
|
echononl " Eingabe [1/2/3]: "
|
||||||
|
|
||||||
|
while [ "$MYSQL_CUR_DISTRIBUTION" != "MySQL" -a "$MYSQL_CUR_DISTRIBUTION" != "MariaDB" -a "$MYSQL_CUR_DISTRIBUTION" != "Percona" ];do
|
||||||
|
read OPTION
|
||||||
|
case $OPTION in
|
||||||
|
1) MYSQL_CUR_DISTRIBUTION="MySQL"
|
||||||
|
;;
|
||||||
|
2) MYSQL_CUR_DISTRIBUTION="Percona"
|
||||||
|
;;
|
||||||
|
3) MYSQL_CUR_DISTRIBUTION="MariaDB"
|
||||||
|
;;
|
||||||
|
*) echo ""
|
||||||
|
echo -e "\tFalsche Eingabe ! [ 1 = MySQL ; 2 = Percona ; 3 = MariaDB ]"
|
||||||
|
echo ""
|
||||||
|
echononl " Eingabe:"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
MYSQL_VERSION="$(echo $_MYSQLD_VERSION | grep -o -E "[0-9]+\.[0-9]+\.[0-9]+(-[0-9]+)?" | head -n 1)"
|
||||||
|
MYSQL_MAJOR_VERSION="$(echo $MYSQL_VERSION | cut -d '.' -f1)"
|
||||||
|
MYSQL_MINOR_VERSION="$(echo $MYSQL_VERSION | cut -d '.' -f2)"
|
||||||
|
MYSQL_PATCH_LEVEL="$(echo $MYSQL_VERSION | cut -d '.' -f3)"
|
||||||
|
MYSQL_MAIN_VERSION="$(echo $MYSQL_VERSION | cut -d '.' -f1,2)"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
trap clean_up SIGHUP SIGINT SIGTERM
|
trap clean_up SIGHUP SIGINT SIGTERM
|
||||||
|
|
||||||
|
|
||||||
@@ -154,15 +212,6 @@ fi
|
|||||||
DEFAULT_DB_HOST="localhost"
|
DEFAULT_DB_HOST="localhost"
|
||||||
DEFAULT_DB_NAME="roundcubemail"
|
DEFAULT_DB_NAME="roundcubemail"
|
||||||
DEFAULT_DB_USER="roundcube"
|
DEFAULT_DB_USER="roundcube"
|
||||||
if [[ -f "/usr/local/mysql/sys-maint.cnf" ]] ; then
|
|
||||||
DEFAULT_MYSQL_CREDENTIALS="--defaults-file=/usr/local/mysql/sys-maint.cnf"
|
|
||||||
elif [[ -f "/etc/mysql/debian.cnf" ]] ; then
|
|
||||||
DEFAULT_MYSQL_CREDENTIALS="--defaults-file=/etc/mysql/debian.cnf"
|
|
||||||
else
|
|
||||||
DEFAULT_MYSQL_CREDENTIALS=""
|
|
||||||
fi
|
|
||||||
DEFAULT_DEBIAN_MYSQL_CREDENTIALS="--defaults-file=/etc/mysql/debian.cnf"
|
|
||||||
DEFAULT_MYSQL_CREDENTIALS="--defaults-file=/usr/local/mysql/sys-maint.cnf"
|
|
||||||
|
|
||||||
|
|
||||||
while IFS='' read -r -d '' _conf_file ; do
|
while IFS='' read -r -d '' _conf_file ; do
|
||||||
@@ -186,6 +235,7 @@ while IFS='' read -r -d '' _conf_file ; do
|
|||||||
fi
|
fi
|
||||||
WEBSITE_NAME=""
|
WEBSITE_NAME=""
|
||||||
done < <(find "${conf_dir}" -maxdepth 1 -type f -name "install_upgrade_roundcube*.conf" -print0)
|
done < <(find "${conf_dir}" -maxdepth 1 -type f -name "install_upgrade_roundcube*.conf" -print0)
|
||||||
|
IFS="$CUR_IFS"
|
||||||
|
|
||||||
if [[ ${#unsorted_website_arr} -eq 0 ]]; then
|
if [[ ${#unsorted_website_arr} -eq 0 ]]; then
|
||||||
fatal "No configuration files found in '${script_dir}/conf' or no website configured!"
|
fatal "No configuration files found in '${script_dir}/conf' or no website configured!"
|
||||||
@@ -194,7 +244,7 @@ fi
|
|||||||
# - Sort array
|
# - Sort array
|
||||||
# -
|
# -
|
||||||
IFS=$'\n' website_arr=($(sort <<<"${unsorted_website_arr[*]}"))
|
IFS=$'\n' website_arr=($(sort <<<"${unsorted_website_arr[*]}"))
|
||||||
IFS=' '
|
IFS="$CUR_IFS"
|
||||||
|
|
||||||
|
|
||||||
WEBSITE_NAME=
|
WEBSITE_NAME=
|
||||||
@@ -208,6 +258,8 @@ for _site in ${website_arr[@]} ; do
|
|||||||
echo " [$i] ${_arr[0]}"
|
echo " [$i] ${_arr[0]}"
|
||||||
((i++))
|
((i++))
|
||||||
done
|
done
|
||||||
|
IFS="$CUR_IFS"
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echononl " Eingabe: "
|
echononl " Eingabe: "
|
||||||
while ! $_OK ; do
|
while ! $_OK ; do
|
||||||
@@ -223,6 +275,7 @@ read _IN
|
|||||||
echononl " Eingabe: "
|
echononl " Eingabe: "
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
IFS="$CUR_IFS"
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echononl " Include Configuration file.."
|
echononl " Include Configuration file.."
|
||||||
@@ -234,6 +287,7 @@ else
|
|||||||
echo_ok
|
echo_ok
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
[[ -n "$WEBSITE_NAME" ]] || fatal "Website's name (WEBSITE_NAME) not present!"
|
[[ -n "$WEBSITE_NAME" ]] || fatal "Website's name (WEBSITE_NAME) not present!"
|
||||||
|
|
||||||
DEFAULT_WEBSITE_BASEDIR="/var/www/${WEBSITE_NAME}"
|
DEFAULT_WEBSITE_BASEDIR="/var/www/${WEBSITE_NAME}"
|
||||||
@@ -269,17 +323,98 @@ if [ "$DB_TYPE" = "postgres" -o "$DB_TYPE" = "postgresql" -o "$DB_TYPE" = "pgsq
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
if [[ "$DB_TYPE" = "mysql" ]]; then
|
if [[ "$DB_TYPE" = "mysql" ]] ; then
|
||||||
if $MYSQL_DEBIAN_INSTALLATION ; then
|
|
||||||
[[ -n "$MYSQL_CREDENTIALS" ]] || MYSQL_CREDENTIALS="$DEFAULT_DEBIAN_MYSQL_CREDENTIALS"
|
if [[ -z ${MYSQL_CREDENTIALS} ]] ; then
|
||||||
else
|
|
||||||
[[ -n "$MYSQL_CREDENTIALS" ]] || MYSQL_CREDENTIALS="$DEFAULT_MYSQL_CREDENTIALS"
|
detect_mysql_version
|
||||||
|
|
||||||
|
if [[ "$MYSQL_CUR_DISTRIBUTION" = "MariaDB" ]] && ([[ $MYSQL_MAJOR_VERSION -gt 10 ]] \
|
||||||
|
|| ( [[ $MYSQL_MAJOR_VERSION -eq 10 ]] && [[ $MYSQL_MINOR_VERSION -gt 3 ]] )) ; then
|
||||||
|
if [[ -S "/tmp/mysql.sock" ]]; then
|
||||||
|
MYSQL_CREDENTIALS="-u root -S /tmp/mysql.sock"
|
||||||
|
elif [[ -S "/run/mysqld/mysqld.sock" ]]; then
|
||||||
|
MYSQL_CREDENTIALS="-u root -S /run/mysqld/mysqld.sock"
|
||||||
|
elif [[ -S "/var/run/mysqld/mysqld.sock" ]]; then
|
||||||
|
MYSQL_CREDENTIALS="-u root -S /var/run/mysqld/mysqld.sock"
|
||||||
|
else
|
||||||
|
fatal "Parameter 'MYSQL_CREDENTIALS' cannot be determined automated.
|
||||||
|
|
||||||
|
Use configuration file "$conf_file" to set
|
||||||
|
parameter manually."
|
||||||
|
fi
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
echononl "\tGet MySQL command.."
|
||||||
|
mysql_command="$(which mysql)"
|
||||||
|
if [[ $? -eq 0 ]]; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
|
||||||
|
if [[ -x "/usr/local/mysql/bin/mysql" ]]; then
|
||||||
|
mysql_command="/usr/local/mysql/bin/mysql"
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
fatal "$(cat $tmp_log_file)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if $(${mysql_command} --login-path=local -e ";" > /dev/null 2>&1) ; then
|
||||||
|
MYSQL_CREDENTIALS="--login-path=local"
|
||||||
|
elif [[ -f "/usr/local/mysql/sys-maint.cnf" ]] ; then
|
||||||
|
MYSQL_CREDENTIALS="--defaults-file=/usr/local/mysql/sys-maint.cnf"
|
||||||
|
elif [[ -f "/etc/mysql/debian.cnf" ]] ; then
|
||||||
|
MYSQL_CREDENTIALS="--defaults-file=/etc/mysql/debian.cnf"
|
||||||
|
else
|
||||||
|
fatal "Parameter 'MYSQL_CREDENTIALS' cannot be determined automated.
|
||||||
|
|
||||||
|
Use configuration file "$conf_file" to set
|
||||||
|
parameter manually."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
#if $MYSQL_DEBIAN_INSTALLATION ; then
|
||||||
|
# [[ -n "$MYSQL_CREDENTIALS" ]] || MYSQL_CREDENTIALS="$DEFAULT_DEBIAN_MYSQL_CREDENTIALS"
|
||||||
|
#else
|
||||||
|
# [[ -n "$MYSQL_CREDENTIALS" ]] || MYSQL_CREDENTIALS="$DEFAULT_MYSQL_CREDENTIALS"
|
||||||
|
#fi
|
||||||
|
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
|
#[[ "$POSTFIX_DB_TYPE" = "pgsql" ]] || fatal "Unknown Database Type '$POSTFIX_DB_TYPE' (POSTFIX_DB_TYPE)"
|
||||||
[[ "$DB_TYPE" = "pgsql" ]] || fatal "Unknown Database Type '$DB_TYPE' (DB_TYPE)"
|
[[ "$DB_TYPE" = "pgsql" ]] || fatal "Unknown Database Type '$DB_TYPE' (DB_TYPE)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
if [[ "$DB_TYPE" = "mysql" ]]; then
|
||||||
|
echononl " Get MySQL command.."
|
||||||
|
mysql_command="$(which mysql)"
|
||||||
|
if [[ $? -eq 0 ]]; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
|
||||||
|
if [[ -x "/usr/local/mysql/bin/mysql" ]]; then
|
||||||
|
mysql_command="/usr/local/mysql/bin/mysql"
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
fatal "$(cat $tmp_log_file)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
elif [[ "$DB_TYPE" = "pgsql" ]] ; then
|
||||||
|
echononl " Get PostgreSQL command.."
|
||||||
|
psql_command="$(which psql)"
|
||||||
|
if [[ $? -eq 0 ]]; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
fi
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
echo -e "\033[32m--\033[m"
|
echo -e "\033[32m--\033[m"
|
||||||
echo ""
|
echo ""
|
||||||
echo "Version of the Roundcube Webmailer to install"
|
echo "Version of the Roundcube Webmailer to install"
|
||||||
@@ -330,8 +465,56 @@ else
|
|||||||
else
|
else
|
||||||
echo_ok
|
echo_ok
|
||||||
fi
|
fi
|
||||||
|
IFS="$CUR_IFS"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# - Get the latest PHP version
|
||||||
|
# -
|
||||||
|
echononl "\tGet major version of latest installed PHP version"
|
||||||
|
php_latest_ver=""
|
||||||
|
if $PHP_DEBIAN_INSTALLATION ; then
|
||||||
|
echo_skipped
|
||||||
|
else
|
||||||
|
if [[ -n "$php_major_versions" ]]; then
|
||||||
|
for _ver in $php_major_versions ; do
|
||||||
|
if [[ -z "$php_latest_ver" ]] ; then
|
||||||
|
php_latest_ver=$_ver
|
||||||
|
elif [[ "${_ver%.*}" -gt "${php_latest_ver%.*}" ]] ; then
|
||||||
|
php_latest_ver=$_ver
|
||||||
|
elif [[ "${_ver%.*}" -eq "${php_latest_ver%.*}" ]] ; then
|
||||||
|
[[ "${_ver#*.}" -gt "${php_latest_ver#*.}" ]] && php_latest_ver=$_ver
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
warn "Getting major version of latest installed PHP version failed! - No installed PHP versiond found!"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# - Get activ PHP version, means that on which is part of $PATH environment
|
||||||
|
# -
|
||||||
|
echononl "\tGet PHP version in PATH environment.."
|
||||||
|
if $(which php > /dev/null 2>&1) ; then
|
||||||
|
php_version_in_path="$(php --version 2> /dev/null | head -1 | cut -d' ' -f2 | cut -d '-' -f1 2> /dev/null)"
|
||||||
|
if [[ $? -eq 0 ]] && [[ -n "${php_version_in_path}" ]]; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
|
||||||
|
fatal "Failed getting PHP Version.."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
|
||||||
|
fatal "No PHP binary found in PATH environment.."
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# - Log directory containing upgrade log files
|
||||||
|
# -
|
||||||
|
_log_dir=${script_dir}/log-upgrade-roundcube-${ROUNDCUBE_VERSION}
|
||||||
|
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo ""
|
echo ""
|
||||||
@@ -383,6 +566,7 @@ else
|
|||||||
done
|
done
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "\tNewest PHP Version...................: $php_latest_ver"
|
echo -e "\tNewest PHP Version...................: $php_latest_ver"
|
||||||
|
echo -e "\tPHP Version of php binary in PATH....: $php_version_in_path"
|
||||||
fi
|
fi
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "\tCrontab backup file..................: $crontab_backup_file"
|
echo -e "\tCrontab backup file..................: $crontab_backup_file"
|
||||||
@@ -399,24 +583,86 @@ else
|
|||||||
fatal "Abort by user request - Answer as not 'YES'"
|
fatal "Abort by user request - Answer as not 'YES'"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
echononl "\tCheck Database connection .."
|
||||||
if [[ "$DB_TYPE" = "mysql" ]]; then
|
if [[ "$DB_TYPE" = "mysql" ]]; then
|
||||||
if ! mysql $MYSQL_CREDENTIALS -N -s -e \
|
${mysql_command} $MYSQL_CREDENTIALS -N -s -e \
|
||||||
"SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = '$DB_NAME'" 2>> $log_file \
|
"SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = '$DB_NAME'" 2>> $log_file \
|
||||||
| grep $DB_NAME >> $log_file 2>&1 ; then
|
| grep $DB_NAME >> $log_file 2>&1
|
||||||
fatal "MySQL Database '$DB_NAME' does not exit. (See Parameter 'DB_NAME')"
|
|
||||||
|
if [[ "$?" = "0" ]]; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
|
||||||
|
echononl "continue anyway [yes/no]: "
|
||||||
|
read OK
|
||||||
|
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||||||
|
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||||||
|
echononl "Wrong entry! - repeat [yes/no]: "
|
||||||
|
read OK
|
||||||
|
done
|
||||||
|
[[ $OK = "yes" ]] || fatal "Abbruch durch User"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
elif [[ "$DB_TYPE" = "pgsql" ]]; then
|
elif [[ "$DB_TYPE" = "pgsql" ]]; then
|
||||||
count=$(su - postgres -c "psql -q -A -t -l" | grep -c -e "^$DB_NAME")
|
count=$(su - postgres -c "${psql_command} -q -A -t -l" | grep -c -e "^$DB_NAME")
|
||||||
if [[ $count -eq 0 ]];then
|
if [[ $count -eq 0 ]];then
|
||||||
fatal "PostgreSQL Database '$DB_NAME' does not exit. (See Parameter 'DB_NAME')"
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
|
||||||
|
echononl "continue anyway [yes/no]: "
|
||||||
|
read OK
|
||||||
|
OK="$(echo "$OK" | tr '[:upper:]' '[:lower:]')"
|
||||||
|
while [[ "$OK" != "yes" ]] && [[ "$OK" != "no" ]] ; do
|
||||||
|
echononl "Wrong entry! - repeat [yes/no]: "
|
||||||
|
read OK
|
||||||
|
done
|
||||||
|
[[ $OK = "yes" ]] || fatal "Abbruch durch User"
|
||||||
|
else
|
||||||
|
echo_ok
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
fatal "Cannot detect database type (value of DB_TYPE is neither 'mysql' nor 'pgsql')"
|
fatal "Cannot detect database type (value of DB_TYPE is neither 'mysql' nor 'pgsql')"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
echononl "\tInstall/Update composer to /usr/local/bin"
|
||||||
|
|
||||||
|
echononl "\tDownload composer from 'getcomposer.org'.."
|
||||||
|
php -r "copy('https://getcomposer.org/installer', '${script_dir}/composer-setup.php');" > $log_file 2>&1
|
||||||
|
if [[ "$?" = "0" ]]; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echononl "\tInstall composer to /usr/local/bin"
|
||||||
|
php ${script_dir}/composer-setup.php --install-dir=/usr/local/bin --filename=composer > $log_file 2>&1
|
||||||
|
if [[ "$?" = "0" ]]; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
echo -e "\n\n \033[37m\033[1mCreate some Backups..\033[m\n"
|
echo -e "\n\n \033[37m\033[1mCreate some Backups..\033[m\n"
|
||||||
|
|
||||||
|
echononl " Backup existing upgrade log directory \033[37m\033[1m$(basename "${_log_dir}")\033[m"
|
||||||
|
if [[ -d "${_log_dir}" ]] ; then
|
||||||
|
mv "${_log_dir}" "${_log_dir}.${backup_date}" > $log_file 2>&1
|
||||||
|
if [[ $? -eq 0 ]]; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo_skipped
|
||||||
|
fi
|
||||||
|
|
||||||
echononl " Backup existing Database '$DB_NAME'"
|
echononl " Backup existing Database '$DB_NAME'"
|
||||||
if [[ "$DB_TYPE" = "mysql" ]]; then
|
if [[ "$DB_TYPE" = "mysql" ]]; then
|
||||||
echo -n " (MySQL).."
|
echo -n " (MySQL).."
|
||||||
@@ -631,8 +877,8 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
echononl " Create log-directory for update log file"
|
echononl " Create log-directory for update log file"
|
||||||
if [[ ! -d "${script_dir}/log" ]]; then
|
if [[ ! -d "${_log_dir}" ]]; then
|
||||||
mkdir "${script_dir}/log" > $log_file 2>&1
|
mkdir "${_log_dir}" > $log_file 2>&1
|
||||||
if [[ $? -eq 0 ]]; then
|
if [[ $? -eq 0 ]]; then
|
||||||
echo_ok
|
echo_ok
|
||||||
else
|
else
|
||||||
@@ -643,10 +889,40 @@ else
|
|||||||
echo_skipped
|
echo_skipped
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
echononl "\tRename the composer.json-dist file into composer.json"
|
||||||
|
cp -a "composer.json-dist" "composer.json" > $log_file 2>&1
|
||||||
|
if [[ $? -eq 0 ]]; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echononl "\tInstall composer to ${WEBSITE_BASEDIR}/roundcubemail-${ROUNDCUBE_VERSION}"
|
||||||
|
php ${script_dir}/composer-setup.php --install-dir=${WEBSITE_BASEDIR}/roundcubemail-${ROUNDCUBE_VERSION} > $log_file 2>&1
|
||||||
|
if [[ "$?" = "0" ]]; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echononl "\tRemove the installer"
|
||||||
|
php -r "unlink('${script_dir}/composer-setup.php');" > $log_file 2>&1
|
||||||
|
if [[ "$?" = "0" ]]; then
|
||||||
|
echo_ok
|
||||||
|
else
|
||||||
|
echo_failed
|
||||||
|
error "$(cat $log_file)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo " Update the the roundcube web-directory to version '${ROUNDCUBE_VERSION}'"
|
echo " Update the the roundcube web-directory to version '${ROUNDCUBE_VERSION}'"
|
||||||
echononl " See: ${script_dir}/log/update_roundcube-${ROUNDCUBE_VERSION}.${backup_date}.log"
|
echononl " See: ${_log_dir}/update_roundcube-${ROUNDCUBE_VERSION}.${backup_date}.log"
|
||||||
echo "y" | ${script_dir}/roundcubemail-${ROUNDCUBE_VERSION}/bin/installto.sh "${WEBSITE_BASEDIR}/roundcubemail-${ROUNDCUBE_VERSION}" > ${script_dir}/log/update_roundcube-${ROUNDCUBE_VERSION}.${backup_date}.log 2>&1
|
echo "y" | ${script_dir}/roundcubemail-${ROUNDCUBE_VERSION}/bin/installto.sh "${WEBSITE_BASEDIR}/roundcubemail-${ROUNDCUBE_VERSION}" > ${_log_dir}/update_roundcube-${ROUNDCUBE_VERSION}.${backup_date}.log 2>&1
|
||||||
if [[ $? -eq 0 ]]; then
|
if [[ $? -eq 0 ]]; then
|
||||||
echo_ok
|
echo_ok
|
||||||
else
|
else
|
||||||
@@ -681,12 +957,12 @@ done
|
|||||||
|
|
||||||
|
|
||||||
echononl " Update dependencies by running 'php composer.phar update --no-dev'"
|
echononl " Update dependencies by running 'php composer.phar update --no-dev'"
|
||||||
php composer.phar --no-interaction update --no-dev > ${script_dir}/log/update_roundcube-${ROUNDCUBE_VERSION}-dependencies.${backup_date}.log 2>&1
|
php composer.phar --no-interaction update --no-dev > ${_log_dir}/update_roundcube-${ROUNDCUBE_VERSION}-dependencies.${backup_date}.log 2>&1
|
||||||
if [[ $? -eq 0 ]]; then
|
if [[ $? -eq 0 ]]; then
|
||||||
echo_ok
|
echo_ok
|
||||||
else
|
else
|
||||||
echo_failed
|
echo_failed
|
||||||
error "command was:\n\t # cd "${WEBSITE_BASEDIR}/roundcubemail-${ROUNDCUBE_VERSION}"\n\t #php composer.phar --no-interaction update --no-dev\n\n$(cat ${script_dir}/log/update_roundcube-${ROUNDCUBE_VERSION}-dependencies.${backup_date}.log)"
|
error "command was:\n\t # cd "${WEBSITE_BASEDIR}/roundcubemail-${ROUNDCUBE_VERSION}"\n\t #php composer.phar --no-interaction update --no-dev\n\n$(cat ${_log_dir}/update_roundcube-${ROUNDCUBE_VERSION}-dependencies.${backup_date}.log)"
|
||||||
|
|
||||||
echononl "continue anyway [yes/no]: "
|
echononl "continue anyway [yes/no]: "
|
||||||
read OK
|
read OK
|
||||||
|
|||||||
Reference in New Issue
Block a user