Author Topic: DMS/Roundcube/Caddy - fail2ban blocks docker gateway  (Read 1867 times)

Offline peracchi

  • Newbie
  • *
  • Posts: 3
DMS/Roundcube/Caddy - fail2ban blocks docker gateway
« on: April 18, 2023, 07:25:54 PM »
Complex "puzzle", I suspect that needs configuration at DMS and Roundcube containers.

Caddy container appears to be doing his part: delivering X-Real-IP and X-Forwarded-For to Roundcube.

Problem occurs when someone tries to login on Roundcube... Three failed attempts and fail2ban on Docker Mailserver blocks docker gateway, 172.18.0.1; then, nobody can login on Roundcube until ban expires. Would like to pin/understand right configuration and not circunvent/disable fail2ban.

After two days of intense research, I suspect that solution may envolve:
- "$config['use_https'] = true;" and "$config['proxy_whitelist'] = ['172.18.0.0/16'];" on Roundcube
- "login_trusted_networks = 172.18.0.0/16" on Dovecot

Tried so many things that I got lost at the problem...


Code: [Select]
external IP  | Linux Server with Containers
----------------------------------------------------------------
                          (172.18.0.2)
                |-  80 -|
              |-|       |--- Caddy ---|
              | |- 443 -|             |          (172.18.0.6)
              |                       |      |                 |
              |                       |- 80 -|--- Roundcube ---|
20.112.52.29 -|                              |        |        |
              |                                       |
              |           (172.18.0.6)                |
              | |-  25 -|             |               |
              | |- 143 -|             |               |
              |-|- 465 -|---  DMS  ---|---------------|
                |- 587 -|             |
                |- 993 -|             |
----------------------------------------------------------------
 external IP  | Linux Server with Containers

Caddyfile block relative to Roundcube:
Code: [Select]
webmail.mydomain.net {
reverse_proxy http://roundcube:80 {
header_up X-Real-IP {remote_host}
}
}
Any ideas/suggestions are welcome.

One year ago I tried to solve this problem but despite some help/ideas I could not discover how to do it.
https://github.com/orgs/docker-mailserver/discussions/2603

Instead of "ressurrect" that old discussion I thought it would be better start a new topic.

---

Code: [Select]
# Caddy / docker-compose.yml
version: "3.9"
services:
  caddy:
    image: caddy-with-cloudflare:2.6.4
    hostname: caddy
    container_name: caddy
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
      - "443:443/udp"
    volumes:
      - $PWD/Caddyfile:/etc/caddy/Caddyfile
      - $PWD/srv:/srv
      - data:/data
      - config:/config
volumes:
  data:
  config:
networks:
  default:
    name: caddy_net
    external: true

# OpenLDAP & phpLDAPadmin / docker-compose.yml
version: "3.9"
services:
  openldap:
    image: osixia/openldap:latest
    container_name: openldap
    hostname: ldap
    restart: unless-stopped
    ports:
      #- "389:389"
      - "636:636"
    volumes:
      - config:/etc/ldap/slapd.d
      - data:/var/lib/ldap
      - /var/lib/docker/volumes/caddy_data/_data/caddy/certificates/acme-v02.api.letsencrypt.org-directory/ldap.mydomain.net:/container/service/slapd/assets/certs
    environment:
      LDAP_LOG_LEVEL: 256
      LDAP_ORGANISATION: MYDOMAIN Net
      LDAP_DOMAIN: mydomain.net
      LDAP_BASE_DN:
      LDAP_ADMIN_PASSWORD: admin-password-123
      LDAP_CONFIG_PASSWORD: config-password-123
      LDAP_READONLY_USER: false
      #LDAP_READONLY_USER_USERNAME: readonly
      #LDAP_READONLY_USER_PASSWORD: readonly
      LDAP_RFC2307BIS_SCHEMA: true
      LDAP_BACKEND: mdb
      LDAP_TLS: true
      LDAP_TLS_CRT_FILENAME: ldap.mydomain.net.crt
      LDAP_TLS_KEY_FILENAME: ldap.mydomain.net.key
      LDAP_TLS_CA_CRT_FILENAME: ldap.mydomain.net.crt
      #LDAP_TLS_DH_PARAM_FILENAME: dhparam.pem
      LDAP_TLS_ENFORCE: false
      LDAP_TLS_CIPHER_SUITE: NORMAL:SECURE256:-VERS-SSL3.0
      LDAP_TLS_VERIFY_CLIENT: try
      LDAP_REPLICATION: false
      KEEP_EXISTING_CONFIG: false
      LDAP_REMOVE_CONFIG_AFTER_SETUP: true
      LDAP_SSL_HELPER_PREFIX: ldap
      LDAP_OPENLDAP_UID: 0
      LDAP_OPENLDAP_GID: 0
    tty: true
    stdin_open: true
    domainname: mydomain.net
  phpldapadmin:
    image: osixia/phpldapadmin:latest
    container_name: phpldapadmin
    hostname: phpldapadmin
    restart: unless-stopped
    #ports:
    # - "8080:80"
    volumes:
      - phpldapadmin:/var/www/phpldapadmin
    environment:
      PHPLDAPADMIN_LDAP_HOSTS: ldap
      PHPLDAPADMIN_HTTPS: false
    depends_on:
      - openldap
volumes:
  config:
  data:
  phpldapadmin:
networks:
  default:
    name: caddy_net
    external: true

# Docker Mailserver / docker-compose.yml
version: "3.9"
services:
  mailserver:
    image: ghcr.io/docker-mailserver/docker-mailserver:12.0.0
    container_name: dms
    hostname: mail
    domainname: mydomain.net
    ports:
      - "25:25"     # SMTP  (explicit TLS => STARTTLS)
      - "143:143"   # IMAP4 (explicit TLS => STARTTLS)
      - "465:465"   # ESMTP (implicit TLS)
      - "587:587"   # ESMTP (explicit TLS => STARTTLS)
      - "993:993"   # IMAP4 (implicit TLS)
      - "4190:4190" # Managesieve
    volumes:
      - $PWD/config/:/tmp/docker-mailserver/
      - $PWD/mail-data/:/var/mail/
      - $PWD/mail-logs/:/var/log/mail/
      - $PWD/mail-state/:/var/mail-state/
      - /etc/localtime:/etc/localtime:ro
      - /var/lib/docker/volumes/caddy_data/_data/caddy/certificates/acme-v02.api.letsencrypt.org-directory:/tmp/dms/custom-certs/:ro
    environment:
      - OVERRIDE_HOSTNAME=mail.mydomain.net
      - LOG_LEVEL=info
      - ACCOUNT_PROVISIONER=LDAP
      - TZ=America/Sao_Paulo
      - SPOOF_PROTECTION=1
      - ENABLE_POLICYD_SPF=0
      - ENABLE_CLAMAV=1
      - ENABLE_RSPAMD=1
      - RSPAMD_LEARN=1
      - RSPAMD_GREYLISTING=1
      - ENABLE_DNSBL=1
      - ENABLE_FAIL2BAN=1
      - FAIL2BAN_BLOCKTYPE=reject
      - ENABLE_MANAGESIEVE=1
      - SSL_TYPE=manual
      - SSL_CERT_PATH=/tmp/dms/custom-certs/mail.mydomain.net/mail.mydomain.net.crt
      - SSL_KEY_PATH=/tmp/dms/custom-certs/mail.mydomain.net/mail.mydomain.net.key
      - POSTFIX_MAILBOX_SIZE_LIMIT=1073741824
      - POSTFIX_MESSAGE_SIZE_LIMIT=52428800
      - PFLOGSUMM_TRIGGER=logrotate
      - LOGWATCH_INTERVAL=weekly
      - REPORT_SENDER=no-reply@mydomain.net
      - LOGROTATE_INTERVAL=monthly
      - POSTFIX_INET_PROTOCOLS=ipv4
      - DOVECOT_INET_PROTOCOLS=ipv4
      - ENABLE_SPAMASSASSIN=1
      - SPAMASSASSIN_SPAM_TO_INBOX=1
      - ENABLE_SPAMASSASSIN_KAM=1
      - MOVE_SPAM_TO_JUNK=1
      - ENABLE_POSTGREY=1
      - LDAP_START_TLS=yes
      - LDAP_SERVER_HOST=ldap
      - LDAP_SEARCH_BASE=dc=mydomain,dc=net
      - LDAP_BIND_DN=cn=admin,dc=mydomain,dc=net
      - LDAP_BIND_PW=admin-password-123
      - LDAP_QUERY_FILTER_DOMAIN=(mail=*@%s)
      - LDAP_QUERY_FILTER_USER=(&(mail=%s)(mailEnabled=TRUE))
      - LDAP_QUERY_FILTER_ALIAS=(&(mailAlias=%s)(mailEnabled=TRUE))
      - LDAP_QUERY_FILTER_GROUP=(&(objectclass=groupOfUniqueNames)(cn=%s))
      - LDAP_QUERY_FILTER_SENDERS=(|(mail=%s)(mailAlias=%s)(mail=admin@*))
      - DOVECOT_USER_FILTER=(&(objectClass=PostfixBookMailAccount)(mail=%u)(mailEnabled=TRUE))
      - DOVECOT_PASS_FILTER=(&(objectClass=PostfixBookMailAccount)(mail=%u)(mailEnabled=TRUE))
      - DOVECOT_AUTH_BIND=yes
      - ENABLE_SASLAUTHD=1
      - SASLAUTHD_MECHANISMS=ldap
      - SASLAUTHD_LDAP_SERVER=ldap
      - SASLAUTHD_LDAP_BIND_DN=cn=admin,dc=mydomain,dc=net
      - SASLAUTHD_LDAP_PASSWORD=admin-password-123
      - SASLAUTHD_LDAP_SEARCH_BASE=dc=mydomain,dc=net
      - SASLAUTHD_LDAP_FILTER=(&(objectClass=PostfixBookMailAccount)(mail=%u@%r)(mailEnabled=TRUE))
    cap_add:
      - NET_ADMIN # For Fail2Ban to work
    restart: always
networks:
  default:
    name: caddy_net
    external: true

# Roundcube / docker-compose.yml
version: "3.9"
services:
  roundcube:
    image: roundcube/roundcubemail:1.6.1-apache
    container_name: roundcube
    hostname: roundcube
    restart: unless-stopped
    volumes:
      - $PWD/config:/var/roundcube/config
      - app:/var/www/html
      - data:/var/roundcube/db
    environment:
      - ROUNDCUBEMAIL_DEFAULT_HOST=tls://mail.mydomain.net
      - ROUNDCUBEMAIL_SMTP_SERVER=tls://mail.mydomain.net
      - ROUNDCUBEMAIL_DB_TYPE=sqlite
      - ROUNDCUBEMAIL_SKIN=elastic
      - ROUNDCUBEMAIL_UPLOAD_MAX_FILESIZE=25M
volumes:
  app:
  data:
networks:
  default:
    name: caddy_net
    external: true

Offline Dmitry42

  • Full Member
  • ***
  • Posts: 232
Re: DMS/Roundcube/Caddy - fail2ban blocks docker gateway
« Reply #1 on: April 18, 2023, 10:23:46 PM »
Problem not in your Roundcube. Your fail2ban have rules for imap,smtp,web logs.
Config your fail2ban - add this IP to whitelist.

Offline peracchi

  • Newbie
  • *
  • Posts: 3
Re: DMS/Roundcube/Caddy - fail2ban blocks docker gateway
« Reply #2 on: April 19, 2023, 11:52:56 AM »
Use case: Firefox on Android phone tries to login on Roundcube using existing user with wrong password.

Pay attention that Roundcube received (and knows) X-Real-IP and X-Forwarded-For.

So, some configuration must be done at Roundcube and DMS to use that information, X-Real-IP and/or X-Forwarded-For.

At Roundcube config level, maybe one or more of this parameters must be adjusted:

Code: [Select]
// tell PHP that it should work as under secure connection
// even if it doesn't recognize it as secure ($_SERVER['HTTPS'] is not set)
// e.g. when you're running Roundcube behind a https proxy
// this option is mutually exclusive to 'force_https' and only either one of them should be set to true.
$config['use_https'] = false;

Code: [Select]
// List of trusted proxies
// X_FORWARDED_* and X_REAL_IP headers are only accepted from these IPs
$config['proxy_whitelist'] = [];

Complete config file at https://github.com/roundcube/roundcubemail/blob/master/config/defaults.inc.php

At DMS config level, for sure something on Dovecot, like:

https://doc.dovecot.org/configuration_manual/forwarding_parameters/

and

https://doc.dovecot.org/settings/core/#core_setting-login_trusted_networks

Below, pertinent parts of DMS and Roundcube logs.

DMS
Code: [Select]
[   INF   ]  Welcome to docker-mailserver 12.0.0
[   INF   ]  Checking configuration
[   INF   ]  Configuring mail server
[ WARNING ]  Rspamd integration is work in progress - expect (breaking) changes at any time
[ WARNING ]  (Rspamd setup) Running Amavis/SA & Rspamd at the same time is discouraged
[   INF   ]  Starting daemons
[   INF   ]  mail.mydomain.net is up and running
Apr 19 11:58:21 mail amavis[1204]: starting. /usr/sbin/amavisd-new at mail.mydomain.net amavisd-new-2.11.1 (20181009), Unicode aware, LC_CTYPE="C.UTF-8"
Apr 19 11:58:21 mail amavis[1204]: perl=5.032001, user=, EUID: 109 (109);  group=, EGID: 111 111 (111 111)
Apr 19 11:58:21 mail amavis[1204]: Net::Server: Group Not Defined.  Defaulting to EGID '111 111'
Apr 19 11:58:21 mail amavis[1204]: Net::Server: User Not Defined.  Defaulting to EUID '109'
Apr 19 11:58:21 mail amavis[1204]: No ext program for   .zoo, tried: zoo
Apr 19 11:58:21 mail amavis[1204]: No ext program for   .doc, tried: ripole
Apr 19 11:58:21 mail amavis[1204]: No decoder for       .F
Apr 19 11:58:21 mail amavis[1204]: No decoder for       .doc
Apr 19 11:58:21 mail amavis[1204]: No decoder for       .zoo
Apr 19 11:58:21 mail amavis[1204]: Using primary internal av scanner code for ClamAV-clamd
Apr 19 11:58:21 mail amavis[1204]: Found secondary av scanner ClamAV-clamscan at /usr/bin/clamscan

...

Apr 19 12:07:28 mail dovecot: auth: ldap(myusername@mydomain.net,172.18.0.1,<H5pGyLH5YpusEgAB>): Password mismatch (for LDAP bind) (SHA1 of given password: 2e6f9b)
Apr 19 12:07:30 mail dovecot: imap-login: Disconnected: Connection closed (auth failed, 1 attempts in 2 secs): user=<myusername@mydomain.net>, method=PLAIN, rip=172.18.0.1, lip=172.18.0.7, TLS, session=<H5pGyLH5YpusEgAB>


Roundcube
Code: [Select]
roundcubemail found in /var/www/html - installing update...
Target installation already in version 1.6.1. Do you want to update again? (y/N)
Copying files to target location...done.

Running update script at target...
Executing database schema update.
/usr/bin/composer
Executing /usr/bin/composer to update dependencies...
Loading composer repositories with package information
Info from https://repo.packagist.org: #StandWithUkraine
Updating dependencies
Nothing to modify in lock file
Installing dependencies from lock file
Nothing to install, update or remove
Generating autoload files
4 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
No security vulnerability advisories found
This instance of Roundcube is up-to-date.
Have fun!
All done.
Loading composer repositories with package information
Updating dependencies
Nothing to modify in lock file
Installing dependencies from lock file
Nothing to install, update or remove
Generating autoload files
4 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
No security vulnerability advisories found
Write Docker config to /var/www/html/config/config.docker.inc.php
Checking for database schema updates...
Generating locales (this might take a while)...
  en_US.UTF-8... done
Generation complete.
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.18.0.6. Set the 'ServerName' directive globally to suppress this message
AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.18.0.6. Set the 'ServerName' directive globally to suppress this message
[Wed Apr 19 15:00:54.610207 2023] [mpm_prefork:notice] [pid 1] AH00163: Apache/2.4.56 (Debian) PHP/8.1.17 configured -- resuming normal operations
[Wed Apr 19 15:00:54.610224 2023] [core:notice] [pid 1] AH00094: Command line: 'apache2 -D FOREGROUND'

...

172.18.0.2 - - [19/Apr/2023:15:04:22 +0000] "GET / HTTP/1.1" 200 2956 "-" "Mozilla/5.0 (Android 10; Mobile; rv:109.0) Gecko/111.0 Firefox/111.0"
172.18.0.2 - - [19/Apr/2023:15:04:22 +0000] "GET /plugins/jqueryui/js/i18n/datepicker-pt-BR.js?s=1674504193 HTTP/1.1" 200 967 "https://webmail.mydomain.net/" "Mozilla/5.0 (Android 10; Mobile; rv:109.0) Gecko/111.0 Firefox/111.0"
172.18.0.2 - - [19/Apr/2023:15:04:22 +0000] "GET /program/js/common.min.js?s=1674504194 HTTP/1.1" 200 5156 "https://webmail.mydomain.net/" "Mozilla/5.0 (Android 10; Mobile; rv:109.0) Gecko/111.0 Firefox/111.0"
172.18.0.2 - - [19/Apr/2023:15:04:22 +0000] "GET /skins/elastic/images/logo.svg?s=1674504194 HTTP/1.1" 200 680 "https://webmail.mydomain.net/" "Mozilla/5.0 (Android 10; Mobile; rv:109.0) Gecko/111.0 Firefox/111.0"
172.18.0.2 - - [19/Apr/2023:15:04:22 +0000] "GET /skins/elastic/styles/styles.min.css?s=1674504194 HTTP/1.1" 200 22637 "https://webmail.mydomain.net/" "Mozilla/5.0 (Android 10; Mobile; rv:109.0) Gecko/111.0 Firefox/111.0"
172.18.0.2 - - [19/Apr/2023:15:04:22 +0000] "GET /skins/elastic/deps/bootstrap.min.css?s=1674504210 HTTP/1.1" 200 24161 "https://webmail.mydomain.net/" "Mozilla/5.0 (Android 10; Mobile; rv:109.0) Gecko/111.0 Firefox/111.0"
172.18.0.2 - - [19/Apr/2023:15:04:22 +0000] "GET /plugins/jqueryui/js/jquery-ui.min.js?s=1674504193 HTTP/1.1" 200 70755 "https://webmail.mydomain.net/" "Mozilla/5.0 (Android 10; Mobile; rv:109.0) Gecko/111.0 Firefox/111.0"
172.18.0.2 - - [19/Apr/2023:15:04:22 +0000] "GET /skins/elastic/ui.min.js?s=1674504194 HTTP/1.1" 200 19970 "https://webmail.mydomain.net/" "Mozilla/5.0 (Android 10; Mobile; rv:109.0) Gecko/111.0 Firefox/111.0"
172.18.0.2 - - [19/Apr/2023:15:04:22 +0000] "GET /skins/elastic/deps/bootstrap.bundle.min.js?s=1674504210 HTTP/1.1" 200 22065 "https://webmail.mydomain.net/" "Mozilla/5.0 (Android 10; Mobile; rv:109.0) Gecko/111.0 Firefox/111.0"
172.18.0.2 - - [19/Apr/2023:15:04:22 +0000] "GET /program/js/jquery.min.js?s=1674504197 HTTP/1.1" 200 32003 "https://webmail.mydomain.net/" "Mozilla/5.0 (Android 10; Mobile; rv:109.0) Gecko/111.0 Firefox/111.0"
172.18.0.2 - - [19/Apr/2023:15:04:23 +0000] "GET /program/js/jstz.min.js?s=1674504197 HTTP/1.1" 200 5309 "https://webmail.mydomain.net/" "Mozilla/5.0 (Android 10; Mobile; rv:109.0) Gecko/111.0 Firefox/111.0"
172.18.0.2 - - [19/Apr/2023:15:04:23 +0000] "GET /plugins/jqueryui/themes/elastic/jquery-ui.min.css?s=1674504193 HTTP/1.1" 200 7659 "https://webmail.mydomain.net/" "Mozilla/5.0 (Android 10; Mobile; rv:109.0) Gecko/111.0 Firefox/111.0"
172.18.0.2 - - [19/Apr/2023:15:04:24 +0000] "GET /program/js/app.min.js?s=1674504194 HTTP/1.1" 200 48356 "https://webmail.mydomain.net/" "Mozilla/5.0 (Android 10; Mobile; rv:109.0) Gecko/111.0 Firefox/111.0"
172.18.0.2 - - [19/Apr/2023:15:04:25 +0000] "GET /skins/elastic/fonts/fa-solid-900.woff2 HTTP/1.1" 200 75697 "https://webmail.mydomain.net/skins/elastic/styles/styles.min.css?s=1674504194" "Mozilla/5.0 (Android 10; Mobile; rv:109.0) Gecko/111.0 Firefox/111.0"
172.18.0.2 - - [19/Apr/2023:15:04:25 +0000] "GET /skins/elastic/images/favicon.ico?s=1674504194 HTTP/1.1" 200 1991 "-" "Mozilla/5.0 (Android 10; Mobile; rv:109.0) Gecko/111.0 Firefox/111.0"
127.0.0.1 - - [19/Apr/2023:15:04:26 +0000] "OPTIONS * HTTP/1.0" 200 126 "-" "Apache/2.4.56 (Debian) PHP/8.1.17 (internal dummy connection)"
127.0.0.1 - - [19/Apr/2023:15:04:27 +0000] "OPTIONS * HTTP/1.0" 200 126 "-" "Apache/2.4.56 (Debian) PHP/8.1.17 (internal dummy connection)"
127.0.0.1 - - [19/Apr/2023:15:04:28 +0000] "OPTIONS * HTTP/1.0" 200 126 "-" "Apache/2.4.56 (Debian) PHP/8.1.17 (internal dummy connection)"
127.0.0.1 - - [19/Apr/2023:15:04:29 +0000] "OPTIONS * HTTP/1.0" 200 126 "-" "Apache/2.4.56 (Debian) PHP/8.1.17 (internal dummy connection)"
127.0.0.1 - - [19/Apr/2023:15:04:30 +0000] "OPTIONS * HTTP/1.0" 200 126 "-" "Apache/2.4.56 (Debian) PHP/8.1.17 (internal dummy connection)"
127.0.0.1 - - [19/Apr/2023:15:04:31 +0000] "OPTIONS * HTTP/1.0" 200 126 "-" "Apache/2.4.56 (Debian) PHP/8.1.17 (internal dummy connection)"
127.0.0.1 - - [19/Apr/2023:15:04:32 +0000] "OPTIONS * HTTP/1.0" 200 126 "-" "Apache/2.4.56 (Debian) PHP/8.1.17 (internal dummy connection)"
127.0.0.1 - - [19/Apr/2023:15:04:33 +0000] "OPTIONS * HTTP/1.0" 200 126 "-" "Apache/2.4.56 (Debian) PHP/8.1.17 (internal dummy connection)"
127.0.0.1 - - [19/Apr/2023:15:04:34 +0000] "OPTIONS * HTTP/1.0" 200 126 "-" "Apache/2.4.56 (Debian) PHP/8.1.17 (internal dummy connection)"
127.0.0.1 - - [19/Apr/2023:15:04:35 +0000] "OPTIONS * HTTP/1.0" 200 126 "-" "Apache/2.4.56 (Debian) PHP/8.1.17 (internal dummy connection)"

...

errors: <bb16ea71> IMAP Error: Login failed for myusername@mydomain.net against mail.mydomain.net from 172.18.0.2 (X-Real-IP: 177.57.148.177,X-Forwarded-For: 177.57.148.177). AUTHENTICATE PLAIN: Authentication failed. in /var/www/html/program/lib/Roundcube/rcube_imap.php on line 211 (POST /?_task=login&_action=login)
172.18.0.2 - - [19/Apr/2023:15:07:28 +0000] "POST /?_task=login HTTP/1.1" 401 3120 "https://webmail.mydomain.net/" "Mozilla/5.0 (Android 10; Mobile; rv:109.0) Gecko/111.0 Firefox/111.0"