From de7350baabe45836e01f42c0b2525783c84e23f3 Mon Sep 17 00:00:00 2001 From: Patrick Niebeling Date: Wed, 6 Nov 2024 17:13:46 +0100 Subject: [PATCH 01/20] First Shot Signed-off-by: Patrick Niebeling --- Stable2.0/Dockerfile | 60 ++ Stable2.0/conf/custom/bad_asn.map | 31 + Stable2.0/conf/custom/bad_header.map | 2 + Stable2.0/conf/custom/bad_languages.map | 1 + Stable2.0/conf/custom/bad_words.map | 29 + Stable2.0/conf/custom/bad_words_de.map | 17 + Stable2.0/conf/custom/bulk_header.map | 19 + Stable2.0/conf/custom/fishy_tlds.map | 65 ++ .../custom/global_mime_from_blacklist.map | 1 + .../custom/global_mime_from_whitelist.map | 1 + .../conf/custom/global_rcpt_blacklist.map | 1 + .../conf/custom/global_rcpt_whitelist.map | 1 + .../custom/global_smtp_from_blacklist.map | 1 + .../custom/global_smtp_from_whitelist.map | 1 + Stable2.0/conf/custom/ip_wl.map | 4 + Stable2.0/conf/custom/monitoring_nolog.map | 7 + Stable2.0/conf/dynmaps/aliasexp.php | 174 +++++ Stable2.0/conf/dynmaps/bcc.php | 88 +++ Stable2.0/conf/dynmaps/footer.php | 113 +++ Stable2.0/conf/dynmaps/forwardinghosts.php | 57 ++ Stable2.0/conf/dynmaps/index.html | 2 + Stable2.0/conf/dynmaps/sasl_logs.php | 2 + Stable2.0/conf/dynmaps/settings.php | 471 ++++++++++++ Stable2.0/conf/dynmaps/vars.inc.php | 6 + Stable2.0/conf/local.d/actions.conf | 3 + Stable2.0/conf/local.d/antivirus.conf | 11 + Stable2.0/conf/local.d/arc.conf | 32 + Stable2.0/conf/local.d/asn.conf | 6 + Stable2.0/conf/local.d/composites.conf | 110 +++ Stable2.0/conf/local.d/dkim_signing.conf | 35 + Stable2.0/conf/local.d/external_services.conf | 12 + Stable2.0/conf/local.d/force_actions.conf | 12 + Stable2.0/conf/local.d/fuzzy_check.conf | 54 ++ Stable2.0/conf/local.d/fuzzy_group.conf | 17 + Stable2.0/conf/local.d/greylist.conf | 4 + Stable2.0/conf/local.d/groups.conf | 59 ++ Stable2.0/conf/local.d/headers_group.conf | 7 + Stable2.0/conf/local.d/hfilter_group.conf | 5 + Stable2.0/conf/local.d/history_redis.conf | 1 + Stable2.0/conf/local.d/metadata_exporter.conf | 72 ++ Stable2.0/conf/local.d/milter_headers.conf | 43 ++ Stable2.0/conf/local.d/mime_types.conf | 47 ++ Stable2.0/conf/local.d/mime_types_group.conf | 7 + Stable2.0/conf/local.d/multimap.conf | 181 +++++ Stable2.0/conf/local.d/mx_check.conf | 7 + Stable2.0/conf/local.d/options.inc | 9 + Stable2.0/conf/local.d/phishing.conf | 1 + Stable2.0/conf/local.d/policies_group.conf | 26 + Stable2.0/conf/local.d/ratelimit.conf | 9 + Stable2.0/conf/local.d/rbl.conf | 26 + Stable2.0/conf/local.d/rbl_group.conf | 277 +++++++ Stable2.0/conf/local.d/redis.conf | 2 + Stable2.0/conf/local.d/reputation.conf | 9 + Stable2.0/conf/local.d/spamassassin.conf | 1 + Stable2.0/conf/local.d/statistic.conf | 26 + Stable2.0/conf/local.d/statistics_group.conf | 10 + Stable2.0/conf/lua/ratelimit.lua | 16 + Stable2.0/conf/lua/rspamd.local.lua | 701 ++++++++++++++++++ Stable2.0/conf/meta_exporter/pipe.php | 260 +++++++ Stable2.0/conf/meta_exporter/pipe_rl.php | 48 ++ Stable2.0/conf/meta_exporter/pushover.php | 275 +++++++ Stable2.0/conf/meta_exporter/vars.inc.php | 6 + Stable2.0/conf/override.d/logging.inc | 5 + Stable2.0/conf/override.d/ratelimit.conf | 4 + .../conf/override.d/worker-controller.inc | 7 + Stable2.0/conf/override.d/worker-fuzzy.inc | 12 + Stable2.0/conf/override.d/worker-normal.inc | 4 + Stable2.0/conf/override.d/worker-proxy.inc | 9 + Stable2.0/conf/plugins.d/README.md | 1 + Stable2.0/conf/rspamd.conf.local | 1 + Stable2.0/conf/rspamd.conf.override | 2 + Stable2.0/hooks/build | 17 + Stable2.0/hooks/post_push | 9 + Stable2.0/rspamd.conf.local.override | 13 + Stable2.0/worker-controller.inc | 1 + Stable2.0/worker-proxy.inc | 1 + 76 files changed, 3667 insertions(+) create mode 100644 Stable2.0/Dockerfile create mode 100644 Stable2.0/conf/custom/bad_asn.map create mode 100644 Stable2.0/conf/custom/bad_header.map create mode 100644 Stable2.0/conf/custom/bad_languages.map create mode 100644 Stable2.0/conf/custom/bad_words.map create mode 100644 Stable2.0/conf/custom/bad_words_de.map create mode 100644 Stable2.0/conf/custom/bulk_header.map create mode 100644 Stable2.0/conf/custom/fishy_tlds.map create mode 100644 Stable2.0/conf/custom/global_mime_from_blacklist.map create mode 100644 Stable2.0/conf/custom/global_mime_from_whitelist.map create mode 100644 Stable2.0/conf/custom/global_rcpt_blacklist.map create mode 100644 Stable2.0/conf/custom/global_rcpt_whitelist.map create mode 100644 Stable2.0/conf/custom/global_smtp_from_blacklist.map create mode 100644 Stable2.0/conf/custom/global_smtp_from_whitelist.map create mode 100644 Stable2.0/conf/custom/ip_wl.map create mode 100644 Stable2.0/conf/custom/monitoring_nolog.map create mode 100644 Stable2.0/conf/dynmaps/aliasexp.php create mode 100644 Stable2.0/conf/dynmaps/bcc.php create mode 100644 Stable2.0/conf/dynmaps/footer.php create mode 100644 Stable2.0/conf/dynmaps/forwardinghosts.php create mode 100644 Stable2.0/conf/dynmaps/index.html create mode 100644 Stable2.0/conf/dynmaps/sasl_logs.php create mode 100644 Stable2.0/conf/dynmaps/settings.php create mode 100644 Stable2.0/conf/dynmaps/vars.inc.php create mode 100644 Stable2.0/conf/local.d/actions.conf create mode 100644 Stable2.0/conf/local.d/antivirus.conf create mode 100644 Stable2.0/conf/local.d/arc.conf create mode 100644 Stable2.0/conf/local.d/asn.conf create mode 100644 Stable2.0/conf/local.d/composites.conf create mode 100644 Stable2.0/conf/local.d/dkim_signing.conf create mode 100644 Stable2.0/conf/local.d/external_services.conf create mode 100644 Stable2.0/conf/local.d/force_actions.conf create mode 100644 Stable2.0/conf/local.d/fuzzy_check.conf create mode 100644 Stable2.0/conf/local.d/fuzzy_group.conf create mode 100644 Stable2.0/conf/local.d/greylist.conf create mode 100644 Stable2.0/conf/local.d/groups.conf create mode 100644 Stable2.0/conf/local.d/headers_group.conf create mode 100644 Stable2.0/conf/local.d/hfilter_group.conf create mode 100644 Stable2.0/conf/local.d/history_redis.conf create mode 100644 Stable2.0/conf/local.d/metadata_exporter.conf create mode 100644 Stable2.0/conf/local.d/milter_headers.conf create mode 100644 Stable2.0/conf/local.d/mime_types.conf create mode 100644 Stable2.0/conf/local.d/mime_types_group.conf create mode 100644 Stable2.0/conf/local.d/multimap.conf create mode 100644 Stable2.0/conf/local.d/mx_check.conf create mode 100644 Stable2.0/conf/local.d/options.inc create mode 100644 Stable2.0/conf/local.d/phishing.conf create mode 100644 Stable2.0/conf/local.d/policies_group.conf create mode 100644 Stable2.0/conf/local.d/ratelimit.conf create mode 100644 Stable2.0/conf/local.d/rbl.conf create mode 100644 Stable2.0/conf/local.d/rbl_group.conf create mode 100644 Stable2.0/conf/local.d/redis.conf create mode 100644 Stable2.0/conf/local.d/reputation.conf create mode 100644 Stable2.0/conf/local.d/spamassassin.conf create mode 100644 Stable2.0/conf/local.d/statistic.conf create mode 100644 Stable2.0/conf/local.d/statistics_group.conf create mode 100644 Stable2.0/conf/lua/ratelimit.lua create mode 100644 Stable2.0/conf/lua/rspamd.local.lua create mode 100644 Stable2.0/conf/meta_exporter/pipe.php create mode 100644 Stable2.0/conf/meta_exporter/pipe_rl.php create mode 100644 Stable2.0/conf/meta_exporter/pushover.php create mode 100644 Stable2.0/conf/meta_exporter/vars.inc.php create mode 100644 Stable2.0/conf/override.d/logging.inc create mode 100644 Stable2.0/conf/override.d/ratelimit.conf create mode 100644 Stable2.0/conf/override.d/worker-controller.inc create mode 100644 Stable2.0/conf/override.d/worker-fuzzy.inc create mode 100644 Stable2.0/conf/override.d/worker-normal.inc create mode 100644 Stable2.0/conf/override.d/worker-proxy.inc create mode 100644 Stable2.0/conf/plugins.d/README.md create mode 100644 Stable2.0/conf/rspamd.conf.local create mode 100644 Stable2.0/conf/rspamd.conf.override create mode 100644 Stable2.0/hooks/build create mode 100644 Stable2.0/hooks/post_push create mode 100644 Stable2.0/rspamd.conf.local.override create mode 100644 Stable2.0/worker-controller.inc create mode 100644 Stable2.0/worker-proxy.inc diff --git a/Stable2.0/Dockerfile b/Stable2.0/Dockerfile new file mode 100644 index 0000000..f5135e8 --- /dev/null +++ b/Stable2.0/Dockerfile @@ -0,0 +1,60 @@ +FROM debian:stable-slim +LABEL maintainer="gnilebein - " + +# Set apt non-interactive +ENV DEBIAN_FRONTEND noninteractive + +# Install Rspamd +RUN set -x \ + && apt update \ + && apt --no-install-recommends install -y lsb-release wget gnupg openssl ca-certificates \ + && DEBIAN_CODE_NAME=`lsb_release -c -s` \ + && wget -O - https://rspamd.com/apt-stable/gpg.key | apt-key add - \ + && echo "deb http://rspamd.com/apt-stable/ $DEBIAN_CODE_NAME main" > /etc/apt/sources.list.d/rspamd.list \ + && apt purge -y lsb-release wget gnupg \ + && apt update \ + && apt --no-install-recommends install -y rspamd \ + && apt autoremove --purge -y \ + && apt clean \ + && rm -rf /var/lib/apt/lists/* + +# Override default settings +COPY rspamd.conf.local.override /etc/rspamd/ +COPY worker-controller.inc /etc/rspamd/override.d/ +COPY worker-proxy.inc /etc/rspamd/override.d/ + +# Keep database and configuration persistent +VOLUME /etc/rspamd/local.d +VOLUME /var/lib/rspamd + +# Port 11334 is for web frontend +# Port 11332 is for milter +# Port 11333 is for worker +EXPOSE 11332 11334 + +# Healtcheck if Rspamd is returning stats +HEALTHCHECK --interval=1m --timeout=5s --start-period=10s \ + CMD /usr/bin/rspamadm control stat || exit 1 + +# Run Rspamd +ENTRYPOINT ["/docker-entrypoint.sh"] +CMD ["/usr/bin/rspamd", "-f", "-u", "_rspamd", "-g", "_rspamd"] + +STOPSIGNAL SIGTERM + +# Setup Labels +ARG VERSION +ARG COMMIT +ARG BRANCH +ARG DATE + +LABEL org.label-schema.name="Rspamd" \ + org.label-schema.description="Rspamd Spam Filter - STABLE" \ + org.label-schema.usage="https://hub.docker.com/r/gnilebein/rspamd/" \ + org.label-schema.url="https://rspamd.com" \ + org.label-schema.vendor="gnilebein" \ + org.label-schema.schema-version="1.0" \ + org.label-schema.version=$VERSION \ + org.label-schema.vcs-url="https://github.com/rspamd/rspamd/" \ + org.label-schema.vcs-ref=$COMMIT \ + org.label-schema.build-date=$DATE \ diff --git a/Stable2.0/conf/custom/bad_asn.map b/Stable2.0/conf/custom/bad_asn.map new file mode 100644 index 0000000..a8d49cf --- /dev/null +++ b/Stable2.0/conf/custom/bad_asn.map @@ -0,0 +1,31 @@ +# High spam networks, disabled by default +# ASN SCORE DESC +# Remove comment to enable score +#12874 5 #Fastweb SpA, Italy +#12876 2 #ONLINE S.A.S, France +#13335 5 #Cloudflare Inc., United States +#14061 4 #DigitalOcean LLC, United States +#16276 2 #OVH SAS, France +#21100 2 #ITL LLC, Ukraine +#28753 5 #Leaseweb Deutschland GmbH, Germany +#29119 5 #ServiHosting Networks S.L., Spain +#29422 5 #Telia Inmics-Nebula Oy, Finland +#30823 3 #combahton GmbH, Germany +#31034 5 #Aruba S.p.A, Italy +#39364 4 #Hormoz IT & Network Waves Connection Co. (PJS), Iran +#42831 5 #UK Dedicated Servers Limited, United Kingdom +#43146 2 #Domain names registrar REG.RU Ltd, Russia +#44493 2 #Chelyabinsk-Signal LLC, Russia +#46606 2 #Unified Layer, United States +#49100 4 #Pishgaman Toseeh Ertebatat Company (Private Joint Stock), Iran +#49505 2 #OOO Network of data-centers Selectel, Russia +#53755 5 #Input Output Flood LLC, United States +#55293 4 #A2 Hosting Inc., United States +#61272 5 #Informacines sistemos ir technologijos - UAB, Lithuania +#62255 4 #Asmunda New Media Ltd., Seychelles +#63018 4 #Dedicated.com, United States +#197518 2 #Rackmarkt SL, Spain +#197695 2 #Domain names registrar REG.RU Ltd, Russia +#198068 2 #P.A.G.M. OU, Estonia +#201942 5 #Soltia Consulting SL, Spain +#213373 4 #IP Connect Inc \ No newline at end of file diff --git a/Stable2.0/conf/custom/bad_header.map b/Stable2.0/conf/custom/bad_header.map new file mode 100644 index 0000000..839c3c3 --- /dev/null +++ b/Stable2.0/conf/custom/bad_header.map @@ -0,0 +1,2 @@ +/Thread-Topic:\s[a-zA-Z]{3}\s[a-zA-Z]{2}[\s\r\n]{0,1}[^a-zA-Z0-9][\r\n]/i +/Thread-Topic:\s[a-zA-Z]{3}\s[a-zA-Z]{2}\s[a-zA-Z]{1}\s[a-zA-Z]{5}[\s\r\n]{0,1}[^a-zA-Z0-9][\r\n]/i diff --git a/Stable2.0/conf/custom/bad_languages.map b/Stable2.0/conf/custom/bad_languages.map new file mode 100644 index 0000000..cf9ce3e --- /dev/null +++ b/Stable2.0/conf/custom/bad_languages.map @@ -0,0 +1 @@ +# Regex! /de/ will also match /de_at/ etc. diff --git a/Stable2.0/conf/custom/bad_words.map b/Stable2.0/conf/custom/bad_words.map new file mode 100644 index 0000000..0d9af8b --- /dev/null +++ b/Stable2.0/conf/custom/bad_words.map @@ -0,0 +1,29 @@ +/\serotic\s/i +/\serection\s/i +/\ssexy\s/i +/\sass\s/i +/\sviagra\s/i +/\stits\s/i +/\stitty\s/i +/\stitties\s/i +/\scum\s/i +/\ssperm\s/i +/\sslut\s/i +/\sporn\s/i +/\scock\s/i +/\spharma\s/i +/\spharmacy\s/i +/\sseo\s/i +/\sjackpot\s/i +/\slottery\s/i +/bitcoin/i +/trojaner/i +/malware/i +/\sscooter\s/i +/testost/i +/web\sdevelopment/i +/\slottery\s/i +/\ssex\s/i +/\svagina\s/i +/\spenis\s/i +/\smarketing\s/i \ No newline at end of file diff --git a/Stable2.0/conf/custom/bad_words_de.map b/Stable2.0/conf/custom/bad_words_de.map new file mode 100644 index 0000000..ccdd586 --- /dev/null +++ b/Stable2.0/conf/custom/bad_words_de.map @@ -0,0 +1,17 @@ +/\slotto\s/i +/pillenversand/i +/\skredithilfe\s/i +/\skapital\s/i +/\skrankenversicherung\s/i +/pƤdophil/i +/paedophil/i +/freiberufler/i +/unternehmer/i +/masturbieren/i +/\sescooter\s/i +/\se-scooter\s/i +/testost/i +/\spotenz\s/i +/potenzmittel/i +/rezeptfrei/i +/apotheke/i \ No newline at end of file diff --git a/Stable2.0/conf/custom/bulk_header.map b/Stable2.0/conf/custom/bulk_header.map new file mode 100644 index 0000000..69a20af --- /dev/null +++ b/Stable2.0/conf/custom/bulk_header.map @@ -0,0 +1,19 @@ +/X-EMV-Platform; .*/i +/.*nur-1-click.*/i +/.*episerver.*/i +/.*supergewinne.*/i +/List-Unsubscribe.*nbps\.eu/i +/.*regiofinder.*/i +/.*EmailSocket.*/i +/List-Unsubscribe:.*respread.*/i +/.*greenflamingo.*/i +/.*senderemailglobal.*/i +/.*promio\.net.*/i +/.*promio\.de.*/i +/.*mailer-service\.com.*/i +/.*mailer-service\.de.*/i +/.*dynamic-lht.*/i +/.*light-house-traffic.*/i +/.*newsletterplus.*/i +/.*X-Chpo.*/i +/.*List-Unsubscribe:.*@nl\..*/i diff --git a/Stable2.0/conf/custom/fishy_tlds.map b/Stable2.0/conf/custom/fishy_tlds.map new file mode 100644 index 0000000..1b8b2b0 --- /dev/null +++ b/Stable2.0/conf/custom/fishy_tlds.map @@ -0,0 +1,65 @@ +/.+\.accountant$/i +/.+\.art$/i +/.+\.asia$/i +/.+\.bid$/i +/.+\.biz$/i +/.+\.care$/i +/.+\.cf$/i +/.+\.click$/i +/.+\.cloud$/i +/.+\.co$/i +/.+\.construction$/i +/.+\.country$/i +/.+\.cricket$/i +/.+\.date$/i +/.+\.desi$/i +/.+\.download$/i +/.+\.estate$/i +/.+\.faith$/i +/.+\.fit$/i +/.+\.flights$/i +/.+\.ga$/i +/.+\.gdn$/i +/.+\.gq$/i +/.+\.guru$/i +/.+\.icu$/i +/.+\.id$/i +/.+\.info$/i +/.+\.in.net$/i +/.+\.ir$/i +/.+\.jetzt$/i +/.+\.kim$/i +/.+\.life$/i +/.+\.link$/i +/.+\.loan$/i +/.+\.mk$/i +/.+\.ml$/i +/.+\.ninja$/i +/.+\.online$/i +/.+\.ooo$/i +/.+\.party$/i +/.+\.pro$/i +/.+\.ps$/i +/.+\.pw$/i +/.+\.racing$/i +/.+\.review$/i +/.+\.rocks$/i +/.+\.ryukyu$/i +/.+\.science$/i +/.+\.site$/i +/.+\.space$/i +/.+\.stream$/i +/.+\.sucks$/i +/.+\.tk$/i +/.+\.top$/i +/.+\.topica\.com$/i +/.+\.town$/i +/.+\.trade$/i +/.+\.uno$/i +/.+\.vip$/i +/.+\.webcam$/i +/.+\.website$/i +/.+\.win$/i +/.+\.work$/i +/.+\.world$/i +/.+\.xyz$/i diff --git a/Stable2.0/conf/custom/global_mime_from_blacklist.map b/Stable2.0/conf/custom/global_mime_from_blacklist.map new file mode 100644 index 0000000..3c87288 --- /dev/null +++ b/Stable2.0/conf/custom/global_mime_from_blacklist.map @@ -0,0 +1 @@ +# /.+example\.com/i diff --git a/Stable2.0/conf/custom/global_mime_from_whitelist.map b/Stable2.0/conf/custom/global_mime_from_whitelist.map new file mode 100644 index 0000000..3c87288 --- /dev/null +++ b/Stable2.0/conf/custom/global_mime_from_whitelist.map @@ -0,0 +1 @@ +# /.+example\.com/i diff --git a/Stable2.0/conf/custom/global_rcpt_blacklist.map b/Stable2.0/conf/custom/global_rcpt_blacklist.map new file mode 100644 index 0000000..3c87288 --- /dev/null +++ b/Stable2.0/conf/custom/global_rcpt_blacklist.map @@ -0,0 +1 @@ +# /.+example\.com/i diff --git a/Stable2.0/conf/custom/global_rcpt_whitelist.map b/Stable2.0/conf/custom/global_rcpt_whitelist.map new file mode 100644 index 0000000..3c87288 --- /dev/null +++ b/Stable2.0/conf/custom/global_rcpt_whitelist.map @@ -0,0 +1 @@ +# /.+example\.com/i diff --git a/Stable2.0/conf/custom/global_smtp_from_blacklist.map b/Stable2.0/conf/custom/global_smtp_from_blacklist.map new file mode 100644 index 0000000..3c87288 --- /dev/null +++ b/Stable2.0/conf/custom/global_smtp_from_blacklist.map @@ -0,0 +1 @@ +# /.+example\.com/i diff --git a/Stable2.0/conf/custom/global_smtp_from_whitelist.map b/Stable2.0/conf/custom/global_smtp_from_whitelist.map new file mode 100644 index 0000000..3c87288 --- /dev/null +++ b/Stable2.0/conf/custom/global_smtp_from_whitelist.map @@ -0,0 +1 @@ +# /.+example\.com/i diff --git a/Stable2.0/conf/custom/ip_wl.map b/Stable2.0/conf/custom/ip_wl.map new file mode 100644 index 0000000..c8bb552 --- /dev/null +++ b/Stable2.0/conf/custom/ip_wl.map @@ -0,0 +1,4 @@ +# IP whitelist +# 127.0.0.1 +# 1.2.3.4 +# ... diff --git a/Stable2.0/conf/custom/monitoring_nolog.map b/Stable2.0/conf/custom/monitoring_nolog.map new file mode 100644 index 0000000..0e00de7 --- /dev/null +++ b/Stable2.0/conf/custom/monitoring_nolog.map @@ -0,0 +1,7 @@ +# Skip logging for these addresses +/monitoring-system@everycloudtech\.us/i +/monitor@tools\.mailflowmonitoring\.com/i +/watchdog@localhost/i +/supertool@mxtoolbox\.com/i +/test@mxtoolboxsmtpdiag\.com/i +/open-relay-check@mailcow\.email/i diff --git a/Stable2.0/conf/dynmaps/aliasexp.php b/Stable2.0/conf/dynmaps/aliasexp.php new file mode 100644 index 0000000..2d75614 --- /dev/null +++ b/Stable2.0/conf/dynmaps/aliasexp.php @@ -0,0 +1,174 @@ + PDO::ERRMODE_EXCEPTION, + PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, + PDO::ATTR_EMULATE_PREPARES => false, +]; +try { + $pdo = new PDO($dsn, $database_user, $database_pass, $opt); +} +catch (PDOException $e) { + error_log("ALIASEXP: " . $e . PHP_EOL); + http_response_code(501); + exit; +} + +// Init Redis +$redis = new Redis(); +$redis->connect('redis-mailcow', 6379); + +function parse_email($email) { + if(!filter_var($email, FILTER_VALIDATE_EMAIL)) return false; + $a = strrpos($email, '@'); + return array('local' => substr($email, 0, $a), 'domain' => substr(substr($email, $a), 1)); +} +if (!function_exists('getallheaders')) { + function getallheaders() { + if (!is_array($_SERVER)) { + return array(); + } + $headers = array(); + foreach ($_SERVER as $name => $value) { + if (substr($name, 0, 5) == 'HTTP_') { + $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value; + } + } + return $headers; + } +} + +// Read headers +$headers = getallheaders(); +// Get rcpt +$rcpt = $headers['Rcpt']; +// Remove tag +$rcpt = preg_replace('/^(.*?)\+.*(@.*)$/', '$1$2', $rcpt); +// Parse email address +$parsed_rcpt = parse_email($rcpt); +// Create array of final mailboxes +$rcpt_final_mailboxes = array(); + +// Skip if not a mailcow handled domain +try { + if (!$redis->hGet('DOMAIN_MAP', $parsed_rcpt['domain'])) { + exit; + } +} +catch (RedisException $e) { + error_log("ALIASEXP: " . $e . PHP_EOL); + http_response_code(504); + exit; +} + +// Always assume rcpt is not a final mailbox but an alias for a mailbox or further aliases +// +// rcpt +// | +// mailbox <-- goto ---> alias1, alias2, mailbox2 +// | | +// mailbox3 | +// | +// alias3 ---> mailbox4 +// +try { + $stmt = $pdo->prepare("SELECT `goto` FROM `alias` WHERE `address` = :rcpt AND `active` = '1'"); + $stmt->execute(array( + ':rcpt' => $rcpt + )); + $gotos = $stmt->fetch(PDO::FETCH_ASSOC)['goto']; + if (empty($gotos)) { + $stmt = $pdo->prepare("SELECT `goto` FROM `alias` WHERE `address` = :rcpt AND `active` = '1'"); + $stmt->execute(array( + ':rcpt' => '@' . $parsed_rcpt['domain'] + )); + $gotos = $stmt->fetch(PDO::FETCH_ASSOC)['goto']; + } + if (empty($gotos)) { + $stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :rcpt AND `active` = '1'"); + $stmt->execute(array(':rcpt' => $parsed_rcpt['domain'])); + $goto_branch = $stmt->fetch(PDO::FETCH_ASSOC)['target_domain']; + if ($goto_branch) { + $gotos = $parsed_rcpt['local'] . '@' . $goto_branch; + } + } + $gotos_array = explode(',', $gotos); + + $loop_c = 0; + + while (count($gotos_array) != 0 && $loop_c <= 20) { + + // Loop through all found gotos + foreach ($gotos_array as $index => &$goto) { + error_log("ALIAS EXPANDER: http pipe: query " . $goto . " as username from mailbox" . PHP_EOL); + $stmt = $pdo->prepare("SELECT `username` FROM `mailbox` WHERE `username` = :goto AND (`active`= '1' OR `active`= '2');"); + $stmt->execute(array(':goto' => $goto)); + $username = $stmt->fetch(PDO::FETCH_ASSOC)['username']; + if (!empty($username)) { + error_log("ALIAS EXPANDER: http pipe: mailbox found: " . $username . PHP_EOL); + // Current goto is a mailbox, save to rcpt_final_mailboxes if not a duplicate + if (!in_array($username, $rcpt_final_mailboxes)) { + $rcpt_final_mailboxes[] = $username; + } + } + else { + $parsed_goto = parse_email($goto); + if (!$redis->hGet('DOMAIN_MAP', $parsed_goto['domain'])) { + error_log("ALIAS EXPANDER:" . $goto . " is not a mailcow handled mailbox or alias address" . PHP_EOL); + } + else { + $stmt = $pdo->prepare("SELECT `goto` FROM `alias` WHERE `address` = :goto AND `active` = '1'"); + $stmt->execute(array(':goto' => $goto)); + $goto_branch = $stmt->fetch(PDO::FETCH_ASSOC)['goto']; + if ($goto_branch) { + error_log("ALIAS EXPANDER: http pipe: goto address " . $goto . " is an alias branch for " . $goto_branch . PHP_EOL); + $goto_branch_array = explode(',', $goto_branch); + } else { + $stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :domain AND `active` AND '1'"); + $stmt->execute(array(':domain' => $parsed_goto['domain'])); + $goto_branch = $stmt->fetch(PDO::FETCH_ASSOC)['target_domain']; + if ($goto_branch) { + error_log("ALIAS EXPANDER: http pipe: goto domain " . $parsed_goto['domain'] . " is a domain alias branch for " . $goto_branch . PHP_EOL); + $goto_branch_array = array($parsed_goto['local'] . '@' . $goto_branch); + } + } + } + } + // goto item was processed, unset + unset($gotos_array[$index]); + } + + // Merge goto branch array derived from previous loop (if any), filter duplicates and unset goto branch array + if (!empty($goto_branch_array)) { + $gotos_array = array_unique(array_merge($gotos_array, $goto_branch_array)); + unset($goto_branch_array); + } + + // Reindex array + $gotos_array = array_values($gotos_array); + + // Force exit if loop cannot be solved + // Postfix does not allow for alias loops, so this should never happen. + $loop_c++; + error_log("ALIAS EXPANDER: http pipe: goto array count on loop #". $loop_c . " is " . count($gotos_array) . PHP_EOL); + } +} +catch (PDOException $e) { + error_log("ALIAS EXPANDER: " . $e->getMessage() . PHP_EOL); + http_response_code(502); + exit; +} + +// Does also return the mailbox name if question == answer (query == mailbox) +if (count($rcpt_final_mailboxes) == 1) { + error_log("ALIASEXP: direct alias " . $rcpt . " expanded to " . $rcpt_final_mailboxes[0] . PHP_EOL); + echo trim($rcpt_final_mailboxes[0]); +} diff --git a/Stable2.0/conf/dynmaps/bcc.php b/Stable2.0/conf/dynmaps/bcc.php new file mode 100644 index 0000000..87f91ca --- /dev/null +++ b/Stable2.0/conf/dynmaps/bcc.php @@ -0,0 +1,88 @@ + PDO::ERRMODE_EXCEPTION, + PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, + PDO::ATTR_EMULATE_PREPARES => false, +]; +try { + $pdo = new PDO($dsn, $database_user, $database_pass, $opt); +} +catch (PDOException $e) { + error_log("BCC MAP SQL ERROR: " . $e . PHP_EOL); + http_response_code(501); + exit; +} + +function parse_email($email) { + if(!filter_var($email, FILTER_VALIDATE_EMAIL)) return false; + $a = strrpos($email, '@'); + return array('local' => substr($email, 0, $a), 'domain' => substr(substr($email, $a), 1)); +} +if (!function_exists('getallheaders')) { + function getallheaders() { + if (!is_array($_SERVER)) { + return array(); + } + $headers = array(); + foreach ($_SERVER as $name => $value) { + if (substr($name, 0, 5) == 'HTTP_') { + $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value; + } + } + return $headers; + } +} + +// Read headers +$headers = getallheaders(); +// Get rcpt +$rcpt = $headers['Rcpt']; +// Get from +$from = $headers['From']; +// Remove tags +$rcpt = preg_replace('/^(.*?)\+.*(@.*)$/', '$1$2', $rcpt); +$from = preg_replace('/^(.*?)\+.*(@.*)$/', '$1$2', $from); + +try { + if (!empty($rcpt)) { + $stmt = $pdo->prepare("SELECT `bcc_dest` FROM `bcc_maps` WHERE `type` = 'rcpt' AND `local_dest` = :local_dest AND `active` = '1'"); + $stmt->execute(array( + ':local_dest' => $rcpt + )); + $bcc_dest = $stmt->fetch(PDO::FETCH_ASSOC)['bcc_dest']; + if (!empty($bcc_dest) && filter_var($bcc_dest, FILTER_VALIDATE_EMAIL)) { + error_log("BCC MAP: returning ". $bcc_dest . " for " . $rcpt . PHP_EOL); + http_response_code(201); + echo trim($bcc_dest); + exit; + } + } + if (!empty($from)) { + $stmt = $pdo->prepare("SELECT `bcc_dest` FROM `bcc_maps` WHERE `type` = 'sender' AND `local_dest` = :local_dest AND `active` = '1'"); + $stmt->execute(array( + ':local_dest' => $from + )); + $bcc_dest = $stmt->fetch(PDO::FETCH_ASSOC)['bcc_dest']; + if (!empty($bcc_dest) && filter_var($bcc_dest, FILTER_VALIDATE_EMAIL)) { + error_log("BCC MAP: returning ". $bcc_dest . " for " . $from . PHP_EOL); + http_response_code(201); + echo trim($bcc_dest); + exit; + } + } +} +catch (PDOException $e) { + error_log("BCC MAP SQL ERROR: " . $e->getMessage() . PHP_EOL); + http_response_code(502); + exit; +} + diff --git a/Stable2.0/conf/dynmaps/footer.php b/Stable2.0/conf/dynmaps/footer.php new file mode 100644 index 0000000..545c45e --- /dev/null +++ b/Stable2.0/conf/dynmaps/footer.php @@ -0,0 +1,113 @@ + PDO::ERRMODE_EXCEPTION, + PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, + PDO::ATTR_EMULATE_PREPARES => false, +]; +try { + $pdo = new PDO($dsn, $database_user, $database_pass, $opt); +} +catch (PDOException $e) { + error_log("FOOTER: " . $e . PHP_EOL); + http_response_code(501); + exit; +} + +if (!function_exists('getallheaders')) { + function getallheaders() { + if (!is_array($_SERVER)) { + return array(); + } + $headers = array(); + foreach ($_SERVER as $name => $value) { + if (substr($name, 0, 5) == 'HTTP_') { + $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value; + } + } + return $headers; + } +} + +// Read headers +$headers = getallheaders(); +// Get Domain +$domain = $headers['Domain']; +// Get Username +$username = $headers['Username']; +// Get From +$from = $headers['From']; +// define empty footer +$empty_footer = json_encode(array( + 'html' => '', + 'plain' => '', + 'skip_replies' => 0, + 'vars' => array() +)); + +error_log("FOOTER: checking for domain " . $domain . ", user " . $username . " and address " . $from . PHP_EOL); + +try { + // try get $target_domain if $domain is an alias_domain + $stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain` + WHERE `alias_domain` = :alias_domain"); + $stmt->execute(array( + ':alias_domain' => $domain + )); + $alias_domain = $stmt->fetch(PDO::FETCH_ASSOC); + if (!$alias_domain) { + $target_domain = $domain; + } else { + $target_domain = $alias_domain['target_domain']; + } + + // get footer associated with the domain + $stmt = $pdo->prepare("SELECT `plain`, `html`, `mbox_exclude`, `alias_domain_exclude`, `skip_replies` FROM `domain_wide_footer` + WHERE `domain` = :domain"); + $stmt->execute(array( + ':domain' => $target_domain + )); + $footer = $stmt->fetch(PDO::FETCH_ASSOC); + + // check if the sender is excluded + if (in_array($from, json_decode($footer['mbox_exclude']))){ + $footer = false; + } + if (in_array($domain, json_decode($footer['alias_domain_exclude']))){ + $footer = false; + } + if (empty($footer)){ + echo $empty_footer; + exit; + } + error_log("FOOTER: " . json_encode($footer) . PHP_EOL); + + // footer will be applied + // get custom mailbox attributes to insert into the footer + $stmt = $pdo->prepare("SELECT `custom_attributes` FROM `mailbox` WHERE `username` = :username"); + $stmt->execute(array( + ':username' => $username + )); + $custom_attributes = $stmt->fetch(PDO::FETCH_ASSOC)['custom_attributes']; + if (empty($custom_attributes)){ + $custom_attributes = (object)array(); + } +} +catch (Exception $e) { + error_log("FOOTER: " . $e->getMessage() . PHP_EOL); + http_response_code(502); + exit; +} + + +// return footer +$footer["vars"] = $custom_attributes; +echo json_encode($footer); diff --git a/Stable2.0/conf/dynmaps/forwardinghosts.php b/Stable2.0/conf/dynmaps/forwardinghosts.php new file mode 100644 index 0000000..10285b7 --- /dev/null +++ b/Stable2.0/conf/dynmaps/forwardinghosts.php @@ -0,0 +1,57 @@ +connect('redis-mailcow', 6379); + +function in_net($addr, $net) { + $net = explode('/', $net); + if (count($net) > 1) { + $mask = $net[1]; + } + $net = inet_pton($net[0]); + $addr = inet_pton($addr); + $length = strlen($net); // 4 for IPv4, 16 for IPv6 + if (strlen($net) != strlen($addr)) { + return false; + } + if (!isset($mask)) { + $mask = $length * 8; + } + $addr_bin = ''; + $net_bin = ''; + for ($i = 0; $i < $length; ++$i) { + $addr_bin .= str_pad(decbin(ord(substr($addr, $i, $i+1))), 8, '0', STR_PAD_LEFT); + $net_bin .= str_pad(decbin(ord(substr($net, $i, $i+1))), 8, '0', STR_PAD_LEFT); + } + return substr($addr_bin, 0, $mask) == substr($net_bin, 0, $mask); +} + +if (isset($_GET['host'])) { + try { + foreach ($redis->hGetAll('WHITELISTED_FWD_HOST') as $host => $source) { + if (in_net($_GET['host'], $host)) { + echo '200 PERMIT'; + exit; + } + } + echo '200 DUNNO'; + } + catch (RedisException $e) { + echo '200 DUNNO'; + exit; + } +} else { + try { + echo '240.240.240.240' . PHP_EOL; + foreach ($redis->hGetAll('WHITELISTED_FWD_HOST') as $host => $source) { + echo $host . PHP_EOL; + } + } + catch (RedisException $e) { + echo '240.240.240.240' . PHP_EOL; + exit; + } +} +?> diff --git a/Stable2.0/conf/dynmaps/index.html b/Stable2.0/conf/dynmaps/index.html new file mode 100644 index 0000000..90531a4 --- /dev/null +++ b/Stable2.0/conf/dynmaps/index.html @@ -0,0 +1,2 @@ + + diff --git a/Stable2.0/conf/dynmaps/sasl_logs.php b/Stable2.0/conf/dynmaps/sasl_logs.php new file mode 100644 index 0000000..2d4cbe6 --- /dev/null +++ b/Stable2.0/conf/dynmaps/sasl_logs.php @@ -0,0 +1,2 @@ + PDO::ERRMODE_EXCEPTION, + PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, + PDO::ATTR_EMULATE_PREPARES => false, +]; +try { + $pdo = new PDO($dsn, $database_user, $database_pass, $opt); + $stmt = $pdo->query("SELECT '1' FROM `filterconf`"); +} +catch (PDOException $e) { + echo 'settings { }'; + exit; +} + +// Check if db changed and return header +$stmt = $pdo->prepare("SELECT GREATEST(COALESCE(MAX(UNIX_TIMESTAMP(UPDATE_TIME)), 1), COALESCE(MAX(UNIX_TIMESTAMP(CREATE_TIME)), 1)) AS `db_update_time` FROM `information_schema`.`tables` + WHERE (`TABLE_NAME` = 'filterconf' OR `TABLE_NAME` = 'settingsmap' OR `TABLE_NAME` = 'sogo_quick_contact' OR `TABLE_NAME` = 'alias') + AND TABLE_SCHEMA = :dbname;"); +$stmt->execute(array( + ':dbname' => $database_name +)); +$db_update_time = $stmt->fetch(PDO::FETCH_ASSOC)['db_update_time']; +if (empty($db_update_time)) { + $db_update_time = 1572048000; +} +if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && (strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $db_update_time)) { + header('Last-Modified: '.gmdate('D, d M Y H:i:s', $db_update_time).' GMT', true, 304); + exit; +} else { + header('Last-Modified: '.gmdate('D, d M Y H:i:s', $db_update_time).' GMT', true, 200); +} + +function parse_email($email) { + if (!filter_var($email, FILTER_VALIDATE_EMAIL)) return false; + $a = strrpos($email, '@'); + return array('local' => substr($email, 0, $a), 'domain' => substr($email, $a)); +} + +function normalize_email($email) { + $email = strtolower(str_replace('/', '\/', $email)); + $gm = "@gmail.com"; + if (substr_compare($email, $gm, -strlen($gm)) == 0) { + $email = explode('@', $email); + $email[0] = str_replace('.', '', $email[0]); + $email = implode('@', $email); + } + $gm_alt = "@googlemail.com"; + if (substr_compare($email, $gm_alt, -strlen($gm_alt)) == 0) { + $email = explode('@', $email); + $email[0] = str_replace('.', '', $email[0]); + $email[1] = str_replace('@', '', $gm); + $email = implode('@', $email); + } + if (str_contains($email, "+")) { + $email = explode('@', $email); + $user = explode('+', $email[0]); + $email[0] = $user[0]; + $email = implode('@', $email); + } + return $email; +} + +function wl_by_sogo() { + global $pdo; + $rcpt = array(); + $stmt = $pdo->query("SELECT DISTINCT(`sogo_folder_info`.`c_path2`) AS `user`, GROUP_CONCAT(`sogo_quick_contact`.`c_mail`) AS `contacts` FROM `sogo_folder_info` + INNER JOIN `sogo_quick_contact` ON `sogo_quick_contact`.`c_folder_id` = `sogo_folder_info`.`c_folder_id` + GROUP BY `c_path2`"); + $sogo_contacts = $stmt->fetchAll(PDO::FETCH_ASSOC); + while ($row = array_shift($sogo_contacts)) { + foreach (explode(',', $row['contacts']) as $contact) { + if (!filter_var($contact, FILTER_VALIDATE_EMAIL)) { + continue; + } + // Explicit from, no mime_from, no regex - envelope must match + // mailcow white and blacklists also cover mime_from + $rcpt[$row['user']][] = normalize_email($contact); + } + } + return $rcpt; +} + +function ucl_rcpts($object, $type) { + global $pdo; + $rcpt = array(); + if ($type == 'mailbox') { + // Standard aliases + $stmt = $pdo->prepare("SELECT `address` FROM `alias` + WHERE `goto` = :object_goto + AND `address` NOT LIKE '@%'"); + $stmt->execute(array( + ':object_goto' => $object + )); + $standard_aliases = $stmt->fetchAll(PDO::FETCH_ASSOC); + while ($row = array_shift($standard_aliases)) { + $local = parse_email($row['address'])['local']; + $domain = parse_email($row['address'])['domain']; + if (!empty($local) && !empty($domain)) { + $rcpt[] = '/^' . str_replace('/', '\/', $local) . '[+].*' . str_replace('/', '\/', $domain) . '$/i'; + } + $rcpt[] = str_replace('/', '\/', $row['address']); + } + // Aliases by alias domains + $stmt = $pdo->prepare("SELECT CONCAT(`local_part`, '@', `alias_domain`.`alias_domain`) AS `alias` FROM `mailbox` + LEFT OUTER JOIN `alias_domain` ON `mailbox`.`domain` = `alias_domain`.`target_domain` + WHERE `mailbox`.`username` = :object"); + $stmt->execute(array( + ':object' => $object + )); + $by_domain_aliases = $stmt->fetchAll(PDO::FETCH_ASSOC); + array_filter($by_domain_aliases); + while ($row = array_shift($by_domain_aliases)) { + if (!empty($row['alias'])) { + $local = parse_email($row['alias'])['local']; + $domain = parse_email($row['alias'])['domain']; + if (!empty($local) && !empty($domain)) { + $rcpt[] = '/^' . str_replace('/', '\/', $local) . '[+].*' . str_replace('/', '\/', $domain) . '$/i'; + } + $rcpt[] = str_replace('/', '\/', $row['alias']); + } + } + } + elseif ($type == 'domain') { + // Domain self + $rcpt[] = '/.*@' . $object . '/i'; + $stmt = $pdo->prepare("SELECT `alias_domain` FROM `alias_domain` + WHERE `target_domain` = :object"); + $stmt->execute(array(':object' => $object)); + $alias_domains = $stmt->fetchAll(PDO::FETCH_ASSOC); + array_filter($alias_domains); + while ($row = array_shift($alias_domains)) { + $rcpt[] = '/.*@' . $row['alias_domain'] . '/i'; + } + } + return $rcpt; +} +?> +settings { + watchdog { + priority = 10; + rcpt_mime = "/null@localhost/i"; + from_mime = "/watchdog@localhost/i"; + apply "default" { + symbols_disabled = ["HISTORY_SAVE", "ARC", "ARC_SIGNED", "DKIM", "DKIM_SIGNED", "CLAM_VIRUS"]; + want_spam = yes; + actions { + reject = 9999.0; + greylist = 9998.0; + "add header" = 9997.0; + } + + } + } +query("SELECT DISTINCT `object` FROM `filterconf` WHERE `option` = 'highspamlevel' OR `option` = 'lowspamlevel'"); +$rows = $stmt->fetchAll(PDO::FETCH_ASSOC); + +while ($row = array_shift($rows)) { + $username_sane = preg_replace("/[^a-zA-Z0-9]+/", "", $row['object']); +?> + score_ { + priority = 4; + + rcpt = ; +prepare("SELECT `option`, `value` FROM `filterconf` + WHERE (`option` = 'highspamlevel' OR `option` = 'lowspamlevel') + AND `object`= :object"); + $stmt->execute(array(':object' => $row['object'])); + $spamscore = $stmt->fetchAll(PDO::FETCH_COLUMN|PDO::FETCH_GROUP); +?> + apply "default" { + actions { + reject = ; + greylist = ; + "add header" = ; + } + } + } + $contacts) { + $username_sane = preg_replace("/[^a-zA-Z0-9]+/", "", $user); +?> + whitelist_sogo_ { + + from = ; + + priority = 4; + + rcpt = ; + + apply "default" { + SOGO_CONTACT = -99.0; + } + symbols [ + "SOGO_CONTACT" + ] + } +query("SELECT DISTINCT `object` FROM `filterconf` WHERE `option` = 'whitelist_from'"); +$rows = $stmt->fetchAll(PDO::FETCH_ASSOC); +while ($row = array_shift($rows)) { + $username_sane = preg_replace("/[^a-zA-Z0-9]+/", "", $row['object']); +?> + whitelist_ { +prepare("SELECT `value` FROM `filterconf` + WHERE `object`= :object + AND `option` = 'whitelist_from'"); + $stmt->execute(array(':object' => $row['object'])); + $list_items = $stmt->fetchAll(PDO::FETCH_ASSOC); + foreach ($list_items as $item) { +?> + from = "//i"; + + priority = 5; + + rcpt = ; + + priority = 6; + + rcpt = ; + + apply "default" { + MAILCOW_WHITE = -999.0; + } + symbols [ + "MAILCOW_WHITE" + ] + } + whitelist_mime_ { + + from_mime = "//i"; + + priority = 5; + + rcpt = ; + + priority = 6; + + rcpt = ; + + apply "default" { + MAILCOW_WHITE = -999.0; + } + symbols [ + "MAILCOW_WHITE" + ] + } +query("SELECT DISTINCT `object` FROM `filterconf` WHERE `option` = 'blacklist_from'"); +$rows = $stmt->fetchAll(PDO::FETCH_ASSOC); +while ($row = array_shift($rows)) { + $username_sane = preg_replace("/[^a-zA-Z0-9]+/", "", $row['object']); +?> + blacklist_ { +prepare("SELECT `value` FROM `filterconf` + WHERE `object`= :object + AND `option` = 'blacklist_from'"); + $stmt->execute(array(':object' => $row['object'])); + $list_items = $stmt->fetchAll(PDO::FETCH_ASSOC); + foreach ($list_items as $item) { +?> + from = "//i"; + + priority = 5; + + rcpt = ; + + priority = 6; + + rcpt = ; + + apply "default" { + MAILCOW_BLACK = 999.0; + } + symbols [ + "MAILCOW_BLACK" + ] + } + blacklist_header_ { + + from_mime = "//i"; + + priority = 5; + + rcpt = ; + + priority = 6; + + rcpt = ; + + apply "default" { + MAILCOW_BLACK = 999.0; + } + symbols [ + "MAILCOW_BLACK" + ] + } + + ham_trap { + + rcpt = ; + + priority = 9; + apply "default" { + symbols_enabled = ["HISTORY_SAVE"]; + } + symbols [ + "HAM_TRAP" + ] + } + + spam_trap { + + rcpt = ; + + priority = 9; + apply "default" { + symbols_enabled = ["HISTORY_SAVE"]; + } + symbols [ + "SPAM_TRAP" + ] + } +query("SELECT `id`, `content` FROM `settingsmap` WHERE `active` = '1'"); +$rows = $stmt->fetchAll(PDO::FETCH_ASSOC); +while ($row = array_shift($rows)) { + $username_sane = preg_replace("/[^a-zA-Z0-9]+/", "", $row['id']); +?> + additional_settings_ { + + } + +} diff --git a/Stable2.0/conf/dynmaps/vars.inc.php b/Stable2.0/conf/dynmaps/vars.inc.php new file mode 100644 index 0000000..79566b0 --- /dev/null +++ b/Stable2.0/conf/dynmaps/vars.inc.php @@ -0,0 +1,6 @@ + diff --git a/Stable2.0/conf/local.d/actions.conf b/Stable2.0/conf/local.d/actions.conf new file mode 100644 index 0000000..3de63a5 --- /dev/null +++ b/Stable2.0/conf/local.d/actions.conf @@ -0,0 +1,3 @@ +reject = 15; +add_header = 8; +greylist = 7; diff --git a/Stable2.0/conf/local.d/antivirus.conf b/Stable2.0/conf/local.d/antivirus.conf new file mode 100644 index 0000000..c8d31d1 --- /dev/null +++ b/Stable2.0/conf/local.d/antivirus.conf @@ -0,0 +1,11 @@ +clamav { + # Scan whole message + scan_mime_parts = false; + #scan_text_mime = true; + #scan_image_mime = true; + symbol = "CLAM_VIRUS"; + type = "clamav"; + log_clean = true; + servers = "clamd:3310"; + max_size = 20971520; +} diff --git a/Stable2.0/conf/local.d/arc.conf b/Stable2.0/conf/local.d/arc.conf new file mode 100644 index 0000000..a857fc4 --- /dev/null +++ b/Stable2.0/conf/local.d/arc.conf @@ -0,0 +1,32 @@ +# If false, messages with empty envelope from are not signed +allow_envfrom_empty = true; +# If true, envelope/header domain mismatch is ignored +allow_hdrfrom_mismatch = true; +# If true, multiple from headers are allowed (but only first is used) +allow_hdrfrom_multiple = false; +# If true, username does not need to contain matching domain +allow_username_mismatch = false; +# If false, messages from authenticated users are not selected for signing +sign_authenticated = false; +# Default path to key, can include '$domain' and '$selector' variables +path = "/data/dkim/keys/$domain.dkim"; +# Default selector to use +selector = "dkim"; +# If false, messages from local networks are not selected for signing +sign_local = false; +# Symbol to add when message is signed +symbol = "ARC_SIGNED"; +# Whether to fallback to global config +try_fallback = true; +# Domain to use for DKIM signing: can be "header" or "envelope" +use_domain = "recipient"; +# Whether to normalise domains to eSLD +use_esld = false; +# Whether to get keys from Redis +use_redis = true; +# Hash for DKIM keys in Redis +key_prefix = "DKIM_PRIV_KEYS"; +# Selector map +selector_prefix = "DKIM_SELECTORS"; +sign_inbound = true; +use_domain_sign_inbound = "recipient"; diff --git a/Stable2.0/conf/local.d/asn.conf b/Stable2.0/conf/local.d/asn.conf new file mode 100644 index 0000000..42b6780 --- /dev/null +++ b/Stable2.0/conf/local.d/asn.conf @@ -0,0 +1,6 @@ +provider_type = "rspamd"; +provider_info { + ip4 = "asn.rspamd.com"; + ip6 = "asn6.rspamd.com"; +} +symbol = "ASN"; diff --git a/Stable2.0/conf/local.d/composites.conf b/Stable2.0/conf/local.d/composites.conf new file mode 100644 index 0000000..9bb8442 --- /dev/null +++ b/Stable2.0/conf/local.d/composites.conf @@ -0,0 +1,110 @@ +MX_IMPLICIT { + expression = "MX_GOOD & MX_MISSING"; + score = -0.01; +} +VIRUS_FOUND { + expression = "CLAM_VIRUS & !MAILCOW_WHITE"; + score = 2000.0; +} +# Bad policy from free mail providers +FREEMAIL_POLICY_FAILURE { + expression = "FREEMAIL_FROM & !DMARC_POLICY_ALLOW & !MAILLIST& !WHITELISTED_FWD_HOST & -g+:policies"; + score = 16.0; +} +# Applies to freemail with undisclosed recipients +FREEMAIL_TO_UNDISC_RCPT { + expression = "FREEMAIL_FROM & ( MISSING_TO | R_UNDISC_RCPT | TO_EQ_FROM )"; + score = 5.0; +} +# Bad policy from non-whitelisted senders +# Remove SOGO_CONTACT symbol for fwd hosts and senders with broken policy +SOGO_CONTACT_EXCLUDE { + expression = "(-WHITELISTED_FWD_HOST | -g+:policies) & ^SOGO_CONTACT & !DMARC_POLICY_ALLOW"; +} +# Remove MAILCOW_WHITE symbol for senders with broken policy recieved not from fwd hosts +MAILCOW_WHITE_EXCLUDE { + expression = "^MAILCOW_WHITE & (-DMARC_POLICY_REJECT | -DMARC_POLICY_QUARANTINE | -R_SPF_PERMFAIL) & !WHITELISTED_FWD_HOST"; +} +# Spoofed header from and broken policy (excluding sieve host, rspamd host, whitelisted senders, authenticated senders and forward hosts) +SPOOFED_UNAUTH { + expression = "!MAILCOW_AUTH & !MAILCOW_WHITE & !RSPAMD_HOST & !SIEVE_HOST & MAILCOW_DOMAIN_HEADER_FROM & !WHITELISTED_FWD_HOST & -g+:policies"; + score = 50.0; +} +# Only apply to inbound unauthed and not whitelisted +OLEFY_MACRO { + expression = "!MAILCOW_AUTH & !MAILCOW_WHITE & OLETOOLS"; + score = 20.0; + policy = "remove_weight"; +} +# Applies to a content filter map +BAD_WORD_BAD_TLD { + expression = "FISHY_TLD & ( BAD_WORDS | BAD_WORDS_DE )"; + score = 10.0; +} +# Forged with bad policies and not fwd host, keep bad policy symbols +FORGED_W_BAD_POLICY { + expression = "( -g+:policies | -R_SPF_NA) & ( ~FROM_NEQ_ENVFROM | ~FORGED_SENDER ) & !WHITELISTED_FWD_HOST & !DMARC_POLICY_ALLOW"; + score = 3.0; +} +# Keep negative (good) scores for rbl, policies and hfilter, disable neural group +WL_FWD_HOST { + expression = "-WHITELISTED_FWD_HOST & (^g+:rbl | ^g+:policies | ^g+:hfilter | ^g:neural)"; +} +# Exclude X-Spam like flags from scoring from fwd and sieve hosts +UPSTREAM_CHECKS_EXCLUDE_FWD_HOST { + expression = "(-SIEVE_HOST | -WHITELISTED_FWD_HOST) & (^UNITEDINTERNET_SPAM | ^SPAM_FLAG | ^KLMS_SPAM | ^AOL_SPAM | ^MICROSOFT_SPAM)"; +} +# Remove fuzzy group from bounces +BOUNCE_FUZZY { + expression = "-BOUNCE & ^g+:fuzzy"; +} +# Remove bayes ham if fuzzy denied +FUZZY_HAM_MISMATCH { + expression = "( -FUZZY_DENIED | -MAILCOW_FUZZY_DENIED | -LOCAL_FUZZY_DENIED ) & ( ^BAYES_HAM | ^NEURAL_HAM_LONG | ^NEURAL_HAM_SHORT )"; +} +# Remove bayes spam if local fuzzy white +FUZZY_SPAM_MISMATCH { + expression = "( -LOCAL_FUZZY_WHITE ) & ( ^BAYES_SPAM | ^NEURAL_SPAM_LONG | ^NEURAL_SPAM_SHORT )"; +} +WL_FWD_HOST { + expression = "-WHITELISTED_FWD_HOST & (^g+:rbl | ^g+:policies | ^g+:hfilter | ^g:neural)"; +} +ENCRYPTED_CHAT { + expression = "CHAT_VERSION_HEADER & ENCRYPTED_PGP"; +} + +CLAMD_SPAM_FOUND { + expression = "CLAM_SECI_SPAM & !MAILCOW_WHITE"; + description = "Probably Spam, Securite Spam Flag set through ClamAV"; + score = 5; +} + +CLAMD_BAD_PDF { + expression = "CLAM_SECI_PDF & !MAILCOW_WHITE"; + description = "Bad PDF Found, Securite bad PDF Flag set through ClamAV"; + score = 8; +} + +CLAMD_BAD_JPG { + expression = "CLAM_SECI_JPG & !MAILCOW_WHITE"; + description = "Bad JPG Found, Securite bad JPG Flag set through ClamAV"; + score = 8; +} + +CLAMD_ASCII_MALWARE { + expression = "CLAM_SECI_ASCII & !MAILCOW_WHITE"; + description = "ASCII malware found, Securite ASCII malware Flag set through ClamAV"; + score = 8; +} + +CLAMD_HTML_MALWARE { + expression = "CLAM_SECI_HTML & !MAILCOW_WHITE"; + description = "HTML malware found, Securite HTML malware Flag set through ClamAV"; + score = 8; +} + +CLAMD_JS_MALWARE { + expression = "CLAM_SECI_JS & !MAILCOW_WHITE"; + description = "JS malware found, Securite JS malware Flag set through ClamAV"; + score = 8; +} diff --git a/Stable2.0/conf/local.d/dkim_signing.conf b/Stable2.0/conf/local.d/dkim_signing.conf new file mode 100644 index 0000000..4fac27f --- /dev/null +++ b/Stable2.0/conf/local.d/dkim_signing.conf @@ -0,0 +1,35 @@ +# If false, messages with empty envelope from are not signed +allow_envfrom_empty = true; +# If true, envelope/header domain mismatch is ignored +allow_hdrfrom_mismatch = true; +# If true, multiple from headers are allowed (but only first is used) +allow_hdrfrom_multiple = true; +# If true, username does not need to contain matching domain +allow_username_mismatch = true; +# If false, messages from authenticated users are not selected for signing +sign_authenticated = true; +# Default path to key, can include '$domain' and '$selector' variables +path = "/data/dkim/keys/$domain.dkim"; +# Default selector to use +selector = "dkim"; +# If false, messages from local networks are not selected for signing +sign_local = true; +# Symbol to add when message is signed +symbol = "DKIM_SIGNED"; +# Whether to fallback to global config +try_fallback = true; +# Domain to use for DKIM signing: can be "header" or "envelope" +use_domain = "envelope"; +# Whether to normalise domains to eSLD +use_esld = false; +# Whether to get keys from Redis +use_redis = true; +# Hash for DKIM keys in Redis +key_prefix = "DKIM_PRIV_KEYS"; +# Selector map +selector_prefix = "DKIM_SELECTORS"; +# Sieve is in sign_networks only +# forwards are arc signed, rejects are dkim signed +sign_networks = "/etc/rspamd/custom/dovecot_trusted.map"; +use_domain_sign_networks = "header"; +sign_headers = "from:sender:reply-to:subject:date:message-id:to:cc:mime-version:content-type:content-transfer-encoding:content-language:resent-to:resent-cc:resent-from:resent-sender:resent-message-id:in-reply-to:references:list-id:list-help:list-owner:list-unsubscribe:list-subscribe:list-post:list-unsubscribe-post:disposition-notification-to:disposition-notification-options:original-recipient:openpgp:autocrypt"; diff --git a/Stable2.0/conf/local.d/external_services.conf b/Stable2.0/conf/local.d/external_services.conf new file mode 100644 index 0000000..2b091ff --- /dev/null +++ b/Stable2.0/conf/local.d/external_services.conf @@ -0,0 +1,12 @@ +oletools { + # default olefy settings + servers = "olefy:10055"; + # needs to be set explicitly for Rspamd < 1.9.5 + scan_mime_parts = true; + # mime-part regex matching in content-type or filename + # block all macros + extended = true; + max_size = 3145728; + timeout = 20.0; + retransmits = 1; +} diff --git a/Stable2.0/conf/local.d/force_actions.conf b/Stable2.0/conf/local.d/force_actions.conf new file mode 100644 index 0000000..a1b9899 --- /dev/null +++ b/Stable2.0/conf/local.d/force_actions.conf @@ -0,0 +1,12 @@ +rules { + WHITELIST_FORWARDING_HOST_NO_REJECT { + action = "add header"; + expression = "WHITELISTED_FWD_HOST"; + require_action = ["reject"]; + } + WHITELIST_FORWARDING_HOST_NO_GREYLIST { + action = "no action"; + expression = "WHITELISTED_FWD_HOST"; + require_action = ["greylist", "soft reject"]; + } +} diff --git a/Stable2.0/conf/local.d/fuzzy_check.conf b/Stable2.0/conf/local.d/fuzzy_check.conf new file mode 100644 index 0000000..855e8d0 --- /dev/null +++ b/Stable2.0/conf/local.d/fuzzy_check.conf @@ -0,0 +1,54 @@ +rule "local" { + # Fuzzy storage server list + servers = "localhost:11445"; + # Default symbol for unknown flags + symbol = "LOCAL_FUZZY_UNKNOWN"; + # Additional mime types to store/check + mime_types = ["application/*"]; + # Hash weight threshold for all maps + max_score = 100.0; + # Whether we can learn this storage + read_only = no; + # Ignore unknown flags + skip_unknown = yes; + # Hash generation algorithm + algorithm = "mumhash"; + + # Map flags to symbols + fuzzy_map = { + LOCAL_FUZZY_DENIED { + max_score = 10.0; + flag = 11; + } + LOCAL_FUZZY_WHITE { + max_score = 5.0; + flag = 13; + } + } +} + +rule "mailcow" { + # Fuzzy storage server list + servers = "fuzzy.mailcow.email:11445"; + # Default symbol for unknown flags + symbol = "MAILCOW_FUZZY_UNKNOWN"; + # Additional mime types to store/check + mime_types = ["application/*"]; + # Hash weight threshold for all maps + max_score = 100.0; + # Whether we can learn this storage + read_only = yes; + # Ignore unknown flags + skip_unknown = yes; + # Hash generation algorithm + algorithm = "mumhash"; + # Encrypt connection + encryption_key = "oa7xjgdr9u7w3hq1xbttas6brgau8qc17yi7ur5huaeq6paq8h4y"; + # Map flags to symbols + fuzzy_map = { + MAILCOW_FUZZY_DENIED { + max_score = 10.0; + flag = 11; + } + } +} diff --git a/Stable2.0/conf/local.d/fuzzy_group.conf b/Stable2.0/conf/local.d/fuzzy_group.conf new file mode 100644 index 0000000..561ac4e --- /dev/null +++ b/Stable2.0/conf/local.d/fuzzy_group.conf @@ -0,0 +1,17 @@ +symbols = { + "LOCAL_FUZZY_UNKNOWN" { + weight = 0.1; + } + "LOCAL_FUZZY_DENIED" { + weight = 15.0; + } + "MAILCOW_FUZZY_UNKNOWN" { + weight = 0.1; + } + "MAILCOW_FUZZY_DENIED" { + weight = 7.0; + } + "LOCAL_FUZZY_WHITE" { + weight = -10.0; + } +} diff --git a/Stable2.0/conf/local.d/greylist.conf b/Stable2.0/conf/local.d/greylist.conf new file mode 100644 index 0000000..c43c907 --- /dev/null +++ b/Stable2.0/conf/local.d/greylist.conf @@ -0,0 +1,4 @@ +whitelisted_ip = "http://nginx:8081/forwardinghosts.php"; +ipv4_mask = 24; +ipv6_mask = 64; +message = "Greylisted, please try again later"; diff --git a/Stable2.0/conf/local.d/groups.conf b/Stable2.0/conf/local.d/groups.conf new file mode 100644 index 0000000..f77d8a4 --- /dev/null +++ b/Stable2.0/conf/local.d/groups.conf @@ -0,0 +1,59 @@ +symbols { + "MAILCOW_AUTH" { + description = "mailcow authenticated"; + score = -20.0; + } + "CTYPE_MIXED_BOGUS" { + score = 0.0; + } + "BAD_REP_POLICIES" { + score = 2.0; + } + "BAD_HEADER" { + score = 10.0; + } + "BULK_HEADER" { + score = 4.0; + } + "ENCRYPTED_CHAT" { + score = -20.0; + } + "SOGO_CONTACT" { + score = -99.0; + } +} + +group "MX" { + "MX_INVALID" { + score = 0.5; + description = "No connectable MX"; + one_shot = true; + } + "MX_MISSING" { + score = 2.0; + description = "No MX record"; + one_shot = true; + } + "MX_GOOD" { + score = -0.01; + description = "MX was ok"; + one_shot = true; + } +} + +group "reputation" { + symbols = { + "IP_REPUTATION_HAM" { + weight = 1.0; + } + "IP_REPUTATION_SPAM" { + weight = 4.0; + } + "SENDER_REP_HAM" { + weight = 1.0; + } + "SENDER_REP_SPAM" { + weight = 2.0; + } + } +} diff --git a/Stable2.0/conf/local.d/headers_group.conf b/Stable2.0/conf/local.d/headers_group.conf new file mode 100644 index 0000000..1df92b5 --- /dev/null +++ b/Stable2.0/conf/local.d/headers_group.conf @@ -0,0 +1,7 @@ +symbols = { + "R_MIXED_CHARSET" { + weight = 1.0; + description = "Mixed characters in a message"; + one_shot = true; + } +} diff --git a/Stable2.0/conf/local.d/hfilter_group.conf b/Stable2.0/conf/local.d/hfilter_group.conf new file mode 100644 index 0000000..3c908c5 --- /dev/null +++ b/Stable2.0/conf/local.d/hfilter_group.conf @@ -0,0 +1,5 @@ +symbols = { + "HFILTER_HOSTNAME_UNKNOWN" { + score = 8.5; + } +} diff --git a/Stable2.0/conf/local.d/history_redis.conf b/Stable2.0/conf/local.d/history_redis.conf new file mode 100644 index 0000000..68a59b0 --- /dev/null +++ b/Stable2.0/conf/local.d/history_redis.conf @@ -0,0 +1 @@ +nrows = 1000; diff --git a/Stable2.0/conf/local.d/metadata_exporter.conf b/Stable2.0/conf/local.d/metadata_exporter.conf new file mode 100644 index 0000000..daaa79b --- /dev/null +++ b/Stable2.0/conf/local.d/metadata_exporter.conf @@ -0,0 +1,72 @@ +rules { + QUARANTINE { + backend = "http"; + url = "http://nginx:9081/pipe.php"; + selector = "reject_no_global_bl"; + formatter = "default"; + meta_headers = true; + } + RLINFO { + backend = "http"; + url = "http://nginx:9081/pipe_rl.php"; + selector = "ratelimited"; + formatter = "json"; + } + PUSHOVERMAIL { + backend = "http"; + url = "http://nginx:9081/pushover.php"; + selector = "mailcow_rcpt"; + formatter = "json"; + meta_headers = true; + } +} + +custom_select { + mailcow_rcpt = < substr($email, 0, $a), 'domain' => substr(substr($email, $a), 1)); +} +if (!function_exists('getallheaders')) { + function getallheaders() { + if (!is_array($_SERVER)) { + return array(); + } + $headers = array(); + foreach ($_SERVER as $name => $value) { + if (substr($name, 0, 5) == 'HTTP_') { + $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value; + } + } + return $headers; + } +} + +$raw_data_content = file_get_contents('php://input'); +$raw_data = mb_convert_encoding($raw_data_content, 'HTML-ENTITIES', "UTF-8"); +$headers = getallheaders(); + +$qid = $headers['X-Rspamd-Qid']; +$fuzzy = $headers['X-Rspamd-Fuzzy']; +$subject = iconv_mime_decode($headers['X-Rspamd-Subject']); +$score = $headers['X-Rspamd-Score']; +$rcpts = $headers['X-Rspamd-Rcpt']; +$user = $headers['X-Rspamd-User']; +$ip = $headers['X-Rspamd-Ip']; +$action = $headers['X-Rspamd-Action']; +$sender = $headers['X-Rspamd-From']; +$symbols = $headers['X-Rspamd-Symbols']; + +$raw_size = (int)$_SERVER['CONTENT_LENGTH']; + +if (empty($sender)) { + error_log("QUARANTINE: Unknown sender, assuming empty-env-from@localhost" . PHP_EOL); + $sender = 'empty-env-from@localhost'; +} + +if ($fuzzy == 'unknown') { + $fuzzy = '[]'; +} + +try { + $max_size = (int)$redis->Get('Q_MAX_SIZE'); + if (($max_size * 1048576) < $raw_size) { + error_log(sprintf("QUARANTINE: Message too large: %d b exceeds %d b", $raw_size, ($max_size * 1048576)) . PHP_EOL); + http_response_code(505); + exit; + } + if ($exclude_domains = $redis->Get('Q_EXCLUDE_DOMAINS')) { + $exclude_domains = json_decode($exclude_domains, true); + } + $retention_size = (int)$redis->Get('Q_RETENTION_SIZE'); +} +catch (RedisException $e) { + error_log("QUARANTINE: " . $e . PHP_EOL); + http_response_code(504); + exit; +} + +$rcpt_final_mailboxes = array(); + +// Loop through all rcpts +foreach (json_decode($rcpts, true) as $rcpt) { + // Remove tag + $rcpt = preg_replace('/^(.*?)\+.*(@.*)$/', '$1$2', $rcpt); + + // Break rcpt into local part and domain part + $parsed_rcpt = parse_email($rcpt); + + // Skip if not a mailcow handled domain + try { + if (!$redis->hGet('DOMAIN_MAP', $parsed_rcpt['domain'])) { + continue; + } + } + catch (RedisException $e) { + error_log("QUARANTINE: " . $e . PHP_EOL); + http_response_code(504); + exit; + } + + // Skip if domain is excluded + if (in_array($parsed_rcpt['domain'], $exclude_domains)) { + error_log(sprintf("QUARANTINE: Skipped domain %s", $parsed_rcpt['domain']) . PHP_EOL); + continue; + } + + // Always assume rcpt is not a final mailbox but an alias for a mailbox or further aliases + // + // rcpt + // | + // mailbox <-- goto ---> alias1, alias2, mailbox2 + // | | + // mailbox3 | + // | + // alias3 ---> mailbox4 + // + try { + $stmt = $pdo->prepare("SELECT `goto` FROM `alias` WHERE `address` = :rcpt AND `active` = '1'"); + $stmt->execute(array( + ':rcpt' => $rcpt + )); + $gotos = $stmt->fetch(PDO::FETCH_ASSOC)['goto']; + if (empty($gotos)) { + $stmt = $pdo->prepare("SELECT `goto` FROM `alias` WHERE `address` = :rcpt AND `active` = '1'"); + $stmt->execute(array( + ':rcpt' => '@' . $parsed_rcpt['domain'] + )); + $gotos = $stmt->fetch(PDO::FETCH_ASSOC)['goto']; + } + if (empty($gotos)) { + $stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :rcpt AND `active` = '1'"); + $stmt->execute(array(':rcpt' => $parsed_rcpt['domain'])); + $goto_branch = $stmt->fetch(PDO::FETCH_ASSOC)['target_domain']; + if ($goto_branch) { + $gotos = $parsed_rcpt['local'] . '@' . $goto_branch; + } + } + $gotos_array = explode(',', $gotos); + + $loop_c = 0; + + while (count($gotos_array) != 0 && $loop_c <= 20) { + + // Loop through all found gotos + foreach ($gotos_array as $index => &$goto) { + error_log("RCPT RESOVLER: http pipe: query " . $goto . " as username from mailbox" . PHP_EOL); + $stmt = $pdo->prepare("SELECT `username` FROM `mailbox` WHERE `username` = :goto AND (`active`= '1' OR `active`= '2');"); + $stmt->execute(array(':goto' => $goto)); + $username = $stmt->fetch(PDO::FETCH_ASSOC)['username']; + if (!empty($username)) { + error_log("RCPT RESOVLER: http pipe: mailbox found: " . $username . PHP_EOL); + // Current goto is a mailbox, save to rcpt_final_mailboxes if not a duplicate + if (!in_array($username, $rcpt_final_mailboxes)) { + $rcpt_final_mailboxes[] = $username; + } + } + else { + $parsed_goto = parse_email($goto); + if (!$redis->hGet('DOMAIN_MAP', $parsed_goto['domain'])) { + error_log("RCPT RESOVLER:" . $goto . " is not a mailcow handled mailbox or alias address" . PHP_EOL); + } + else { + $stmt = $pdo->prepare("SELECT `goto` FROM `alias` WHERE `address` = :goto AND `active` = '1'"); + $stmt->execute(array(':goto' => $goto)); + $goto_branch = $stmt->fetch(PDO::FETCH_ASSOC)['goto']; + if ($goto_branch) { + error_log("RCPT RESOVLER: http pipe: goto address " . $goto . " is an alias branch for " . $goto_branch . PHP_EOL); + $goto_branch_array = explode(',', $goto_branch); + } else { + $stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :domain AND `active` AND '1'"); + $stmt->execute(array(':domain' => $parsed_goto['domain'])); + $goto_branch = $stmt->fetch(PDO::FETCH_ASSOC)['target_domain']; + if ($goto_branch) { + error_log("RCPT RESOVLER: http pipe: goto domain " . $parsed_goto['domain'] . " is a domain alias branch for " . $goto_branch . PHP_EOL); + $goto_branch_array = array($parsed_goto['local'] . '@' . $goto_branch); + } + } + } + } + // goto item was processed, unset + unset($gotos_array[$index]); + } + + // Merge goto branch array derived from previous loop (if any), filter duplicates and unset goto branch array + if (!empty($goto_branch_array)) { + $gotos_array = array_unique(array_merge($gotos_array, $goto_branch_array)); + unset($goto_branch_array); + } + + // Reindex array + $gotos_array = array_values($gotos_array); + + // Force exit if loop cannot be solved + // Postfix does not allow for alias loops, so this should never happen. + $loop_c++; + error_log("RCPT RESOVLER: http pipe: goto array count on loop #". $loop_c . " is " . count($gotos_array) . PHP_EOL); + } + } + catch (PDOException $e) { + error_log("RCPT RESOVLER: " . $e->getMessage() . PHP_EOL); + http_response_code(502); + exit; + } +} + +foreach ($rcpt_final_mailboxes as $rcpt_final) { + error_log("QUARANTINE: quarantine pipe: processing quarantine message for rcpt " . $rcpt_final . PHP_EOL); + try { + $stmt = $pdo->prepare("INSERT INTO `quarantine` (`qid`, `subject`, `score`, `sender`, `rcpt`, `symbols`, `user`, `ip`, `msg`, `action`, `fuzzy_hashes`) + VALUES (:qid, :subject, :score, :sender, :rcpt, :symbols, :user, :ip, :msg, :action, :fuzzy_hashes)"); + $stmt->execute(array( + ':qid' => $qid, + ':subject' => $subject, + ':score' => $score, + ':sender' => $sender, + ':rcpt' => $rcpt_final, + ':symbols' => $symbols, + ':user' => $user, + ':ip' => $ip, + ':msg' => $raw_data, + ':action' => $action, + ':fuzzy_hashes' => $fuzzy + )); + $stmt = $pdo->prepare('DELETE FROM `quarantine` WHERE `rcpt` = :rcpt AND `id` NOT IN ( + SELECT `id` + FROM ( + SELECT `id` + FROM `quarantine` + WHERE `rcpt` = :rcpt2 + ORDER BY id DESC + LIMIT :retention_size + ) x + );'); + $stmt->execute(array( + ':rcpt' => $rcpt_final, + ':rcpt2' => $rcpt_final, + ':retention_size' => $retention_size + )); + } + catch (PDOException $e) { + error_log("QUARANTINE: " . $e->getMessage() . PHP_EOL); + http_response_code(503); + exit; + } +} + diff --git a/Stable2.0/conf/meta_exporter/pipe_rl.php b/Stable2.0/conf/meta_exporter/pipe_rl.php new file mode 100644 index 0000000..0bb1b31 --- /dev/null +++ b/Stable2.0/conf/meta_exporter/pipe_rl.php @@ -0,0 +1,48 @@ +connect(getenv('REDIS_SLAVEOF_IP'), getenv('REDIS_SLAVEOF_PORT')); + } + else { + $redis->connect('redis-mailcow', 6379); + } +} +catch (Exception $e) { + exit; +} + +$raw_data_content = file_get_contents('php://input'); +$raw_data_decoded = json_decode($raw_data_content, true); + +$data['time'] = time(); +$data['rcpt'] = implode(', ', $raw_data_decoded['rcpt']); +$data['from'] = $raw_data_decoded['from']; +$data['user'] = $raw_data_decoded['user']; +$symbol_rl_key = array_search('RATELIMITED', array_column($raw_data_decoded['symbols'], 'name')); +$data['rl_info'] = implode($raw_data_decoded['symbols'][$symbol_rl_key]['options']); +preg_match('/(.+)\((.+)\)/i', $data['rl_info'], $rl_matches); +if (!empty($rl_matches[1]) && !empty($rl_matches[2])) { + $data['rl_name'] = $rl_matches[1]; + $data['rl_hash'] = $rl_matches[2]; +} +else { + $data['rl_name'] = 'err'; + $data['rl_hash'] = 'err'; +} +$data['qid'] = $raw_data_decoded['qid']; +$data['ip'] = $raw_data_decoded['ip']; +$data['message_id'] = $raw_data_decoded['message_id']; +$data['header_subject'] = implode(' ', $raw_data_decoded['header_subject']); +$data['header_from'] = implode(', ', $raw_data_decoded['header_from']); + +$redis->lpush('RL_LOG', json_encode($data)); +exit; + diff --git a/Stable2.0/conf/meta_exporter/pushover.php b/Stable2.0/conf/meta_exporter/pushover.php new file mode 100644 index 0000000..d6d01e9 --- /dev/null +++ b/Stable2.0/conf/meta_exporter/pushover.php @@ -0,0 +1,275 @@ + PDO::ERRMODE_EXCEPTION, + PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, + PDO::ATTR_EMULATE_PREPARES => false, +]; +try { + $pdo = new PDO($dsn, $database_user, $database_pass, $opt); +} +catch (PDOException $e) { + error_log("NOTIFY: " . $e . PHP_EOL); + http_response_code(501); + exit; +} +// Init Redis +$redis = new Redis(); +$redis->connect('redis-mailcow', 6379); + +// Functions +function parse_email($email) { + if(!filter_var($email, FILTER_VALIDATE_EMAIL)) return false; + $a = strrpos($email, '@'); + return array('local' => substr($email, 0, $a), 'domain' => substr(substr($email, $a), 1)); +} +if (!function_exists('getallheaders')) { + function getallheaders() { + if (!is_array($_SERVER)) { + return array(); + } + $headers = array(); + foreach ($_SERVER as $name => $value) { + if (substr($name, 0, 5) == 'HTTP_') { + $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value; + } + } + return $headers; + } +} + +$headers = getallheaders(); +$json_body = json_decode(file_get_contents('php://input')); + +$qid = $headers['X-Rspamd-Qid']; +$rcpts = $headers['X-Rspamd-Rcpt']; +$sender = $headers['X-Rspamd-From']; +$ip = $headers['X-Rspamd-Ip']; +$subject = iconv_mime_decode($headers['X-Rspamd-Subject']); +$messageid= $json_body->message_id; +$priority = 0; + +$symbols_array = json_decode($headers['X-Rspamd-Symbols'], true); +if (is_array($symbols_array)) { + foreach ($symbols_array as $symbol) { + if ($symbol['name'] == 'HAS_X_PRIO_ONE') { + $priority = 1; + break; + } + } +} + +$sender_address = $json_body->header_from[0]; +$sender_name = '-'; +if (preg_match('/(?.*?)<(?
.*?)>/i', $sender_address, $matches)) { + $sender_address = $matches['address']; + $sender_name = trim($matches['name'], '"\' '); +} + +$to_address = $json_body->header_to[0]; +$to_name = '-'; +if (preg_match('/(?.*?)<(?
.*?)>/i', $to_address, $matches)) { + $to_address = $matches['address']; + $to_name = trim($matches['name'], '"\' '); +} + +$rcpt_final_mailboxes = array(); + +// Loop through all rcpts +foreach (json_decode($rcpts, true) as $rcpt) { + // Remove tag + $rcpt = preg_replace('/^(.*?)\+.*(@.*)$/', '$1$2', $rcpt); + + // Break rcpt into local part and domain part + $parsed_rcpt = parse_email($rcpt); + + // Skip if not a mailcow handled domain + try { + if (!$redis->hGet('DOMAIN_MAP', $parsed_rcpt['domain'])) { + continue; + } + } + catch (RedisException $e) { + error_log("NOTIFY: " . $e . PHP_EOL); + http_response_code(504); + exit; + } + + // Always assume rcpt is not a final mailbox but an alias for a mailbox or further aliases + // + // rcpt + // | + // mailbox <-- goto ---> alias1, alias2, mailbox2 + // | | + // mailbox3 | + // | + // alias3 ---> mailbox4 + // + try { + $stmt = $pdo->prepare("SELECT `goto` FROM `alias` WHERE `address` = :rcpt AND `active` = '1'"); + $stmt->execute(array( + ':rcpt' => $rcpt + )); + $gotos = $stmt->fetch(PDO::FETCH_ASSOC)['goto']; + if (empty($gotos)) { + $stmt = $pdo->prepare("SELECT `goto` FROM `alias` WHERE `address` = :rcpt AND `active` = '1'"); + $stmt->execute(array( + ':rcpt' => '@' . $parsed_rcpt['domain'] + )); + $gotos = $stmt->fetch(PDO::FETCH_ASSOC)['goto']; + } + if (empty($gotos)) { + $stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :rcpt AND `active` = '1'"); + $stmt->execute(array(':rcpt' => $parsed_rcpt['domain'])); + $goto_branch = $stmt->fetch(PDO::FETCH_ASSOC)['target_domain']; + if ($goto_branch) { + $gotos = $parsed_rcpt['local'] . '@' . $goto_branch; + } + } + $gotos_array = explode(',', $gotos); + + $loop_c = 0; + + while (count($gotos_array) != 0 && $loop_c <= 20) { + + // Loop through all found gotos + foreach ($gotos_array as $index => &$goto) { + error_log("RCPT RESOVLER: http pipe: query " . $goto . " as username from mailbox" . PHP_EOL); + $stmt = $pdo->prepare("SELECT `username` FROM `mailbox` WHERE `username` = :goto AND (`active`= '1' OR `active`= '2');"); + $stmt->execute(array(':goto' => $goto)); + $username = $stmt->fetch(PDO::FETCH_ASSOC)['username']; + if (!empty($username)) { + error_log("RCPT RESOVLER: http pipe: mailbox found: " . $username . PHP_EOL); + // Current goto is a mailbox, save to rcpt_final_mailboxes if not a duplicate + if (!in_array($username, $rcpt_final_mailboxes)) { + $rcpt_final_mailboxes[] = $username; + } + } + else { + $parsed_goto = parse_email($goto); + if (!$redis->hGet('DOMAIN_MAP', $parsed_goto['domain'])) { + error_log("RCPT RESOVLER:" . $goto . " is not a mailcow handled mailbox or alias address" . PHP_EOL); + } + else { + $stmt = $pdo->prepare("SELECT `goto` FROM `alias` WHERE `address` = :goto AND `active` = '1'"); + $stmt->execute(array(':goto' => $goto)); + $goto_branch = $stmt->fetch(PDO::FETCH_ASSOC)['goto']; + if ($goto_branch) { + error_log("RCPT RESOVLER: http pipe: goto address " . $goto . " is an alias branch for " . $goto_branch . PHP_EOL); + $goto_branch_array = explode(',', $goto_branch); + } else { + $stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :domain AND `active` AND '1'"); + $stmt->execute(array(':domain' => $parsed_goto['domain'])); + $goto_branch = $stmt->fetch(PDO::FETCH_ASSOC)['target_domain']; + if ($goto_branch) { + error_log("RCPT RESOVLER: http pipe: goto domain " . $parsed_goto['domain'] . " is a domain alias branch for " . $goto_branch . PHP_EOL); + $goto_branch_array = array($parsed_goto['local'] . '@' . $goto_branch); + } + } + } + } + // goto item was processed, unset + unset($gotos_array[$index]); + } + + // Merge goto branch array derived from previous loop (if any), filter duplicates and unset goto branch array + if (!empty($goto_branch_array)) { + $gotos_array = array_unique(array_merge($gotos_array, $goto_branch_array)); + unset($goto_branch_array); + } + + // Reindex array + $gotos_array = array_values($gotos_array); + + // Force exit if loop cannot be solved + // Postfix does not allow for alias loops, so this should never happen. + $loop_c++; + error_log("RCPT RESOVLER: http pipe: goto array count on loop #". $loop_c . " is " . count($gotos_array) . PHP_EOL); + } + } + catch (PDOException $e) { + error_log("RCPT RESOVLER: " . $e->getMessage() . PHP_EOL); + http_response_code(502); + exit; + } +} + + +foreach ($rcpt_final_mailboxes as $rcpt_final) { + error_log("NOTIFY: pushover pipe: processing pushover message for rcpt " . $rcpt_final . PHP_EOL); + $stmt = $pdo->prepare("SELECT * FROM `pushover` + WHERE `username` = :username AND `active` = '1'"); + $stmt->execute(array( + ':username' => $rcpt_final + )); + $api_data = $stmt->fetch(PDO::FETCH_ASSOC); + if (isset($api_data['key']) && isset($api_data['token'])) { + $title = (!empty($api_data['title'])) ? $api_data['title'] : 'Mail'; + $text = (!empty($api_data['text'])) ? $api_data['text'] : 'You\'ve got mail šŸ“§'; + $attributes = json_decode($api_data['attributes'], true); + $senders = explode(',', $api_data['senders']); + $senders = array_filter($senders); + $senders_regex = $api_data['senders_regex']; + $sender_validated = false; + if (empty($senders) && empty($senders_regex)) { + $sender_validated = true; + } + else { + if (!empty($senders)) { + if (in_array($sender, $senders)) { + $sender_validated = true; + } + } + if (!empty($senders_regex) && $sender_validated !== true) { + if (preg_match($senders_regex, $sender)) { + $sender_validated = true; + } + } + } + if ($sender_validated === false) { + error_log("NOTIFY: pushover pipe: skipping unwanted sender " . $sender); + continue; + } + if ($attributes['only_x_prio'] == "1" && $priority == 0) { + error_log("NOTIFY: pushover pipe: mail has no X-Priority: 1 header, skipping"); + continue; + } + $post_fields = array( + "token" => $api_data['token'], + "user" => $api_data['key'], + "title" => sprintf("%s", str_replace( + array('{SUBJECT}', '{SENDER}', '{SENDER_NAME}', '{SENDER_ADDRESS}', '{TO_NAME}', '{TO_ADDRESS}', '{MSG_ID}'), + array($subject, $sender, $sender_name, $sender_address, $to_name, $to_address, $messageid), $title) + ), + "priority" => $priority, + "message" => sprintf("%s", str_replace( + array('{SUBJECT}', '{SENDER}', '{SENDER_NAME}', '{SENDER_ADDRESS}', '{TO_NAME}', '{TO_ADDRESS}', '{MSG_ID}', '\n'), + array($subject, $sender, $sender_name, $sender_address, $to_name, $to_address, $messageid, PHP_EOL), $text) + ), + "sound" => $attributes['sound'] ?? "pushover" + ); + if ($attributes['evaluate_x_prio'] == "1" && $priority == 1) { + $post_fields['expire'] = 600; + $post_fields['retry'] = 120; + $post_fields['priority'] = 2; + } + curl_setopt_array($ch = curl_init(), array( + CURLOPT_URL => "https://api.pushover.net/1/messages.json", + CURLOPT_POSTFIELDS => $post_fields, + CURLOPT_SAFE_UPLOAD => true, + CURLOPT_RETURNTRANSFER => true, + )); + $result = curl_exec($ch); + $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + curl_close($ch); + error_log("NOTIFY: result: " . $httpcode . PHP_EOL); + } +} diff --git a/Stable2.0/conf/meta_exporter/vars.inc.php b/Stable2.0/conf/meta_exporter/vars.inc.php new file mode 100644 index 0000000..79566b0 --- /dev/null +++ b/Stable2.0/conf/meta_exporter/vars.inc.php @@ -0,0 +1,6 @@ + diff --git a/Stable2.0/conf/override.d/logging.inc b/Stable2.0/conf/override.d/logging.inc new file mode 100644 index 0000000..64d4064 --- /dev/null +++ b/Stable2.0/conf/override.d/logging.inc @@ -0,0 +1,5 @@ +level = "silent"; +type = "console"; +systemd = false; +.include "$CONFDIR/logging.inc" +.include(try=true; priority=20) "$CONFDIR/override.d/logging.custom.inc" diff --git a/Stable2.0/conf/override.d/ratelimit.conf b/Stable2.0/conf/override.d/ratelimit.conf new file mode 100644 index 0000000..3379149 --- /dev/null +++ b/Stable2.0/conf/override.d/ratelimit.conf @@ -0,0 +1,4 @@ +whitelisted_rcpts = "postmaster,mailer-daemon"; +max_rcpt = 25; +custom_keywords = "/etc/rspamd/lua/ratelimit.lua"; +info_symbol = "RATELIMITED"; diff --git a/Stable2.0/conf/override.d/worker-controller.inc b/Stable2.0/conf/override.d/worker-controller.inc new file mode 100644 index 0000000..8c929b1 --- /dev/null +++ b/Stable2.0/conf/override.d/worker-controller.inc @@ -0,0 +1,7 @@ +bind_socket = "*:11334"; +count = 1; +secure_ip = "127.0.0.1"; +secure_ip = "::1"; +bind_socket = "/var/lib/rspamd/rspamd.sock mode=0666 owner=nobody"; +.include(try=true; priority=10) "$CONFDIR/override.d/worker-controller-password.inc" +.include(try=true; priority=30) "$CONFDIR/override.d/worker-controller.custom.inc" diff --git a/Stable2.0/conf/override.d/worker-fuzzy.inc b/Stable2.0/conf/override.d/worker-fuzzy.inc new file mode 100644 index 0000000..291e615 --- /dev/null +++ b/Stable2.0/conf/override.d/worker-fuzzy.inc @@ -0,0 +1,12 @@ +# Socket to listen on (UDP and TCP from rspamd 1.3) +bind_socket = "*:11445"; +allow_update = ["127.0.0.1", "::1"]; +# Number of processes to serve this storage (useful for read scaling) +count = 1; +# Backend ("sqlite" or "redis" - default "sqlite") +backend = "redis"; +# Hashes storage time (3 months) +expire = 90d; +# Synchronize updates to the storage each minute +sync = 1min; + diff --git a/Stable2.0/conf/override.d/worker-normal.inc b/Stable2.0/conf/override.d/worker-normal.inc new file mode 100644 index 0000000..d206757 --- /dev/null +++ b/Stable2.0/conf/override.d/worker-normal.inc @@ -0,0 +1,4 @@ +bind_socket = "*:11333"; +task_timeout = 25s; +count = 1; +.include(try=true; priority=30) "$CONFDIR/override.d/worker-normal.custom.inc" diff --git a/Stable2.0/conf/override.d/worker-proxy.inc b/Stable2.0/conf/override.d/worker-proxy.inc new file mode 100644 index 0000000..9eb4775 --- /dev/null +++ b/Stable2.0/conf/override.d/worker-proxy.inc @@ -0,0 +1,9 @@ +bind_socket = "rspamd:9900"; +milter = true; +upstream "local" { + name = "localhost"; + default = true; + hosts = "rspamd:11333" +} +reject_message = "This message does not meet our delivery requirements"; +.include(try=true; priority=30) "$CONFDIR/override.d/worker-proxy.custom.inc" diff --git a/Stable2.0/conf/plugins.d/README.md b/Stable2.0/conf/plugins.d/README.md new file mode 100644 index 0000000..1516cf2 --- /dev/null +++ b/Stable2.0/conf/plugins.d/README.md @@ -0,0 +1 @@ +This is where you should copy any rspamd custom module diff --git a/Stable2.0/conf/rspamd.conf.local b/Stable2.0/conf/rspamd.conf.local new file mode 100644 index 0000000..9f2f8f1 --- /dev/null +++ b/Stable2.0/conf/rspamd.conf.local @@ -0,0 +1 @@ +# rspamd.conf.local diff --git a/Stable2.0/conf/rspamd.conf.override b/Stable2.0/conf/rspamd.conf.override new file mode 100644 index 0000000..d033e8e --- /dev/null +++ b/Stable2.0/conf/rspamd.conf.override @@ -0,0 +1,2 @@ +# rspamd.conf.override + diff --git a/Stable2.0/hooks/build b/Stable2.0/hooks/build new file mode 100644 index 0000000..f7670db --- /dev/null +++ b/Stable2.0/hooks/build @@ -0,0 +1,17 @@ +#!/bin/bash +# hooks/build +# https://docs.docker.com/docker-cloud/builds/advanced/ + +# $IMAGE_NAME var is injected into the build so the tag is correct. +echo "[***] Build hook running" + +VERSION=$(git ls-remote --tags -q https://github.com/rspamd/rspamd | sed -n "s/^[[:xdigit:]]\{40\}[[:blank:]]refs\/tags\/\([0-9]\{1\}\.[0-9]\{1,2\}\($\|\.[0-9]\{1,2\}$\)\)/\1/p" | sort --version-sort | tail -1) + +IMAGE_NAME=docker-rspamd + +docker build \ + --build-arg VERSION=${VERSION} \ + --build-arg COMMIT=$(git ls-remote --tags -q https://github.com/rspamd/rspamd | sed -n "s/^\([[:xdigit:]]\{40\}\)[[:blank:]]refs\/tags\/${VERSION}^{}$/\1/p" | xargs git rev-parse --short) \ + --build-arg BRANCH=$(git rev-parse --abbrev-ref HEAD) \ + --build-arg DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ") \ + -t ${IMAGE_NAME} . \ No newline at end of file diff --git a/Stable2.0/hooks/post_push b/Stable2.0/hooks/post_push new file mode 100644 index 0000000..3a3788f --- /dev/null +++ b/Stable2.0/hooks/post_push @@ -0,0 +1,9 @@ +#!/bin/bash + +VERSION=$(git ls-remote --tags -q https://github.com/rspamd/rspamd | sed -n "s/^[[:xdigit:]]\{40\}[[:blank:]]refs\/tags\/\([0-9]\{1\}\.[0-9]\{1,2\}\($\|\.[0-9]\{1,2\}$\)\)/\1/p" | sort --version-sort | tail -1) + +docker tag \ + "${IMAGE_NAME}" \ + "${DOCKER_REPO}:stable-${VERSION}" +docker push \ + "${DOCKER_REPO}:stable-${VERSION}" diff --git a/Stable2.0/rspamd.conf.local.override b/Stable2.0/rspamd.conf.local.override new file mode 100644 index 0000000..226a170 --- /dev/null +++ b/Stable2.0/rspamd.conf.local.override @@ -0,0 +1,13 @@ +options { + pidfile = false; + .include "$CONFDIR/options.inc" + .include(try=true; priority=1,duplicate=merge) "$LOCAL_CONFDIR/local.d/options.inc" + .include(try=true; priority=10) "$LOCAL_CONFDIR/override.d/options.inc" +} + +logging { + type = "console"; + .include "$CONFDIR/logging.inc" + .include(try=true; priority=1,duplicate=merge) "$LOCAL_CONFDIR/local.d/logging.inc" + .include(try=true; priority=10) "$LOCAL_CONFDIR/override.d/logging.inc" +} \ No newline at end of file diff --git a/Stable2.0/worker-controller.inc b/Stable2.0/worker-controller.inc new file mode 100644 index 0000000..2b6378a --- /dev/null +++ b/Stable2.0/worker-controller.inc @@ -0,0 +1 @@ +bind_socket = "*:11334"; diff --git a/Stable2.0/worker-proxy.inc b/Stable2.0/worker-proxy.inc new file mode 100644 index 0000000..0fe2cf0 --- /dev/null +++ b/Stable2.0/worker-proxy.inc @@ -0,0 +1 @@ +bind_socket = *:11332; From 35fad2ffcf31fbcdd8b1c3a9228e1629cf550881 Mon Sep 17 00:00:00 2001 From: Patrick Niebeling Date: Wed, 6 Nov 2024 17:17:45 +0100 Subject: [PATCH 02/20] Add No Cache Signed-off-by: Patrick Niebeling --- Stable2.0/hooks/build | 1 + 1 file changed, 1 insertion(+) diff --git a/Stable2.0/hooks/build b/Stable2.0/hooks/build index f7670db..fdce536 100644 --- a/Stable2.0/hooks/build +++ b/Stable2.0/hooks/build @@ -10,6 +10,7 @@ VERSION=$(git ls-remote --tags -q https://github.com/rspamd/rspamd | sed -n "s/^ IMAGE_NAME=docker-rspamd docker build \ + --no-cache \ --build-arg VERSION=${VERSION} \ --build-arg COMMIT=$(git ls-remote --tags -q https://github.com/rspamd/rspamd | sed -n "s/^\([[:xdigit:]]\{40\}\)[[:blank:]]refs\/tags\/${VERSION}^{}$/\1/p" | xargs git rev-parse --short) \ --build-arg BRANCH=$(git rev-parse --abbrev-ref HEAD) \ From fa36c114226fc71f7eb4b65de749cd410d5d198d Mon Sep 17 00:00:00 2001 From: Patrick Niebeling Date: Wed, 6 Nov 2024 17:37:25 +0100 Subject: [PATCH 03/20] Add Volumes Signed-off-by: Patrick Niebeling --- Stable2.0/Dockerfile | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Stable2.0/Dockerfile b/Stable2.0/Dockerfile index f5135e8..575b6ba 100644 --- a/Stable2.0/Dockerfile +++ b/Stable2.0/Dockerfile @@ -24,13 +24,20 @@ COPY worker-controller.inc /etc/rspamd/override.d/ COPY worker-proxy.inc /etc/rspamd/override.d/ # Keep database and configuration persistent +VOLUME /hooks +VOLUME /etc/rspamd/custom +VOLUME /etc/rspamd/override.d VOLUME /etc/rspamd/local.d +VOLUME /etc/rspamd/plugins.d +VOLUME /etc/rspamd/lua/ +VOLUME /etc/rspamd/rspamd.conf.local +VOLUME /etc/rspamd/rspamd.conf.override VOLUME /var/lib/rspamd # Port 11334 is for web frontend # Port 11332 is for milter # Port 11333 is for worker -EXPOSE 11332 11334 +EXPOSE 11332 11333 11334 # Healtcheck if Rspamd is returning stats HEALTHCHECK --interval=1m --timeout=5s --start-period=10s \ From 76adfdfc6ee3db453637f5dc936982b69033b997 Mon Sep 17 00:00:00 2001 From: Patrick Niebeling Date: Wed, 6 Nov 2024 17:52:14 +0100 Subject: [PATCH 04/20] Copy Config Signed-off-by: Patrick Niebeling --- Stable copy/Dockerfile | 57 ++++++++++++++++++++++++++++++++++++++++++ Stable2.0/Dockerfile | 5 ++-- 2 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 Stable copy/Dockerfile diff --git a/Stable copy/Dockerfile b/Stable copy/Dockerfile new file mode 100644 index 0000000..359677e --- /dev/null +++ b/Stable copy/Dockerfile @@ -0,0 +1,57 @@ +FROM debian:stable-slim +LABEL maintainer="gnilebein - " + +# Set apt non-interactive +ENV DEBIAN_FRONTEND noninteractive + +# Install Rspamd +RUN set -x \ + && apt update \ + && apt --no-install-recommends install -y lsb-release wget gnupg openssl ca-certificates \ + && DEBIAN_CODE_NAME=`lsb_release -c -s` \ + && wget -O - https://rspamd.com/apt-stable/gpg.key | apt-key add - \ + && echo "deb http://rspamd.com/apt-stable/ $DEBIAN_CODE_NAME main" > /etc/apt/sources.list.d/rspamd.list \ + && apt purge -y lsb-release wget gnupg \ + && apt update \ + && apt --no-install-recommends install -y rspamd \ + && apt autoremove --purge -y \ + && apt clean \ + && rm -rf /var/lib/apt/lists/* + +# Override default settings +COPY rspamd.conf.local.override /etc/rspamd/ +COPY worker-controller.inc /etc/rspamd/override.d/ +COPY worker-proxy.inc /etc/rspamd/override.d/ + +# Keep database and configuration persistent +VOLUME /etc/rspamd/local.d +VOLUME /var/lib/rspamd + +# Port 11334 is for web frontend +# Port 11332 is for milter +# Port 11333 is for worker +EXPOSE 11332 11334 + +# Healtcheck if Rspamd is returning stats +HEALTHCHECK --interval=1m --timeout=5s --start-period=10s \ + CMD /usr/bin/rspamadm control stat || exit 1 + +# Run Rspamd +ENTRYPOINT ["/usr/bin/rspamd","-f","-u","_rspamd","-g","_rspamd"] + +# Setup Labels +ARG VERSION +ARG COMMIT +ARG BRANCH +ARG DATE + +LABEL org.label-schema.name="Rspamd" \ + org.label-schema.description="Rspamd Spam Filter - STABLE" \ + org.label-schema.usage="https://hub.docker.com/r/gnilebein/rspamd/" \ + org.label-schema.url="https://rspamd.com" \ + org.label-schema.vendor="gnilebein" \ + org.label-schema.schema-version="1.0" \ + org.label-schema.version=$VERSION \ + org.label-schema.vcs-url="https://github.com/rspamd/rspamd/" \ + org.label-schema.vcs-ref=$COMMIT \ + org.label-schema.build-date=$DATE \ \ No newline at end of file diff --git a/Stable2.0/Dockerfile b/Stable2.0/Dockerfile index 575b6ba..6f2de08 100644 --- a/Stable2.0/Dockerfile +++ b/Stable2.0/Dockerfile @@ -2,7 +2,7 @@ FROM debian:stable-slim LABEL maintainer="gnilebein - " # Set apt non-interactive -ENV DEBIAN_FRONTEND noninteractive +ENV DEBIAN_FRONTEND=noninteractive # Install Rspamd RUN set -x \ @@ -19,6 +19,7 @@ RUN set -x \ && rm -rf /var/lib/apt/lists/* # Override default settings +COPY conf/* /etc/rspamd/ COPY rspamd.conf.local.override /etc/rspamd/ COPY worker-controller.inc /etc/rspamd/override.d/ COPY worker-proxy.inc /etc/rspamd/override.d/ @@ -64,4 +65,4 @@ LABEL org.label-schema.name="Rspamd" \ org.label-schema.version=$VERSION \ org.label-schema.vcs-url="https://github.com/rspamd/rspamd/" \ org.label-schema.vcs-ref=$COMMIT \ - org.label-schema.build-date=$DATE \ + org.label-schema.build-date=$DATE \ \ No newline at end of file From 0d3d892bbb165339f0e1938df78d71ebc646836a Mon Sep 17 00:00:00 2001 From: Patrick Niebeling Date: Wed, 6 Nov 2024 17:57:36 +0100 Subject: [PATCH 05/20] Extend Dockerfile Signed-off-by: Patrick Niebeling --- Stable2.0/Dockerfile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Stable2.0/Dockerfile b/Stable2.0/Dockerfile index 6f2de08..707eaf7 100644 --- a/Stable2.0/Dockerfile +++ b/Stable2.0/Dockerfile @@ -7,7 +7,7 @@ ENV DEBIAN_FRONTEND=noninteractive # Install Rspamd RUN set -x \ && apt update \ - && apt --no-install-recommends install -y lsb-release wget gnupg openssl ca-certificates \ + && apt --no-install-recommends install -y lsb-release wget gnupg openssl ca-certificates less nano grep\ && DEBIAN_CODE_NAME=`lsb_release -c -s` \ && wget -O - https://rspamd.com/apt-stable/gpg.key | apt-key add - \ && echo "deb http://rspamd.com/apt-stable/ $DEBIAN_CODE_NAME main" > /etc/apt/sources.list.d/rspamd.list \ @@ -16,7 +16,8 @@ RUN set -x \ && apt --no-install-recommends install -y rspamd \ && apt autoremove --purge -y \ && apt clean \ - && rm -rf /var/lib/apt/lists/* + && rm -rf /var/lib/apt/lists/* \ + && echo 'alias ll="ls -la --color"' >> ~/.bashrc # Override default settings COPY conf/* /etc/rspamd/ From e0d3755eed8e5b173c8ac2e3ec0a93fb74242052 Mon Sep 17 00:00:00 2001 From: Patrick Niebeling Date: Wed, 6 Nov 2024 20:50:40 +0100 Subject: [PATCH 06/20] Optimize Signed-off-by: Patrick Niebeling --- Stable copy/Dockerfile | 57 -- Stable/hooks/build | 2 + Stable2.0/Dockerfile | 22 +- Stable2.0/conf/custom/bad_asn.map | 31 - Stable2.0/conf/custom/bad_header.map | 2 - Stable2.0/conf/custom/bad_languages.map | 1 - Stable2.0/conf/custom/bad_words.map | 29 - Stable2.0/conf/custom/bad_words_de.map | 17 - Stable2.0/conf/custom/bulk_header.map | 19 - Stable2.0/conf/custom/fishy_tlds.map | 65 -- .../custom/global_mime_from_blacklist.map | 1 - .../custom/global_mime_from_whitelist.map | 1 - .../conf/custom/global_rcpt_blacklist.map | 1 - .../conf/custom/global_rcpt_whitelist.map | 1 - .../custom/global_smtp_from_blacklist.map | 1 - .../custom/global_smtp_from_whitelist.map | 1 - Stable2.0/conf/custom/ip_wl.map | 4 - Stable2.0/conf/custom/monitoring_nolog.map | 7 - Stable2.0/conf/dynmaps/aliasexp.php | 174 ----- Stable2.0/conf/dynmaps/bcc.php | 88 --- Stable2.0/conf/dynmaps/footer.php | 113 --- Stable2.0/conf/dynmaps/forwardinghosts.php | 57 -- Stable2.0/conf/dynmaps/index.html | 2 - Stable2.0/conf/dynmaps/sasl_logs.php | 2 - Stable2.0/conf/dynmaps/settings.php | 471 ------------ Stable2.0/conf/dynmaps/vars.inc.php | 6 - Stable2.0/conf/local.d/actions.conf | 3 - Stable2.0/conf/local.d/antivirus.conf | 11 - Stable2.0/conf/local.d/arc.conf | 32 - Stable2.0/conf/local.d/asn.conf | 6 - Stable2.0/conf/local.d/composites.conf | 110 --- Stable2.0/conf/local.d/dkim_signing.conf | 35 - Stable2.0/conf/local.d/external_services.conf | 12 - Stable2.0/conf/local.d/force_actions.conf | 12 - Stable2.0/conf/local.d/fuzzy_check.conf | 54 -- Stable2.0/conf/local.d/fuzzy_group.conf | 17 - Stable2.0/conf/local.d/greylist.conf | 4 - Stable2.0/conf/local.d/groups.conf | 59 -- Stable2.0/conf/local.d/headers_group.conf | 7 - Stable2.0/conf/local.d/hfilter_group.conf | 5 - Stable2.0/conf/local.d/history_redis.conf | 1 - Stable2.0/conf/local.d/metadata_exporter.conf | 72 -- Stable2.0/conf/local.d/milter_headers.conf | 43 -- Stable2.0/conf/local.d/mime_types.conf | 47 -- Stable2.0/conf/local.d/mime_types_group.conf | 7 - Stable2.0/conf/local.d/multimap.conf | 181 ----- Stable2.0/conf/local.d/mx_check.conf | 7 - Stable2.0/conf/local.d/options.inc | 9 - Stable2.0/conf/local.d/phishing.conf | 1 - Stable2.0/conf/local.d/policies_group.conf | 26 - Stable2.0/conf/local.d/ratelimit.conf | 9 - Stable2.0/conf/local.d/rbl.conf | 26 - Stable2.0/conf/local.d/rbl_group.conf | 277 ------- Stable2.0/conf/local.d/redis.conf | 2 - Stable2.0/conf/local.d/reputation.conf | 9 - Stable2.0/conf/local.d/spamassassin.conf | 1 - Stable2.0/conf/local.d/statistic.conf | 26 - Stable2.0/conf/local.d/statistics_group.conf | 10 - Stable2.0/conf/lua/ratelimit.lua | 16 - Stable2.0/conf/lua/rspamd.local.lua | 701 ------------------ Stable2.0/conf/meta_exporter/pipe.php | 260 ------- Stable2.0/conf/meta_exporter/pipe_rl.php | 48 -- Stable2.0/conf/meta_exporter/pushover.php | 275 ------- Stable2.0/conf/meta_exporter/vars.inc.php | 6 - Stable2.0/conf/override.d/logging.inc | 5 - Stable2.0/conf/override.d/ratelimit.conf | 4 - .../conf/override.d/worker-controller.inc | 7 - Stable2.0/conf/override.d/worker-fuzzy.inc | 12 - Stable2.0/conf/override.d/worker-normal.inc | 4 - Stable2.0/conf/override.d/worker-proxy.inc | 9 - Stable2.0/conf/plugins.d/README.md | 1 - Stable2.0/conf/rspamd.conf.local | 1 - Stable2.0/conf/rspamd.conf.override | 2 - Stable2.0/docker-entrypoint.sh | 267 +++++++ Stable2.0/hooks/build | 3 +- Stable2.0/set_worker_password.sh | 12 + 76 files changed, 291 insertions(+), 3638 deletions(-) delete mode 100644 Stable copy/Dockerfile delete mode 100644 Stable2.0/conf/custom/bad_asn.map delete mode 100644 Stable2.0/conf/custom/bad_header.map delete mode 100644 Stable2.0/conf/custom/bad_languages.map delete mode 100644 Stable2.0/conf/custom/bad_words.map delete mode 100644 Stable2.0/conf/custom/bad_words_de.map delete mode 100644 Stable2.0/conf/custom/bulk_header.map delete mode 100644 Stable2.0/conf/custom/fishy_tlds.map delete mode 100644 Stable2.0/conf/custom/global_mime_from_blacklist.map delete mode 100644 Stable2.0/conf/custom/global_mime_from_whitelist.map delete mode 100644 Stable2.0/conf/custom/global_rcpt_blacklist.map delete mode 100644 Stable2.0/conf/custom/global_rcpt_whitelist.map delete mode 100644 Stable2.0/conf/custom/global_smtp_from_blacklist.map delete mode 100644 Stable2.0/conf/custom/global_smtp_from_whitelist.map delete mode 100644 Stable2.0/conf/custom/ip_wl.map delete mode 100644 Stable2.0/conf/custom/monitoring_nolog.map delete mode 100644 Stable2.0/conf/dynmaps/aliasexp.php delete mode 100644 Stable2.0/conf/dynmaps/bcc.php delete mode 100644 Stable2.0/conf/dynmaps/footer.php delete mode 100644 Stable2.0/conf/dynmaps/forwardinghosts.php delete mode 100644 Stable2.0/conf/dynmaps/index.html delete mode 100644 Stable2.0/conf/dynmaps/sasl_logs.php delete mode 100644 Stable2.0/conf/dynmaps/settings.php delete mode 100644 Stable2.0/conf/dynmaps/vars.inc.php delete mode 100644 Stable2.0/conf/local.d/actions.conf delete mode 100644 Stable2.0/conf/local.d/antivirus.conf delete mode 100644 Stable2.0/conf/local.d/arc.conf delete mode 100644 Stable2.0/conf/local.d/asn.conf delete mode 100644 Stable2.0/conf/local.d/composites.conf delete mode 100644 Stable2.0/conf/local.d/dkim_signing.conf delete mode 100644 Stable2.0/conf/local.d/external_services.conf delete mode 100644 Stable2.0/conf/local.d/force_actions.conf delete mode 100644 Stable2.0/conf/local.d/fuzzy_check.conf delete mode 100644 Stable2.0/conf/local.d/fuzzy_group.conf delete mode 100644 Stable2.0/conf/local.d/greylist.conf delete mode 100644 Stable2.0/conf/local.d/groups.conf delete mode 100644 Stable2.0/conf/local.d/headers_group.conf delete mode 100644 Stable2.0/conf/local.d/hfilter_group.conf delete mode 100644 Stable2.0/conf/local.d/history_redis.conf delete mode 100644 Stable2.0/conf/local.d/metadata_exporter.conf delete mode 100644 Stable2.0/conf/local.d/milter_headers.conf delete mode 100644 Stable2.0/conf/local.d/mime_types.conf delete mode 100644 Stable2.0/conf/local.d/mime_types_group.conf delete mode 100644 Stable2.0/conf/local.d/multimap.conf delete mode 100644 Stable2.0/conf/local.d/mx_check.conf delete mode 100644 Stable2.0/conf/local.d/options.inc delete mode 100644 Stable2.0/conf/local.d/phishing.conf delete mode 100644 Stable2.0/conf/local.d/policies_group.conf delete mode 100644 Stable2.0/conf/local.d/ratelimit.conf delete mode 100644 Stable2.0/conf/local.d/rbl.conf delete mode 100644 Stable2.0/conf/local.d/rbl_group.conf delete mode 100644 Stable2.0/conf/local.d/redis.conf delete mode 100644 Stable2.0/conf/local.d/reputation.conf delete mode 100644 Stable2.0/conf/local.d/spamassassin.conf delete mode 100644 Stable2.0/conf/local.d/statistic.conf delete mode 100644 Stable2.0/conf/local.d/statistics_group.conf delete mode 100644 Stable2.0/conf/lua/ratelimit.lua delete mode 100644 Stable2.0/conf/lua/rspamd.local.lua delete mode 100644 Stable2.0/conf/meta_exporter/pipe.php delete mode 100644 Stable2.0/conf/meta_exporter/pipe_rl.php delete mode 100644 Stable2.0/conf/meta_exporter/pushover.php delete mode 100644 Stable2.0/conf/meta_exporter/vars.inc.php delete mode 100644 Stable2.0/conf/override.d/logging.inc delete mode 100644 Stable2.0/conf/override.d/ratelimit.conf delete mode 100644 Stable2.0/conf/override.d/worker-controller.inc delete mode 100644 Stable2.0/conf/override.d/worker-fuzzy.inc delete mode 100644 Stable2.0/conf/override.d/worker-normal.inc delete mode 100644 Stable2.0/conf/override.d/worker-proxy.inc delete mode 100644 Stable2.0/conf/plugins.d/README.md delete mode 100644 Stable2.0/conf/rspamd.conf.local delete mode 100644 Stable2.0/conf/rspamd.conf.override create mode 100644 Stable2.0/docker-entrypoint.sh create mode 100644 Stable2.0/set_worker_password.sh diff --git a/Stable copy/Dockerfile b/Stable copy/Dockerfile deleted file mode 100644 index 359677e..0000000 --- a/Stable copy/Dockerfile +++ /dev/null @@ -1,57 +0,0 @@ -FROM debian:stable-slim -LABEL maintainer="gnilebein - " - -# Set apt non-interactive -ENV DEBIAN_FRONTEND noninteractive - -# Install Rspamd -RUN set -x \ - && apt update \ - && apt --no-install-recommends install -y lsb-release wget gnupg openssl ca-certificates \ - && DEBIAN_CODE_NAME=`lsb_release -c -s` \ - && wget -O - https://rspamd.com/apt-stable/gpg.key | apt-key add - \ - && echo "deb http://rspamd.com/apt-stable/ $DEBIAN_CODE_NAME main" > /etc/apt/sources.list.d/rspamd.list \ - && apt purge -y lsb-release wget gnupg \ - && apt update \ - && apt --no-install-recommends install -y rspamd \ - && apt autoremove --purge -y \ - && apt clean \ - && rm -rf /var/lib/apt/lists/* - -# Override default settings -COPY rspamd.conf.local.override /etc/rspamd/ -COPY worker-controller.inc /etc/rspamd/override.d/ -COPY worker-proxy.inc /etc/rspamd/override.d/ - -# Keep database and configuration persistent -VOLUME /etc/rspamd/local.d -VOLUME /var/lib/rspamd - -# Port 11334 is for web frontend -# Port 11332 is for milter -# Port 11333 is for worker -EXPOSE 11332 11334 - -# Healtcheck if Rspamd is returning stats -HEALTHCHECK --interval=1m --timeout=5s --start-period=10s \ - CMD /usr/bin/rspamadm control stat || exit 1 - -# Run Rspamd -ENTRYPOINT ["/usr/bin/rspamd","-f","-u","_rspamd","-g","_rspamd"] - -# Setup Labels -ARG VERSION -ARG COMMIT -ARG BRANCH -ARG DATE - -LABEL org.label-schema.name="Rspamd" \ - org.label-schema.description="Rspamd Spam Filter - STABLE" \ - org.label-schema.usage="https://hub.docker.com/r/gnilebein/rspamd/" \ - org.label-schema.url="https://rspamd.com" \ - org.label-schema.vendor="gnilebein" \ - org.label-schema.schema-version="1.0" \ - org.label-schema.version=$VERSION \ - org.label-schema.vcs-url="https://github.com/rspamd/rspamd/" \ - org.label-schema.vcs-ref=$COMMIT \ - org.label-schema.build-date=$DATE \ \ No newline at end of file diff --git a/Stable/hooks/build b/Stable/hooks/build index f7670db..bff954c 100644 --- a/Stable/hooks/build +++ b/Stable/hooks/build @@ -9,6 +9,8 @@ VERSION=$(git ls-remote --tags -q https://github.com/rspamd/rspamd | sed -n "s/^ IMAGE_NAME=docker-rspamd +zip -r config + docker build \ --build-arg VERSION=${VERSION} \ --build-arg COMMIT=$(git ls-remote --tags -q https://github.com/rspamd/rspamd | sed -n "s/^\([[:xdigit:]]\{40\}\)[[:blank:]]refs\/tags\/${VERSION}^{}$/\1/p" | xargs git rev-parse --short) \ diff --git a/Stable2.0/Dockerfile b/Stable2.0/Dockerfile index 707eaf7..a4916da 100644 --- a/Stable2.0/Dockerfile +++ b/Stable2.0/Dockerfile @@ -2,12 +2,12 @@ FROM debian:stable-slim LABEL maintainer="gnilebein - " # Set apt non-interactive -ENV DEBIAN_FRONTEND=noninteractive +ENV DEBIAN_FRONTEND noninteractive # Install Rspamd RUN set -x \ && apt update \ - && apt --no-install-recommends install -y lsb-release wget gnupg openssl ca-certificates less nano grep\ + && apt --no-install-recommends install -y lsb-release wget gnupg openssl ca-certificates nano less \ && DEBIAN_CODE_NAME=`lsb_release -c -s` \ && wget -O - https://rspamd.com/apt-stable/gpg.key | apt-key add - \ && echo "deb http://rspamd.com/apt-stable/ $DEBIAN_CODE_NAME main" > /etc/apt/sources.list.d/rspamd.list \ @@ -17,23 +17,19 @@ RUN set -x \ && apt autoremove --purge -y \ && apt clean \ && rm -rf /var/lib/apt/lists/* \ - && echo 'alias ll="ls -la --color"' >> ~/.bashrc + && echo 'alias ll="ls -la --color"' >> ~/.bashrc # Override default settings -COPY conf/* /etc/rspamd/ COPY rspamd.conf.local.override /etc/rspamd/ COPY worker-controller.inc /etc/rspamd/override.d/ COPY worker-proxy.inc /etc/rspamd/override.d/ +COPY set_worker_password.sh /set_worker_password.sh +COPY docker-entrypoint.sh /docker-entrypoint.sh # Keep database and configuration persistent -VOLUME /hooks -VOLUME /etc/rspamd/custom -VOLUME /etc/rspamd/override.d VOLUME /etc/rspamd/local.d -VOLUME /etc/rspamd/plugins.d -VOLUME /etc/rspamd/lua/ -VOLUME /etc/rspamd/rspamd.conf.local -VOLUME /etc/rspamd/rspamd.conf.override +VOLUME /etc/rspamd/override.d +VOLUME /etc/rspamd/custom VOLUME /var/lib/rspamd # Port 11334 is for web frontend @@ -49,8 +45,6 @@ HEALTHCHECK --interval=1m --timeout=5s --start-period=10s \ ENTRYPOINT ["/docker-entrypoint.sh"] CMD ["/usr/bin/rspamd", "-f", "-u", "_rspamd", "-g", "_rspamd"] -STOPSIGNAL SIGTERM - # Setup Labels ARG VERSION ARG COMMIT @@ -66,4 +60,4 @@ LABEL org.label-schema.name="Rspamd" \ org.label-schema.version=$VERSION \ org.label-schema.vcs-url="https://github.com/rspamd/rspamd/" \ org.label-schema.vcs-ref=$COMMIT \ - org.label-schema.build-date=$DATE \ \ No newline at end of file + org.label-schema.build-date=$DATE \ diff --git a/Stable2.0/conf/custom/bad_asn.map b/Stable2.0/conf/custom/bad_asn.map deleted file mode 100644 index a8d49cf..0000000 --- a/Stable2.0/conf/custom/bad_asn.map +++ /dev/null @@ -1,31 +0,0 @@ -# High spam networks, disabled by default -# ASN SCORE DESC -# Remove comment to enable score -#12874 5 #Fastweb SpA, Italy -#12876 2 #ONLINE S.A.S, France -#13335 5 #Cloudflare Inc., United States -#14061 4 #DigitalOcean LLC, United States -#16276 2 #OVH SAS, France -#21100 2 #ITL LLC, Ukraine -#28753 5 #Leaseweb Deutschland GmbH, Germany -#29119 5 #ServiHosting Networks S.L., Spain -#29422 5 #Telia Inmics-Nebula Oy, Finland -#30823 3 #combahton GmbH, Germany -#31034 5 #Aruba S.p.A, Italy -#39364 4 #Hormoz IT & Network Waves Connection Co. (PJS), Iran -#42831 5 #UK Dedicated Servers Limited, United Kingdom -#43146 2 #Domain names registrar REG.RU Ltd, Russia -#44493 2 #Chelyabinsk-Signal LLC, Russia -#46606 2 #Unified Layer, United States -#49100 4 #Pishgaman Toseeh Ertebatat Company (Private Joint Stock), Iran -#49505 2 #OOO Network of data-centers Selectel, Russia -#53755 5 #Input Output Flood LLC, United States -#55293 4 #A2 Hosting Inc., United States -#61272 5 #Informacines sistemos ir technologijos - UAB, Lithuania -#62255 4 #Asmunda New Media Ltd., Seychelles -#63018 4 #Dedicated.com, United States -#197518 2 #Rackmarkt SL, Spain -#197695 2 #Domain names registrar REG.RU Ltd, Russia -#198068 2 #P.A.G.M. OU, Estonia -#201942 5 #Soltia Consulting SL, Spain -#213373 4 #IP Connect Inc \ No newline at end of file diff --git a/Stable2.0/conf/custom/bad_header.map b/Stable2.0/conf/custom/bad_header.map deleted file mode 100644 index 839c3c3..0000000 --- a/Stable2.0/conf/custom/bad_header.map +++ /dev/null @@ -1,2 +0,0 @@ -/Thread-Topic:\s[a-zA-Z]{3}\s[a-zA-Z]{2}[\s\r\n]{0,1}[^a-zA-Z0-9][\r\n]/i -/Thread-Topic:\s[a-zA-Z]{3}\s[a-zA-Z]{2}\s[a-zA-Z]{1}\s[a-zA-Z]{5}[\s\r\n]{0,1}[^a-zA-Z0-9][\r\n]/i diff --git a/Stable2.0/conf/custom/bad_languages.map b/Stable2.0/conf/custom/bad_languages.map deleted file mode 100644 index cf9ce3e..0000000 --- a/Stable2.0/conf/custom/bad_languages.map +++ /dev/null @@ -1 +0,0 @@ -# Regex! /de/ will also match /de_at/ etc. diff --git a/Stable2.0/conf/custom/bad_words.map b/Stable2.0/conf/custom/bad_words.map deleted file mode 100644 index 0d9af8b..0000000 --- a/Stable2.0/conf/custom/bad_words.map +++ /dev/null @@ -1,29 +0,0 @@ -/\serotic\s/i -/\serection\s/i -/\ssexy\s/i -/\sass\s/i -/\sviagra\s/i -/\stits\s/i -/\stitty\s/i -/\stitties\s/i -/\scum\s/i -/\ssperm\s/i -/\sslut\s/i -/\sporn\s/i -/\scock\s/i -/\spharma\s/i -/\spharmacy\s/i -/\sseo\s/i -/\sjackpot\s/i -/\slottery\s/i -/bitcoin/i -/trojaner/i -/malware/i -/\sscooter\s/i -/testost/i -/web\sdevelopment/i -/\slottery\s/i -/\ssex\s/i -/\svagina\s/i -/\spenis\s/i -/\smarketing\s/i \ No newline at end of file diff --git a/Stable2.0/conf/custom/bad_words_de.map b/Stable2.0/conf/custom/bad_words_de.map deleted file mode 100644 index ccdd586..0000000 --- a/Stable2.0/conf/custom/bad_words_de.map +++ /dev/null @@ -1,17 +0,0 @@ -/\slotto\s/i -/pillenversand/i -/\skredithilfe\s/i -/\skapital\s/i -/\skrankenversicherung\s/i -/pƤdophil/i -/paedophil/i -/freiberufler/i -/unternehmer/i -/masturbieren/i -/\sescooter\s/i -/\se-scooter\s/i -/testost/i -/\spotenz\s/i -/potenzmittel/i -/rezeptfrei/i -/apotheke/i \ No newline at end of file diff --git a/Stable2.0/conf/custom/bulk_header.map b/Stable2.0/conf/custom/bulk_header.map deleted file mode 100644 index 69a20af..0000000 --- a/Stable2.0/conf/custom/bulk_header.map +++ /dev/null @@ -1,19 +0,0 @@ -/X-EMV-Platform; .*/i -/.*nur-1-click.*/i -/.*episerver.*/i -/.*supergewinne.*/i -/List-Unsubscribe.*nbps\.eu/i -/.*regiofinder.*/i -/.*EmailSocket.*/i -/List-Unsubscribe:.*respread.*/i -/.*greenflamingo.*/i -/.*senderemailglobal.*/i -/.*promio\.net.*/i -/.*promio\.de.*/i -/.*mailer-service\.com.*/i -/.*mailer-service\.de.*/i -/.*dynamic-lht.*/i -/.*light-house-traffic.*/i -/.*newsletterplus.*/i -/.*X-Chpo.*/i -/.*List-Unsubscribe:.*@nl\..*/i diff --git a/Stable2.0/conf/custom/fishy_tlds.map b/Stable2.0/conf/custom/fishy_tlds.map deleted file mode 100644 index 1b8b2b0..0000000 --- a/Stable2.0/conf/custom/fishy_tlds.map +++ /dev/null @@ -1,65 +0,0 @@ -/.+\.accountant$/i -/.+\.art$/i -/.+\.asia$/i -/.+\.bid$/i -/.+\.biz$/i -/.+\.care$/i -/.+\.cf$/i -/.+\.click$/i -/.+\.cloud$/i -/.+\.co$/i -/.+\.construction$/i -/.+\.country$/i -/.+\.cricket$/i -/.+\.date$/i -/.+\.desi$/i -/.+\.download$/i -/.+\.estate$/i -/.+\.faith$/i -/.+\.fit$/i -/.+\.flights$/i -/.+\.ga$/i -/.+\.gdn$/i -/.+\.gq$/i -/.+\.guru$/i -/.+\.icu$/i -/.+\.id$/i -/.+\.info$/i -/.+\.in.net$/i -/.+\.ir$/i -/.+\.jetzt$/i -/.+\.kim$/i -/.+\.life$/i -/.+\.link$/i -/.+\.loan$/i -/.+\.mk$/i -/.+\.ml$/i -/.+\.ninja$/i -/.+\.online$/i -/.+\.ooo$/i -/.+\.party$/i -/.+\.pro$/i -/.+\.ps$/i -/.+\.pw$/i -/.+\.racing$/i -/.+\.review$/i -/.+\.rocks$/i -/.+\.ryukyu$/i -/.+\.science$/i -/.+\.site$/i -/.+\.space$/i -/.+\.stream$/i -/.+\.sucks$/i -/.+\.tk$/i -/.+\.top$/i -/.+\.topica\.com$/i -/.+\.town$/i -/.+\.trade$/i -/.+\.uno$/i -/.+\.vip$/i -/.+\.webcam$/i -/.+\.website$/i -/.+\.win$/i -/.+\.work$/i -/.+\.world$/i -/.+\.xyz$/i diff --git a/Stable2.0/conf/custom/global_mime_from_blacklist.map b/Stable2.0/conf/custom/global_mime_from_blacklist.map deleted file mode 100644 index 3c87288..0000000 --- a/Stable2.0/conf/custom/global_mime_from_blacklist.map +++ /dev/null @@ -1 +0,0 @@ -# /.+example\.com/i diff --git a/Stable2.0/conf/custom/global_mime_from_whitelist.map b/Stable2.0/conf/custom/global_mime_from_whitelist.map deleted file mode 100644 index 3c87288..0000000 --- a/Stable2.0/conf/custom/global_mime_from_whitelist.map +++ /dev/null @@ -1 +0,0 @@ -# /.+example\.com/i diff --git a/Stable2.0/conf/custom/global_rcpt_blacklist.map b/Stable2.0/conf/custom/global_rcpt_blacklist.map deleted file mode 100644 index 3c87288..0000000 --- a/Stable2.0/conf/custom/global_rcpt_blacklist.map +++ /dev/null @@ -1 +0,0 @@ -# /.+example\.com/i diff --git a/Stable2.0/conf/custom/global_rcpt_whitelist.map b/Stable2.0/conf/custom/global_rcpt_whitelist.map deleted file mode 100644 index 3c87288..0000000 --- a/Stable2.0/conf/custom/global_rcpt_whitelist.map +++ /dev/null @@ -1 +0,0 @@ -# /.+example\.com/i diff --git a/Stable2.0/conf/custom/global_smtp_from_blacklist.map b/Stable2.0/conf/custom/global_smtp_from_blacklist.map deleted file mode 100644 index 3c87288..0000000 --- a/Stable2.0/conf/custom/global_smtp_from_blacklist.map +++ /dev/null @@ -1 +0,0 @@ -# /.+example\.com/i diff --git a/Stable2.0/conf/custom/global_smtp_from_whitelist.map b/Stable2.0/conf/custom/global_smtp_from_whitelist.map deleted file mode 100644 index 3c87288..0000000 --- a/Stable2.0/conf/custom/global_smtp_from_whitelist.map +++ /dev/null @@ -1 +0,0 @@ -# /.+example\.com/i diff --git a/Stable2.0/conf/custom/ip_wl.map b/Stable2.0/conf/custom/ip_wl.map deleted file mode 100644 index c8bb552..0000000 --- a/Stable2.0/conf/custom/ip_wl.map +++ /dev/null @@ -1,4 +0,0 @@ -# IP whitelist -# 127.0.0.1 -# 1.2.3.4 -# ... diff --git a/Stable2.0/conf/custom/monitoring_nolog.map b/Stable2.0/conf/custom/monitoring_nolog.map deleted file mode 100644 index 0e00de7..0000000 --- a/Stable2.0/conf/custom/monitoring_nolog.map +++ /dev/null @@ -1,7 +0,0 @@ -# Skip logging for these addresses -/monitoring-system@everycloudtech\.us/i -/monitor@tools\.mailflowmonitoring\.com/i -/watchdog@localhost/i -/supertool@mxtoolbox\.com/i -/test@mxtoolboxsmtpdiag\.com/i -/open-relay-check@mailcow\.email/i diff --git a/Stable2.0/conf/dynmaps/aliasexp.php b/Stable2.0/conf/dynmaps/aliasexp.php deleted file mode 100644 index 2d75614..0000000 --- a/Stable2.0/conf/dynmaps/aliasexp.php +++ /dev/null @@ -1,174 +0,0 @@ - PDO::ERRMODE_EXCEPTION, - PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, - PDO::ATTR_EMULATE_PREPARES => false, -]; -try { - $pdo = new PDO($dsn, $database_user, $database_pass, $opt); -} -catch (PDOException $e) { - error_log("ALIASEXP: " . $e . PHP_EOL); - http_response_code(501); - exit; -} - -// Init Redis -$redis = new Redis(); -$redis->connect('redis-mailcow', 6379); - -function parse_email($email) { - if(!filter_var($email, FILTER_VALIDATE_EMAIL)) return false; - $a = strrpos($email, '@'); - return array('local' => substr($email, 0, $a), 'domain' => substr(substr($email, $a), 1)); -} -if (!function_exists('getallheaders')) { - function getallheaders() { - if (!is_array($_SERVER)) { - return array(); - } - $headers = array(); - foreach ($_SERVER as $name => $value) { - if (substr($name, 0, 5) == 'HTTP_') { - $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value; - } - } - return $headers; - } -} - -// Read headers -$headers = getallheaders(); -// Get rcpt -$rcpt = $headers['Rcpt']; -// Remove tag -$rcpt = preg_replace('/^(.*?)\+.*(@.*)$/', '$1$2', $rcpt); -// Parse email address -$parsed_rcpt = parse_email($rcpt); -// Create array of final mailboxes -$rcpt_final_mailboxes = array(); - -// Skip if not a mailcow handled domain -try { - if (!$redis->hGet('DOMAIN_MAP', $parsed_rcpt['domain'])) { - exit; - } -} -catch (RedisException $e) { - error_log("ALIASEXP: " . $e . PHP_EOL); - http_response_code(504); - exit; -} - -// Always assume rcpt is not a final mailbox but an alias for a mailbox or further aliases -// -// rcpt -// | -// mailbox <-- goto ---> alias1, alias2, mailbox2 -// | | -// mailbox3 | -// | -// alias3 ---> mailbox4 -// -try { - $stmt = $pdo->prepare("SELECT `goto` FROM `alias` WHERE `address` = :rcpt AND `active` = '1'"); - $stmt->execute(array( - ':rcpt' => $rcpt - )); - $gotos = $stmt->fetch(PDO::FETCH_ASSOC)['goto']; - if (empty($gotos)) { - $stmt = $pdo->prepare("SELECT `goto` FROM `alias` WHERE `address` = :rcpt AND `active` = '1'"); - $stmt->execute(array( - ':rcpt' => '@' . $parsed_rcpt['domain'] - )); - $gotos = $stmt->fetch(PDO::FETCH_ASSOC)['goto']; - } - if (empty($gotos)) { - $stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :rcpt AND `active` = '1'"); - $stmt->execute(array(':rcpt' => $parsed_rcpt['domain'])); - $goto_branch = $stmt->fetch(PDO::FETCH_ASSOC)['target_domain']; - if ($goto_branch) { - $gotos = $parsed_rcpt['local'] . '@' . $goto_branch; - } - } - $gotos_array = explode(',', $gotos); - - $loop_c = 0; - - while (count($gotos_array) != 0 && $loop_c <= 20) { - - // Loop through all found gotos - foreach ($gotos_array as $index => &$goto) { - error_log("ALIAS EXPANDER: http pipe: query " . $goto . " as username from mailbox" . PHP_EOL); - $stmt = $pdo->prepare("SELECT `username` FROM `mailbox` WHERE `username` = :goto AND (`active`= '1' OR `active`= '2');"); - $stmt->execute(array(':goto' => $goto)); - $username = $stmt->fetch(PDO::FETCH_ASSOC)['username']; - if (!empty($username)) { - error_log("ALIAS EXPANDER: http pipe: mailbox found: " . $username . PHP_EOL); - // Current goto is a mailbox, save to rcpt_final_mailboxes if not a duplicate - if (!in_array($username, $rcpt_final_mailboxes)) { - $rcpt_final_mailboxes[] = $username; - } - } - else { - $parsed_goto = parse_email($goto); - if (!$redis->hGet('DOMAIN_MAP', $parsed_goto['domain'])) { - error_log("ALIAS EXPANDER:" . $goto . " is not a mailcow handled mailbox or alias address" . PHP_EOL); - } - else { - $stmt = $pdo->prepare("SELECT `goto` FROM `alias` WHERE `address` = :goto AND `active` = '1'"); - $stmt->execute(array(':goto' => $goto)); - $goto_branch = $stmt->fetch(PDO::FETCH_ASSOC)['goto']; - if ($goto_branch) { - error_log("ALIAS EXPANDER: http pipe: goto address " . $goto . " is an alias branch for " . $goto_branch . PHP_EOL); - $goto_branch_array = explode(',', $goto_branch); - } else { - $stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :domain AND `active` AND '1'"); - $stmt->execute(array(':domain' => $parsed_goto['domain'])); - $goto_branch = $stmt->fetch(PDO::FETCH_ASSOC)['target_domain']; - if ($goto_branch) { - error_log("ALIAS EXPANDER: http pipe: goto domain " . $parsed_goto['domain'] . " is a domain alias branch for " . $goto_branch . PHP_EOL); - $goto_branch_array = array($parsed_goto['local'] . '@' . $goto_branch); - } - } - } - } - // goto item was processed, unset - unset($gotos_array[$index]); - } - - // Merge goto branch array derived from previous loop (if any), filter duplicates and unset goto branch array - if (!empty($goto_branch_array)) { - $gotos_array = array_unique(array_merge($gotos_array, $goto_branch_array)); - unset($goto_branch_array); - } - - // Reindex array - $gotos_array = array_values($gotos_array); - - // Force exit if loop cannot be solved - // Postfix does not allow for alias loops, so this should never happen. - $loop_c++; - error_log("ALIAS EXPANDER: http pipe: goto array count on loop #". $loop_c . " is " . count($gotos_array) . PHP_EOL); - } -} -catch (PDOException $e) { - error_log("ALIAS EXPANDER: " . $e->getMessage() . PHP_EOL); - http_response_code(502); - exit; -} - -// Does also return the mailbox name if question == answer (query == mailbox) -if (count($rcpt_final_mailboxes) == 1) { - error_log("ALIASEXP: direct alias " . $rcpt . " expanded to " . $rcpt_final_mailboxes[0] . PHP_EOL); - echo trim($rcpt_final_mailboxes[0]); -} diff --git a/Stable2.0/conf/dynmaps/bcc.php b/Stable2.0/conf/dynmaps/bcc.php deleted file mode 100644 index 87f91ca..0000000 --- a/Stable2.0/conf/dynmaps/bcc.php +++ /dev/null @@ -1,88 +0,0 @@ - PDO::ERRMODE_EXCEPTION, - PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, - PDO::ATTR_EMULATE_PREPARES => false, -]; -try { - $pdo = new PDO($dsn, $database_user, $database_pass, $opt); -} -catch (PDOException $e) { - error_log("BCC MAP SQL ERROR: " . $e . PHP_EOL); - http_response_code(501); - exit; -} - -function parse_email($email) { - if(!filter_var($email, FILTER_VALIDATE_EMAIL)) return false; - $a = strrpos($email, '@'); - return array('local' => substr($email, 0, $a), 'domain' => substr(substr($email, $a), 1)); -} -if (!function_exists('getallheaders')) { - function getallheaders() { - if (!is_array($_SERVER)) { - return array(); - } - $headers = array(); - foreach ($_SERVER as $name => $value) { - if (substr($name, 0, 5) == 'HTTP_') { - $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value; - } - } - return $headers; - } -} - -// Read headers -$headers = getallheaders(); -// Get rcpt -$rcpt = $headers['Rcpt']; -// Get from -$from = $headers['From']; -// Remove tags -$rcpt = preg_replace('/^(.*?)\+.*(@.*)$/', '$1$2', $rcpt); -$from = preg_replace('/^(.*?)\+.*(@.*)$/', '$1$2', $from); - -try { - if (!empty($rcpt)) { - $stmt = $pdo->prepare("SELECT `bcc_dest` FROM `bcc_maps` WHERE `type` = 'rcpt' AND `local_dest` = :local_dest AND `active` = '1'"); - $stmt->execute(array( - ':local_dest' => $rcpt - )); - $bcc_dest = $stmt->fetch(PDO::FETCH_ASSOC)['bcc_dest']; - if (!empty($bcc_dest) && filter_var($bcc_dest, FILTER_VALIDATE_EMAIL)) { - error_log("BCC MAP: returning ". $bcc_dest . " for " . $rcpt . PHP_EOL); - http_response_code(201); - echo trim($bcc_dest); - exit; - } - } - if (!empty($from)) { - $stmt = $pdo->prepare("SELECT `bcc_dest` FROM `bcc_maps` WHERE `type` = 'sender' AND `local_dest` = :local_dest AND `active` = '1'"); - $stmt->execute(array( - ':local_dest' => $from - )); - $bcc_dest = $stmt->fetch(PDO::FETCH_ASSOC)['bcc_dest']; - if (!empty($bcc_dest) && filter_var($bcc_dest, FILTER_VALIDATE_EMAIL)) { - error_log("BCC MAP: returning ". $bcc_dest . " for " . $from . PHP_EOL); - http_response_code(201); - echo trim($bcc_dest); - exit; - } - } -} -catch (PDOException $e) { - error_log("BCC MAP SQL ERROR: " . $e->getMessage() . PHP_EOL); - http_response_code(502); - exit; -} - diff --git a/Stable2.0/conf/dynmaps/footer.php b/Stable2.0/conf/dynmaps/footer.php deleted file mode 100644 index 545c45e..0000000 --- a/Stable2.0/conf/dynmaps/footer.php +++ /dev/null @@ -1,113 +0,0 @@ - PDO::ERRMODE_EXCEPTION, - PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, - PDO::ATTR_EMULATE_PREPARES => false, -]; -try { - $pdo = new PDO($dsn, $database_user, $database_pass, $opt); -} -catch (PDOException $e) { - error_log("FOOTER: " . $e . PHP_EOL); - http_response_code(501); - exit; -} - -if (!function_exists('getallheaders')) { - function getallheaders() { - if (!is_array($_SERVER)) { - return array(); - } - $headers = array(); - foreach ($_SERVER as $name => $value) { - if (substr($name, 0, 5) == 'HTTP_') { - $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value; - } - } - return $headers; - } -} - -// Read headers -$headers = getallheaders(); -// Get Domain -$domain = $headers['Domain']; -// Get Username -$username = $headers['Username']; -// Get From -$from = $headers['From']; -// define empty footer -$empty_footer = json_encode(array( - 'html' => '', - 'plain' => '', - 'skip_replies' => 0, - 'vars' => array() -)); - -error_log("FOOTER: checking for domain " . $domain . ", user " . $username . " and address " . $from . PHP_EOL); - -try { - // try get $target_domain if $domain is an alias_domain - $stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain` - WHERE `alias_domain` = :alias_domain"); - $stmt->execute(array( - ':alias_domain' => $domain - )); - $alias_domain = $stmt->fetch(PDO::FETCH_ASSOC); - if (!$alias_domain) { - $target_domain = $domain; - } else { - $target_domain = $alias_domain['target_domain']; - } - - // get footer associated with the domain - $stmt = $pdo->prepare("SELECT `plain`, `html`, `mbox_exclude`, `alias_domain_exclude`, `skip_replies` FROM `domain_wide_footer` - WHERE `domain` = :domain"); - $stmt->execute(array( - ':domain' => $target_domain - )); - $footer = $stmt->fetch(PDO::FETCH_ASSOC); - - // check if the sender is excluded - if (in_array($from, json_decode($footer['mbox_exclude']))){ - $footer = false; - } - if (in_array($domain, json_decode($footer['alias_domain_exclude']))){ - $footer = false; - } - if (empty($footer)){ - echo $empty_footer; - exit; - } - error_log("FOOTER: " . json_encode($footer) . PHP_EOL); - - // footer will be applied - // get custom mailbox attributes to insert into the footer - $stmt = $pdo->prepare("SELECT `custom_attributes` FROM `mailbox` WHERE `username` = :username"); - $stmt->execute(array( - ':username' => $username - )); - $custom_attributes = $stmt->fetch(PDO::FETCH_ASSOC)['custom_attributes']; - if (empty($custom_attributes)){ - $custom_attributes = (object)array(); - } -} -catch (Exception $e) { - error_log("FOOTER: " . $e->getMessage() . PHP_EOL); - http_response_code(502); - exit; -} - - -// return footer -$footer["vars"] = $custom_attributes; -echo json_encode($footer); diff --git a/Stable2.0/conf/dynmaps/forwardinghosts.php b/Stable2.0/conf/dynmaps/forwardinghosts.php deleted file mode 100644 index 10285b7..0000000 --- a/Stable2.0/conf/dynmaps/forwardinghosts.php +++ /dev/null @@ -1,57 +0,0 @@ -connect('redis-mailcow', 6379); - -function in_net($addr, $net) { - $net = explode('/', $net); - if (count($net) > 1) { - $mask = $net[1]; - } - $net = inet_pton($net[0]); - $addr = inet_pton($addr); - $length = strlen($net); // 4 for IPv4, 16 for IPv6 - if (strlen($net) != strlen($addr)) { - return false; - } - if (!isset($mask)) { - $mask = $length * 8; - } - $addr_bin = ''; - $net_bin = ''; - for ($i = 0; $i < $length; ++$i) { - $addr_bin .= str_pad(decbin(ord(substr($addr, $i, $i+1))), 8, '0', STR_PAD_LEFT); - $net_bin .= str_pad(decbin(ord(substr($net, $i, $i+1))), 8, '0', STR_PAD_LEFT); - } - return substr($addr_bin, 0, $mask) == substr($net_bin, 0, $mask); -} - -if (isset($_GET['host'])) { - try { - foreach ($redis->hGetAll('WHITELISTED_FWD_HOST') as $host => $source) { - if (in_net($_GET['host'], $host)) { - echo '200 PERMIT'; - exit; - } - } - echo '200 DUNNO'; - } - catch (RedisException $e) { - echo '200 DUNNO'; - exit; - } -} else { - try { - echo '240.240.240.240' . PHP_EOL; - foreach ($redis->hGetAll('WHITELISTED_FWD_HOST') as $host => $source) { - echo $host . PHP_EOL; - } - } - catch (RedisException $e) { - echo '240.240.240.240' . PHP_EOL; - exit; - } -} -?> diff --git a/Stable2.0/conf/dynmaps/index.html b/Stable2.0/conf/dynmaps/index.html deleted file mode 100644 index 90531a4..0000000 --- a/Stable2.0/conf/dynmaps/index.html +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/Stable2.0/conf/dynmaps/sasl_logs.php b/Stable2.0/conf/dynmaps/sasl_logs.php deleted file mode 100644 index 2d4cbe6..0000000 --- a/Stable2.0/conf/dynmaps/sasl_logs.php +++ /dev/null @@ -1,2 +0,0 @@ - PDO::ERRMODE_EXCEPTION, - PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, - PDO::ATTR_EMULATE_PREPARES => false, -]; -try { - $pdo = new PDO($dsn, $database_user, $database_pass, $opt); - $stmt = $pdo->query("SELECT '1' FROM `filterconf`"); -} -catch (PDOException $e) { - echo 'settings { }'; - exit; -} - -// Check if db changed and return header -$stmt = $pdo->prepare("SELECT GREATEST(COALESCE(MAX(UNIX_TIMESTAMP(UPDATE_TIME)), 1), COALESCE(MAX(UNIX_TIMESTAMP(CREATE_TIME)), 1)) AS `db_update_time` FROM `information_schema`.`tables` - WHERE (`TABLE_NAME` = 'filterconf' OR `TABLE_NAME` = 'settingsmap' OR `TABLE_NAME` = 'sogo_quick_contact' OR `TABLE_NAME` = 'alias') - AND TABLE_SCHEMA = :dbname;"); -$stmt->execute(array( - ':dbname' => $database_name -)); -$db_update_time = $stmt->fetch(PDO::FETCH_ASSOC)['db_update_time']; -if (empty($db_update_time)) { - $db_update_time = 1572048000; -} -if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && (strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $db_update_time)) { - header('Last-Modified: '.gmdate('D, d M Y H:i:s', $db_update_time).' GMT', true, 304); - exit; -} else { - header('Last-Modified: '.gmdate('D, d M Y H:i:s', $db_update_time).' GMT', true, 200); -} - -function parse_email($email) { - if (!filter_var($email, FILTER_VALIDATE_EMAIL)) return false; - $a = strrpos($email, '@'); - return array('local' => substr($email, 0, $a), 'domain' => substr($email, $a)); -} - -function normalize_email($email) { - $email = strtolower(str_replace('/', '\/', $email)); - $gm = "@gmail.com"; - if (substr_compare($email, $gm, -strlen($gm)) == 0) { - $email = explode('@', $email); - $email[0] = str_replace('.', '', $email[0]); - $email = implode('@', $email); - } - $gm_alt = "@googlemail.com"; - if (substr_compare($email, $gm_alt, -strlen($gm_alt)) == 0) { - $email = explode('@', $email); - $email[0] = str_replace('.', '', $email[0]); - $email[1] = str_replace('@', '', $gm); - $email = implode('@', $email); - } - if (str_contains($email, "+")) { - $email = explode('@', $email); - $user = explode('+', $email[0]); - $email[0] = $user[0]; - $email = implode('@', $email); - } - return $email; -} - -function wl_by_sogo() { - global $pdo; - $rcpt = array(); - $stmt = $pdo->query("SELECT DISTINCT(`sogo_folder_info`.`c_path2`) AS `user`, GROUP_CONCAT(`sogo_quick_contact`.`c_mail`) AS `contacts` FROM `sogo_folder_info` - INNER JOIN `sogo_quick_contact` ON `sogo_quick_contact`.`c_folder_id` = `sogo_folder_info`.`c_folder_id` - GROUP BY `c_path2`"); - $sogo_contacts = $stmt->fetchAll(PDO::FETCH_ASSOC); - while ($row = array_shift($sogo_contacts)) { - foreach (explode(',', $row['contacts']) as $contact) { - if (!filter_var($contact, FILTER_VALIDATE_EMAIL)) { - continue; - } - // Explicit from, no mime_from, no regex - envelope must match - // mailcow white and blacklists also cover mime_from - $rcpt[$row['user']][] = normalize_email($contact); - } - } - return $rcpt; -} - -function ucl_rcpts($object, $type) { - global $pdo; - $rcpt = array(); - if ($type == 'mailbox') { - // Standard aliases - $stmt = $pdo->prepare("SELECT `address` FROM `alias` - WHERE `goto` = :object_goto - AND `address` NOT LIKE '@%'"); - $stmt->execute(array( - ':object_goto' => $object - )); - $standard_aliases = $stmt->fetchAll(PDO::FETCH_ASSOC); - while ($row = array_shift($standard_aliases)) { - $local = parse_email($row['address'])['local']; - $domain = parse_email($row['address'])['domain']; - if (!empty($local) && !empty($domain)) { - $rcpt[] = '/^' . str_replace('/', '\/', $local) . '[+].*' . str_replace('/', '\/', $domain) . '$/i'; - } - $rcpt[] = str_replace('/', '\/', $row['address']); - } - // Aliases by alias domains - $stmt = $pdo->prepare("SELECT CONCAT(`local_part`, '@', `alias_domain`.`alias_domain`) AS `alias` FROM `mailbox` - LEFT OUTER JOIN `alias_domain` ON `mailbox`.`domain` = `alias_domain`.`target_domain` - WHERE `mailbox`.`username` = :object"); - $stmt->execute(array( - ':object' => $object - )); - $by_domain_aliases = $stmt->fetchAll(PDO::FETCH_ASSOC); - array_filter($by_domain_aliases); - while ($row = array_shift($by_domain_aliases)) { - if (!empty($row['alias'])) { - $local = parse_email($row['alias'])['local']; - $domain = parse_email($row['alias'])['domain']; - if (!empty($local) && !empty($domain)) { - $rcpt[] = '/^' . str_replace('/', '\/', $local) . '[+].*' . str_replace('/', '\/', $domain) . '$/i'; - } - $rcpt[] = str_replace('/', '\/', $row['alias']); - } - } - } - elseif ($type == 'domain') { - // Domain self - $rcpt[] = '/.*@' . $object . '/i'; - $stmt = $pdo->prepare("SELECT `alias_domain` FROM `alias_domain` - WHERE `target_domain` = :object"); - $stmt->execute(array(':object' => $object)); - $alias_domains = $stmt->fetchAll(PDO::FETCH_ASSOC); - array_filter($alias_domains); - while ($row = array_shift($alias_domains)) { - $rcpt[] = '/.*@' . $row['alias_domain'] . '/i'; - } - } - return $rcpt; -} -?> -settings { - watchdog { - priority = 10; - rcpt_mime = "/null@localhost/i"; - from_mime = "/watchdog@localhost/i"; - apply "default" { - symbols_disabled = ["HISTORY_SAVE", "ARC", "ARC_SIGNED", "DKIM", "DKIM_SIGNED", "CLAM_VIRUS"]; - want_spam = yes; - actions { - reject = 9999.0; - greylist = 9998.0; - "add header" = 9997.0; - } - - } - } -query("SELECT DISTINCT `object` FROM `filterconf` WHERE `option` = 'highspamlevel' OR `option` = 'lowspamlevel'"); -$rows = $stmt->fetchAll(PDO::FETCH_ASSOC); - -while ($row = array_shift($rows)) { - $username_sane = preg_replace("/[^a-zA-Z0-9]+/", "", $row['object']); -?> - score_ { - priority = 4; - - rcpt = ; -prepare("SELECT `option`, `value` FROM `filterconf` - WHERE (`option` = 'highspamlevel' OR `option` = 'lowspamlevel') - AND `object`= :object"); - $stmt->execute(array(':object' => $row['object'])); - $spamscore = $stmt->fetchAll(PDO::FETCH_COLUMN|PDO::FETCH_GROUP); -?> - apply "default" { - actions { - reject = ; - greylist = ; - "add header" = ; - } - } - } - $contacts) { - $username_sane = preg_replace("/[^a-zA-Z0-9]+/", "", $user); -?> - whitelist_sogo_ { - - from = ; - - priority = 4; - - rcpt = ; - - apply "default" { - SOGO_CONTACT = -99.0; - } - symbols [ - "SOGO_CONTACT" - ] - } -query("SELECT DISTINCT `object` FROM `filterconf` WHERE `option` = 'whitelist_from'"); -$rows = $stmt->fetchAll(PDO::FETCH_ASSOC); -while ($row = array_shift($rows)) { - $username_sane = preg_replace("/[^a-zA-Z0-9]+/", "", $row['object']); -?> - whitelist_ { -prepare("SELECT `value` FROM `filterconf` - WHERE `object`= :object - AND `option` = 'whitelist_from'"); - $stmt->execute(array(':object' => $row['object'])); - $list_items = $stmt->fetchAll(PDO::FETCH_ASSOC); - foreach ($list_items as $item) { -?> - from = "//i"; - - priority = 5; - - rcpt = ; - - priority = 6; - - rcpt = ; - - apply "default" { - MAILCOW_WHITE = -999.0; - } - symbols [ - "MAILCOW_WHITE" - ] - } - whitelist_mime_ { - - from_mime = "//i"; - - priority = 5; - - rcpt = ; - - priority = 6; - - rcpt = ; - - apply "default" { - MAILCOW_WHITE = -999.0; - } - symbols [ - "MAILCOW_WHITE" - ] - } -query("SELECT DISTINCT `object` FROM `filterconf` WHERE `option` = 'blacklist_from'"); -$rows = $stmt->fetchAll(PDO::FETCH_ASSOC); -while ($row = array_shift($rows)) { - $username_sane = preg_replace("/[^a-zA-Z0-9]+/", "", $row['object']); -?> - blacklist_ { -prepare("SELECT `value` FROM `filterconf` - WHERE `object`= :object - AND `option` = 'blacklist_from'"); - $stmt->execute(array(':object' => $row['object'])); - $list_items = $stmt->fetchAll(PDO::FETCH_ASSOC); - foreach ($list_items as $item) { -?> - from = "//i"; - - priority = 5; - - rcpt = ; - - priority = 6; - - rcpt = ; - - apply "default" { - MAILCOW_BLACK = 999.0; - } - symbols [ - "MAILCOW_BLACK" - ] - } - blacklist_header_ { - - from_mime = "//i"; - - priority = 5; - - rcpt = ; - - priority = 6; - - rcpt = ; - - apply "default" { - MAILCOW_BLACK = 999.0; - } - symbols [ - "MAILCOW_BLACK" - ] - } - - ham_trap { - - rcpt = ; - - priority = 9; - apply "default" { - symbols_enabled = ["HISTORY_SAVE"]; - } - symbols [ - "HAM_TRAP" - ] - } - - spam_trap { - - rcpt = ; - - priority = 9; - apply "default" { - symbols_enabled = ["HISTORY_SAVE"]; - } - symbols [ - "SPAM_TRAP" - ] - } -query("SELECT `id`, `content` FROM `settingsmap` WHERE `active` = '1'"); -$rows = $stmt->fetchAll(PDO::FETCH_ASSOC); -while ($row = array_shift($rows)) { - $username_sane = preg_replace("/[^a-zA-Z0-9]+/", "", $row['id']); -?> - additional_settings_ { - - } - -} diff --git a/Stable2.0/conf/dynmaps/vars.inc.php b/Stable2.0/conf/dynmaps/vars.inc.php deleted file mode 100644 index 79566b0..0000000 --- a/Stable2.0/conf/dynmaps/vars.inc.php +++ /dev/null @@ -1,6 +0,0 @@ - diff --git a/Stable2.0/conf/local.d/actions.conf b/Stable2.0/conf/local.d/actions.conf deleted file mode 100644 index 3de63a5..0000000 --- a/Stable2.0/conf/local.d/actions.conf +++ /dev/null @@ -1,3 +0,0 @@ -reject = 15; -add_header = 8; -greylist = 7; diff --git a/Stable2.0/conf/local.d/antivirus.conf b/Stable2.0/conf/local.d/antivirus.conf deleted file mode 100644 index c8d31d1..0000000 --- a/Stable2.0/conf/local.d/antivirus.conf +++ /dev/null @@ -1,11 +0,0 @@ -clamav { - # Scan whole message - scan_mime_parts = false; - #scan_text_mime = true; - #scan_image_mime = true; - symbol = "CLAM_VIRUS"; - type = "clamav"; - log_clean = true; - servers = "clamd:3310"; - max_size = 20971520; -} diff --git a/Stable2.0/conf/local.d/arc.conf b/Stable2.0/conf/local.d/arc.conf deleted file mode 100644 index a857fc4..0000000 --- a/Stable2.0/conf/local.d/arc.conf +++ /dev/null @@ -1,32 +0,0 @@ -# If false, messages with empty envelope from are not signed -allow_envfrom_empty = true; -# If true, envelope/header domain mismatch is ignored -allow_hdrfrom_mismatch = true; -# If true, multiple from headers are allowed (but only first is used) -allow_hdrfrom_multiple = false; -# If true, username does not need to contain matching domain -allow_username_mismatch = false; -# If false, messages from authenticated users are not selected for signing -sign_authenticated = false; -# Default path to key, can include '$domain' and '$selector' variables -path = "/data/dkim/keys/$domain.dkim"; -# Default selector to use -selector = "dkim"; -# If false, messages from local networks are not selected for signing -sign_local = false; -# Symbol to add when message is signed -symbol = "ARC_SIGNED"; -# Whether to fallback to global config -try_fallback = true; -# Domain to use for DKIM signing: can be "header" or "envelope" -use_domain = "recipient"; -# Whether to normalise domains to eSLD -use_esld = false; -# Whether to get keys from Redis -use_redis = true; -# Hash for DKIM keys in Redis -key_prefix = "DKIM_PRIV_KEYS"; -# Selector map -selector_prefix = "DKIM_SELECTORS"; -sign_inbound = true; -use_domain_sign_inbound = "recipient"; diff --git a/Stable2.0/conf/local.d/asn.conf b/Stable2.0/conf/local.d/asn.conf deleted file mode 100644 index 42b6780..0000000 --- a/Stable2.0/conf/local.d/asn.conf +++ /dev/null @@ -1,6 +0,0 @@ -provider_type = "rspamd"; -provider_info { - ip4 = "asn.rspamd.com"; - ip6 = "asn6.rspamd.com"; -} -symbol = "ASN"; diff --git a/Stable2.0/conf/local.d/composites.conf b/Stable2.0/conf/local.d/composites.conf deleted file mode 100644 index 9bb8442..0000000 --- a/Stable2.0/conf/local.d/composites.conf +++ /dev/null @@ -1,110 +0,0 @@ -MX_IMPLICIT { - expression = "MX_GOOD & MX_MISSING"; - score = -0.01; -} -VIRUS_FOUND { - expression = "CLAM_VIRUS & !MAILCOW_WHITE"; - score = 2000.0; -} -# Bad policy from free mail providers -FREEMAIL_POLICY_FAILURE { - expression = "FREEMAIL_FROM & !DMARC_POLICY_ALLOW & !MAILLIST& !WHITELISTED_FWD_HOST & -g+:policies"; - score = 16.0; -} -# Applies to freemail with undisclosed recipients -FREEMAIL_TO_UNDISC_RCPT { - expression = "FREEMAIL_FROM & ( MISSING_TO | R_UNDISC_RCPT | TO_EQ_FROM )"; - score = 5.0; -} -# Bad policy from non-whitelisted senders -# Remove SOGO_CONTACT symbol for fwd hosts and senders with broken policy -SOGO_CONTACT_EXCLUDE { - expression = "(-WHITELISTED_FWD_HOST | -g+:policies) & ^SOGO_CONTACT & !DMARC_POLICY_ALLOW"; -} -# Remove MAILCOW_WHITE symbol for senders with broken policy recieved not from fwd hosts -MAILCOW_WHITE_EXCLUDE { - expression = "^MAILCOW_WHITE & (-DMARC_POLICY_REJECT | -DMARC_POLICY_QUARANTINE | -R_SPF_PERMFAIL) & !WHITELISTED_FWD_HOST"; -} -# Spoofed header from and broken policy (excluding sieve host, rspamd host, whitelisted senders, authenticated senders and forward hosts) -SPOOFED_UNAUTH { - expression = "!MAILCOW_AUTH & !MAILCOW_WHITE & !RSPAMD_HOST & !SIEVE_HOST & MAILCOW_DOMAIN_HEADER_FROM & !WHITELISTED_FWD_HOST & -g+:policies"; - score = 50.0; -} -# Only apply to inbound unauthed and not whitelisted -OLEFY_MACRO { - expression = "!MAILCOW_AUTH & !MAILCOW_WHITE & OLETOOLS"; - score = 20.0; - policy = "remove_weight"; -} -# Applies to a content filter map -BAD_WORD_BAD_TLD { - expression = "FISHY_TLD & ( BAD_WORDS | BAD_WORDS_DE )"; - score = 10.0; -} -# Forged with bad policies and not fwd host, keep bad policy symbols -FORGED_W_BAD_POLICY { - expression = "( -g+:policies | -R_SPF_NA) & ( ~FROM_NEQ_ENVFROM | ~FORGED_SENDER ) & !WHITELISTED_FWD_HOST & !DMARC_POLICY_ALLOW"; - score = 3.0; -} -# Keep negative (good) scores for rbl, policies and hfilter, disable neural group -WL_FWD_HOST { - expression = "-WHITELISTED_FWD_HOST & (^g+:rbl | ^g+:policies | ^g+:hfilter | ^g:neural)"; -} -# Exclude X-Spam like flags from scoring from fwd and sieve hosts -UPSTREAM_CHECKS_EXCLUDE_FWD_HOST { - expression = "(-SIEVE_HOST | -WHITELISTED_FWD_HOST) & (^UNITEDINTERNET_SPAM | ^SPAM_FLAG | ^KLMS_SPAM | ^AOL_SPAM | ^MICROSOFT_SPAM)"; -} -# Remove fuzzy group from bounces -BOUNCE_FUZZY { - expression = "-BOUNCE & ^g+:fuzzy"; -} -# Remove bayes ham if fuzzy denied -FUZZY_HAM_MISMATCH { - expression = "( -FUZZY_DENIED | -MAILCOW_FUZZY_DENIED | -LOCAL_FUZZY_DENIED ) & ( ^BAYES_HAM | ^NEURAL_HAM_LONG | ^NEURAL_HAM_SHORT )"; -} -# Remove bayes spam if local fuzzy white -FUZZY_SPAM_MISMATCH { - expression = "( -LOCAL_FUZZY_WHITE ) & ( ^BAYES_SPAM | ^NEURAL_SPAM_LONG | ^NEURAL_SPAM_SHORT )"; -} -WL_FWD_HOST { - expression = "-WHITELISTED_FWD_HOST & (^g+:rbl | ^g+:policies | ^g+:hfilter | ^g:neural)"; -} -ENCRYPTED_CHAT { - expression = "CHAT_VERSION_HEADER & ENCRYPTED_PGP"; -} - -CLAMD_SPAM_FOUND { - expression = "CLAM_SECI_SPAM & !MAILCOW_WHITE"; - description = "Probably Spam, Securite Spam Flag set through ClamAV"; - score = 5; -} - -CLAMD_BAD_PDF { - expression = "CLAM_SECI_PDF & !MAILCOW_WHITE"; - description = "Bad PDF Found, Securite bad PDF Flag set through ClamAV"; - score = 8; -} - -CLAMD_BAD_JPG { - expression = "CLAM_SECI_JPG & !MAILCOW_WHITE"; - description = "Bad JPG Found, Securite bad JPG Flag set through ClamAV"; - score = 8; -} - -CLAMD_ASCII_MALWARE { - expression = "CLAM_SECI_ASCII & !MAILCOW_WHITE"; - description = "ASCII malware found, Securite ASCII malware Flag set through ClamAV"; - score = 8; -} - -CLAMD_HTML_MALWARE { - expression = "CLAM_SECI_HTML & !MAILCOW_WHITE"; - description = "HTML malware found, Securite HTML malware Flag set through ClamAV"; - score = 8; -} - -CLAMD_JS_MALWARE { - expression = "CLAM_SECI_JS & !MAILCOW_WHITE"; - description = "JS malware found, Securite JS malware Flag set through ClamAV"; - score = 8; -} diff --git a/Stable2.0/conf/local.d/dkim_signing.conf b/Stable2.0/conf/local.d/dkim_signing.conf deleted file mode 100644 index 4fac27f..0000000 --- a/Stable2.0/conf/local.d/dkim_signing.conf +++ /dev/null @@ -1,35 +0,0 @@ -# If false, messages with empty envelope from are not signed -allow_envfrom_empty = true; -# If true, envelope/header domain mismatch is ignored -allow_hdrfrom_mismatch = true; -# If true, multiple from headers are allowed (but only first is used) -allow_hdrfrom_multiple = true; -# If true, username does not need to contain matching domain -allow_username_mismatch = true; -# If false, messages from authenticated users are not selected for signing -sign_authenticated = true; -# Default path to key, can include '$domain' and '$selector' variables -path = "/data/dkim/keys/$domain.dkim"; -# Default selector to use -selector = "dkim"; -# If false, messages from local networks are not selected for signing -sign_local = true; -# Symbol to add when message is signed -symbol = "DKIM_SIGNED"; -# Whether to fallback to global config -try_fallback = true; -# Domain to use for DKIM signing: can be "header" or "envelope" -use_domain = "envelope"; -# Whether to normalise domains to eSLD -use_esld = false; -# Whether to get keys from Redis -use_redis = true; -# Hash for DKIM keys in Redis -key_prefix = "DKIM_PRIV_KEYS"; -# Selector map -selector_prefix = "DKIM_SELECTORS"; -# Sieve is in sign_networks only -# forwards are arc signed, rejects are dkim signed -sign_networks = "/etc/rspamd/custom/dovecot_trusted.map"; -use_domain_sign_networks = "header"; -sign_headers = "from:sender:reply-to:subject:date:message-id:to:cc:mime-version:content-type:content-transfer-encoding:content-language:resent-to:resent-cc:resent-from:resent-sender:resent-message-id:in-reply-to:references:list-id:list-help:list-owner:list-unsubscribe:list-subscribe:list-post:list-unsubscribe-post:disposition-notification-to:disposition-notification-options:original-recipient:openpgp:autocrypt"; diff --git a/Stable2.0/conf/local.d/external_services.conf b/Stable2.0/conf/local.d/external_services.conf deleted file mode 100644 index 2b091ff..0000000 --- a/Stable2.0/conf/local.d/external_services.conf +++ /dev/null @@ -1,12 +0,0 @@ -oletools { - # default olefy settings - servers = "olefy:10055"; - # needs to be set explicitly for Rspamd < 1.9.5 - scan_mime_parts = true; - # mime-part regex matching in content-type or filename - # block all macros - extended = true; - max_size = 3145728; - timeout = 20.0; - retransmits = 1; -} diff --git a/Stable2.0/conf/local.d/force_actions.conf b/Stable2.0/conf/local.d/force_actions.conf deleted file mode 100644 index a1b9899..0000000 --- a/Stable2.0/conf/local.d/force_actions.conf +++ /dev/null @@ -1,12 +0,0 @@ -rules { - WHITELIST_FORWARDING_HOST_NO_REJECT { - action = "add header"; - expression = "WHITELISTED_FWD_HOST"; - require_action = ["reject"]; - } - WHITELIST_FORWARDING_HOST_NO_GREYLIST { - action = "no action"; - expression = "WHITELISTED_FWD_HOST"; - require_action = ["greylist", "soft reject"]; - } -} diff --git a/Stable2.0/conf/local.d/fuzzy_check.conf b/Stable2.0/conf/local.d/fuzzy_check.conf deleted file mode 100644 index 855e8d0..0000000 --- a/Stable2.0/conf/local.d/fuzzy_check.conf +++ /dev/null @@ -1,54 +0,0 @@ -rule "local" { - # Fuzzy storage server list - servers = "localhost:11445"; - # Default symbol for unknown flags - symbol = "LOCAL_FUZZY_UNKNOWN"; - # Additional mime types to store/check - mime_types = ["application/*"]; - # Hash weight threshold for all maps - max_score = 100.0; - # Whether we can learn this storage - read_only = no; - # Ignore unknown flags - skip_unknown = yes; - # Hash generation algorithm - algorithm = "mumhash"; - - # Map flags to symbols - fuzzy_map = { - LOCAL_FUZZY_DENIED { - max_score = 10.0; - flag = 11; - } - LOCAL_FUZZY_WHITE { - max_score = 5.0; - flag = 13; - } - } -} - -rule "mailcow" { - # Fuzzy storage server list - servers = "fuzzy.mailcow.email:11445"; - # Default symbol for unknown flags - symbol = "MAILCOW_FUZZY_UNKNOWN"; - # Additional mime types to store/check - mime_types = ["application/*"]; - # Hash weight threshold for all maps - max_score = 100.0; - # Whether we can learn this storage - read_only = yes; - # Ignore unknown flags - skip_unknown = yes; - # Hash generation algorithm - algorithm = "mumhash"; - # Encrypt connection - encryption_key = "oa7xjgdr9u7w3hq1xbttas6brgau8qc17yi7ur5huaeq6paq8h4y"; - # Map flags to symbols - fuzzy_map = { - MAILCOW_FUZZY_DENIED { - max_score = 10.0; - flag = 11; - } - } -} diff --git a/Stable2.0/conf/local.d/fuzzy_group.conf b/Stable2.0/conf/local.d/fuzzy_group.conf deleted file mode 100644 index 561ac4e..0000000 --- a/Stable2.0/conf/local.d/fuzzy_group.conf +++ /dev/null @@ -1,17 +0,0 @@ -symbols = { - "LOCAL_FUZZY_UNKNOWN" { - weight = 0.1; - } - "LOCAL_FUZZY_DENIED" { - weight = 15.0; - } - "MAILCOW_FUZZY_UNKNOWN" { - weight = 0.1; - } - "MAILCOW_FUZZY_DENIED" { - weight = 7.0; - } - "LOCAL_FUZZY_WHITE" { - weight = -10.0; - } -} diff --git a/Stable2.0/conf/local.d/greylist.conf b/Stable2.0/conf/local.d/greylist.conf deleted file mode 100644 index c43c907..0000000 --- a/Stable2.0/conf/local.d/greylist.conf +++ /dev/null @@ -1,4 +0,0 @@ -whitelisted_ip = "http://nginx:8081/forwardinghosts.php"; -ipv4_mask = 24; -ipv6_mask = 64; -message = "Greylisted, please try again later"; diff --git a/Stable2.0/conf/local.d/groups.conf b/Stable2.0/conf/local.d/groups.conf deleted file mode 100644 index f77d8a4..0000000 --- a/Stable2.0/conf/local.d/groups.conf +++ /dev/null @@ -1,59 +0,0 @@ -symbols { - "MAILCOW_AUTH" { - description = "mailcow authenticated"; - score = -20.0; - } - "CTYPE_MIXED_BOGUS" { - score = 0.0; - } - "BAD_REP_POLICIES" { - score = 2.0; - } - "BAD_HEADER" { - score = 10.0; - } - "BULK_HEADER" { - score = 4.0; - } - "ENCRYPTED_CHAT" { - score = -20.0; - } - "SOGO_CONTACT" { - score = -99.0; - } -} - -group "MX" { - "MX_INVALID" { - score = 0.5; - description = "No connectable MX"; - one_shot = true; - } - "MX_MISSING" { - score = 2.0; - description = "No MX record"; - one_shot = true; - } - "MX_GOOD" { - score = -0.01; - description = "MX was ok"; - one_shot = true; - } -} - -group "reputation" { - symbols = { - "IP_REPUTATION_HAM" { - weight = 1.0; - } - "IP_REPUTATION_SPAM" { - weight = 4.0; - } - "SENDER_REP_HAM" { - weight = 1.0; - } - "SENDER_REP_SPAM" { - weight = 2.0; - } - } -} diff --git a/Stable2.0/conf/local.d/headers_group.conf b/Stable2.0/conf/local.d/headers_group.conf deleted file mode 100644 index 1df92b5..0000000 --- a/Stable2.0/conf/local.d/headers_group.conf +++ /dev/null @@ -1,7 +0,0 @@ -symbols = { - "R_MIXED_CHARSET" { - weight = 1.0; - description = "Mixed characters in a message"; - one_shot = true; - } -} diff --git a/Stable2.0/conf/local.d/hfilter_group.conf b/Stable2.0/conf/local.d/hfilter_group.conf deleted file mode 100644 index 3c908c5..0000000 --- a/Stable2.0/conf/local.d/hfilter_group.conf +++ /dev/null @@ -1,5 +0,0 @@ -symbols = { - "HFILTER_HOSTNAME_UNKNOWN" { - score = 8.5; - } -} diff --git a/Stable2.0/conf/local.d/history_redis.conf b/Stable2.0/conf/local.d/history_redis.conf deleted file mode 100644 index 68a59b0..0000000 --- a/Stable2.0/conf/local.d/history_redis.conf +++ /dev/null @@ -1 +0,0 @@ -nrows = 1000; diff --git a/Stable2.0/conf/local.d/metadata_exporter.conf b/Stable2.0/conf/local.d/metadata_exporter.conf deleted file mode 100644 index daaa79b..0000000 --- a/Stable2.0/conf/local.d/metadata_exporter.conf +++ /dev/null @@ -1,72 +0,0 @@ -rules { - QUARANTINE { - backend = "http"; - url = "http://nginx:9081/pipe.php"; - selector = "reject_no_global_bl"; - formatter = "default"; - meta_headers = true; - } - RLINFO { - backend = "http"; - url = "http://nginx:9081/pipe_rl.php"; - selector = "ratelimited"; - formatter = "json"; - } - PUSHOVERMAIL { - backend = "http"; - url = "http://nginx:9081/pushover.php"; - selector = "mailcow_rcpt"; - formatter = "json"; - meta_headers = true; - } -} - -custom_select { - mailcow_rcpt = < substr($email, 0, $a), 'domain' => substr(substr($email, $a), 1)); -} -if (!function_exists('getallheaders')) { - function getallheaders() { - if (!is_array($_SERVER)) { - return array(); - } - $headers = array(); - foreach ($_SERVER as $name => $value) { - if (substr($name, 0, 5) == 'HTTP_') { - $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value; - } - } - return $headers; - } -} - -$raw_data_content = file_get_contents('php://input'); -$raw_data = mb_convert_encoding($raw_data_content, 'HTML-ENTITIES', "UTF-8"); -$headers = getallheaders(); - -$qid = $headers['X-Rspamd-Qid']; -$fuzzy = $headers['X-Rspamd-Fuzzy']; -$subject = iconv_mime_decode($headers['X-Rspamd-Subject']); -$score = $headers['X-Rspamd-Score']; -$rcpts = $headers['X-Rspamd-Rcpt']; -$user = $headers['X-Rspamd-User']; -$ip = $headers['X-Rspamd-Ip']; -$action = $headers['X-Rspamd-Action']; -$sender = $headers['X-Rspamd-From']; -$symbols = $headers['X-Rspamd-Symbols']; - -$raw_size = (int)$_SERVER['CONTENT_LENGTH']; - -if (empty($sender)) { - error_log("QUARANTINE: Unknown sender, assuming empty-env-from@localhost" . PHP_EOL); - $sender = 'empty-env-from@localhost'; -} - -if ($fuzzy == 'unknown') { - $fuzzy = '[]'; -} - -try { - $max_size = (int)$redis->Get('Q_MAX_SIZE'); - if (($max_size * 1048576) < $raw_size) { - error_log(sprintf("QUARANTINE: Message too large: %d b exceeds %d b", $raw_size, ($max_size * 1048576)) . PHP_EOL); - http_response_code(505); - exit; - } - if ($exclude_domains = $redis->Get('Q_EXCLUDE_DOMAINS')) { - $exclude_domains = json_decode($exclude_domains, true); - } - $retention_size = (int)$redis->Get('Q_RETENTION_SIZE'); -} -catch (RedisException $e) { - error_log("QUARANTINE: " . $e . PHP_EOL); - http_response_code(504); - exit; -} - -$rcpt_final_mailboxes = array(); - -// Loop through all rcpts -foreach (json_decode($rcpts, true) as $rcpt) { - // Remove tag - $rcpt = preg_replace('/^(.*?)\+.*(@.*)$/', '$1$2', $rcpt); - - // Break rcpt into local part and domain part - $parsed_rcpt = parse_email($rcpt); - - // Skip if not a mailcow handled domain - try { - if (!$redis->hGet('DOMAIN_MAP', $parsed_rcpt['domain'])) { - continue; - } - } - catch (RedisException $e) { - error_log("QUARANTINE: " . $e . PHP_EOL); - http_response_code(504); - exit; - } - - // Skip if domain is excluded - if (in_array($parsed_rcpt['domain'], $exclude_domains)) { - error_log(sprintf("QUARANTINE: Skipped domain %s", $parsed_rcpt['domain']) . PHP_EOL); - continue; - } - - // Always assume rcpt is not a final mailbox but an alias for a mailbox or further aliases - // - // rcpt - // | - // mailbox <-- goto ---> alias1, alias2, mailbox2 - // | | - // mailbox3 | - // | - // alias3 ---> mailbox4 - // - try { - $stmt = $pdo->prepare("SELECT `goto` FROM `alias` WHERE `address` = :rcpt AND `active` = '1'"); - $stmt->execute(array( - ':rcpt' => $rcpt - )); - $gotos = $stmt->fetch(PDO::FETCH_ASSOC)['goto']; - if (empty($gotos)) { - $stmt = $pdo->prepare("SELECT `goto` FROM `alias` WHERE `address` = :rcpt AND `active` = '1'"); - $stmt->execute(array( - ':rcpt' => '@' . $parsed_rcpt['domain'] - )); - $gotos = $stmt->fetch(PDO::FETCH_ASSOC)['goto']; - } - if (empty($gotos)) { - $stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :rcpt AND `active` = '1'"); - $stmt->execute(array(':rcpt' => $parsed_rcpt['domain'])); - $goto_branch = $stmt->fetch(PDO::FETCH_ASSOC)['target_domain']; - if ($goto_branch) { - $gotos = $parsed_rcpt['local'] . '@' . $goto_branch; - } - } - $gotos_array = explode(',', $gotos); - - $loop_c = 0; - - while (count($gotos_array) != 0 && $loop_c <= 20) { - - // Loop through all found gotos - foreach ($gotos_array as $index => &$goto) { - error_log("RCPT RESOVLER: http pipe: query " . $goto . " as username from mailbox" . PHP_EOL); - $stmt = $pdo->prepare("SELECT `username` FROM `mailbox` WHERE `username` = :goto AND (`active`= '1' OR `active`= '2');"); - $stmt->execute(array(':goto' => $goto)); - $username = $stmt->fetch(PDO::FETCH_ASSOC)['username']; - if (!empty($username)) { - error_log("RCPT RESOVLER: http pipe: mailbox found: " . $username . PHP_EOL); - // Current goto is a mailbox, save to rcpt_final_mailboxes if not a duplicate - if (!in_array($username, $rcpt_final_mailboxes)) { - $rcpt_final_mailboxes[] = $username; - } - } - else { - $parsed_goto = parse_email($goto); - if (!$redis->hGet('DOMAIN_MAP', $parsed_goto['domain'])) { - error_log("RCPT RESOVLER:" . $goto . " is not a mailcow handled mailbox or alias address" . PHP_EOL); - } - else { - $stmt = $pdo->prepare("SELECT `goto` FROM `alias` WHERE `address` = :goto AND `active` = '1'"); - $stmt->execute(array(':goto' => $goto)); - $goto_branch = $stmt->fetch(PDO::FETCH_ASSOC)['goto']; - if ($goto_branch) { - error_log("RCPT RESOVLER: http pipe: goto address " . $goto . " is an alias branch for " . $goto_branch . PHP_EOL); - $goto_branch_array = explode(',', $goto_branch); - } else { - $stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :domain AND `active` AND '1'"); - $stmt->execute(array(':domain' => $parsed_goto['domain'])); - $goto_branch = $stmt->fetch(PDO::FETCH_ASSOC)['target_domain']; - if ($goto_branch) { - error_log("RCPT RESOVLER: http pipe: goto domain " . $parsed_goto['domain'] . " is a domain alias branch for " . $goto_branch . PHP_EOL); - $goto_branch_array = array($parsed_goto['local'] . '@' . $goto_branch); - } - } - } - } - // goto item was processed, unset - unset($gotos_array[$index]); - } - - // Merge goto branch array derived from previous loop (if any), filter duplicates and unset goto branch array - if (!empty($goto_branch_array)) { - $gotos_array = array_unique(array_merge($gotos_array, $goto_branch_array)); - unset($goto_branch_array); - } - - // Reindex array - $gotos_array = array_values($gotos_array); - - // Force exit if loop cannot be solved - // Postfix does not allow for alias loops, so this should never happen. - $loop_c++; - error_log("RCPT RESOVLER: http pipe: goto array count on loop #". $loop_c . " is " . count($gotos_array) . PHP_EOL); - } - } - catch (PDOException $e) { - error_log("RCPT RESOVLER: " . $e->getMessage() . PHP_EOL); - http_response_code(502); - exit; - } -} - -foreach ($rcpt_final_mailboxes as $rcpt_final) { - error_log("QUARANTINE: quarantine pipe: processing quarantine message for rcpt " . $rcpt_final . PHP_EOL); - try { - $stmt = $pdo->prepare("INSERT INTO `quarantine` (`qid`, `subject`, `score`, `sender`, `rcpt`, `symbols`, `user`, `ip`, `msg`, `action`, `fuzzy_hashes`) - VALUES (:qid, :subject, :score, :sender, :rcpt, :symbols, :user, :ip, :msg, :action, :fuzzy_hashes)"); - $stmt->execute(array( - ':qid' => $qid, - ':subject' => $subject, - ':score' => $score, - ':sender' => $sender, - ':rcpt' => $rcpt_final, - ':symbols' => $symbols, - ':user' => $user, - ':ip' => $ip, - ':msg' => $raw_data, - ':action' => $action, - ':fuzzy_hashes' => $fuzzy - )); - $stmt = $pdo->prepare('DELETE FROM `quarantine` WHERE `rcpt` = :rcpt AND `id` NOT IN ( - SELECT `id` - FROM ( - SELECT `id` - FROM `quarantine` - WHERE `rcpt` = :rcpt2 - ORDER BY id DESC - LIMIT :retention_size - ) x - );'); - $stmt->execute(array( - ':rcpt' => $rcpt_final, - ':rcpt2' => $rcpt_final, - ':retention_size' => $retention_size - )); - } - catch (PDOException $e) { - error_log("QUARANTINE: " . $e->getMessage() . PHP_EOL); - http_response_code(503); - exit; - } -} - diff --git a/Stable2.0/conf/meta_exporter/pipe_rl.php b/Stable2.0/conf/meta_exporter/pipe_rl.php deleted file mode 100644 index 0bb1b31..0000000 --- a/Stable2.0/conf/meta_exporter/pipe_rl.php +++ /dev/null @@ -1,48 +0,0 @@ -connect(getenv('REDIS_SLAVEOF_IP'), getenv('REDIS_SLAVEOF_PORT')); - } - else { - $redis->connect('redis-mailcow', 6379); - } -} -catch (Exception $e) { - exit; -} - -$raw_data_content = file_get_contents('php://input'); -$raw_data_decoded = json_decode($raw_data_content, true); - -$data['time'] = time(); -$data['rcpt'] = implode(', ', $raw_data_decoded['rcpt']); -$data['from'] = $raw_data_decoded['from']; -$data['user'] = $raw_data_decoded['user']; -$symbol_rl_key = array_search('RATELIMITED', array_column($raw_data_decoded['symbols'], 'name')); -$data['rl_info'] = implode($raw_data_decoded['symbols'][$symbol_rl_key]['options']); -preg_match('/(.+)\((.+)\)/i', $data['rl_info'], $rl_matches); -if (!empty($rl_matches[1]) && !empty($rl_matches[2])) { - $data['rl_name'] = $rl_matches[1]; - $data['rl_hash'] = $rl_matches[2]; -} -else { - $data['rl_name'] = 'err'; - $data['rl_hash'] = 'err'; -} -$data['qid'] = $raw_data_decoded['qid']; -$data['ip'] = $raw_data_decoded['ip']; -$data['message_id'] = $raw_data_decoded['message_id']; -$data['header_subject'] = implode(' ', $raw_data_decoded['header_subject']); -$data['header_from'] = implode(', ', $raw_data_decoded['header_from']); - -$redis->lpush('RL_LOG', json_encode($data)); -exit; - diff --git a/Stable2.0/conf/meta_exporter/pushover.php b/Stable2.0/conf/meta_exporter/pushover.php deleted file mode 100644 index d6d01e9..0000000 --- a/Stable2.0/conf/meta_exporter/pushover.php +++ /dev/null @@ -1,275 +0,0 @@ - PDO::ERRMODE_EXCEPTION, - PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, - PDO::ATTR_EMULATE_PREPARES => false, -]; -try { - $pdo = new PDO($dsn, $database_user, $database_pass, $opt); -} -catch (PDOException $e) { - error_log("NOTIFY: " . $e . PHP_EOL); - http_response_code(501); - exit; -} -// Init Redis -$redis = new Redis(); -$redis->connect('redis-mailcow', 6379); - -// Functions -function parse_email($email) { - if(!filter_var($email, FILTER_VALIDATE_EMAIL)) return false; - $a = strrpos($email, '@'); - return array('local' => substr($email, 0, $a), 'domain' => substr(substr($email, $a), 1)); -} -if (!function_exists('getallheaders')) { - function getallheaders() { - if (!is_array($_SERVER)) { - return array(); - } - $headers = array(); - foreach ($_SERVER as $name => $value) { - if (substr($name, 0, 5) == 'HTTP_') { - $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value; - } - } - return $headers; - } -} - -$headers = getallheaders(); -$json_body = json_decode(file_get_contents('php://input')); - -$qid = $headers['X-Rspamd-Qid']; -$rcpts = $headers['X-Rspamd-Rcpt']; -$sender = $headers['X-Rspamd-From']; -$ip = $headers['X-Rspamd-Ip']; -$subject = iconv_mime_decode($headers['X-Rspamd-Subject']); -$messageid= $json_body->message_id; -$priority = 0; - -$symbols_array = json_decode($headers['X-Rspamd-Symbols'], true); -if (is_array($symbols_array)) { - foreach ($symbols_array as $symbol) { - if ($symbol['name'] == 'HAS_X_PRIO_ONE') { - $priority = 1; - break; - } - } -} - -$sender_address = $json_body->header_from[0]; -$sender_name = '-'; -if (preg_match('/(?.*?)<(?
.*?)>/i', $sender_address, $matches)) { - $sender_address = $matches['address']; - $sender_name = trim($matches['name'], '"\' '); -} - -$to_address = $json_body->header_to[0]; -$to_name = '-'; -if (preg_match('/(?.*?)<(?
.*?)>/i', $to_address, $matches)) { - $to_address = $matches['address']; - $to_name = trim($matches['name'], '"\' '); -} - -$rcpt_final_mailboxes = array(); - -// Loop through all rcpts -foreach (json_decode($rcpts, true) as $rcpt) { - // Remove tag - $rcpt = preg_replace('/^(.*?)\+.*(@.*)$/', '$1$2', $rcpt); - - // Break rcpt into local part and domain part - $parsed_rcpt = parse_email($rcpt); - - // Skip if not a mailcow handled domain - try { - if (!$redis->hGet('DOMAIN_MAP', $parsed_rcpt['domain'])) { - continue; - } - } - catch (RedisException $e) { - error_log("NOTIFY: " . $e . PHP_EOL); - http_response_code(504); - exit; - } - - // Always assume rcpt is not a final mailbox but an alias for a mailbox or further aliases - // - // rcpt - // | - // mailbox <-- goto ---> alias1, alias2, mailbox2 - // | | - // mailbox3 | - // | - // alias3 ---> mailbox4 - // - try { - $stmt = $pdo->prepare("SELECT `goto` FROM `alias` WHERE `address` = :rcpt AND `active` = '1'"); - $stmt->execute(array( - ':rcpt' => $rcpt - )); - $gotos = $stmt->fetch(PDO::FETCH_ASSOC)['goto']; - if (empty($gotos)) { - $stmt = $pdo->prepare("SELECT `goto` FROM `alias` WHERE `address` = :rcpt AND `active` = '1'"); - $stmt->execute(array( - ':rcpt' => '@' . $parsed_rcpt['domain'] - )); - $gotos = $stmt->fetch(PDO::FETCH_ASSOC)['goto']; - } - if (empty($gotos)) { - $stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :rcpt AND `active` = '1'"); - $stmt->execute(array(':rcpt' => $parsed_rcpt['domain'])); - $goto_branch = $stmt->fetch(PDO::FETCH_ASSOC)['target_domain']; - if ($goto_branch) { - $gotos = $parsed_rcpt['local'] . '@' . $goto_branch; - } - } - $gotos_array = explode(',', $gotos); - - $loop_c = 0; - - while (count($gotos_array) != 0 && $loop_c <= 20) { - - // Loop through all found gotos - foreach ($gotos_array as $index => &$goto) { - error_log("RCPT RESOVLER: http pipe: query " . $goto . " as username from mailbox" . PHP_EOL); - $stmt = $pdo->prepare("SELECT `username` FROM `mailbox` WHERE `username` = :goto AND (`active`= '1' OR `active`= '2');"); - $stmt->execute(array(':goto' => $goto)); - $username = $stmt->fetch(PDO::FETCH_ASSOC)['username']; - if (!empty($username)) { - error_log("RCPT RESOVLER: http pipe: mailbox found: " . $username . PHP_EOL); - // Current goto is a mailbox, save to rcpt_final_mailboxes if not a duplicate - if (!in_array($username, $rcpt_final_mailboxes)) { - $rcpt_final_mailboxes[] = $username; - } - } - else { - $parsed_goto = parse_email($goto); - if (!$redis->hGet('DOMAIN_MAP', $parsed_goto['domain'])) { - error_log("RCPT RESOVLER:" . $goto . " is not a mailcow handled mailbox or alias address" . PHP_EOL); - } - else { - $stmt = $pdo->prepare("SELECT `goto` FROM `alias` WHERE `address` = :goto AND `active` = '1'"); - $stmt->execute(array(':goto' => $goto)); - $goto_branch = $stmt->fetch(PDO::FETCH_ASSOC)['goto']; - if ($goto_branch) { - error_log("RCPT RESOVLER: http pipe: goto address " . $goto . " is an alias branch for " . $goto_branch . PHP_EOL); - $goto_branch_array = explode(',', $goto_branch); - } else { - $stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :domain AND `active` AND '1'"); - $stmt->execute(array(':domain' => $parsed_goto['domain'])); - $goto_branch = $stmt->fetch(PDO::FETCH_ASSOC)['target_domain']; - if ($goto_branch) { - error_log("RCPT RESOVLER: http pipe: goto domain " . $parsed_goto['domain'] . " is a domain alias branch for " . $goto_branch . PHP_EOL); - $goto_branch_array = array($parsed_goto['local'] . '@' . $goto_branch); - } - } - } - } - // goto item was processed, unset - unset($gotos_array[$index]); - } - - // Merge goto branch array derived from previous loop (if any), filter duplicates and unset goto branch array - if (!empty($goto_branch_array)) { - $gotos_array = array_unique(array_merge($gotos_array, $goto_branch_array)); - unset($goto_branch_array); - } - - // Reindex array - $gotos_array = array_values($gotos_array); - - // Force exit if loop cannot be solved - // Postfix does not allow for alias loops, so this should never happen. - $loop_c++; - error_log("RCPT RESOVLER: http pipe: goto array count on loop #". $loop_c . " is " . count($gotos_array) . PHP_EOL); - } - } - catch (PDOException $e) { - error_log("RCPT RESOVLER: " . $e->getMessage() . PHP_EOL); - http_response_code(502); - exit; - } -} - - -foreach ($rcpt_final_mailboxes as $rcpt_final) { - error_log("NOTIFY: pushover pipe: processing pushover message for rcpt " . $rcpt_final . PHP_EOL); - $stmt = $pdo->prepare("SELECT * FROM `pushover` - WHERE `username` = :username AND `active` = '1'"); - $stmt->execute(array( - ':username' => $rcpt_final - )); - $api_data = $stmt->fetch(PDO::FETCH_ASSOC); - if (isset($api_data['key']) && isset($api_data['token'])) { - $title = (!empty($api_data['title'])) ? $api_data['title'] : 'Mail'; - $text = (!empty($api_data['text'])) ? $api_data['text'] : 'You\'ve got mail šŸ“§'; - $attributes = json_decode($api_data['attributes'], true); - $senders = explode(',', $api_data['senders']); - $senders = array_filter($senders); - $senders_regex = $api_data['senders_regex']; - $sender_validated = false; - if (empty($senders) && empty($senders_regex)) { - $sender_validated = true; - } - else { - if (!empty($senders)) { - if (in_array($sender, $senders)) { - $sender_validated = true; - } - } - if (!empty($senders_regex) && $sender_validated !== true) { - if (preg_match($senders_regex, $sender)) { - $sender_validated = true; - } - } - } - if ($sender_validated === false) { - error_log("NOTIFY: pushover pipe: skipping unwanted sender " . $sender); - continue; - } - if ($attributes['only_x_prio'] == "1" && $priority == 0) { - error_log("NOTIFY: pushover pipe: mail has no X-Priority: 1 header, skipping"); - continue; - } - $post_fields = array( - "token" => $api_data['token'], - "user" => $api_data['key'], - "title" => sprintf("%s", str_replace( - array('{SUBJECT}', '{SENDER}', '{SENDER_NAME}', '{SENDER_ADDRESS}', '{TO_NAME}', '{TO_ADDRESS}', '{MSG_ID}'), - array($subject, $sender, $sender_name, $sender_address, $to_name, $to_address, $messageid), $title) - ), - "priority" => $priority, - "message" => sprintf("%s", str_replace( - array('{SUBJECT}', '{SENDER}', '{SENDER_NAME}', '{SENDER_ADDRESS}', '{TO_NAME}', '{TO_ADDRESS}', '{MSG_ID}', '\n'), - array($subject, $sender, $sender_name, $sender_address, $to_name, $to_address, $messageid, PHP_EOL), $text) - ), - "sound" => $attributes['sound'] ?? "pushover" - ); - if ($attributes['evaluate_x_prio'] == "1" && $priority == 1) { - $post_fields['expire'] = 600; - $post_fields['retry'] = 120; - $post_fields['priority'] = 2; - } - curl_setopt_array($ch = curl_init(), array( - CURLOPT_URL => "https://api.pushover.net/1/messages.json", - CURLOPT_POSTFIELDS => $post_fields, - CURLOPT_SAFE_UPLOAD => true, - CURLOPT_RETURNTRANSFER => true, - )); - $result = curl_exec($ch); - $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE); - curl_close($ch); - error_log("NOTIFY: result: " . $httpcode . PHP_EOL); - } -} diff --git a/Stable2.0/conf/meta_exporter/vars.inc.php b/Stable2.0/conf/meta_exporter/vars.inc.php deleted file mode 100644 index 79566b0..0000000 --- a/Stable2.0/conf/meta_exporter/vars.inc.php +++ /dev/null @@ -1,6 +0,0 @@ - diff --git a/Stable2.0/conf/override.d/logging.inc b/Stable2.0/conf/override.d/logging.inc deleted file mode 100644 index 64d4064..0000000 --- a/Stable2.0/conf/override.d/logging.inc +++ /dev/null @@ -1,5 +0,0 @@ -level = "silent"; -type = "console"; -systemd = false; -.include "$CONFDIR/logging.inc" -.include(try=true; priority=20) "$CONFDIR/override.d/logging.custom.inc" diff --git a/Stable2.0/conf/override.d/ratelimit.conf b/Stable2.0/conf/override.d/ratelimit.conf deleted file mode 100644 index 3379149..0000000 --- a/Stable2.0/conf/override.d/ratelimit.conf +++ /dev/null @@ -1,4 +0,0 @@ -whitelisted_rcpts = "postmaster,mailer-daemon"; -max_rcpt = 25; -custom_keywords = "/etc/rspamd/lua/ratelimit.lua"; -info_symbol = "RATELIMITED"; diff --git a/Stable2.0/conf/override.d/worker-controller.inc b/Stable2.0/conf/override.d/worker-controller.inc deleted file mode 100644 index 8c929b1..0000000 --- a/Stable2.0/conf/override.d/worker-controller.inc +++ /dev/null @@ -1,7 +0,0 @@ -bind_socket = "*:11334"; -count = 1; -secure_ip = "127.0.0.1"; -secure_ip = "::1"; -bind_socket = "/var/lib/rspamd/rspamd.sock mode=0666 owner=nobody"; -.include(try=true; priority=10) "$CONFDIR/override.d/worker-controller-password.inc" -.include(try=true; priority=30) "$CONFDIR/override.d/worker-controller.custom.inc" diff --git a/Stable2.0/conf/override.d/worker-fuzzy.inc b/Stable2.0/conf/override.d/worker-fuzzy.inc deleted file mode 100644 index 291e615..0000000 --- a/Stable2.0/conf/override.d/worker-fuzzy.inc +++ /dev/null @@ -1,12 +0,0 @@ -# Socket to listen on (UDP and TCP from rspamd 1.3) -bind_socket = "*:11445"; -allow_update = ["127.0.0.1", "::1"]; -# Number of processes to serve this storage (useful for read scaling) -count = 1; -# Backend ("sqlite" or "redis" - default "sqlite") -backend = "redis"; -# Hashes storage time (3 months) -expire = 90d; -# Synchronize updates to the storage each minute -sync = 1min; - diff --git a/Stable2.0/conf/override.d/worker-normal.inc b/Stable2.0/conf/override.d/worker-normal.inc deleted file mode 100644 index d206757..0000000 --- a/Stable2.0/conf/override.d/worker-normal.inc +++ /dev/null @@ -1,4 +0,0 @@ -bind_socket = "*:11333"; -task_timeout = 25s; -count = 1; -.include(try=true; priority=30) "$CONFDIR/override.d/worker-normal.custom.inc" diff --git a/Stable2.0/conf/override.d/worker-proxy.inc b/Stable2.0/conf/override.d/worker-proxy.inc deleted file mode 100644 index 9eb4775..0000000 --- a/Stable2.0/conf/override.d/worker-proxy.inc +++ /dev/null @@ -1,9 +0,0 @@ -bind_socket = "rspamd:9900"; -milter = true; -upstream "local" { - name = "localhost"; - default = true; - hosts = "rspamd:11333" -} -reject_message = "This message does not meet our delivery requirements"; -.include(try=true; priority=30) "$CONFDIR/override.d/worker-proxy.custom.inc" diff --git a/Stable2.0/conf/plugins.d/README.md b/Stable2.0/conf/plugins.d/README.md deleted file mode 100644 index 1516cf2..0000000 --- a/Stable2.0/conf/plugins.d/README.md +++ /dev/null @@ -1 +0,0 @@ -This is where you should copy any rspamd custom module diff --git a/Stable2.0/conf/rspamd.conf.local b/Stable2.0/conf/rspamd.conf.local deleted file mode 100644 index 9f2f8f1..0000000 --- a/Stable2.0/conf/rspamd.conf.local +++ /dev/null @@ -1 +0,0 @@ -# rspamd.conf.local diff --git a/Stable2.0/conf/rspamd.conf.override b/Stable2.0/conf/rspamd.conf.override deleted file mode 100644 index d033e8e..0000000 --- a/Stable2.0/conf/rspamd.conf.override +++ /dev/null @@ -1,2 +0,0 @@ -# rspamd.conf.override - diff --git a/Stable2.0/docker-entrypoint.sh b/Stable2.0/docker-entrypoint.sh new file mode 100644 index 0000000..f7c2203 --- /dev/null +++ b/Stable2.0/docker-entrypoint.sh @@ -0,0 +1,267 @@ +#!/bin/bash + +# mkdir -p /etc/rspamd/plugins.d \ +# /etc/rspamd/custom + +# touch /etc/rspamd/rspamd.conf.local \ +# /etc/rspamd/rspamd.conf.override + +chmod 755 /var/lib/rspamd + + +[[ ! -f /etc/rspamd/override.d/worker-controller-password.inc ]] && echo '# Autogenerated' > /etc/rspamd/override.d/worker-controller-password.inc + +if [[ ! -z ${REDIS_SLAVEOF_IP} ]]; then + cat < /etc/rspamd/local.d/redis.conf +read_servers = "redis:6379"; +write_servers = "${REDIS_SLAVEOF_IP}:${REDIS_SLAVEOF_PORT}"; +timeout = 10; +EOF + until [[ $(redis-cli -h redis-mailcow PING) == "PONG" ]]; do + echo "Waiting for Redis @redis-mailcow..." + sleep 2 + done + until [[ $(redis-cli -h ${REDIS_SLAVEOF_IP} -p ${REDIS_SLAVEOF_PORT} PING) == "PONG" ]]; do + echo "Waiting for Redis @${REDIS_SLAVEOF_IP}..." + sleep 2 + done + redis-cli -h redis-mailcow SLAVEOF ${REDIS_SLAVEOF_IP} ${REDIS_SLAVEOF_PORT} +else + cat < /etc/rspamd/local.d/redis.conf +servers = "redis:6379"; +timeout = 10; +db = 1 +EOF +fi + +# Provide additional lua modules +ln -s /usr/lib/$(uname -m)-linux-gnu/liblua5.1-cjson.so.0.0.0 /usr/lib/rspamd/cjson.so + +chown -R _rspamd:_rspamd /var/lib/rspamd \ + /etc/rspamd/local.d \ + /etc/rspamd/override.d \ + /etc/rspamd/rspamd.conf.local \ + /etc/rspamd/rspamd.conf.override \ + /etc/rspamd/plugins.d + +# Fix missing default global maps, if any +# These exists in mailcow UI and should not be removed +touch /etc/rspamd/custom/global_mime_from_blacklist.map \ + /etc/rspamd/custom/global_rcpt_blacklist.map \ + /etc/rspamd/custom/global_smtp_from_blacklist.map \ + /etc/rspamd/custom/global_mime_from_whitelist.map \ + /etc/rspamd/custom/global_rcpt_whitelist.map \ + /etc/rspamd/custom/global_smtp_from_whitelist.map \ + /etc/rspamd/custom/bad_languages.map \ + /etc/rspamd/custom/sa-rules \ + /etc/rspamd/custom/dovecot_trusted.map \ + /etc/rspamd/custom/rspamd_trusted.map \ + /etc/rspamd/custom/mailcow_networks.map \ + /etc/rspamd/custom/ip_wl.map \ + /etc/rspamd/custom/fishy_tlds.map \ + /etc/rspamd/custom/bad_words.map \ + /etc/rspamd/custom/bad_asn.map \ + /etc/rspamd/custom/bad_words_de.map \ + /etc/rspamd/custom/bulk_header.map \ + /etc/rspamd/custom/bad_header.map + +# www-data (82) group needs to write to these files +chown _rspamd:_rspamd /etc/rspamd/custom/ +chmod 0755 /etc/rspamd/custom/. +chmod 644 -R /etc/rspamd/custom/* + +# Run hooks +for file in /hooks/*; do + if [ -x "${file}" ]; then + echo "Running hook ${file}" + "${file}" + fi +done + +# If DQS KEY is set in mailcow.conf add Spamhaus DQS RBLs +if [[ ! -z ${SPAMHAUS_DQS_KEY} ]]; then + cat < /etc/rspamd/custom/dqs-rbl.conf + # Autogenerated by mailcow. DO NOT TOUCH! + spamhaus { + rbl = "${SPAMHAUS_DQS_KEY}.zen.dq.spamhaus.net"; + from = false; + } + spamhaus_from { + from = true; + received = false; + rbl = "${SPAMHAUS_DQS_KEY}.zen.dq.spamhaus.net"; + returncodes { + SPAMHAUS_ZEN = [ "127.0.0.2", "127.0.0.3", "127.0.0.4", "127.0.0.5", "127.0.0.6", "127.0.0.7", "127.0.0.9", "127.0.0.10", "127.0.0.11" ]; + } + } + spamhaus_authbl_received { + # Check if the sender client is listed in AuthBL (AuthBL is *not* part of ZEN) + rbl = "${SPAMHAUS_DQS_KEY}.authbl.dq.spamhaus.net"; + from = false; + received = true; + ipv6 = true; + returncodes { + SH_AUTHBL_RECEIVED = "127.0.0.20" + } + } + spamhaus_dbl { + # Add checks on the HELO string + rbl = "${SPAMHAUS_DQS_KEY}.dbl.dq.spamhaus.net"; + helo = true; + rdns = true; + dkim = true; + disable_monitoring = true; + returncodes { + RBL_DBL_SPAM = "127.0.1.2"; + RBL_DBL_PHISH = "127.0.1.4"; + RBL_DBL_MALWARE = "127.0.1.5"; + RBL_DBL_BOTNET = "127.0.1.6"; + RBL_DBL_ABUSED_SPAM = "127.0.1.102"; + RBL_DBL_ABUSED_PHISH = "127.0.1.104"; + RBL_DBL_ABUSED_MALWARE = "127.0.1.105"; + RBL_DBL_ABUSED_BOTNET = "127.0.1.106"; + RBL_DBL_DONT_QUERY_IPS = "127.0.1.255"; + } + } + spamhaus_dbl_fullurls { + ignore_defaults = true; + no_ip = true; + rbl = "${SPAMHAUS_DQS_KEY}.dbl.dq.spamhaus.net"; + selector = 'urls:get_host' + disable_monitoring = true; + returncodes { + DBLABUSED_SPAM_FULLURLS = "127.0.1.102"; + DBLABUSED_PHISH_FULLURLS = "127.0.1.104"; + DBLABUSED_MALWARE_FULLURLS = "127.0.1.105"; + DBLABUSED_BOTNET_FULLURLS = "127.0.1.106"; + } + } + spamhaus_zrd { + # Add checks on the HELO string also for DQS + rbl = "${SPAMHAUS_DQS_KEY}.zrd.dq.spamhaus.net"; + helo = true; + rdns = true; + dkim = true; + disable_monitoring = true; + returncodes { + RBL_ZRD_VERY_FRESH_DOMAIN = ["127.0.2.2", "127.0.2.3", "127.0.2.4"]; + RBL_ZRD_FRESH_DOMAIN = [ + "127.0.2.5", "127.0.2.6", "127.0.2.7", "127.0.2.8", "127.0.2.9", "127.0.2.10", "127.0.2.11", "127.0.2.12", "127.0.2.13", "127.0.2.14", "127.0.2.15", "127.0.2.16", "127.0.2.17", "127.0.2.18", "127.0.2.19", "127.0.2.20", "127.0.2.21", "127.0.2.22", "127.0.2.23", "127.0.2.24" + ]; + RBL_ZRD_DONT_QUERY_IPS = "127.0.2.255"; + } + } + "SPAMHAUS_ZEN_URIBL" { + enabled = true; + rbl = "${SPAMHAUS_DQS_KEY}.zen.dq.spamhaus.net"; + resolve_ip = true; + checks = ['urls']; + replyto = true; + emails = true; + ipv4 = true; + ipv6 = true; + emails_domainonly = true; + returncodes { + URIBL_SBL = "127.0.0.2"; + URIBL_SBL_CSS = "127.0.0.3"; + URIBL_XBL = ["127.0.0.4", "127.0.0.5", "127.0.0.6", "127.0.0.7"]; + URIBL_PBL = ["127.0.0.10", "127.0.0.11"]; + URIBL_DROP = "127.0.0.9"; + } + } + SH_EMAIL_DBL { + ignore_defaults = true; + replyto = true; + emails_domainonly = true; + disable_monitoring = true; + rbl = "${SPAMHAUS_DQS_KEY}.dbl.dq.spamhaus.net"; + returncodes = { + SH_EMAIL_DBL = [ + "127.0.1.2", + "127.0.1.4", + "127.0.1.5", + "127.0.1.6" + ]; + SH_EMAIL_DBL_ABUSED = [ + "127.0.1.102", + "127.0.1.104", + "127.0.1.105", + "127.0.1.106" + ]; + SH_EMAIL_DBL_DONT_QUERY_IPS = [ "127.0.1.255" ]; + } + } + SH_EMAIL_ZRD { + ignore_defaults = true; + replyto = true; + emails_domainonly = true; + disable_monitoring = true; + rbl = "${SPAMHAUS_DQS_KEY}.zrd.dq.spamhaus.net"; + returncodes = { + SH_EMAIL_ZRD_VERY_FRESH_DOMAIN = ["127.0.2.2", "127.0.2.3", "127.0.2.4"]; + SH_EMAIL_ZRD_FRESH_DOMAIN = [ + "127.0.2.5", "127.0.2.6", "127.0.2.7", "127.0.2.8", "127.0.2.9", "127.0.2.10", "127.0.2.11", "127.0.2.12", "127.0.2.13", "127.0.2.14", "127.0.2.15", "127.0.2.16", "127.0.2.17", "127.0.2.18", "127.0.2.19", "127.0.2.20", "127.0.2.21", "127.0.2.22", "127.0.2.23", "127.0.2.24" + ]; + SH_EMAIL_ZRD_DONT_QUERY_IPS = [ "127.0.2.255" ]; + } + } + "DBL" { + # override the defaults for DBL defined in modules.d/rbl.conf + rbl = "${SPAMHAUS_DQS_KEY}.dbl.dq.spamhaus.net"; + disable_monitoring = true; + } + "ZRD" { + ignore_defaults = true; + rbl = "${SPAMHAUS_DQS_KEY}.zrd.dq.spamhaus.net"; + no_ip = true; + dkim = true; + emails = true; + emails_domainonly = true; + urls = true; + returncodes = { + ZRD_VERY_FRESH_DOMAIN = ["127.0.2.2", "127.0.2.3", "127.0.2.4"]; + ZRD_FRESH_DOMAIN = ["127.0.2.5", "127.0.2.6", "127.0.2.7", "127.0.2.8", "127.0.2.9", "127.0.2.10", "127.0.2.11", "127.0.2.12", "127.0.2.13", "127.0.2.14", "127.0.2.15", "127.0.2.16", "127.0.2.17", "127.0.2.18", "127.0.2.19", "127.0.2.20", "127.0.2.21", "127.0.2.22", "127.0.2.23", "127.0.2.24"]; + } + } + spamhaus_sbl_url { + ignore_defaults = true + rbl = "${SPAMHAUS_DQS_KEY}.sbl.dq.spamhaus.net"; + checks = ['urls']; + disable_monitoring = true; + returncodes { + SPAMHAUS_SBL_URL = "127.0.0.2"; + } + } + + SH_HBL_EMAIL { + ignore_defaults = true; + rbl = "_email.${SPAMHAUS_DQS_KEY}.hbl.dq.spamhaus.net"; + emails_domainonly = false; + selector = "from('smtp').lower;from('mime').lower"; + ignore_whitelist = true; + checks = ['emails', 'replyto']; + hash = "sha1"; + returncodes = { + SH_HBL_EMAIL = [ + "127.0.3.2" + ]; + } + } + + spamhaus_dqs_hbl { + symbol = "HBL_FILE_UNKNOWN"; + rbl = "_file.${SPAMHAUS_DQS_KEY}.hbl.dq.spamhaus.net."; + selector = "attachments('rbase32', 'sha256')"; + ignore_whitelist = true; + ignore_defaults = true; + returncodes { + SH_HBL_FILE_MALICIOUS = "127.0.3.10"; + SH_HBL_FILE_SUSPICIOUS = "127.0.3.15"; + } + } +EOF +else + rm -rf /etc/rspamd/custom/dqs-rbl.conf +fi + +exec "$@" \ No newline at end of file diff --git a/Stable2.0/hooks/build b/Stable2.0/hooks/build index fdce536..bff954c 100644 --- a/Stable2.0/hooks/build +++ b/Stable2.0/hooks/build @@ -9,8 +9,9 @@ VERSION=$(git ls-remote --tags -q https://github.com/rspamd/rspamd | sed -n "s/^ IMAGE_NAME=docker-rspamd +zip -r config + docker build \ - --no-cache \ --build-arg VERSION=${VERSION} \ --build-arg COMMIT=$(git ls-remote --tags -q https://github.com/rspamd/rspamd | sed -n "s/^\([[:xdigit:]]\{40\}\)[[:blank:]]refs\/tags\/${VERSION}^{}$/\1/p" | xargs git rev-parse --short) \ --build-arg BRANCH=$(git rev-parse --abbrev-ref HEAD) \ diff --git a/Stable2.0/set_worker_password.sh b/Stable2.0/set_worker_password.sh new file mode 100644 index 0000000..7205e88 --- /dev/null +++ b/Stable2.0/set_worker_password.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +password_file='/etc/rspamd/override.d/worker-controller-password.inc' +password_hash=`/usr/bin/rspamadm pw -e -p $1` + +echo 'enable_password = "'$password_hash'";' > $password_file + +if grep -q "$password_hash" "$password_file"; then + echo "OK" +else + echo "ERROR" +fi \ No newline at end of file From 990d21511af9a6078a2904bfccaeceec3c8722c0 Mon Sep 17 00:00:00 2001 From: Patrick Niebeling Date: Wed, 6 Nov 2024 20:52:44 +0100 Subject: [PATCH 07/20] Add No Cache Signed-off-by: Patrick Niebeling --- Stable2.0/hooks/build | 1 + 1 file changed, 1 insertion(+) diff --git a/Stable2.0/hooks/build b/Stable2.0/hooks/build index bff954c..0071a64 100644 --- a/Stable2.0/hooks/build +++ b/Stable2.0/hooks/build @@ -12,6 +12,7 @@ IMAGE_NAME=docker-rspamd zip -r config docker build \ + --no-cache \ --build-arg VERSION=${VERSION} \ --build-arg COMMIT=$(git ls-remote --tags -q https://github.com/rspamd/rspamd | sed -n "s/^\([[:xdigit:]]\{40\}\)[[:blank:]]refs\/tags\/${VERSION}^{}$/\1/p" | xargs git rev-parse --short) \ --build-arg BRANCH=$(git rev-parse --abbrev-ref HEAD) \ From 59bafa2ba4e123c1bc92e8951c44e4f1f62798e8 Mon Sep 17 00:00:00 2001 From: Patrick Niebeling Date: Wed, 6 Nov 2024 20:53:24 +0100 Subject: [PATCH 08/20] Remove Config Signed-off-by: Patrick Niebeling --- Stable2.0/hooks/build | 2 -- 1 file changed, 2 deletions(-) diff --git a/Stable2.0/hooks/build b/Stable2.0/hooks/build index 0071a64..fdce536 100644 --- a/Stable2.0/hooks/build +++ b/Stable2.0/hooks/build @@ -9,8 +9,6 @@ VERSION=$(git ls-remote --tags -q https://github.com/rspamd/rspamd | sed -n "s/^ IMAGE_NAME=docker-rspamd -zip -r config - docker build \ --no-cache \ --build-arg VERSION=${VERSION} \ From b1df8681a4f4784228f3f1ac6decd02a1c3c9b86 Mon Sep 17 00:00:00 2001 From: Patrick Niebeling Date: Wed, 6 Nov 2024 20:54:14 +0100 Subject: [PATCH 09/20] Fix warning Signed-off-by: Patrick Niebeling --- Stable2.0/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Stable2.0/Dockerfile b/Stable2.0/Dockerfile index a4916da..1dcfade 100644 --- a/Stable2.0/Dockerfile +++ b/Stable2.0/Dockerfile @@ -2,7 +2,7 @@ FROM debian:stable-slim LABEL maintainer="gnilebein - " # Set apt non-interactive -ENV DEBIAN_FRONTEND noninteractive +ENV DEBIAN_FRONTEND=noninteractive # Install Rspamd RUN set -x \ From db022c363fc54042bb1b763bd1a518d7e07f3e80 Mon Sep 17 00:00:00 2001 From: Patrick Niebeling Date: Wed, 6 Nov 2024 21:00:07 +0100 Subject: [PATCH 10/20] Fix Things Signed-off-by: Patrick Niebeling --- Stable2.0/docker-entrypoint.sh | 26 ++------------------------ 1 file changed, 2 insertions(+), 24 deletions(-) diff --git a/Stable2.0/docker-entrypoint.sh b/Stable2.0/docker-entrypoint.sh index f7c2203..969507e 100644 --- a/Stable2.0/docker-entrypoint.sh +++ b/Stable2.0/docker-entrypoint.sh @@ -11,41 +11,19 @@ chmod 755 /var/lib/rspamd [[ ! -f /etc/rspamd/override.d/worker-controller-password.inc ]] && echo '# Autogenerated' > /etc/rspamd/override.d/worker-controller-password.inc -if [[ ! -z ${REDIS_SLAVEOF_IP} ]]; then - cat < /etc/rspamd/local.d/redis.conf -read_servers = "redis:6379"; -write_servers = "${REDIS_SLAVEOF_IP}:${REDIS_SLAVEOF_PORT}"; -timeout = 10; -EOF - until [[ $(redis-cli -h redis-mailcow PING) == "PONG" ]]; do - echo "Waiting for Redis @redis-mailcow..." - sleep 2 - done - until [[ $(redis-cli -h ${REDIS_SLAVEOF_IP} -p ${REDIS_SLAVEOF_PORT} PING) == "PONG" ]]; do - echo "Waiting for Redis @${REDIS_SLAVEOF_IP}..." - sleep 2 - done - redis-cli -h redis-mailcow SLAVEOF ${REDIS_SLAVEOF_IP} ${REDIS_SLAVEOF_PORT} -else - cat < /etc/rspamd/local.d/redis.conf -servers = "redis:6379"; -timeout = 10; -db = 1 -EOF -fi - # Provide additional lua modules ln -s /usr/lib/$(uname -m)-linux-gnu/liblua5.1-cjson.so.0.0.0 /usr/lib/rspamd/cjson.so chown -R _rspamd:_rspamd /var/lib/rspamd \ /etc/rspamd/local.d \ + /etc/rspamd/custom \ /etc/rspamd/override.d \ /etc/rspamd/rspamd.conf.local \ /etc/rspamd/rspamd.conf.override \ /etc/rspamd/plugins.d # Fix missing default global maps, if any -# These exists in mailcow UI and should not be removed +# These exists in UI and should not be removed touch /etc/rspamd/custom/global_mime_from_blacklist.map \ /etc/rspamd/custom/global_rcpt_blacklist.map \ /etc/rspamd/custom/global_smtp_from_blacklist.map \ From 5c156f1c8d0b1b36e743ebeeb05222b2bea65e77 Mon Sep 17 00:00:00 2001 From: Patrick Niebeling Date: Wed, 6 Nov 2024 21:16:50 +0100 Subject: [PATCH 11/20] Fix Signed-off-by: Patrick Niebeling --- Stable2.0/Dockerfile | 5 ++++- Stable2.0/docker-entrypoint.sh | 18 ------------------ 2 files changed, 4 insertions(+), 19 deletions(-) diff --git a/Stable2.0/Dockerfile b/Stable2.0/Dockerfile index 1dcfade..afabd73 100644 --- a/Stable2.0/Dockerfile +++ b/Stable2.0/Dockerfile @@ -43,6 +43,9 @@ HEALTHCHECK --interval=1m --timeout=5s --start-period=10s \ # Run Rspamd ENTRYPOINT ["/docker-entrypoint.sh"] + +STOPSIGNAL SIGTERM + CMD ["/usr/bin/rspamd", "-f", "-u", "_rspamd", "-g", "_rspamd"] # Setup Labels @@ -60,4 +63,4 @@ LABEL org.label-schema.name="Rspamd" \ org.label-schema.version=$VERSION \ org.label-schema.vcs-url="https://github.com/rspamd/rspamd/" \ org.label-schema.vcs-ref=$COMMIT \ - org.label-schema.build-date=$DATE \ + org.label-schema.build-date=$DATE \ \ No newline at end of file diff --git a/Stable2.0/docker-entrypoint.sh b/Stable2.0/docker-entrypoint.sh index 969507e..70e7ae4 100644 --- a/Stable2.0/docker-entrypoint.sh +++ b/Stable2.0/docker-entrypoint.sh @@ -1,19 +1,10 @@ #!/bin/bash -# mkdir -p /etc/rspamd/plugins.d \ -# /etc/rspamd/custom - -# touch /etc/rspamd/rspamd.conf.local \ -# /etc/rspamd/rspamd.conf.override - chmod 755 /var/lib/rspamd [[ ! -f /etc/rspamd/override.d/worker-controller-password.inc ]] && echo '# Autogenerated' > /etc/rspamd/override.d/worker-controller-password.inc -# Provide additional lua modules -ln -s /usr/lib/$(uname -m)-linux-gnu/liblua5.1-cjson.so.0.0.0 /usr/lib/rspamd/cjson.so - chown -R _rspamd:_rspamd /var/lib/rspamd \ /etc/rspamd/local.d \ /etc/rspamd/custom \ @@ -43,19 +34,10 @@ touch /etc/rspamd/custom/global_mime_from_blacklist.map \ /etc/rspamd/custom/bulk_header.map \ /etc/rspamd/custom/bad_header.map -# www-data (82) group needs to write to these files chown _rspamd:_rspamd /etc/rspamd/custom/ chmod 0755 /etc/rspamd/custom/. chmod 644 -R /etc/rspamd/custom/* -# Run hooks -for file in /hooks/*; do - if [ -x "${file}" ]; then - echo "Running hook ${file}" - "${file}" - fi -done - # If DQS KEY is set in mailcow.conf add Spamhaus DQS RBLs if [[ ! -z ${SPAMHAUS_DQS_KEY} ]]; then cat < /etc/rspamd/custom/dqs-rbl.conf From b26117e5e3da23cd5ab741cb12be5d291ed8ae77 Mon Sep 17 00:00:00 2001 From: Patrick Niebeling Date: Wed, 6 Nov 2024 21:34:45 +0100 Subject: [PATCH 12/20] Fix Entry Signed-off-by: Patrick Niebeling --- Stable2.0/docker-entrypoint.sh | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/Stable2.0/docker-entrypoint.sh b/Stable2.0/docker-entrypoint.sh index 70e7ae4..e453925 100644 --- a/Stable2.0/docker-entrypoint.sh +++ b/Stable2.0/docker-entrypoint.sh @@ -2,16 +2,11 @@ chmod 755 /var/lib/rspamd - [[ ! -f /etc/rspamd/override.d/worker-controller-password.inc ]] && echo '# Autogenerated' > /etc/rspamd/override.d/worker-controller-password.inc -chown -R _rspamd:_rspamd /var/lib/rspamd \ - /etc/rspamd/local.d \ - /etc/rspamd/custom \ - /etc/rspamd/override.d \ - /etc/rspamd/rspamd.conf.local \ - /etc/rspamd/rspamd.conf.override \ - /etc/rspamd/plugins.d +mkdir -p /etc/rspamd/custom + +chown -R _rspamd:_rspamd /var/lib/rspamd /etc/rspamd/ # Fix missing default global maps, if any # These exists in UI and should not be removed @@ -34,10 +29,6 @@ touch /etc/rspamd/custom/global_mime_from_blacklist.map \ /etc/rspamd/custom/bulk_header.map \ /etc/rspamd/custom/bad_header.map -chown _rspamd:_rspamd /etc/rspamd/custom/ -chmod 0755 /etc/rspamd/custom/. -chmod 644 -R /etc/rspamd/custom/* - # If DQS KEY is set in mailcow.conf add Spamhaus DQS RBLs if [[ ! -z ${SPAMHAUS_DQS_KEY} ]]; then cat < /etc/rspamd/custom/dqs-rbl.conf From c4aed2f96c597540a698f203eca0a8d5b276bb68 Mon Sep 17 00:00:00 2001 From: Patrick Niebeling Date: Wed, 6 Nov 2024 21:40:07 +0100 Subject: [PATCH 13/20] Fix Signed-off-by: Patrick Niebeling --- Stable2.0/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Stable2.0/Dockerfile b/Stable2.0/Dockerfile index afabd73..d2d6522 100644 --- a/Stable2.0/Dockerfile +++ b/Stable2.0/Dockerfile @@ -42,7 +42,7 @@ HEALTHCHECK --interval=1m --timeout=5s --start-period=10s \ CMD /usr/bin/rspamadm control stat || exit 1 # Run Rspamd -ENTRYPOINT ["/docker-entrypoint.sh"] +ENTRYPOINT ["bash", "-c", "/docker-entrypoint.sh"] STOPSIGNAL SIGTERM From 6b6b65d28e58c8cc450cb2a7d4304abe3d93b97f Mon Sep 17 00:00:00 2001 From: Patrick Niebeling Date: Wed, 6 Nov 2024 22:08:21 +0100 Subject: [PATCH 14/20] Remove VOlumes Signed-off-by: Patrick Niebeling --- Stable2.0/Dockerfile | 52 +++++++++++++++++----------------- Stable2.0/docker-entrypoint.sh | 42 +++++++++++++-------------- 2 files changed, 47 insertions(+), 47 deletions(-) diff --git a/Stable2.0/Dockerfile b/Stable2.0/Dockerfile index d2d6522..8e99652 100644 --- a/Stable2.0/Dockerfile +++ b/Stable2.0/Dockerfile @@ -1,5 +1,22 @@ FROM debian:stable-slim -LABEL maintainer="gnilebein - " +LABEL maintainer="gnilebein - " + +# Setup Labels +ARG VERSION +ARG COMMIT +ARG BRANCH +ARG DATE + +LABEL org.label-schema.name="Rspamd" \ + org.label-schema.description="Rspamd Spam Filter - STABLE" \ + org.label-schema.usage="https://hub.docker.com/r/gnilebein/rspamd/" \ + org.label-schema.url="https://rspamd.com" \ + org.label-schema.vendor="gnilebein" \ + org.label-schema.schema-version="1.0" \ + org.label-schema.version=$VERSION \ + org.label-schema.vcs-url="https://github.com/rspamd/rspamd/" \ + org.label-schema.vcs-ref=$COMMIT \ + org.label-schema.build-date=$DATE # Set apt non-interactive ENV DEBIAN_FRONTEND=noninteractive @@ -7,7 +24,7 @@ ENV DEBIAN_FRONTEND=noninteractive # Install Rspamd RUN set -x \ && apt update \ - && apt --no-install-recommends install -y lsb-release wget gnupg openssl ca-certificates nano less \ + && apt --no-install-recommends install -y apt-transport-https dnsutils netcat-traditional lsb-release wget gnupg openssl ca-certificates nano less \ && DEBIAN_CODE_NAME=`lsb_release -c -s` \ && wget -O - https://rspamd.com/apt-stable/gpg.key | apt-key add - \ && echo "deb http://rspamd.com/apt-stable/ $DEBIAN_CODE_NAME main" > /etc/apt/sources.list.d/rspamd.list \ @@ -26,11 +43,11 @@ COPY worker-proxy.inc /etc/rspamd/override.d/ COPY set_worker_password.sh /set_worker_password.sh COPY docker-entrypoint.sh /docker-entrypoint.sh -# Keep database and configuration persistent -VOLUME /etc/rspamd/local.d -VOLUME /etc/rspamd/override.d -VOLUME /etc/rspamd/custom -VOLUME /var/lib/rspamd +# # Keep database and configuration persistent +# VOLUME /etc/rspamd/local.d +# VOLUME /etc/rspamd/override.d +# VOLUME /etc/rspamd/custom +# VOLUME /var/lib/rspamd # Port 11334 is for web frontend # Port 11332 is for milter @@ -42,25 +59,8 @@ HEALTHCHECK --interval=1m --timeout=5s --start-period=10s \ CMD /usr/bin/rspamadm control stat || exit 1 # Run Rspamd -ENTRYPOINT ["bash", "-c", "/docker-entrypoint.sh"] +ENTRYPOINT ["/docker-entrypoint.sh"] STOPSIGNAL SIGTERM -CMD ["/usr/bin/rspamd", "-f", "-u", "_rspamd", "-g", "_rspamd"] - -# Setup Labels -ARG VERSION -ARG COMMIT -ARG BRANCH -ARG DATE - -LABEL org.label-schema.name="Rspamd" \ - org.label-schema.description="Rspamd Spam Filter - STABLE" \ - org.label-schema.usage="https://hub.docker.com/r/gnilebein/rspamd/" \ - org.label-schema.url="https://rspamd.com" \ - org.label-schema.vendor="gnilebein" \ - org.label-schema.schema-version="1.0" \ - org.label-schema.version=$VERSION \ - org.label-schema.vcs-url="https://github.com/rspamd/rspamd/" \ - org.label-schema.vcs-ref=$COMMIT \ - org.label-schema.build-date=$DATE \ \ No newline at end of file +CMD ["/usr/bin/rspamd", "-f", "-u", "_rspamd", "-g", "_rspamd"] \ No newline at end of file diff --git a/Stable2.0/docker-entrypoint.sh b/Stable2.0/docker-entrypoint.sh index e453925..59186f2 100644 --- a/Stable2.0/docker-entrypoint.sh +++ b/Stable2.0/docker-entrypoint.sh @@ -2,36 +2,36 @@ chmod 755 /var/lib/rspamd -[[ ! -f /etc/rspamd/override.d/worker-controller-password.inc ]] && echo '# Autogenerated' > /etc/rspamd/override.d/worker-controller-password.inc +[[ ! -f /etc/rspamd/override.d/worker-controller-password.inc ]] && echo '# Autogenerated' >/etc/rspamd/override.d/worker-controller-password.inc mkdir -p /etc/rspamd/custom -chown -R _rspamd:_rspamd /var/lib/rspamd /etc/rspamd/ +chown -R _rspamd:_rspamd /var/lib/rspamd /etc/rspamd/ # Fix missing default global maps, if any # These exists in UI and should not be removed touch /etc/rspamd/custom/global_mime_from_blacklist.map \ - /etc/rspamd/custom/global_rcpt_blacklist.map \ - /etc/rspamd/custom/global_smtp_from_blacklist.map \ - /etc/rspamd/custom/global_mime_from_whitelist.map \ - /etc/rspamd/custom/global_rcpt_whitelist.map \ - /etc/rspamd/custom/global_smtp_from_whitelist.map \ - /etc/rspamd/custom/bad_languages.map \ - /etc/rspamd/custom/sa-rules \ - /etc/rspamd/custom/dovecot_trusted.map \ - /etc/rspamd/custom/rspamd_trusted.map \ - /etc/rspamd/custom/mailcow_networks.map \ - /etc/rspamd/custom/ip_wl.map \ - /etc/rspamd/custom/fishy_tlds.map \ - /etc/rspamd/custom/bad_words.map \ - /etc/rspamd/custom/bad_asn.map \ - /etc/rspamd/custom/bad_words_de.map \ - /etc/rspamd/custom/bulk_header.map \ - /etc/rspamd/custom/bad_header.map + /etc/rspamd/custom/global_rcpt_blacklist.map \ + /etc/rspamd/custom/global_smtp_from_blacklist.map \ + /etc/rspamd/custom/global_mime_from_whitelist.map \ + /etc/rspamd/custom/global_rcpt_whitelist.map \ + /etc/rspamd/custom/global_smtp_from_whitelist.map \ + /etc/rspamd/custom/bad_languages.map \ + /etc/rspamd/custom/sa-rules \ + /etc/rspamd/custom/dovecot_trusted.map \ + /etc/rspamd/custom/rspamd_trusted.map \ + /etc/rspamd/custom/mailcow_networks.map \ + /etc/rspamd/custom/ip_wl.map \ + /etc/rspamd/custom/fishy_tlds.map \ + /etc/rspamd/custom/bad_words.map \ + /etc/rspamd/custom/bad_asn.map \ + /etc/rspamd/custom/bad_words_de.map \ + /etc/rspamd/custom/bulk_header.map \ + /etc/rspamd/custom/bad_header.map # If DQS KEY is set in mailcow.conf add Spamhaus DQS RBLs if [[ ! -z ${SPAMHAUS_DQS_KEY} ]]; then - cat < /etc/rspamd/custom/dqs-rbl.conf + cat </etc/rspamd/custom/dqs-rbl.conf # Autogenerated by mailcow. DO NOT TOUCH! spamhaus { rbl = "${SPAMHAUS_DQS_KEY}.zen.dq.spamhaus.net"; @@ -212,7 +212,7 @@ if [[ ! -z ${SPAMHAUS_DQS_KEY} ]]; then } EOF else - rm -rf /etc/rspamd/custom/dqs-rbl.conf + rm -rf /etc/rspamd/custom/dqs-rbl.conf fi exec "$@" \ No newline at end of file From fbf56f47a8b37f6fa501ffb7446a1fdfb36dde98 Mon Sep 17 00:00:00 2001 From: Patrick Niebeling Date: Wed, 6 Nov 2024 22:22:39 +0100 Subject: [PATCH 15/20] Fix Signed-off-by: Patrick Niebeling --- Stable2.0/Dockerfile | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/Stable2.0/Dockerfile b/Stable2.0/Dockerfile index 8e99652..ba38408 100644 --- a/Stable2.0/Dockerfile +++ b/Stable2.0/Dockerfile @@ -6,6 +6,10 @@ ARG VERSION ARG COMMIT ARG BRANCH ARG DATE +ARG DEBIAN_FRONTEND=noninteractive + +# Set apt non-interactive +ENV DEBIAN_FRONTEND=noninteractive LABEL org.label-schema.name="Rspamd" \ org.label-schema.description="Rspamd Spam Filter - STABLE" \ @@ -13,18 +17,26 @@ LABEL org.label-schema.name="Rspamd" \ org.label-schema.url="https://rspamd.com" \ org.label-schema.vendor="gnilebein" \ org.label-schema.schema-version="1.0" \ - org.label-schema.version=$VERSION \ - org.label-schema.vcs-url="https://github.com/rspamd/rspamd/" \ - org.label-schema.vcs-ref=$COMMIT \ + org.label-schema.version=$VERSION \ + org.label-schema.vcs-url="https://github.com/rspamd/rspamd/" \ + org.label-schema.vcs-ref=$COMMIT \ org.label-schema.build-date=$DATE -# Set apt non-interactive -ENV DEBIAN_FRONTEND=noninteractive - # Install Rspamd RUN set -x \ && apt update \ - && apt --no-install-recommends install -y apt-transport-https dnsutils netcat-traditional lsb-release wget gnupg openssl ca-certificates nano less \ + && apt --no-install-recommends install -y \ + apt-transport-https \ + dnsutils \ + netcat-traditional \ + lsb-release \ + wget \ + gnupg \ + openssl \ + ca-certificates \ + nano \ + less \ + ca-certificates \ && DEBIAN_CODE_NAME=`lsb_release -c -s` \ && wget -O - https://rspamd.com/apt-stable/gpg.key | apt-key add - \ && echo "deb http://rspamd.com/apt-stable/ $DEBIAN_CODE_NAME main" > /etc/apt/sources.list.d/rspamd.list \ @@ -59,7 +71,7 @@ HEALTHCHECK --interval=1m --timeout=5s --start-period=10s \ CMD /usr/bin/rspamadm control stat || exit 1 # Run Rspamd -ENTRYPOINT ["/docker-entrypoint.sh"] +ENTRYPOINT ["bash", "/docker-entrypoint.sh"] STOPSIGNAL SIGTERM From 0132930949a9e1ef5ee5e54b426a8654a5efe0b2 Mon Sep 17 00:00:00 2001 From: Patrick Niebeling Date: Wed, 6 Nov 2024 23:06:44 +0100 Subject: [PATCH 16/20] Fix Signed-off-by: Patrick Niebeling --- Stable2.0/docker-entrypoint.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Stable2.0/docker-entrypoint.sh b/Stable2.0/docker-entrypoint.sh index 59186f2..e5b7741 100644 --- a/Stable2.0/docker-entrypoint.sh +++ b/Stable2.0/docker-entrypoint.sh @@ -13,7 +13,9 @@ chown -R _rspamd:_rspamd /var/lib/rspamd /etc/rspamd/ touch /etc/rspamd/custom/global_mime_from_blacklist.map \ /etc/rspamd/custom/global_rcpt_blacklist.map \ /etc/rspamd/custom/global_smtp_from_blacklist.map \ + /etc/rspamd/custom/global_smtp_domain_blacklist.map \ /etc/rspamd/custom/global_mime_from_whitelist.map \ + /etc/rspamd/custom/global_mime_domain_whitelist.map \ /etc/rspamd/custom/global_rcpt_whitelist.map \ /etc/rspamd/custom/global_smtp_from_whitelist.map \ /etc/rspamd/custom/bad_languages.map \ @@ -21,7 +23,8 @@ touch /etc/rspamd/custom/global_mime_from_blacklist.map \ /etc/rspamd/custom/dovecot_trusted.map \ /etc/rspamd/custom/rspamd_trusted.map \ /etc/rspamd/custom/mailcow_networks.map \ - /etc/rspamd/custom/ip_wl.map \ + /etc/rspamd/custom/global_ip_whitelist.map \ + /etc/rspamd/custom/global_ip_blacklist.map \ /etc/rspamd/custom/fishy_tlds.map \ /etc/rspamd/custom/bad_words.map \ /etc/rspamd/custom/bad_asn.map \ From f343fb9a7c8ec0a2c4769b6adadf283a5809fbcb Mon Sep 17 00:00:00 2001 From: Patrick Niebeling Date: Wed, 6 Nov 2024 23:11:49 +0100 Subject: [PATCH 17/20] Rename Signed-off-by: Patrick Niebeling --- Stable2.0/docker-entrypoint.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Stable2.0/docker-entrypoint.sh b/Stable2.0/docker-entrypoint.sh index e5b7741..d0419c7 100644 --- a/Stable2.0/docker-entrypoint.sh +++ b/Stable2.0/docker-entrypoint.sh @@ -14,17 +14,17 @@ touch /etc/rspamd/custom/global_mime_from_blacklist.map \ /etc/rspamd/custom/global_rcpt_blacklist.map \ /etc/rspamd/custom/global_smtp_from_blacklist.map \ /etc/rspamd/custom/global_smtp_domain_blacklist.map \ + /etc/rspamd/custom/global_ip_blacklist.map \ /etc/rspamd/custom/global_mime_from_whitelist.map \ - /etc/rspamd/custom/global_mime_domain_whitelist.map \ /etc/rspamd/custom/global_rcpt_whitelist.map \ + /etc/rspamd/custom/global_smtp_domain_whitelist.map \ /etc/rspamd/custom/global_smtp_from_whitelist.map \ + /etc/rspamd/custom/global_ip_whitelist.map \ /etc/rspamd/custom/bad_languages.map \ /etc/rspamd/custom/sa-rules \ /etc/rspamd/custom/dovecot_trusted.map \ /etc/rspamd/custom/rspamd_trusted.map \ /etc/rspamd/custom/mailcow_networks.map \ - /etc/rspamd/custom/global_ip_whitelist.map \ - /etc/rspamd/custom/global_ip_blacklist.map \ /etc/rspamd/custom/fishy_tlds.map \ /etc/rspamd/custom/bad_words.map \ /etc/rspamd/custom/bad_asn.map \ From a2f70631e351c3e87c7d50b3b2467535c275b1a0 Mon Sep 17 00:00:00 2001 From: Patrick Niebeling Date: Wed, 6 Nov 2024 23:19:15 +0100 Subject: [PATCH 18/20] Reoder Signed-off-by: Patrick Niebeling --- Stable2.0/docker-entrypoint.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Stable2.0/docker-entrypoint.sh b/Stable2.0/docker-entrypoint.sh index d0419c7..8f37f6d 100644 --- a/Stable2.0/docker-entrypoint.sh +++ b/Stable2.0/docker-entrypoint.sh @@ -6,8 +6,6 @@ chmod 755 /var/lib/rspamd mkdir -p /etc/rspamd/custom -chown -R _rspamd:_rspamd /var/lib/rspamd /etc/rspamd/ - # Fix missing default global maps, if any # These exists in UI and should not be removed touch /etc/rspamd/custom/global_mime_from_blacklist.map \ @@ -218,4 +216,6 @@ else rm -rf /etc/rspamd/custom/dqs-rbl.conf fi +chown -R _rspamd:_rspamd /var/lib/rspamd /etc/rspamd/ + exec "$@" \ No newline at end of file From d61511f49d7a9a0b4986c5023c6634bfe1306179 Mon Sep 17 00:00:00 2001 From: Patrick Niebeling Date: Wed, 6 Nov 2024 23:40:55 +0100 Subject: [PATCH 19/20] Fix Entry Signed-off-by: Patrick Niebeling --- Stable2.0/docker-entrypoint.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/Stable2.0/docker-entrypoint.sh b/Stable2.0/docker-entrypoint.sh index 8f37f6d..1c7bae0 100644 --- a/Stable2.0/docker-entrypoint.sh +++ b/Stable2.0/docker-entrypoint.sh @@ -20,7 +20,6 @@ touch /etc/rspamd/custom/global_mime_from_blacklist.map \ /etc/rspamd/custom/global_ip_whitelist.map \ /etc/rspamd/custom/bad_languages.map \ /etc/rspamd/custom/sa-rules \ - /etc/rspamd/custom/dovecot_trusted.map \ /etc/rspamd/custom/rspamd_trusted.map \ /etc/rspamd/custom/mailcow_networks.map \ /etc/rspamd/custom/fishy_tlds.map \ From 1c782e3bc2323dbab7eb69094c925005d6daa5d5 Mon Sep 17 00:00:00 2001 From: Patrick Niebeling Date: Wed, 6 Nov 2024 23:44:54 +0100 Subject: [PATCH 20/20] Fix Signed-off-by: Patrick Niebeling --- Stable2.0/docker-entrypoint.sh | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/Stable2.0/docker-entrypoint.sh b/Stable2.0/docker-entrypoint.sh index 1c7bae0..b94f8e4 100644 --- a/Stable2.0/docker-entrypoint.sh +++ b/Stable2.0/docker-entrypoint.sh @@ -6,29 +6,6 @@ chmod 755 /var/lib/rspamd mkdir -p /etc/rspamd/custom -# Fix missing default global maps, if any -# These exists in UI and should not be removed -touch /etc/rspamd/custom/global_mime_from_blacklist.map \ - /etc/rspamd/custom/global_rcpt_blacklist.map \ - /etc/rspamd/custom/global_smtp_from_blacklist.map \ - /etc/rspamd/custom/global_smtp_domain_blacklist.map \ - /etc/rspamd/custom/global_ip_blacklist.map \ - /etc/rspamd/custom/global_mime_from_whitelist.map \ - /etc/rspamd/custom/global_rcpt_whitelist.map \ - /etc/rspamd/custom/global_smtp_domain_whitelist.map \ - /etc/rspamd/custom/global_smtp_from_whitelist.map \ - /etc/rspamd/custom/global_ip_whitelist.map \ - /etc/rspamd/custom/bad_languages.map \ - /etc/rspamd/custom/sa-rules \ - /etc/rspamd/custom/rspamd_trusted.map \ - /etc/rspamd/custom/mailcow_networks.map \ - /etc/rspamd/custom/fishy_tlds.map \ - /etc/rspamd/custom/bad_words.map \ - /etc/rspamd/custom/bad_asn.map \ - /etc/rspamd/custom/bad_words_de.map \ - /etc/rspamd/custom/bulk_header.map \ - /etc/rspamd/custom/bad_header.map - # If DQS KEY is set in mailcow.conf add Spamhaus DQS RBLs if [[ ! -z ${SPAMHAUS_DQS_KEY} ]]; then cat </etc/rspamd/custom/dqs-rbl.conf