Featured image of post mailu邮件服务部署|配置|备份|fail2ban

mailu邮件服务部署|配置|备份|fail2ban

延伸阅读:基于 FRP 的 Mailu 邮件服务器内网穿透部署

基本条件

  1. 具备至少1G内存的可公网访问的服务器,可通过25端口发送和接受信息(通过telnet可验证);
  2. 拥有自己的域名,可自行配置dns服务;
  3. 已安装 docker compose,可访问 GitHub 上的镜像下载服务。

验证端口可访问性方法(首先确认ufw等防火墙开放25端口):

1
2
telnet smtp.qq.com 25          # 验证可发送
telnet 1.1.1.1(你的服务器ip) 25  # 验证可接收

出现 Connected 代表端口开放。

mailu配置

本教程基于 mailu 2024.06 版本。

配置文件生成

使用官网提供的配置文件生成服务.

其中,关键选项配置为:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
Choose how you wish to handle security TLS certificates:
$$letsencrypt$$

Enable Web email client:
$$roundcube$$

Enable oletools.

IPv4 listen address:
服务器IP

Public hostnames:
你准备设定的邮件服务域名,如`mail.hlmg.tech`

设置完成后在服务器新建/mailu文件夹,并在其中下载保存yml与env文件。

配置文件修改

docker-compose.yml

修改front容器,保留25,80,465,993端口的映射,并将80端口的映射修改为本地端口以备后续配置反向代理,添加日志服务,如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
  front:
    image: ${DOCKER_ORG:-ghcr.io/mailu}/${DOCKER_PREFIX:-}nginx:${MAILU_VERSION:-2024.06}
    restart: always
    env_file: mailu.env
    logging:
      driver: journald
      options:
        tag: mailu-front
    ports:
      - "127.0.0.1:9198:80"
      - "服务器ip:25:25"
      - "服务器ip:465:465"
      - "服务器ip:993:993"
    networks:
      - default
      - webmail
    volumes:
      - "/mailu/certs:/certs"
      - "/mailu/overrides/nginx:/overrides:ro"
    depends_on:
      - resolver
    dns:
      - 192.168.203.254
    # 下面是额外添加的日志服务,为fail2ban准备
    logging:
      driver: journald
      options:
        tag: mailu-front

同样的,在admin中添加日志服务:

1
2
3
4
logging:
  driver: journald
  options:
    tag: mailu-admin

mailu.env

这里给出我认为比较关键的选项:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
###################################
# Mail settings
###################################

# Welcome email, enable and set a topic and body if you wish to send welcome emails to all users.
WELCOME=true
WELCOME_SUBJECT=Welcome to your new hlmg.tech email account
WELCOME_BODY=Welcome to your new mailu on hlmg.tech email account, if you can read this, then it is configured properly!

# Maildir Compression
# choose compression-method, default: none (value: gz, bz2, zstd)
COMPRESSION=zstd
# change compression-level, default: 6 (value: 1-9)
COMPRESSION_LEVEL=6

###################################
# Advanced settings
###################################

# 要求非网页登陆方式仅可通过token登陆,增强安全性,token在网页端的admin->认证令牌界面可配置。
AUTH_REQUIRE_TOKENS=true

LD_PRELOAD=
# /usr/lib/libhardened_malloc.so # 如果你的服务器支持avx2(x86_64)或Ircpc(arm)指令集可开启该项,使用`cat /proc/cpuinfo | grep avx2` 查看,若不支持,必须保持留空

# Timezone for the Mailu containers. See this link for all possible values https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
TZ=Asia/Shanghai

# 配置初始化管理员帐号
INITIAL_ADMIN_ACCOUNT=admin
INITIAL_ADMIN_DOMAIN=hlmg.tech
INITIAL_ADMIN_PW="2Su2aHdX59SXZhCnFDQe"
INITIAL_ADMIN_MODE=ifmissing

启动mailu服务

为网页端服务设置反向代理,提供https(使用caddy实现),以下是Caddyfile中的相关部分。

1
2
3
4
mail.hlmg.tech {
	encode zstd gzip
	reverse_proxy localhost:9198
}

/mailu目录下启动服务,调试时先不加-d以观察日志:

1
docker compose up -d

启动服务后,访问设置的邮件服务域名,登陆admin进行进一步配置。

进入管理->邮件域->点如下位置查看dns配置信息,该图右上角的“新域”可以添加新邮件用户:

dns配置信息位置

点击 Download zonefile 下载dns配置文件,删去其中的如下配置:

1
2
3
4
_imap._tcp.hlmg.tech. 600 IN SRV 0 0 0 .
_pop3._tcp.hlmg.tech. 600 IN SRV 0 0 0 .
_submission._tcp.hlmg.tech. 600 IN SRV 0 0 0 .
_pop3s._tcp.hlmg.tech. 600 IN SRV 10 1 995 mail.hlmg.tech.

进入域名的dns管理页面,以cloudflare为例,在如下位置导入dns配置即可:

cloudflare dns导入

导入dns完成后,稍等一段时间即可尝试发送、接收邮件验证基本功能是否正常。

如果有条件,可为服务器设置rDNS,以进一步增强邮件服务器的可信程度。

mailu备份

至此,邮件服务器已可供使用,通过web和imap均可访问,mailu是基于文件的邮件服务器,备份可通过restic+rclone备份整个 /mailu 文件夹完成。

配置fail2ban缓解攻击

在官网fail2ban配置基础上,针对我受到的攻击进行了一些修改:

首先安装fail2ban和ipset,并按照上述docker-compose.yml中的参考添加日志部分:

1
apt install fail2ban ipset -y

新增配置文件 /etc/fail2ban/filter.d/bad-auth-bots.conf

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# vim /etc/fail2ban/filter.d/bad-auth-bots.conf

# Fail2Ban configuration file for mailu-front log file
[Definition]
failregex = ^.* mailu-front\[\d+\]: .* Info: Disconnected: Connection closed:.*user=<>, rip=<HOST>,.*$
            ^.* mailu-front\[\d+\]: .* client login failed: \"AUTH not supported\" while in http auth state, client: <HOST>, server: .*$
            ^.* mailu-front\[\d+\]: .* SSL_do_handshake\(\) failed \(SSL: error:.*while in starttls state, client: <HOST>.*$

ignoreregex =
journalmatch = CONTAINER_TAG=mailu-front

新增配置文件 /etc/fail2ban/jail.d/bad-auth-bots.conf

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# vim /etc/fail2ban/jail.d/bad-auth-bots.conf
[bad-auth-bots]
enabled = true
backend = systemd
filter = bad-auth-bots
bantime = 604800
findtime = 3600
maxretry = 3
action = docker-action-net
ignoreip = x.x.x.x/24  # 可添加忽略ip

新增配置文件 /etc/fail2ban/action.d/docker-action-net.conf

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# vim /etc/fail2ban/action.d/docker-action-net.conf

[Definition]

actionstart = ipset --create f2b-bad-auth-bots nethash
              iptables -I DOCKER-USER -m set --match-set f2b-bad-auth-bots src -p tcp -m tcp --dport 25 -j DROP
              iptables -I DOCKER-USER -m set --match-set f2b-bad-auth-bots src -p tcp -m tcp --dport 465 -j DROP
              iptables -I DOCKER-USER -m set --match-set f2b-bad-auth-bots src -p tcp -m tcp --dport 993 -j DROP

actionstop = iptables -D DOCKER-USER -m set --match-set f2b-bad-auth-bots src -p tcp -m tcp --dport 25 -j DROP
	         iptables -D DOCKER-USER -m set --match-set f2b-bad-auth-bots src -p tcp -m tcp --dport 465 -j DROP
             iptables -D DOCKER-USER -m set --match-set f2b-bad-auth-bots src -p tcp -m tcp --dport 993 -j DROP
             ipset --destroy f2b-bad-auth-bots


actionban = ipset add -exist f2b-bad-auth-bots <ip>/24

actionunban = ipset del -exist f2b-bad-auth-bots <ip>/24

新增配置文件 /etc/fail2ban/filter.d/bad-auth.conf:

1
2
3
4
5
6
# vim /etc/fail2ban/filter.d/bad-auth.conf

[Definition]
failregex = ^.*: Authentication attempt from <HOST> has been rate-limited\.$
ignoreregex =
journalmatch = CONTAINER_TAG=mailu-admin

新增配置文件 /etc/fail2ban/jail.d/bad-auth.conf

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# vim /etc/fail2ban/jail.d/bad-auth.conf

[bad-auth]
enabled = true
backend = systemd
filter = bad-auth
bantime = 604800
findtime = 3600
maxretry = 3
action = docker-action

新增配置文件 /etc/fail2ban/action.d/docker-action.conf

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# vim /etc/fail2ban/action.d/docker-action.conf

[Definition]

actionstart = ipset --create f2b-bad-auth iphash
              iptables -I DOCKER-USER -m set --match-set f2b-bad-auth src -j DROP

actionstop = iptables -D DOCKER-USER -m set --match-set f2b-bad-auth src -j DROP
             ipset --destroy f2b-bad-auth


actionban = ipset add -exist f2b-bad-auth <ip>

actionunban = ipset del -exist f2b-bad-auth <ip>

修改配置文件使得fail2ban在docker后启动:

1
systemctl edit fail2ban

在其中修改以下内容:

1
2
[Unit]
After=docker.service

重启fail2ban服务以应用更改:

1
systemctl restart fail2ban

查看当前fail2ban状态:

1
2
3
fail2ban-client status
fail2ban-client status bad-auth-bots
fail2ban-client status bad-auth

参考

使用 Hugo 构建
主题 StackJimmy 设计