From 92c0016e32483e67dbddeb11f122dcc4aef3cb69 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Wed, 4 Jan 2023 12:42:13 +0100 Subject: [PATCH 1/5] Fix snappymail --- webmails/snuffleupagus.rules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webmails/snuffleupagus.rules b/webmails/snuffleupagus.rules index fbb8a776..a2304fe0 100644 --- a/webmails/snuffleupagus.rules +++ b/webmails/snuffleupagus.rules @@ -98,7 +98,7 @@ sp.disable_function.function("is_callable").param("value").value("eval").drop(); sp.disable_function.function("is_callable").param("value").value("exec").drop(); sp.disable_function.function("is_callable").param("value").value("system").drop(); sp.disable_function.function("is_callable").param("value").value("shell_exec").drop(); -sp.disable_function.function("is_callable").filename_r("^/var/www/snappymail/snappymail/v/\d+\.\d+\.\d+/app/libraries/snappymail/pgp/gpg\.php$").param("value").value("proc_open").allow(); +sp.disable_function.function("is_callable").filename_r("^/var/www/snappymail/snappymail/v/[0-9]+\.[0-9]+\.[0-9]+/app/libraries/snappymail/pgp/gpg\.php$").param("value").value("proc_open").allow(); sp.disable_function.function("is_callable").param("value").value("proc_open").drop(); sp.disable_function.function("is_callable").param("value").value("passthru").drop(); From e85a2a7e9903e7c00c2db3b23b0e3c0352d538c0 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Wed, 4 Jan 2023 11:01:50 +0100 Subject: [PATCH 2/5] Step1: expose managesieve, make the webmails use it --- core/dovecot/conf/dovecot.conf | 6 ++++++ core/nginx/Dockerfile | 5 +++-- core/nginx/conf/nginx.conf | 21 +++++++++++++++++++++ webmails/roundcube/config/config.inc.php | 2 +- webmails/snappymail/defaults/default.json | 4 ++-- 5 files changed, 33 insertions(+), 5 deletions(-) diff --git a/core/dovecot/conf/dovecot.conf b/core/dovecot/conf/dovecot.conf index 60c94238..c60f7491 100644 --- a/core/dovecot/conf/dovecot.conf +++ b/core/dovecot/conf/dovecot.conf @@ -135,10 +135,16 @@ service lmtp { service managesieve-login { inet_listener sieve { port = 4190 + haproxy = yes } } +protocol sieve { + ssl = no +} + service managesieve { + process_limit = 1024 } plugin { diff --git a/core/nginx/Dockerfile b/core/nginx/Dockerfile index f271fc07..27757920 100644 --- a/core/nginx/Dockerfile +++ b/core/nginx/Dockerfile @@ -17,7 +17,8 @@ ARG VERSION LABEL version=$VERSION RUN set -euxo pipefail \ - ; apk add --no-cache certbot nginx nginx-mod-mail openssl + ; apk add --no-cache certbot nginx nginx-mod-http-brotli nginx-mod-stream nginx-mod-mail openssl \ + ; rm /etc/nginx/conf.d/stream.conf COPY conf/ /conf/ COPY --from=static /static/ /static/ @@ -25,7 +26,7 @@ COPY *.py / RUN echo $VERSION >/version -EXPOSE 80/tcp 443/tcp 110/tcp 143/tcp 465/tcp 587/tcp 993/tcp 995/tcp 25/tcp 10025/tcp 10143/tcp +EXPOSE 80/tcp 443/tcp 110/tcp 143/tcp 465/tcp 587/tcp 993/tcp 995/tcp 25/tcp 14190/tcp 10025/tcp 10143/tcp HEALTHCHECK --start-period=60s CMD curl -skfLo /dev/null http://localhost/health VOLUME ["/certs", "/overrides"] diff --git a/core/nginx/conf/nginx.conf b/core/nginx/conf/nginx.conf index d1b4923e..44fca726 100644 --- a/core/nginx/conf/nginx.conf +++ b/core/nginx/conf/nginx.conf @@ -1,9 +1,11 @@ # Basic configuration user nginx; worker_processes auto; +pcre_jit on; error_log /dev/stderr notice; pid /var/run/nginx.pid; load_module "modules/ngx_mail_module.so"; +load_module "modules/ngx_stream_module.so"; events { worker_connections 1024; @@ -275,6 +277,25 @@ http { include /etc/nginx/conf.d/*.conf; } +stream { + log_format main '$remote_addr [$time_local] ' + '$protocol $status $bytes_sent $bytes_received ' + '$session_time "$upstream_addr" ' + '"$upstream_bytes_sent" "$upstream_bytes_received" "$upstream_connect_time"'; + access_log /dev/stdout main; + + # managesieve + server { + listen 14190; + resolver {{ RESOLVER }} valid=30s; + + proxy_connect_timeout 1s; + proxy_timeout 1m; + proxy_protocol on; + proxy_pass {{ IMAP_ADDRESS }}:4190; + } +} + mail { server_name {{ HOSTNAMES.split(",")[0] }}; auth_http http://127.0.0.1:8000/auth/email; diff --git a/webmails/roundcube/config/config.inc.php b/webmails/roundcube/config/config.inc.php index 665ef1ad..f271eebc 100644 --- a/webmails/roundcube/config/config.inc.php +++ b/webmails/roundcube/config/config.inc.php @@ -28,7 +28,7 @@ $config['default_host'] = '{{ FRONT_ADDRESS or "front" }}'; $config['default_port'] = '10143'; // Sieve script management -$config['managesieve_host'] = '{{ IMAP_ADDRESS or "imap" }}'; +$config['managesieve_host'] = '{{ FRONT_ADDRESS or "front" }}:14190'; // We access the IMAP and SMTP servers locally with internal names, SSL // will obviously fail but this sounds better than allowing insecure login diff --git a/webmails/snappymail/defaults/default.json b/webmails/snappymail/defaults/default.json index ecbf116c..0d49bfb4 100644 --- a/webmails/snappymail/defaults/default.json +++ b/webmails/snappymail/defaults/default.json @@ -32,8 +32,8 @@ "usePhpMail": false }, "Sieve": { - "host": "{{ IMAP_ADDRESS }}", - "port": 4190, + "host": "{{ FRONT_ADDRESS }}", + "port": 14190, "secure": 0, "shortLogin": false, "ssl": { From f18776fa0faf639f2d00b68ab3b238602231f2e5 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Wed, 4 Jan 2023 15:03:47 +0100 Subject: [PATCH 3/5] Step2: put radicale and webmails on their own network --- setup/flavors/compose/docker-compose.yml | 28 ++++++++++++++---------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/setup/flavors/compose/docker-compose.yml b/setup/flavors/compose/docker-compose.yml index 6eb4c409..87b4183b 100644 --- a/setup/flavors/compose/docker-compose.yml +++ b/setup/flavors/compose/docker-compose.yml @@ -36,6 +36,9 @@ services: - "{{ bind6 }}:{{ port }}:{{ port }}" {% endif %} {% endfor %} + networks: + - default + - webmail volumes: - "{{ root }}/certs:/certs" - "{{ root }}/overrides/nginx:/overrides:ro" @@ -169,12 +172,8 @@ services: env_file: {{ env }} volumes: - "{{ root }}/dav:/data" - {% if resolver_enabled %} - depends_on: - - resolver - dns: - - {{ dns }} - {% endif %} + networks: + - radicale {% endif %} {% if fetchmail_enabled %} @@ -204,13 +203,10 @@ services: volumes: - "{{ root }}/webmail:/data" - "{{ root }}/overrides/{{ webmail_type }}:/overrides:ro" + networks: + - webmail depends_on: - - imap - {% if resolver_enabled %} - - resolver - dns: - - {{ dns }} - {% endif %} + - front {% endif %} networks: @@ -226,6 +222,14 @@ networks: {% if ipv6_enabled %} - subnet: {{ subnet6 }} {% endif %} +{% if webdav_enabled %} + radicale: + driver: bridge +{% endif %} +{% if webmail_type != 'none' %} + webmail: + driver: bridge +{% endif %} {% if oletools_enabled %} noinet: driver: bridge From 8b9bb350ec7d3c2f6cd39886f23adb1f897a3af4 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Wed, 4 Jan 2023 15:11:29 +0100 Subject: [PATCH 4/5] towncrier --- towncrier/newsfragments/2613.feature | 1 + 1 file changed, 1 insertion(+) create mode 100644 towncrier/newsfragments/2613.feature diff --git a/towncrier/newsfragments/2613.feature b/towncrier/newsfragments/2613.feature new file mode 100644 index 00000000..453f59a3 --- /dev/null +++ b/towncrier/newsfragments/2613.feature @@ -0,0 +1 @@ +Isolate radicale and webmail on their own network. This ensures they don't have privileged access to any of the other containers. From 9d555b0eec2c87869599b3dce3c4e0295129b37f Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Wed, 4 Jan 2023 19:19:43 +0100 Subject: [PATCH 5/5] Don't expose any port (suggestion from ghost) --- core/admin/Dockerfile | 2 +- core/nginx/Dockerfile | 3 ++- core/oletools/Dockerfile | 2 +- core/postfix/Dockerfile | 2 +- core/rspamd/Dockerfile | 2 +- optional/clamav/Dockerfile | 2 +- optional/radicale/Dockerfile | 2 +- optional/unbound/Dockerfile | 2 +- webmails/Dockerfile | 2 +- 9 files changed, 10 insertions(+), 9 deletions(-) diff --git a/core/admin/Dockerfile b/core/admin/Dockerfile index 600c3e9f..e6d70e61 100644 --- a/core/admin/Dockerfile +++ b/core/admin/Dockerfile @@ -22,7 +22,7 @@ RUN set -euxo pipefail \ RUN echo $VERSION >/version -EXPOSE 80/tcp +#EXPOSE 80/tcp HEALTHCHECK CMD curl -skfLo /dev/null http://localhost/sso/login?next=ui.index VOLUME ["/data","/dkim"] diff --git a/core/nginx/Dockerfile b/core/nginx/Dockerfile index 27757920..76c3906a 100644 --- a/core/nginx/Dockerfile +++ b/core/nginx/Dockerfile @@ -26,7 +26,8 @@ COPY *.py / RUN echo $VERSION >/version -EXPOSE 80/tcp 443/tcp 110/tcp 143/tcp 465/tcp 587/tcp 993/tcp 995/tcp 25/tcp 14190/tcp 10025/tcp 10143/tcp +EXPOSE 80/tcp 443/tcp 110/tcp 143/tcp 465/tcp 587/tcp 993/tcp 995/tcp 25/tcp +# EXPOSE 10025/tcp 10143/tcp 14190/tcp HEALTHCHECK --start-period=60s CMD curl -skfLo /dev/null http://localhost/health VOLUME ["/certs", "/overrides"] diff --git a/core/oletools/Dockerfile b/core/oletools/Dockerfile index 8bb98cd9..8526e506 100644 --- a/core/oletools/Dockerfile +++ b/core/oletools/Dockerfile @@ -14,7 +14,7 @@ RUN set -euxo pipefail \ RUN echo $VERSION >/version HEALTHCHECK --start-period=60s CMD echo PING|nc -q1 127.0.0.1 11343|grep "PONG" -EXPOSE 11343/tcp +#EXPOSE 11343/tcp USER nobody:nobody diff --git a/core/postfix/Dockerfile b/core/postfix/Dockerfile index df902dd4..8565d865 100644 --- a/core/postfix/Dockerfile +++ b/core/postfix/Dockerfile @@ -14,7 +14,7 @@ COPY start.py / RUN echo $VERSION >/version -EXPOSE 25/tcp 10025/tcp +#EXPOSE 25/tcp 10025/tcp HEALTHCHECK --start-period=350s CMD /usr/sbin/postfix status VOLUME ["/queue"] diff --git a/core/rspamd/Dockerfile b/core/rspamd/Dockerfile index eca8e62b..08ac0871 100644 --- a/core/rspamd/Dockerfile +++ b/core/rspamd/Dockerfile @@ -15,7 +15,7 @@ COPY start.py / RUN echo $VERSION >/version -EXPOSE 11332/tcp 11334/tcp 11335/tcp +#EXPOSE 11332/tcp 11334/tcp 11335/tcp HEALTHCHECK --start-period=350s CMD curl -skfLo /dev/null http://localhost:11334/ VOLUME ["/var/lib/rspamd"] diff --git a/optional/clamav/Dockerfile b/optional/clamav/Dockerfile index 9beded99..bfe02780 100644 --- a/optional/clamav/Dockerfile +++ b/optional/clamav/Dockerfile @@ -14,7 +14,7 @@ COPY start.py / RUN echo $VERSION >/version -EXPOSE 3310/tcp +#EXPOSE 3310/tcp HEALTHCHECK --start-period=350s CMD echo PING|nc localhost 3310|grep "PONG" VOLUME ["/data"] diff --git a/optional/radicale/Dockerfile b/optional/radicale/Dockerfile index 56606494..904e47db 100644 --- a/optional/radicale/Dockerfile +++ b/optional/radicale/Dockerfile @@ -10,7 +10,7 @@ COPY radicale.conf / RUN echo $VERSION >/version -EXPOSE 5232/tcp +#EXPOSE 5232/tcp HEALTHCHECK CMD curl -f -L http://localhost:5232/ || exit 1 VOLUME ["/data"] diff --git a/optional/unbound/Dockerfile b/optional/unbound/Dockerfile index 831476ab..95c63707 100644 --- a/optional/unbound/Dockerfile +++ b/optional/unbound/Dockerfile @@ -18,7 +18,7 @@ COPY start.py / RUN echo $VERSION >/version -EXPOSE 53/udp 53/tcp +#EXPOSE 53/udp 53/tcp HEALTHCHECK CMD dig @127.0.0.1 || exit 1 CMD /start.py diff --git a/webmails/Dockerfile b/webmails/Dockerfile index fb0d9090..9dc3514a 100644 --- a/webmails/Dockerfile +++ b/webmails/Dockerfile @@ -86,7 +86,7 @@ COPY php-webmail.conf /etc/php81/php-fpm.d/ COPY nginx-webmail.conf /conf/ COPY snuffleupagus.rules /etc/snuffleupagus.rules.tpl -EXPOSE 80/tcp +# EXPOSE 80/tcp VOLUME /data VOLUME /overrides