From 97d57db7a86a1e2004221f191c7d3c61284e6dd6 Mon Sep 17 00:00:00 2001 From: JM-Lemmi Date: Sat, 13 Nov 2021 12:08:14 +0100 Subject: [PATCH 1/6] Updated Readme changed Title to match repo docker run with `:latest` tag updated restrictions --- Readme.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Readme.md b/Readme.md index b0d343b..e596423 100644 --- a/Readme.md +++ b/Readme.md @@ -1,12 +1,11 @@ -# SMTP-Zimbraweb-Bridge in Docker +# Zimbraweb-SMTP-Bridge in Docker This Container allows users to send E-Mails via SMTP to a Zimbra Web Interface. It utilizes Postfix as receiver and the python package [zimbraweb](https://github.com/cirosec-studis/python-zimbra-web). This Container is still in development and should not be used in Production environments or for important E-Mails! ‼ Currently it only supports plain SMTP over Port 587, no TLS. **Your password is readable to anyone on the network**
-‼ It also only supports Plaintext E-Mails, no Attachments, until this is implemented in zimbraweb.
-‼ SMTP will also not return an error if the sending was unsuccessfull, you need to check the Postifx logs to see if it was successful. +‼ It only supports Plaintext E-Mails, and Attachments, but not HTML or RTF-Mails. This is due to a restriction in the Zimbra Webinterface
## Setup @@ -14,8 +13,9 @@ This Container allows users to send E-Mails via SMTP to a Zimbra Web Interface. To start the container use the following command ``` -docker run -p 587:587 ghcr.io/cirosec-studis/zimbraweb-smtp-bridge:a.2 +docker run -p 587:587 ghcr.io/cirosec-studis/zimbraweb-smtp-bridge ``` + Optionally mount a logs directory by adding `-v /path/to/logs:/srv/zimbraweb/logs/`. You can now connect to the container with your SMTP client at localhost:587. From 5401c3c03f0caf512036296d3db1fe6696837d06 Mon Sep 17 00:00:00 2001 From: Frederik Reiter Date: Sun, 14 Nov 2021 14:55:25 +0100 Subject: [PATCH 2/6] =?UTF-8?q?=F0=9F=90=B3=20=20=20Run=20Docker=20Deploy?= =?UTF-8?q?=20nightly=20and=20on=20develop?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This now runs more Docker builds and for more platforms (linux/amd64, linux/arm64 and linux/arm) `ghcr.io/cirosec-studis/zimbraweb-smtp-bridge:nightly` - This builds from `main` every night so that changes in the zimbraweb package are pulled into the container. Use this one to stay up to date. `ghcr.io/cirosec-studis/zimbraweb-smtp-bridge:latest` - Latest tagged build `ghcr.io/cirosec-studis/zimbraweb-smtp-bridge:vX.Y.Z` - Version X.Y.Z (e.g. v1.0.0) `ghcr.io/cirosec-studis/zimbraweb-smtp-bridge:develop` - Development build --- .github/workflows/deploy.yml | 48 ++++++++++++++++++++++++++++++++++++ Readme.md | 32 +++++++++++++++++++++++- 2 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/deploy.yml diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..8ddfd01 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,48 @@ +name: Deploy Docker + +# Run workflow on tags starting with v (eg. v2, v1.2.0) +on: + push: + tags: + - v* + branches: + - main + - develop + schedule: + - cron: "0 0 * * *" + +jobs: + Deploy: + runs-on: ubuntu-latest + steps: + - name: Checkout Code + uses: actions/checkout@v1 + - name: Docker meta + id: meta + uses: docker/metadata-action@v3 + with: + # list of Docker images to use as base name for tags + images: | + ghcr.io/${{ github.repository }} + # generate Docker tags based on the following events/attributes + tags: | + type=schedule + type=semver,pattern={{raw}} + type=ref,event=branch + - name: Set up QEMU + uses: docker/setup-qemu-action@v1 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + - name: Login to GitHub Container Registry + uses: docker/login-action@v1 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ github.token }} + - name: Build and Push Docker Image + uses: docker/build-push-action@v2 + with: + platforms: linux/amd64,linux/arm64,linux/arm + push: true # Will only build if this is not here + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} \ No newline at end of file diff --git a/Readme.md b/Readme.md index e596423..04ddae1 100644 --- a/Readme.md +++ b/Readme.md @@ -13,9 +13,22 @@ This Container allows users to send E-Mails via SMTP to a Zimbra Web Interface. To start the container use the following command ``` -docker run -p 587:587 ghcr.io/cirosec-studis/zimbraweb-smtp-bridge +docker run -p 587:587 ghcr.io/cirosec-studis/zimbraweb-smtp-bridge:nightly ``` +### Docker Tags + +The following tags are available: + +`ghcr.io/cirosec-studis/zimbraweb-smtp-bridge:nightly` - This builds from `main` every night so that changes in the zimbraweb package are pulled into the container. Use this one to stay up to date. +`ghcr.io/cirosec-studis/zimbraweb-smtp-bridge:latest` - Latest tagged build +`ghcr.io/cirosec-studis/zimbraweb-smtp-bridge:vX.Y.Z` - Version X.Y.Z (e.g. v1.0.0) +`ghcr.io/cirosec-studis/zimbraweb-smtp-bridge:develop` - development build + + + +If you're on a raspberry pi, note the section [Docker on Raspberry Pi](#docker-on-raspberry-pi). + Optionally mount a logs directory by adding `-v /path/to/logs:/srv/zimbraweb/logs/`. You can now connect to the container with your SMTP client at localhost:587. @@ -32,3 +45,20 @@ In Thunderbird you should go to Acccount Settings, select "Composition & Address ### Other clients You need to make sure your client sends emails in text/plain because Zimbra Web does not support HTML emails. + +### Docker on Raspberry Pi + +Note that currently the alpine image does not work on raspberry pi without the following tweak: + +```bash +# Get signing keys to verify the new packages, otherwise they will not install +rpi ~$ sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 04EE7237B7D453EC 648ACFD622F3D138 + +# Add the Buster backport repository to apt sources.list +rpi ~$ echo 'deb http://httpredir.debian.org/debian buster-backports main contrib non-free' | sudo tee -a /etc/apt/sources.list.d/debian-backports.list + +rpi ~$ sudo apt update +rpi ~$ sudo apt install libseccomp2 -t buster-backports +``` + +This fix is from https://blog.samcater.com/fix-workaround-rpi4-docker-libseccomp2-docker-20/. Alpine requires libseccomp2>2.4.2 but on debian buster has 2.3.6, this fix installes a newer version from the backports repository. From cc04cf47a297054f3967437e13d447af6786f28d Mon Sep 17 00:00:00 2001 From: Frederik Reiter Date: Sun, 14 Nov 2021 15:34:21 +0000 Subject: [PATCH 3/6] Update Readme.md --- Readme.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Readme.md b/Readme.md index 04ddae1..43bb2f9 100644 --- a/Readme.md +++ b/Readme.md @@ -20,10 +20,10 @@ docker run -p 587:587 ghcr.io/cirosec-studis/zimbraweb-smtp-bridge:nightly The following tags are available: -`ghcr.io/cirosec-studis/zimbraweb-smtp-bridge:nightly` - This builds from `main` every night so that changes in the zimbraweb package are pulled into the container. Use this one to stay up to date. -`ghcr.io/cirosec-studis/zimbraweb-smtp-bridge:latest` - Latest tagged build -`ghcr.io/cirosec-studis/zimbraweb-smtp-bridge:vX.Y.Z` - Version X.Y.Z (e.g. v1.0.0) -`ghcr.io/cirosec-studis/zimbraweb-smtp-bridge:develop` - development build +* `ghcr.io/cirosec-studis/zimbraweb-smtp-bridge:nightly` - This builds from `main` every night so that changes in the zimbraweb package are pulled into the container. Use this one to stay up to date. +* `ghcr.io/cirosec-studis/zimbraweb-smtp-bridge:latest` - Latest tagged build +* `ghcr.io/cirosec-studis/zimbraweb-smtp-bridge:vX.Y.Z` - Version X.Y.Z (e.g. v1.0.0) +* `ghcr.io/cirosec-studis/zimbraweb-smtp-bridge:develop` - development build From b2591435a82d4ca51dfdbb2b3bbe27a2da20d5b6 Mon Sep 17 00:00:00 2001 From: Frederik Reiter Date: Mon, 15 Nov 2021 15:28:54 +0100 Subject: [PATCH 4/6] Add TLS support (#30) * Add TLS support * TLS can now be enabled by copying the certificate and private key into the container and running /tls.sh inside the container. * Add instructions for Outlook and Thunderbird and information about the public bridge. --- Dockerfile | 3 +++ Readme.md | 75 ++++++++++++++++++++++++++++++++++++++++++---------- files/tls.sh | 25 ++++++++++++++++++ 3 files changed, 89 insertions(+), 14 deletions(-) create mode 100644 files/tls.sh diff --git a/Dockerfile b/Dockerfile index b72be5a..96e4290 100644 --- a/Dockerfile +++ b/Dockerfile @@ -62,4 +62,7 @@ EXPOSE 587 ADD ./files/start.sh / RUN chmod +x /start.sh + +ADD ./files/tls.sh / +RUN chmod +x /tls.sh CMD ["/start.sh"] diff --git a/Readme.md b/Readme.md index 43bb2f9..9af8006 100644 --- a/Readme.md +++ b/Readme.md @@ -7,15 +7,74 @@ This Container allows users to send E-Mails via SMTP to a Zimbra Web Interface. ‼ Currently it only supports plain SMTP over Port 587, no TLS. **Your password is readable to anyone on the network**
‼ It only supports Plaintext E-Mails, and Attachments, but not HTML or RTF-Mails. This is due to a restriction in the Zimbra Webinterface
+## Public Bridge -## Setup +There is a public server available at dhbw-mannheim.email at port 2525. Connect to it via SMTP with STARTTLS. For increased security we recommend hosting the Bridge yourself if you have a server available, [more on that below](#self-hosting). The public bridge is configured to automatically purge all data every 60 minutes. No logging data is written to disk at all, auth tokens (which are needed to authenticated with the Web Client) are kept only in memory and for 60 minutes at most, but in almost all cases will be deleted immediately after successful email delivery. + +You can use the following settings: + +IMAP (SSL/TLS): `studgate.dhbw-mannheim.de` at port `993` + +SMTP (STARTTLS): `dhbw-mannheim.email` at port `2525` + +Authenticate with the same credentials that you use for the Web Interface (--> without the @student.dhbw.mannheim.de part!) + +You need to make sure your client sends emails in text/plain because Zimbra Web does not support HTML emails. + +### Outlook + +https://user-images.githubusercontent.com/18506129/141695204-2dd563d1-2a69-4a9c-97b9-0e1ee1667c24.mp4 + +In Outlook, you should set your default mail format to "Plain Text" ("Nur Text") by going to File->Options->Mail ("Datei->Optionen->E-mail") and selecting "Plain Text" ("Nur Text") in the "Compose messages in this format" ("Nachrichten in diesem Format verfassen") dropdown. + +### Thunderbird + +https://user-images.githubusercontent.com/18506129/141694660-e9a54848-7474-45b1-9ffb-956a3e1ee264.mp4 + +Please note that lowering the minimum TLS version is requried because the Zimbra IMAP server uses outdated IMAP. There is sadly nothing we can do on our side to fix this. The SMTP Bridge uses up-to-date TLS. + +In Thunderbird you should go to Acccount Settings, select "Composition & Addressing" in the Account and deselect "Compose messages in HTML format." + +## Self-Hosting To start the container use the following command ``` -docker run -p 587:587 ghcr.io/cirosec-studis/zimbraweb-smtp-bridge:nightly +docker run --name smtp_bridge -p 587:587 ghcr.io/cirosec-studis/zimbraweb-smtp-bridge:nightly +``` + +### TLS Support + +### Getting a certificate + +To enable TLS you first need to generate a certificate. You can do this on the host machine using [`certbot`](https://certbot.eff.org/), here's how to do it in Ubuntu: + +```bash +$ sudo apt install certbot +$ sudo certbot certonly --standalone -d +``` + +Follow the prompts. The certificate and key should end up in `/etc/letsencrypt/live//fullchain.pem` and `/etc/letsencrypt/live//privkey.pem`. + +### Enabling TLS in the Container + +The following commands assume your Docker container is named `smtp_bride`. Substitute as necessary. + +Copy the certificate and key into the container: +``` +# docker cp /etc/letsencrypt/live//fullchain.pem smtp_bridge:/srv/zimbraweb/ssl_certificate.pem +# docker cp /etc/letsencrypt/live//privkey.pem smtp_bridge:/srv/zimbraweb/private_key.pem +``` + +Enable TLS in the Container: +``` +# docker run --it smtp_bridge /tls.sh ``` +Follow the prompt again, you should be able accept the default values for the certificate and key location. + +That's it, TLS is now enabled! Use STARTTLS on port 2525. + ### Docker Tags The following tags are available: @@ -34,18 +93,6 @@ Optionally mount a logs directory by adding `-v /path/to/logs:/srv/zimbraweb/log You can now connect to the container with your SMTP client at localhost:587. To authenticate, use your Zimbra Webclient login credentials (without the @domain.tld part!). -### Outlook - -In Outlook, you should set your default mail format to "Plain Text" ("Nur Text") by going to File->Options->Mail ("Datei->Optionen->E-mail") and selecting "Plain Text" ("Nur Text") in the "Compose messages in this format" ("Nachrichten in diesem Format verfassen") dropdown. - -### Thunderbird - -In Thunderbird you should go to Acccount Settings, select "Composition & Addressing" in the Account and deselect "Compose messages in HTML format." - -### Other clients - -You need to make sure your client sends emails in text/plain because Zimbra Web does not support HTML emails. - ### Docker on Raspberry Pi Note that currently the alpine image does not work on raspberry pi without the following tweak: diff --git a/files/tls.sh b/files/tls.sh new file mode 100644 index 0000000..c1425ad --- /dev/null +++ b/files/tls.sh @@ -0,0 +1,25 @@ +#!/bin/sh +echo "NOTE: none of these parameters are verified. If you screw something up, run the script again. If you want to remove TLS you need to reset the container." + +read -p 'What domain is this server running on? ' hostname + +read -p 'Where is the domain certificate located (within the docker container)? [default: /srv/zimbraweb/ssl_certificate.pem]: ' certfile +certfile=${certfile:-/srv/zimbraweb/ssl_certificate.pem} + +read -p 'Where is the private key located (within the docker container)? [default: /srv/zimbraweb/private_key.pem]: ' keyfile +keyfile=${keyfile:-/srv/zimbraweb/private_key.pem} + +chmod 777 ${keyfile} +chmod 777 ${certfile} + +postconf -e myhostname=$hostname +postconf -e "smtpd_tls_cert_file = ${certfile}" +postconf -e "smtpd_tls_key_file = ${keyfile}" +postconf -e 'smtp_tls_security_level = may' +postconf -e 'smtpd_tls_security_level = may' +postconf -e 'smtp_tls_note_starttls_offer = yes' +postconf -e 'smtpd_tls_loglevel = 1' +postconf -e 'smtpd_tls_received_header = yes' + +postfix stop +postfix start \ No newline at end of file From d6539375414d65c04b7c80a0df1d3d4e0189726c Mon Sep 17 00:00:00 2001 From: Frederik Reiter Date: Mon, 15 Nov 2021 14:32:54 +0000 Subject: [PATCH 5/6] Update Readme.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove "no TLS support" warning from README.md 🤦 --- Readme.md | 1 - 1 file changed, 1 deletion(-) diff --git a/Readme.md b/Readme.md index 9af8006..ded999c 100644 --- a/Readme.md +++ b/Readme.md @@ -4,7 +4,6 @@ This Container allows users to send E-Mails via SMTP to a Zimbra Web Interface. This Container is still in development and should not be used in Production environments or for important E-Mails! -‼ Currently it only supports plain SMTP over Port 587, no TLS. **Your password is readable to anyone on the network**
‼ It only supports Plaintext E-Mails, and Attachments, but not HTML or RTF-Mails. This is due to a restriction in the Zimbra Webinterface
## Public Bridge From 5dc257fdacc0e3d1bbccd8790f65e5f74235c5ae Mon Sep 17 00:00:00 2001 From: Frederik Reiter Date: Mon, 15 Nov 2021 19:31:54 +0100 Subject: [PATCH 6/6] Add self-signed certificate by default --- Dockerfile | 2 ++ Readme.md | 32 ++++++++++++-------------------- files/start.sh | 1 + files/tls.sh | 19 +++++++++---------- 4 files changed, 24 insertions(+), 30 deletions(-) diff --git a/Dockerfile b/Dockerfile index 96e4290..50b2796 100644 --- a/Dockerfile +++ b/Dockerfile @@ -65,4 +65,6 @@ RUN chmod +x /start.sh ADD ./files/tls.sh / RUN chmod +x /tls.sh +RUN mkdir /tls/ + CMD ["/start.sh"] diff --git a/Readme.md b/Readme.md index ded999c..f2941ef 100644 --- a/Readme.md +++ b/Readme.md @@ -39,40 +39,32 @@ In Thunderbird you should go to Acccount Settings, select "Composition & Address To start the container use the following command ``` -docker run --name smtp_bridge -p 587:587 ghcr.io/cirosec-studis/zimbraweb-smtp-bridge:nightly +docker run --name smtp_bridge -h -p 587:587 ghcr.io/cirosec-studis/zimbraweb-smtp-bridge:nightly ``` +If you do not have a domain name associated with the server, you can use whatever hostname you want, e.g. "smtp_bridge.local". + ### TLS Support -### Getting a certificate +TLS is enabled by default, using a self-signed certificate for the hostname you provided. This will be enough in most cases, you will just need to accept the self-signed certificate in your email client. Thunderbird and Outlook will tell you that the certificate could not be verified. You will need to add an exception. -To enable TLS you first need to generate a certificate. You can do this on the host machine using [`certbot`](https://certbot.eff.org/), here's how to do it in Ubuntu: +#### CA-signed certificates -```bash -$ sudo apt install certbot -$ sudo certbot certonly --standalone -d -``` +If you want to use a certificate signed by a Certificate Authority, e.g. Let's Encrypt, you can do that. -Follow the prompts. The certificate and key should end up in `/etc/letsencrypt/live//fullchain.pem` and `/etc/letsencrypt/live//privkey.pem`. +You already need to have a certificate and a private key file. You can get them with [`certbot`](https://certbot.eff.org/lets-encrypt/). Usually running `sudo certbot certonly --standalone -d ` will do the trick. The certificate and key should end up in `/etc/letsencrypt/live//fullchain.pem` and `/etc/letsencrypt/live//privkey.pem`. -### Enabling TLS in the Container +Make sure to run the docker container with the same hostname as the certificate you are using. -The following commands assume your Docker container is named `smtp_bride`. Substitute as necessary. +Put the certificate and key into a folder on your host and name them `cert.pem` and `key.pem` respectively. -Copy the certificate and key into the container: -``` -# docker cp /etc/letsencrypt/live//fullchain.pem smtp_bridge:/srv/zimbraweb/ssl_certificate.pem -# docker cp /etc/letsencrypt/live//privkey.pem smtp_bridge:/srv/zimbraweb/private_key.pem -``` +Then you can use the following command to start the container with the certificate and key you just created: -Enable TLS in the Container: ``` -# docker run --it smtp_bridge /tls.sh +docker run -v /host/path/to/tls/folder/:/tls/ --name smtp_bridge -h -p 587:587 ghcr.io/cirosec-studis/zimbraweb-smtp-bridge:nightly ``` -Follow the prompt again, you should be able accept the default values for the certificate and key location. - -That's it, TLS is now enabled! Use STARTTLS on port 2525. +That's it, the container will now use the signed TLS certificate. ### Docker Tags diff --git a/files/start.sh b/files/start.sh index 11f1d3a..48efe2d 100644 --- a/files/start.sh +++ b/files/start.sh @@ -1,5 +1,6 @@ #!/bin/sh python3 /srv/zimbraweb/zimbra_config.py +/tls.sh dovecot postfix start python3 /srv/zimbraweb/zimbra_milter.py \ No newline at end of file diff --git a/files/tls.sh b/files/tls.sh index c1425ad..df40e52 100644 --- a/files/tls.sh +++ b/files/tls.sh @@ -1,18 +1,17 @@ #!/bin/sh -echo "NOTE: none of these parameters are verified. If you screw something up, run the script again. If you want to remove TLS you need to reset the container." -read -p 'What domain is this server running on? ' hostname +certfile=/tls/cert.pem +keyfile=/tls/key.pem -read -p 'Where is the domain certificate located (within the docker container)? [default: /srv/zimbraweb/ssl_certificate.pem]: ' certfile -certfile=${certfile:-/srv/zimbraweb/ssl_certificate.pem} +if [ ! -f "$certfile" ]; then + # generate a self signed certificate (valid for 10 years) + openssl req -x509 -newkey rsa:4096 -keyout $keyfile -out $certfile -sha256 -days 3650 -nodes -subj "/CN=$HOSTNAME" +fi -read -p 'Where is the private key located (within the docker container)? [default: /srv/zimbraweb/private_key.pem]: ' keyfile -keyfile=${keyfile:-/srv/zimbraweb/private_key.pem} +chmod 600 $certfile +chmod 600 $keyfile -chmod 777 ${keyfile} -chmod 777 ${certfile} - -postconf -e myhostname=$hostname +postconf -e myhostname=$HOSTNAME postconf -e "smtpd_tls_cert_file = ${certfile}" postconf -e "smtpd_tls_key_file = ${keyfile}" postconf -e 'smtp_tls_security_level = may'