Merge branch 'master' of https://github.com/Mailu/Mailu into HEAD
commit
3721a6aa02
@ -0,0 +1,25 @@
|
|||||||
|
""" Add fetch.scan and fetch.folders
|
||||||
|
|
||||||
|
Revision ID: f4f0f89e0047
|
||||||
|
Revises: 8f9ea78776f4
|
||||||
|
Create Date: 2022-11-13 16:29:01.246509
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = 'f4f0f89e0047'
|
||||||
|
down_revision = '8f9ea78776f4'
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
import mailu
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
with op.batch_alter_table('fetch') as batch:
|
||||||
|
batch.add_column(sa.Column('scan', sa.Boolean(), nullable=False, server_default=sa.sql.expression.false()))
|
||||||
|
batch.add_column(sa.Column('folders', mailu.models.CommaSeparatedList(), nullable=True))
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
with op.batch_alter_table('fetch') as batch:
|
||||||
|
batch.drop_column('fetch', 'folders')
|
||||||
|
batch.drop_column('fetch', 'scan')
|
@ -1,12 +0,0 @@
|
|||||||
Flask==1.0.2
|
|
||||||
Flask-Bootstrap==3.3.7.1
|
|
||||||
gunicorn==19.9.0
|
|
||||||
redis==3.2.1
|
|
||||||
Jinja2==3.0.3
|
|
||||||
MarkupSafe==2.1.0
|
|
||||||
Werkzeug==2.0.3
|
|
||||||
click==8.0.3
|
|
||||||
dominate==2.6.0
|
|
||||||
itsdangerous==2.0.1
|
|
||||||
redis==3.2.1
|
|
||||||
visitor==0.1.3
|
|
@ -0,0 +1,7 @@
|
|||||||
|
# GTUBE should be blocked, see https://rspamd.com/doc/gtube_patterns.html
|
||||||
|
python3 tests/email_test.py "XJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X"
|
||||||
|
if [ $? -eq 25 ]; then
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
exit 1
|
||||||
|
fi
|
@ -1,106 +0,0 @@
|
|||||||
# This file is auto-generated by the Mailu configuration wizard.
|
|
||||||
# Please read the documentation before attempting any change.
|
|
||||||
# Generated for compose flavor
|
|
||||||
|
|
||||||
version: '3.6'
|
|
||||||
|
|
||||||
services:
|
|
||||||
|
|
||||||
# External dependencies
|
|
||||||
redis:
|
|
||||||
image: redis:alpine
|
|
||||||
restart: always
|
|
||||||
volumes:
|
|
||||||
- "/mailu/redis:/data"
|
|
||||||
|
|
||||||
# Core services
|
|
||||||
front:
|
|
||||||
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}nginx:${MAILU_VERSION:-local}
|
|
||||||
restart: always
|
|
||||||
env_file: mailu.env
|
|
||||||
logging:
|
|
||||||
driver: json-file
|
|
||||||
ports:
|
|
||||||
- "127.0.0.1:80:80"
|
|
||||||
- "127.0.0.1:443:443"
|
|
||||||
- "127.0.0.1:25:25"
|
|
||||||
- "127.0.0.1:465:465"
|
|
||||||
- "127.0.0.1:587:587"
|
|
||||||
- "127.0.0.1:110:110"
|
|
||||||
- "127.0.0.1:995:995"
|
|
||||||
- "127.0.0.1:143:143"
|
|
||||||
- "127.0.0.1:993:993"
|
|
||||||
volumes:
|
|
||||||
- "/mailu/certs:/certs"
|
|
||||||
|
|
||||||
admin:
|
|
||||||
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}admin:${MAILU_VERSION:-local}
|
|
||||||
restart: always
|
|
||||||
env_file: mailu.env
|
|
||||||
volumes:
|
|
||||||
- "/mailu/data:/data"
|
|
||||||
- "/mailu/dkim:/dkim"
|
|
||||||
depends_on:
|
|
||||||
- redis
|
|
||||||
- resolver
|
|
||||||
dns:
|
|
||||||
- 192.168.203.254
|
|
||||||
|
|
||||||
imap:
|
|
||||||
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}dovecot:${MAILU_VERSION:-local}
|
|
||||||
restart: always
|
|
||||||
env_file: mailu.env
|
|
||||||
volumes:
|
|
||||||
- "/mailu/mail:/mail"
|
|
||||||
- "/mailu/overrides:/overrides"
|
|
||||||
depends_on:
|
|
||||||
- front
|
|
||||||
|
|
||||||
smtp:
|
|
||||||
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}postfix:${MAILU_VERSION:-local}
|
|
||||||
restart: always
|
|
||||||
env_file: mailu.env
|
|
||||||
volumes:
|
|
||||||
- "/mailu/overrides:/overrides"
|
|
||||||
depends_on:
|
|
||||||
- front
|
|
||||||
|
|
||||||
antispam:
|
|
||||||
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}rspamd:${MAILU_VERSION:-local}
|
|
||||||
restart: always
|
|
||||||
env_file: mailu.env
|
|
||||||
volumes:
|
|
||||||
- "/mailu/filter:/var/lib/rspamd"
|
|
||||||
- "/mailu/dkim:/dkim"
|
|
||||||
- "/mailu/overrides/rspamd:/etc/rspamd/override.d"
|
|
||||||
depends_on:
|
|
||||||
- front
|
|
||||||
|
|
||||||
# Optional services
|
|
||||||
|
|
||||||
resolver:
|
|
||||||
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}unbound:${MAILU_VERSION:-local}
|
|
||||||
env_file: mailu.env
|
|
||||||
restart: always
|
|
||||||
networks:
|
|
||||||
default:
|
|
||||||
ipv4_address: 192.168.203.254
|
|
||||||
|
|
||||||
# Webmail
|
|
||||||
webmail:
|
|
||||||
image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}snappymail:${MAILU_VERSION:-local}
|
|
||||||
restart: always
|
|
||||||
env_file: mailu.env
|
|
||||||
volumes:
|
|
||||||
- "/mailu/webmail:/data"
|
|
||||||
depends_on:
|
|
||||||
- imap
|
|
||||||
|
|
||||||
|
|
||||||
networks:
|
|
||||||
default:
|
|
||||||
driver: bridge
|
|
||||||
ipam:
|
|
||||||
driver: default
|
|
||||||
config:
|
|
||||||
- subnet: 192.168.203.0/24
|
|
@ -1,138 +0,0 @@
|
|||||||
# Mailu main configuration file
|
|
||||||
#
|
|
||||||
# Generated for compose flavor
|
|
||||||
#
|
|
||||||
# This file is autogenerated by the configuration management wizard.
|
|
||||||
# For a detailed list of configuration variables, see the documentation at
|
|
||||||
# https://mailu.io
|
|
||||||
|
|
||||||
###################################
|
|
||||||
# Common configuration variables
|
|
||||||
###################################
|
|
||||||
|
|
||||||
# Set this to the path where Mailu data and configuration is stored
|
|
||||||
# This variable is now set directly in `docker-compose.yml by the setup utility
|
|
||||||
# ROOT=/mailu
|
|
||||||
|
|
||||||
# Mailu version to run (1.0, 1.1, etc. or master)
|
|
||||||
#VERSION=master
|
|
||||||
|
|
||||||
# Set to a randomly generated 16 bytes string
|
|
||||||
SECRET_KEY=V5J4SHRYVW9PZIQU
|
|
||||||
|
|
||||||
# Address where listening ports should bind
|
|
||||||
# This variables are now set directly in `docker-compose.yml by the setup utility
|
|
||||||
# PUBLIC_IPV4= 127.0.0.1 (default: 127.0.0.1)
|
|
||||||
# PUBLIC_IPV6= (default: ::1)
|
|
||||||
|
|
||||||
# Subnet of the docker network. This should not conflict with any networks to which your system is connected. (Internal and external!)
|
|
||||||
SUBNET=192.168.203.0/24
|
|
||||||
|
|
||||||
# Main mail domain
|
|
||||||
DOMAIN=mailu.io
|
|
||||||
|
|
||||||
# Hostnames for this server, separated with comas
|
|
||||||
HOSTNAMES=localhost
|
|
||||||
|
|
||||||
# Postmaster local part (will append the main mail domain)
|
|
||||||
POSTMASTER=admin
|
|
||||||
|
|
||||||
# Choose how secure connections will behave (value: letsencrypt, cert, notls, mail, mail-letsencrypt)
|
|
||||||
TLS_FLAVOR=cert
|
|
||||||
|
|
||||||
# Authentication rate limit (per source IP address)
|
|
||||||
AUTH_RATELIMIT=10/minute;1000/hour
|
|
||||||
|
|
||||||
# Opt-out of statistics, replace with "True" to opt out
|
|
||||||
DISABLE_STATISTICS=False
|
|
||||||
|
|
||||||
###################################
|
|
||||||
# Optional features
|
|
||||||
###################################
|
|
||||||
|
|
||||||
# Expose the admin interface (value: true, false)
|
|
||||||
ADMIN=false
|
|
||||||
|
|
||||||
# Choose which webmail to run if any (values: roundcube, snappymail, none)
|
|
||||||
WEBMAIL=snappymail
|
|
||||||
|
|
||||||
# Dav server implementation (value: radicale, none)
|
|
||||||
WEBDAV=none
|
|
||||||
|
|
||||||
# Antivirus solution (value: clamav, none)
|
|
||||||
#ANTIVIRUS=none
|
|
||||||
|
|
||||||
#Antispam solution
|
|
||||||
ANTISPAM=none
|
|
||||||
|
|
||||||
###################################
|
|
||||||
# Mail settings
|
|
||||||
###################################
|
|
||||||
|
|
||||||
# Message size limit in bytes
|
|
||||||
# Default: accept messages up to 50MB
|
|
||||||
MESSAGE_SIZE_LIMIT=50000000
|
|
||||||
|
|
||||||
# Networks granted relay permissions
|
|
||||||
# Use this with care, all hosts in this networks will be able to send mail without authentication!
|
|
||||||
RELAYNETS=
|
|
||||||
|
|
||||||
# Will relay all outgoing mails if configured
|
|
||||||
RELAYHOST=
|
|
||||||
|
|
||||||
# Fetchmail delay
|
|
||||||
FETCHMAIL_DELAY=600
|
|
||||||
|
|
||||||
# Recipient delimiter, character used to delimiter localpart from custom address part
|
|
||||||
RECIPIENT_DELIMITER=+
|
|
||||||
|
|
||||||
# DMARC rua and ruf email
|
|
||||||
DMARC_RUA=admin
|
|
||||||
DMARC_RUF=admin
|
|
||||||
|
|
||||||
|
|
||||||
# Maildir Compression
|
|
||||||
# choose compression-method, default: none (value: gz, bz2, lz4, zstd)
|
|
||||||
COMPRESSION=
|
|
||||||
# change compression-level, default: 6 (value: 1-9)
|
|
||||||
COMPRESSION_LEVEL=
|
|
||||||
|
|
||||||
###################################
|
|
||||||
# Web settings
|
|
||||||
###################################
|
|
||||||
|
|
||||||
# Path to the admin interface if enabled
|
|
||||||
WEB_ADMIN=/admin
|
|
||||||
|
|
||||||
# Path to the webmail if enabled
|
|
||||||
WEB_WEBMAIL=/webmail
|
|
||||||
|
|
||||||
# Website name
|
|
||||||
SITENAME=Mailu
|
|
||||||
|
|
||||||
# Linked Website URL
|
|
||||||
WEBSITE=https://mailu.io
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
###################################
|
|
||||||
# Advanced settings
|
|
||||||
###################################
|
|
||||||
|
|
||||||
# Log driver for front service. Possible values:
|
|
||||||
# json-file (default)
|
|
||||||
# journald (On systemd platforms, useful for Fail2Ban integration)
|
|
||||||
# syslog (Non systemd platforms, Fail2Ban integration. Disables `docker-compose log` for front!)
|
|
||||||
# LOG_DRIVER=json-file
|
|
||||||
|
|
||||||
# Docker-compose project name, this will prepended to containers names.
|
|
||||||
COMPOSE_PROJECT_NAME=mailu
|
|
||||||
|
|
||||||
# Header to take the real ip from
|
|
||||||
REAL_IP_HEADER=
|
|
||||||
|
|
||||||
# IPs for nginx set_real_ip_from (CIDR list separated by commas)
|
|
||||||
REAL_IP_FROM=
|
|
||||||
|
|
||||||
# choose wether mailu bounces (no) or rejects (yes) mail when recipient is unknown (value: yes, no)
|
|
||||||
REJECT_UNLISTED_RECIPIENT=
|
|
@ -0,0 +1,10 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
IP="$(docker inspect webmail_webmail_1|jq -r '.[0].NetworkSettings.Networks.webmail_default.IPAddress')"
|
||||||
|
|
||||||
|
MAIN_RETURN_CODE=$(curl -I -so /dev/null -w "%{http_code}" http://$IP/)
|
||||||
|
[[ $MAIN_RETURN_CODE -ne 200 && $MAIN_RETURN_CODE -ne 302 ]] && echo "The default page of snappymail hasn't returned 200 but $MAIN_RETURN_CODE!" >>/dev/stderr && exit 1
|
||||||
|
[[ $(curl -I -so /dev/null -w "%{http_code}" http://$IP/?admin) -ne 403 ]] && echo "The admin of snappymail is not disabled!" >>/dev/stderr && exit 1
|
||||||
|
echo "Everything OK" >/dev/stderr
|
||||||
|
|
||||||
|
exit 0
|
@ -0,0 +1 @@
|
|||||||
|
Add an option so that emails fetched with fetchmail don't go through the filters (closes #1231)
|
@ -0,0 +1 @@
|
|||||||
|
Make public announcement bypass the filters. They may still time-out before being sent if there is a large number of users.
|
@ -0,0 +1 @@
|
|||||||
|
Fetchmail: Missing support for '*_ADDRESS' env vars
|
@ -0,0 +1 @@
|
|||||||
|
Upgrade Snappymail to 2.21 and merge the webmail containers
|
@ -0,0 +1 @@
|
|||||||
|
Upgrade to Alpine 3.16.3; Make setup, admin and rspamd run without root privs. Please ensure that your folder overrides/rspamd is owned by 1000:1000
|
@ -0,0 +1 @@
|
|||||||
|
Add Snuffleupagus to protect webmails (a Suhosin replacement)
|
@ -0,0 +1 @@
|
|||||||
|
Allow other folders to be synced by fetchmail
|
@ -0,0 +1,96 @@
|
|||||||
|
# syntax=docker/dockerfile-upstream:1.4.3
|
||||||
|
|
||||||
|
FROM base
|
||||||
|
|
||||||
|
ARG VERSION
|
||||||
|
LABEL version=$VERSION
|
||||||
|
|
||||||
|
COPY snappymail/pubkey.asc /tmp/snappymail.asc
|
||||||
|
COPY roundcube/pubkey.asc /tmp/roundcube.asc
|
||||||
|
|
||||||
|
RUN set -euxo pipefail \
|
||||||
|
; apk add --no-cache \
|
||||||
|
nginx gpg gpg-agent \
|
||||||
|
php81 php81-fpm php81-mbstring php81-zip php81-xml php81-simplexml php81-pecl-apcu \
|
||||||
|
php81-dom php81-curl php81-exif gd php81-gd php81-iconv php81-intl php81-openssl \
|
||||||
|
php81-pdo_sqlite php81-pdo_mysql php81-pdo_pgsql php81-pdo php81-sodium libsodium php81-tidy php81-pecl-uuid \
|
||||||
|
php81-pspell php81-pecl-imagick php81-opcache php81-session php81-sockets php81-fileinfo \
|
||||||
|
aspell-uk aspell-ru aspell-fr aspell-de aspell-en \
|
||||||
|
; rm /etc/nginx/http.d/default.conf \
|
||||||
|
; rm /etc/php81/php-fpm.d/www.conf \
|
||||||
|
; ln -s /usr/bin/php81 /usr/bin/php \
|
||||||
|
; gpg --import /tmp/snappymail.asc \
|
||||||
|
; gpg --import /tmp/roundcube.asc \
|
||||||
|
; echo extension=snuffleupagus > /etc/php81/conf.d/snuffleupagus.ini \
|
||||||
|
; rm -f /tmp/roundcube.asc /tmp/snappymail.asc \
|
||||||
|
; mkdir -p /run/nginx /conf
|
||||||
|
|
||||||
|
# roundcube
|
||||||
|
ENV ROUNDCUBE_URL https://github.com/roundcube/roundcubemail/releases/download/1.5.3/roundcubemail-1.5.3-complete.tar.gz
|
||||||
|
ENV CARDDAV_URL https://github.com/mstilkerich/rcmcarddav/releases/download/v4.4.3/carddav-v4.4.3.tar.gz
|
||||||
|
|
||||||
|
RUN set -euxo pipefail \
|
||||||
|
; cd /var/www \
|
||||||
|
; curl -sLo /dev/shm/roundcube.tgz ${ROUNDCUBE_URL} \
|
||||||
|
; curl -sLo /dev/shm/roundcube.tgz.asc ${ROUNDCUBE_URL}.asc \
|
||||||
|
; gpg --status-fd 1 --verify /dev/shm/roundcube.tgz.asc \
|
||||||
|
; tar xzf /dev/shm/roundcube.tgz \
|
||||||
|
; curl -sL ${CARDDAV_URL} | tar xz \
|
||||||
|
; mv roundcubemail-* roundcube \
|
||||||
|
; mkdir -p /var/www/roundcube/config \
|
||||||
|
; mv carddav roundcube/plugins/ \
|
||||||
|
; cd roundcube \
|
||||||
|
; rm -rf CHANGELOG.md SECURITY.md INSTALL LICENSE README.md UPGRADING composer.json-dist installer composer.* \
|
||||||
|
; ln -sf index.php /var/www/roundcube/public_html/sso.php \
|
||||||
|
; rm -rf plugins/{autologon,example_addressbook,http_authentication,krb_authentication,new_user_identity,password,redundant_attachments,squirrelmail_usercopy,userinfo,virtuser_file,virtuser_query} \
|
||||||
|
; sed -i '/suhosin.session.encrypt/d;/mbstring\.func_overload/d' program/lib/Roundcube/bootstrap.php
|
||||||
|
|
||||||
|
COPY roundcube/config/config.inc.php /conf/
|
||||||
|
COPY roundcube/login/mailu.php /var/www/roundcube/plugins/mailu/
|
||||||
|
COPY roundcube/config/config.inc.carddav.php /var/www/roundcube/plugins/carddav/config.inc.php
|
||||||
|
|
||||||
|
# snappymail
|
||||||
|
|
||||||
|
ENV SNAPPYMAIL_URL https://github.com/the-djmaze/snappymail/releases/download/v2.21.3/snappymail-2.21.3.tar.gz
|
||||||
|
|
||||||
|
RUN set -euxo pipefail \
|
||||||
|
; mkdir /var/www/snappymail \
|
||||||
|
; cd /var/www/snappymail \
|
||||||
|
; curl -sLo /dev/shm/snappymail.tgz ${SNAPPYMAIL_URL} \
|
||||||
|
; curl -sLo /dev/shm/snappymail.tgz.asc ${SNAPPYMAIL_URL}.asc \
|
||||||
|
; gpg --status-fd 1 --verify /dev/shm/snappymail.tgz.asc \
|
||||||
|
; tar xzf /dev/shm/snappymail.tgz
|
||||||
|
|
||||||
|
# SnappyMail login
|
||||||
|
COPY snappymail/login/include.php /var/www/snappymail/
|
||||||
|
COPY snappymail/login/sso.php /var/www/snappymail/
|
||||||
|
|
||||||
|
# Parsed and moved at startup
|
||||||
|
COPY snappymail/defaults/application.ini /defaults/
|
||||||
|
COPY snappymail/defaults/default.json /defaults/
|
||||||
|
|
||||||
|
# set perms
|
||||||
|
RUN set -euxo pipefail \
|
||||||
|
; chmod -R a+rX /var/www/snappymail \
|
||||||
|
; chown -R root:root /var/www/snappymail \
|
||||||
|
; chown -R mailu:mailu /var/www/snappymail/data \
|
||||||
|
; chown -R root:root /var/www/roundcube/ \
|
||||||
|
; chown -R mailu:mailu /var/www/roundcube/temp /var/www/roundcube/logs \
|
||||||
|
; chmod -R a+rX /var/www/roundcube
|
||||||
|
|
||||||
|
# common
|
||||||
|
COPY start.py /
|
||||||
|
COPY php.ini /defaults/
|
||||||
|
COPY php-webmail.conf /etc/php81/php-fpm.d/
|
||||||
|
COPY nginx-webmail.conf /conf/
|
||||||
|
COPY snuffleupagus.rules /etc/snuffleupagus.rules.tpl
|
||||||
|
|
||||||
|
EXPOSE 80/tcp
|
||||||
|
VOLUME /data
|
||||||
|
VOLUME /overrides
|
||||||
|
|
||||||
|
CMD /start.py
|
||||||
|
|
||||||
|
HEALTHCHECK CMD curl -f -L http://localhost/ping || exit 1
|
||||||
|
|
||||||
|
RUN echo $VERSION >> /version
|
@ -0,0 +1,15 @@
|
|||||||
|
expose_php=Off
|
||||||
|
date.timezone={{ TZ }}
|
||||||
|
upload_max_filesize = {{ MAX_FILESIZE }}M
|
||||||
|
post_max_size = {{ MAX_FILESIZE }}M
|
||||||
|
session.auto_start=Off
|
||||||
|
mbstring.func_overload=Off
|
||||||
|
file_uploads=On
|
||||||
|
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT & ~E_NOTICE
|
||||||
|
display_errors=Off
|
||||||
|
log_errors=On
|
||||||
|
zlib.output_compression=Off
|
||||||
|
access.log = /dev/fd/2
|
||||||
|
error_log = /dev/fd/2
|
||||||
|
module=snuffleupagus.so
|
||||||
|
sp.configuration_file=/etc/snuffleupagus.rules
|
@ -1,58 +0,0 @@
|
|||||||
# syntax=docker/dockerfile-upstream:1.4.3
|
|
||||||
|
|
||||||
#roundcube image
|
|
||||||
FROM base
|
|
||||||
|
|
||||||
ARG VERSION
|
|
||||||
LABEL version=$VERSION
|
|
||||||
|
|
||||||
RUN set -euxo pipefail \
|
|
||||||
; apk add --no-cache \
|
|
||||||
nginx gpg gpg-agent \
|
|
||||||
php81 php81-fpm php81-mbstring php81-zip php81-xml php81-simplexml \
|
|
||||||
php81-dom php81-curl php81-exif gd php81-gd php81-iconv php81-intl php81-openssl \
|
|
||||||
php81-pdo_sqlite php81-pdo_mysql php81-pdo_pgsql php81-pdo php81-sodium libsodium php81-tidy php81-pecl-uuid \
|
|
||||||
php81-pspell php81-pecl-imagick php81-opcache php81-session php81-sockets php81-fileinfo \
|
|
||||||
; rm /etc/nginx/http.d/default.conf \
|
|
||||||
; rm /etc/php81/php-fpm.d/www.conf \
|
|
||||||
; ln -s /usr/bin/php81 /usr/bin/php \
|
|
||||||
; mkdir -p /run/nginx \
|
|
||||||
; mkdir -p /conf
|
|
||||||
|
|
||||||
ENV ROUNDCUBE_URL https://github.com/roundcube/roundcubemail/releases/download/1.5.3/roundcubemail-1.5.3-complete.tar.gz
|
|
||||||
ENV CARDDAV_URL https://github.com/mstilkerich/rcmcarddav/releases/download/v4.4.3/carddav-v4.4.3.tar.gz
|
|
||||||
|
|
||||||
RUN set -euxo pipefail \
|
|
||||||
; cd /var/www \
|
|
||||||
; curl -sL ${ROUNDCUBE_URL} | tar xz \
|
|
||||||
; curl -sL ${CARDDAV_URL} | tar xz \
|
|
||||||
; mv roundcubemail-* webmail \
|
|
||||||
; mkdir -p /var/www/webmail/config \
|
|
||||||
; mv carddav webmail/plugins/ \
|
|
||||||
; cd webmail \
|
|
||||||
; rm -rf CHANGELOG.md SECURITY.md INSTALL LICENSE README.md UPGRADING composer.json-dist installer composer.* \
|
|
||||||
; ln -sf index.php /var/www/webmail/sso.php \
|
|
||||||
; chmod -R u+w,a+rX /var/www/webmail \
|
|
||||||
; chown -R nginx:nginx /var/www/webmail \
|
|
||||||
; rm -rf plugins/{autologon,example_addressbook,http_authentication,krb_authentication,new_user_identity,password,redundant_attachments,squirrelmail_usercopy,userinfo,virtuser_file,virtuser_query}
|
|
||||||
|
|
||||||
|
|
||||||
# nginx / PHP config files
|
|
||||||
COPY config/nginx-roundcube.conf /conf/
|
|
||||||
COPY config/php-roundcube.conf /etc/php81/php-fpm.d/roundcube.conf
|
|
||||||
COPY config/php.ini /conf/
|
|
||||||
COPY config/config.inc.php /conf/
|
|
||||||
COPY login/mailu.php /var/www/webmail/plugins/mailu/
|
|
||||||
COPY config/config.inc.carddav.php /var/www/webmail/plugins/carddav/config.inc.php
|
|
||||||
|
|
||||||
COPY start.py /
|
|
||||||
|
|
||||||
EXPOSE 80/tcp
|
|
||||||
VOLUME /data
|
|
||||||
VOLUME /overrides
|
|
||||||
|
|
||||||
CMD /start.py
|
|
||||||
|
|
||||||
HEALTHCHECK CMD curl -f -L http://localhost/ping || exit 1
|
|
||||||
|
|
||||||
RUN echo $VERSION >> /version
|
|
@ -1,63 +0,0 @@
|
|||||||
server {
|
|
||||||
listen 80 default_server;
|
|
||||||
listen [::]:80 default_server;
|
|
||||||
|
|
||||||
root /var/www/webmail;
|
|
||||||
|
|
||||||
include /etc/nginx/mime.types;
|
|
||||||
|
|
||||||
# /dev/stdout (Default), <path>, off
|
|
||||||
access_log off;
|
|
||||||
|
|
||||||
# /dev/stderr (Default), <path>, debug, info, notice, warn, error, crit, alert, emerg
|
|
||||||
error_log /dev/stderr notice;
|
|
||||||
|
|
||||||
index index.php;
|
|
||||||
|
|
||||||
# set maximum body size to configured limit
|
|
||||||
client_max_body_size {{ MESSAGE_SIZE_LIMIT|int + 8388608 }};
|
|
||||||
|
|
||||||
location / {
|
|
||||||
try_files $uri $uri/ /index.php$args;
|
|
||||||
}
|
|
||||||
|
|
||||||
location ~ \.php$ {
|
|
||||||
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
|
|
||||||
if (!-f $document_root$fastcgi_script_name) {
|
|
||||||
return 404;
|
|
||||||
}
|
|
||||||
include /etc/nginx/fastcgi_params;
|
|
||||||
|
|
||||||
fastcgi_intercept_errors on;
|
|
||||||
fastcgi_index index.php;
|
|
||||||
|
|
||||||
fastcgi_keep_conn on;
|
|
||||||
|
|
||||||
fastcgi_pass unix:/var/run/php8-fpm.sock;
|
|
||||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
|
||||||
{% if WEB_WEBMAIL == '/' %}
|
|
||||||
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
|
|
||||||
{% else %}
|
|
||||||
fastcgi_param SCRIPT_NAME {{WEB_WEBMAIL}}/$fastcgi_script_name;
|
|
||||||
{% endif %}
|
|
||||||
}
|
|
||||||
|
|
||||||
location ~ /\. {
|
|
||||||
deny all;
|
|
||||||
}
|
|
||||||
|
|
||||||
location ^~ /data {
|
|
||||||
deny all;
|
|
||||||
}
|
|
||||||
|
|
||||||
location = /ping {
|
|
||||||
allow 127.0.0.1;
|
|
||||||
allow ::1;
|
|
||||||
deny all;
|
|
||||||
|
|
||||||
include /etc/nginx/fastcgi_params;
|
|
||||||
fastcgi_index index.php;
|
|
||||||
fastcgi_pass unix:/var/run/php8-fpm.sock;
|
|
||||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
expose_php=Off
|
|
||||||
date.timezone={{ TZ }}
|
|
||||||
upload_max_filesize = {{ MAX_FILESIZE }}M
|
|
||||||
post_max_size = {{ MAX_FILESIZE }}M
|
|
||||||
suhosin.session.encrypt=Off
|
|
||||||
session.auto_start=Off
|
|
||||||
mbstring.func_overload=Off
|
|
||||||
file_uploads=On
|
|
@ -0,0 +1,102 @@
|
|||||||
|
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||||
|
|
||||||
|
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
|
||||||
|
0dXJnhEe7eXkwBbfEzk=
|
||||||
|
=lBKd
|
||||||
|
-----END PGP PUBLIC KEY BLOCK-----
|
@ -1,54 +0,0 @@
|
|||||||
# syntax=docker/dockerfile-upstream:1.4.3
|
|
||||||
|
|
||||||
#snappymail image
|
|
||||||
FROM base
|
|
||||||
|
|
||||||
ARG VERSION
|
|
||||||
LABEL version=$VERSION
|
|
||||||
|
|
||||||
RUN set -euxo pipefail \
|
|
||||||
; apk add --no-cache \
|
|
||||||
nginx curl \
|
|
||||||
php81 php81-fpm php81-mbstring php81-zip php81-xml php81-simplexml \
|
|
||||||
php81-dom php81-curl php81-exif gd php81-gd php81-iconv php81-intl php81-openssl \
|
|
||||||
php81-pdo_sqlite php81-pdo php81-sodium libsodium php81-tidy php81-pecl-uuid \
|
|
||||||
; ln -s /usr/bin/php81 /usr/bin/php \
|
|
||||||
; rm /etc/nginx/http.d/default.conf \
|
|
||||||
; rm /etc/php81/php-fpm.d/www.conf \
|
|
||||||
; mkdir -p /run/nginx \
|
|
||||||
; mkdir -p /var/www/webmail \
|
|
||||||
; mkdir -p /config
|
|
||||||
|
|
||||||
# nginx / PHP config files
|
|
||||||
COPY config/nginx-snappymail.conf /config/
|
|
||||||
COPY config/php-snappymail.conf /etc/php81/php-fpm.d/snappymail.conf
|
|
||||||
|
|
||||||
# Parsed and moved at startup
|
|
||||||
COPY defaults/php.ini /defaults/
|
|
||||||
COPY defaults/application.ini /defaults/
|
|
||||||
COPY defaults/default.ini /defaults/
|
|
||||||
|
|
||||||
# Install Snappymail from source
|
|
||||||
ENV SNAPPYMAIL_URL https://github.com/the-djmaze/snappymail/releases/download/v2.19.4/snappymail-2.19.4.tar.gz
|
|
||||||
# Note. This is the last working snappymail version. 2.19.6 up to 2.20.6 do not work.
|
|
||||||
|
|
||||||
RUN set -euxo pipefail \
|
|
||||||
; cd /var/www/webmail \
|
|
||||||
; curl -sL ${SNAPPYMAIL_URL} | tar xz \
|
|
||||||
; chmod -R u+w,a+rX /var/www/webmail \
|
|
||||||
; chown -R nginx:nginx /var/www/webmail
|
|
||||||
|
|
||||||
# SnappyMail login
|
|
||||||
COPY login/include.php /var/www/webmail/
|
|
||||||
COPY login/sso.php /var/www/webmail/
|
|
||||||
|
|
||||||
COPY start.py /
|
|
||||||
COPY config.py /
|
|
||||||
|
|
||||||
EXPOSE 80/tcp
|
|
||||||
VOLUME ["/data"]
|
|
||||||
|
|
||||||
CMD /start.py
|
|
||||||
|
|
||||||
HEALTHCHECK CMD curl -f -L http://localhost/ping || exit 1
|
|
||||||
RUN echo $VERSION >> /version
|
|
@ -1,16 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
import os
|
|
||||||
import logging as log
|
|
||||||
import sys
|
|
||||||
|
|
||||||
from socrate import system, conf
|
|
||||||
|
|
||||||
args = os.environ.copy()
|
|
||||||
|
|
||||||
log.basicConfig(stream=sys.stderr, level=args.get("LOG_LEVEL", "WARNING"))
|
|
||||||
|
|
||||||
# Build final configuration paths
|
|
||||||
conf.jinja("/config/nginx-snappymail.conf", args, "/etc/nginx/http.d/snappymail.conf")
|
|
||||||
if os.path.exists("/var/run/nginx.pid"):
|
|
||||||
os.system("nginx -s reload")
|
|
@ -1,118 +0,0 @@
|
|||||||
; Start a new pool named 'snappymail'.
|
|
||||||
; the variable $pool can be used in any directive and will be replaced by the
|
|
||||||
; pool name ('snappymail' here)
|
|
||||||
[snappymail]
|
|
||||||
|
|
||||||
; Redirect worker stdout and stderr into main error log. If not set, stdout and
|
|
||||||
; stderr will be redirected to /dev/null according to FastCGI specs.
|
|
||||||
; Default value: no.
|
|
||||||
catch_workers_output = 1
|
|
||||||
|
|
||||||
; Unix user/group of processes
|
|
||||||
; Note: The user is mandatory. If the group is not set, the default user's group
|
|
||||||
; will be used.
|
|
||||||
user = nginx
|
|
||||||
group = nginx
|
|
||||||
|
|
||||||
; The address on which to accept FastCGI requests.
|
|
||||||
; Valid syntaxes are:
|
|
||||||
; 'ip.add.re.ss:port' - to listen on a TCP socket to a specific IPv4 address on
|
|
||||||
; a specific port;
|
|
||||||
; '[ip:6:addr:ess]:port' - to listen on a TCP socket to a specific IPv6 address on
|
|
||||||
; a specific port;
|
|
||||||
; 'port' - to listen on a TCP socket to all addresses
|
|
||||||
; (IPv6 and IPv4-mapped) on a specific port;
|
|
||||||
; '/path/to/unix/socket' - to listen on a unix socket.
|
|
||||||
; Note: This value is mandatory.
|
|
||||||
listen = /var/run/php8-fpm.sock
|
|
||||||
|
|
||||||
; Set permissions for unix socket, if one is used. In Linux, read/write
|
|
||||||
; permissions must be set in order to allow connections from a web server. Many
|
|
||||||
; BSD-derived systems allow connections regardless of permissions.
|
|
||||||
; Default Values: user and group are set as the running user
|
|
||||||
; mode is set to 0660
|
|
||||||
listen.owner = nginx
|
|
||||||
listen.group = nginx
|
|
||||||
listen.mode = 0660
|
|
||||||
|
|
||||||
; Choose how the process manager will control the number of child processes.
|
|
||||||
; Possible Values:
|
|
||||||
; static - a fixed number (pm.max_children) of child processes;
|
|
||||||
; dynamic - the number of child processes are set dynamically based on the
|
|
||||||
; following directives. With this process management, there will be
|
|
||||||
; always at least 1 children.
|
|
||||||
; pm.max_children - the maximum number of children that can
|
|
||||||
; be alive at the same time.
|
|
||||||
; pm.start_servers - the number of children created on startup.
|
|
||||||
; pm.min_spare_servers - the minimum number of children in 'idle'
|
|
||||||
; state (waiting to process). If the number
|
|
||||||
; of 'idle' processes is less than this
|
|
||||||
; number then some children will be created.
|
|
||||||
; pm.max_spare_servers - the maximum number of children in 'idle'
|
|
||||||
; state (waiting to process). If the number
|
|
||||||
; of 'idle' processes is greater than this
|
|
||||||
; number then some children will be killed.
|
|
||||||
; ondemand - no children are created at startup. Children will be forked when
|
|
||||||
; new requests will connect. The following parameter are used:
|
|
||||||
; pm.max_children - the maximum number of children that
|
|
||||||
; can be alive at the same time.
|
|
||||||
; pm.process_idle_timeout - The number of seconds after which
|
|
||||||
; an idle process will be killed.
|
|
||||||
; Note: This value is mandatory.
|
|
||||||
pm = ondemand
|
|
||||||
|
|
||||||
; The number of child processes to be created when pm is set to 'static' and the
|
|
||||||
; maximum number of child processes when pm is set to 'dynamic' or 'ondemand'.
|
|
||||||
; This value sets the limit on the number of simultaneous requests that will be
|
|
||||||
; served. Equivalent to the ApacheMaxClients directive with mpm_prefork.
|
|
||||||
; Equivalent to the PHP_FCGI_CHILDREN environment variable in the original PHP
|
|
||||||
; CGI. The below defaults are based on a server without much resources. Don't
|
|
||||||
; forget to tweak pm.* to fit your needs.
|
|
||||||
; Note: Used when pm is set to 'static', 'dynamic' or 'ondemand'
|
|
||||||
; Note: This value is mandatory.
|
|
||||||
pm.max_children = 5
|
|
||||||
|
|
||||||
; The number of child processes created on startup.
|
|
||||||
; Note: Used only when pm is set to 'dynamic'
|
|
||||||
; Default Value: min_spare_servers + (max_spare_servers - min_spare_servers) / 2
|
|
||||||
; pm.start_servers = 2
|
|
||||||
|
|
||||||
; The desired minimum number of idle server processes.
|
|
||||||
; Note: Used only when pm is set to 'dynamic'
|
|
||||||
; Note: Mandatory when pm is set to 'dynamic'
|
|
||||||
; pm.min_spare_servers = 1
|
|
||||||
|
|
||||||
; The desired maximum number of idle server processes.
|
|
||||||
; Note: Used only when pm is set to 'dynamic'
|
|
||||||
; Note: Mandatory when pm is set to 'dynamic'
|
|
||||||
; pm.max_spare_servers = 3
|
|
||||||
|
|
||||||
; This sets the maximum time in seconds a script is allowed to run before it is
|
|
||||||
; terminated by the parser. This helps prevent poorly written scripts from tying up
|
|
||||||
; the server. The default setting is 30s.
|
|
||||||
; Note: Used only when pm is set to 'ondemand'
|
|
||||||
pm.process_idle_timeout = 10s
|
|
||||||
|
|
||||||
; The number of requests each child process should execute before respawning.
|
|
||||||
; This can be useful to work around memory leaks in 3rd party libraries. For endless
|
|
||||||
; request processing specify '0'.
|
|
||||||
; Equivalent to PHP_FCGI_MAX_REQUESTS. Default value: 0.
|
|
||||||
; Noted: Used only when pm is set to 'ondemand'
|
|
||||||
pm.max_requests = 200
|
|
||||||
|
|
||||||
; The ping URI to call the monitoring page of FPM. If this value is not set, no
|
|
||||||
; URI will be recognized as a ping page. This could be used to test from outside
|
|
||||||
; that FPM is alive and responding, or to
|
|
||||||
; - create a graph of FPM availability (rrd or such);
|
|
||||||
; - remove a server from a group if it is not responding (load balancing);
|
|
||||||
; - trigger alerts for the operating team (24/7).
|
|
||||||
; Note: The value must start with a leading slash (/). The value can be
|
|
||||||
; anything, but it may not be a good idea to use the .php extension or it
|
|
||||||
; may conflict with a real PHP file.
|
|
||||||
; Default Value: not set
|
|
||||||
ping.path = /ping
|
|
||||||
|
|
||||||
; This directive may be used to customize the response of a ping request. The
|
|
||||||
; response is formatted as text/plain with a 200 response code.
|
|
||||||
; Default Value: pong
|
|
||||||
;ping.response = pong
|
|
@ -1,15 +0,0 @@
|
|||||||
imap_host = "{{ FRONT_ADDRESS }}"
|
|
||||||
imap_port = 10143
|
|
||||||
imap_secure = "None"
|
|
||||||
imap_short_login = Off
|
|
||||||
sieve_use = On
|
|
||||||
sieve_allow_raw = Off
|
|
||||||
sieve_host = "{{ IMAP_ADDRESS }}"
|
|
||||||
sieve_port = 4190
|
|
||||||
sieve_secure = "None"
|
|
||||||
smtp_host = "{{ FRONT_ADDRESS }}"
|
|
||||||
smtp_port = 10025
|
|
||||||
smtp_secure = "None"
|
|
||||||
smtp_short_login = Off
|
|
||||||
smtp_auth = On
|
|
||||||
smtp_php_mail = Off
|
|
@ -0,0 +1,50 @@
|
|||||||
|
{
|
||||||
|
"name": "*",
|
||||||
|
"IMAP": {
|
||||||
|
"host": "{{ FRONT_ADDRESS }}",
|
||||||
|
"port": 10143,
|
||||||
|
"secure": 0,
|
||||||
|
"shortLogin": false,
|
||||||
|
"ssl": {
|
||||||
|
"verify_peer": false,
|
||||||
|
"verify_peer_name": false,
|
||||||
|
"allow_self_signed": false,
|
||||||
|
"SNI_enabled": true,
|
||||||
|
"disable_compression": true,
|
||||||
|
"security_level": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"SMTP": {
|
||||||
|
"host": "{{ FRONT_ADDRESS }}",
|
||||||
|
"port": 10025,
|
||||||
|
"secure": 0,
|
||||||
|
"shortLogin": false,
|
||||||
|
"ssl": {
|
||||||
|
"verify_peer": false,
|
||||||
|
"verify_peer_name": false,
|
||||||
|
"allow_self_signed": false,
|
||||||
|
"SNI_enabled": true,
|
||||||
|
"disable_compression": true,
|
||||||
|
"security_level": 1
|
||||||
|
},
|
||||||
|
"useAuth": true,
|
||||||
|
"setSender": false,
|
||||||
|
"usePhpMail": false
|
||||||
|
},
|
||||||
|
"Sieve": {
|
||||||
|
"host": "{{ IMAP_ADDRESS }}",
|
||||||
|
"port": 4190,
|
||||||
|
"secure": 0,
|
||||||
|
"shortLogin": false,
|
||||||
|
"ssl": {
|
||||||
|
"verify_peer": false,
|
||||||
|
"verify_peer_name": false,
|
||||||
|
"allow_self_signed": false,
|
||||||
|
"SNI_enabled": true,
|
||||||
|
"disable_compression": true,
|
||||||
|
"security_level": 1
|
||||||
|
},
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
"whiteList": ""
|
||||||
|
}
|
@ -1,5 +0,0 @@
|
|||||||
expose_php=Off
|
|
||||||
date.timezone={{ TZ }}
|
|
||||||
upload_max_filesize = {{ MAX_FILESIZE }}M
|
|
||||||
post_max_size = {{ MAX_FILESIZE }}M
|
|
||||||
|
|
@ -0,0 +1,11 @@
|
|||||||
|
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||||
|
Comment: Hostname:
|
||||||
|
Version: Hockeypuck 2.1.0-184-g50f1108
|
||||||
|
|
||||||
|
xjMEYg0atBYJKwYBBAHaRw8BAQdA2S2tvGavChACjtBastsKRThD3rsBW1LUZLmN
|
||||||
|
Zbs4uaHNI1NuYXBweU1haWwgPHJlbGVhc2VzQHNuYXBweW1haWwuZXU+wpQEExYK
|
||||||
|
ADwWIQQQFuRweRRVQvi6EzVIIIuhMpDz6wUCYg0atAIbAwULCQgHAgMiAgEGFQoJ
|
||||||
|
CAsCBBYCAwECHgcCF4AACgkQSCCLoTKQ8+u9SAD/Q/IoAwjUkKDJBPq0RGwCFnl6
|
||||||
|
FG/VHB97CvBSpGOxtIsBAMCwMhWlsaBHAEqbzxiN+cdlMYwV23+SWLUJ/XMFgukE
|
||||||
|
=vC/h
|
||||||
|
-----END PGP PUBLIC KEY BLOCK-----
|
@ -1,34 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
import os
|
|
||||||
import shutil
|
|
||||||
import logging as log
|
|
||||||
import sys
|
|
||||||
import subprocess
|
|
||||||
|
|
||||||
from socrate import system, conf
|
|
||||||
|
|
||||||
log.basicConfig(stream=sys.stderr, level=os.environ.get("LOG_LEVEL", "WARNING"))
|
|
||||||
|
|
||||||
# Actual startup script
|
|
||||||
os.environ["FRONT_ADDRESS"] = system.resolve_address(os.environ.get("HOST_FRONT", "front"))
|
|
||||||
os.environ["IMAP_ADDRESS"] = system.resolve_address(os.environ.get("HOST_IMAP", "imap"))
|
|
||||||
|
|
||||||
os.environ["MAX_FILESIZE"] = str(int(int(os.environ.get("MESSAGE_SIZE_LIMIT"))*0.66/1048576))
|
|
||||||
|
|
||||||
base = "/data/_data_/_default_/"
|
|
||||||
shutil.rmtree(base + "domains/", ignore_errors=True)
|
|
||||||
os.makedirs(base + "domains", exist_ok=True)
|
|
||||||
os.makedirs(base + "configs", exist_ok=True)
|
|
||||||
|
|
||||||
conf.jinja("/defaults/default.ini", os.environ, "/data/_data_/_default_/domains/default.ini")
|
|
||||||
conf.jinja("/defaults/application.ini", os.environ, "/data/_data_/_default_/configs/application.ini")
|
|
||||||
conf.jinja("/defaults/php.ini", os.environ, "/etc/php81/php.ini")
|
|
||||||
# Start the fastcgi process manager now that config files have been adjusted
|
|
||||||
os.system("php-fpm81")
|
|
||||||
|
|
||||||
os.system("chown -R nginx:nginx /data")
|
|
||||||
os.system("chmod -R a+rX /var/www/webmail/")
|
|
||||||
|
|
||||||
subprocess.call(["/config.py"])
|
|
||||||
os.execv("/usr/sbin/nginx", ["nginx", "-g", "daemon off;"])
|
|
@ -0,0 +1,133 @@
|
|||||||
|
# This is based on default configuration file for Snuffleupagus (https://snuffleupagus.rtfd.io),
|
||||||
|
# for php8.
|
||||||
|
# It contains "reasonable" defaults that won't break your websites,
|
||||||
|
# and a lot of commented directives that you can enable if you want to
|
||||||
|
# have a better protection.
|
||||||
|
|
||||||
|
# Harden the PRNG
|
||||||
|
sp.harden_random.enable();
|
||||||
|
|
||||||
|
# Disabled XXE
|
||||||
|
sp.xxe_protection.enable();
|
||||||
|
|
||||||
|
# Global configuration variables
|
||||||
|
sp.global.secret_key("{{ SNUFFLEUPAGUS_KEY }}");
|
||||||
|
|
||||||
|
# Globally activate strict mode
|
||||||
|
# https://www.php.net/manual/en/language.types.declarations.php#language.types.declarations.strict
|
||||||
|
sp.global_strict.enable();
|
||||||
|
|
||||||
|
# Prevent unserialize-related exploits
|
||||||
|
# sp.unserialize_hmac.enable();
|
||||||
|
|
||||||
|
# Only allow execution of read-only files. This is a low-hanging fruit that you should enable.
|
||||||
|
sp.readonly_exec.enable();
|
||||||
|
|
||||||
|
# PHP has a lot of wrappers, most of them aren't usually useful, you should
|
||||||
|
# only enable the ones you're using.
|
||||||
|
sp.wrappers_whitelist.list("file,php,phar,mailsosubstreams");
|
||||||
|
|
||||||
|
# Prevent sloppy comparisons.
|
||||||
|
sp.sloppy_comparison.enable();
|
||||||
|
|
||||||
|
# Use SameSite on session cookie
|
||||||
|
# https://snuffleupagus.readthedocs.io/features.html#protection-against-cross-site-request-forgery
|
||||||
|
sp.cookie.name("PHPSESSID").samesite("lax");
|
||||||
|
|
||||||
|
# Harden the `chmod` function (0777 (oct = 511, 0666 = 438)
|
||||||
|
sp.disable_function.function("chmod").param("permissions").value("438").drop();
|
||||||
|
sp.disable_function.function("chmod").param("permissions").value("511").drop();
|
||||||
|
|
||||||
|
# Prevent various `mail`-related vulnerabilities
|
||||||
|
sp.disable_function.function("mail").param("additional_parameters").value_r("\\-").drop();
|
||||||
|
|
||||||
|
# Since it's now burned, me might as well mitigate it publicly
|
||||||
|
sp.disable_function.function("putenv").param("assignment").value_r("LD_").drop()
|
||||||
|
|
||||||
|
# This one was burned in Nov 2019 - https://gist.github.com/LoadLow/90b60bd5535d6c3927bb24d5f9955b80
|
||||||
|
sp.disable_function.function("putenv").param("assignment").value_r("GCONV_").drop()
|
||||||
|
|
||||||
|
# Since people are stupid enough to use `extract` on things like $_GET or $_POST, we might as well mitigate this vector
|
||||||
|
sp.disable_function.function("extract").param("array").value_r("^_").drop()
|
||||||
|
sp.disable_function.function("extract").param("flags").value("0").drop()
|
||||||
|
|
||||||
|
# This is also burned:
|
||||||
|
# ini_set('open_basedir','..');chdir('..');…;chdir('..');ini_set('open_basedir','/');echo(file_get_contents('/etc/passwd'));
|
||||||
|
# Since we have no way of matching on two parameters at the same time, we're
|
||||||
|
# blocking calls to open_basedir altogether: nobody is using it via ini_set anyway.
|
||||||
|
# Moreover, there are non-public bypasses that are also using this vector ;)
|
||||||
|
sp.disable_function.function("ini_set").param("option").value_r("open_basedir").drop()
|
||||||
|
|
||||||
|
# Prevent various `include`-related vulnerabilities
|
||||||
|
sp.disable_function.function("require_once").value_r("\.(inc|phtml|php)$").allow();
|
||||||
|
sp.disable_function.function("include_once").value_r("\.(inc|phtml|php)$").allow();
|
||||||
|
sp.disable_function.function("require").value_r("\.(inc|phtml|php)$").allow();
|
||||||
|
sp.disable_function.function("include").value_r("\.(inc|phtml|php)$").allow();
|
||||||
|
sp.disable_function.function("require_once").drop()
|
||||||
|
sp.disable_function.function("include_once").drop()
|
||||||
|
sp.disable_function.function("require").drop()
|
||||||
|
sp.disable_function.function("include").drop()
|
||||||
|
|
||||||
|
# Prevent `system`-related injections
|
||||||
|
sp.disable_function.function("system").param("command").value_r("[$|;&`\\n\\(\\)\\\\]").drop();
|
||||||
|
sp.disable_function.function("shell_exec").param("command").value_r("[$|;&`\\n\\(\\)\\\\]").drop();
|
||||||
|
sp.disable_function.function("exec").param("command").value_r("[$|;&`\\n\\(\\)\\\\]").drop();
|
||||||
|
# This is **very** broad but doing better is non-straightforward
|
||||||
|
sp.disable_function.function("proc_open").param("command").value_r("^gpg ").allow();
|
||||||
|
sp.disable_function.function("proc_open").param("command").value_r("[$|;&`\\n\\(\\)\\\\]").drop();
|
||||||
|
|
||||||
|
# Prevent runtime modification of interesting things
|
||||||
|
sp.disable_function.function("ini_set").param("option").value("assert.active").drop();
|
||||||
|
sp.disable_function.function("ini_set").param("option").value("zend.assertions").drop();
|
||||||
|
sp.disable_function.function("ini_set").param("option").value("memory_limit").drop();
|
||||||
|
sp.disable_function.function("ini_set").param("option").value("include_path").drop();
|
||||||
|
sp.disable_function.function("ini_set").param("option").value("open_basedir").drop();
|
||||||
|
|
||||||
|
# Detect some backdoors via environment recon
|
||||||
|
sp.disable_function.function("ini_get").param("option").value("allow_url_fopen").drop();
|
||||||
|
sp.disable_function.function("ini_get").param("option").value("open_basedir").drop();
|
||||||
|
sp.disable_function.function("ini_get").param("option").value_r("suhosin").drop();
|
||||||
|
sp.disable_function.function("function_exists").param("function").value("eval").drop();
|
||||||
|
sp.disable_function.function("function_exists").param("function").value("exec").drop();
|
||||||
|
sp.disable_function.function("function_exists").param("function").value("system").drop();
|
||||||
|
sp.disable_function.function("function_exists").param("function").value("shell_exec").drop();
|
||||||
|
sp.disable_function.function("function_exists").param("function").value("proc_open").drop();
|
||||||
|
sp.disable_function.function("function_exists").param("function").value("passthru").drop();
|
||||||
|
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("/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();
|
||||||
|
|
||||||
|
# Ghetto error-based sqli detection
|
||||||
|
#sp.disable_function.function("mysql_query").ret("FALSE").drop();
|
||||||
|
#sp.disable_function.function("mysqli_query").ret("FALSE").drop();
|
||||||
|
#sp.disable_function.function("PDO::query").ret("FALSE").drop();
|
||||||
|
|
||||||
|
# Ensure that certificates are properly verified
|
||||||
|
sp.disable_function.function("curl_setopt").param("value").value("1").allow();
|
||||||
|
sp.disable_function.function("curl_setopt").param("value").value("2").allow();
|
||||||
|
# `81` is SSL_VERIFYHOST and `64` SSL_VERIFYPEER
|
||||||
|
sp.disable_function.function("curl_setopt").param("option").value("64").drop().alias("Please don't turn CURLOPT_SSL_VERIFYCLIENT off.");
|
||||||
|
sp.disable_function.function("curl_setopt").param("option").value("81").drop().alias("Please don't turn CURLOPT_SSL_VERIFYHOST off.");
|
||||||
|
|
||||||
|
# File upload
|
||||||
|
sp.disable_function.function("move_uploaded_file").param("to").value_r("\\.ph").drop();
|
||||||
|
sp.disable_function.function("move_uploaded_file").param("to").value_r("\\.ht").drop();
|
||||||
|
|
||||||
|
# Logging lockdown
|
||||||
|
sp.disable_function.function("ini_set").param("option").value_r("error_log").drop()
|
||||||
|
sp.disable_function.function("ini_set").param("option").value_r("display_errors").drop()
|
||||||
|
|
||||||
|
sp.auto_cookie_secure.enable();
|
||||||
|
# TODO: consider encrypting the cookies?
|
||||||
|
# TODO: ensure this is up to date
|
||||||
|
sp.cookie.name("roundcube_sessauth").samesite("strict");
|
||||||
|
sp.cookie.name("roundcube_sessid").samesite("strict");
|
||||||
|
sp.ini_protection.policy_silent_fail();
|
||||||
|
|
||||||
|
# roundcube uses unserialize() everywhere.
|
||||||
|
# This should do the job until https://github.com/jvoisin/snuffleupagus/issues/438 is implemented.
|
||||||
|
sp.disable_function.function("unserialize").param("data").value_r("[cCoO]:\d+:[\"{]").drop();
|
Loading…
Reference in New Issue