前言
這篇是紀錄如何自行架設郵件伺服器 (Mail Server) 的過程,使用開源的 mailcow 建置
說明
當初在找開源的 Email 軟體時,主要是比較 mailcow 和 Roundcube 這兩套,
需求為:
- 收發信
- 有 WebMail 介面
- 方便管理所有 Email 的介面
- 權限管理功能
- 有 API 可以打
- 容易建置
- 容易升級
- 開源專案有持續地維護
因此選擇以 mailcow 作為首選
若想要比較不同 Email 的服務差異,可以參考 SaaShub 或 LibHunt ,可以比較任兩套的軟體
安裝步驟
以下建置過程是在 Ubuntu Server 22.04.2 LTS ,可參考這篇如何建置
1. 設定 DNS
建議先設定好 DNS ,生效會需要一些時間
假設我的固定 IP 是 123.45.67.89
假設我的 domain 是 riverye.com
Name | Type | Value |
---|---|---|
IN A | 123.45.67.89 | |
autoconfig | IN CNAME | smtp.riverye.com |
autodiscover | IN CNAME | smtp.riverye.com |
riverye.com | IN MX 10 | smtp.riverye.com |
2. 安裝 Docker
照著 Docker 官方文件,複製貼上,執行即可
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 sudo apt-get update
sudo apt-get install ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
echo \
"deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
"$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y
3. 下載 mailcow
1
2
3
4 sudo su -
cd /opt
git clone https://github.com/mailcow/mailcow-dockerized
cd mailcow-dockerized
4. 設定 mailcow 的 generate_config.sh
和 mailcow.conf
4-1. 設定 generate_config.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 ./generate_config.sh
Found Docker Compose Plugin (native).
Setting the DOCKER_COMPOSE_VERSION Variable to native
Notice: You´ll have to update this Compose Version via your Package Manager manually!
Press enter to confirm the detected value '[value]' where applicable or enter a custom value.
Mail server hostname (FQDN) - this is not your mail domain, but your mail servers hostname: mail.riverye.com
Timezone [Asia/Taipei]:
Which branch of mailcow do you want to use?
Available Branches:
- master branch (stable updates) | default, recommended [1]
- nightly branch (unstable updates, testing) | not-production ready [2]
Choose the Branch with it´s number [1/2] 1
Fetching origin
Your branch is up to date with 'origin/master'.
Generating snake-oil certificate...
..+.+...+.....+.......+............+...........+.+......+.....+...............+....+........+.+.....+..........+......+...+...+........+...........................+...+.+.....+....+..+...+....+..+.+.....+...............+.......+.....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*.........+..+...+.+.................+...+....+......+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*....+.+...+.........+...+.........+...+..+.........................+.....+....+.....+.+.....+......+...+....+...+..+...+...+....+..+................+.....+............+.+.........+............+.....+..................+.+......+......+.........+.....+....+..+.......+..+..........+.....+....+..+....+......+...+......+.....+.+..+......+.......+.....+....+.....+.+.........+...+........+...............+.......+..................+.....+...+.+.....+..........+......+...+.........+.....+.......+...+......+...........+...+...+.......+...........+.+.........+..............................+.........+............+...+.......................+.........+...+......+.........+.+..+.........+.+..+......+...............+....+...+.............................+.+.................+.+....................+...............+.+......+.....+............+............................+............+.....+..........+.....+...+...+.........+............+..........+.....+.........+.......+...+.....+............+.........+...+...............+......+.........+............+......+...+.+......+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
...+.....+...+.............+.....+.......+...+..+....+.....+.........+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*...................+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*..+....+...........+......+...+.+...+...........................+......+.........+...+.................+....+.....................+..............+.......+.....+....+.....+.+..................+..+...+......+...+......+......+.............+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-----
Copying snake-oil certificate...
Detecting if your IP is listed on Spamhaus Bad ASN List...
Check completed! Your IP is clean
4-2. 設定 mailcow.conf
以下是我有調整的部分,可依照需求自行更改
1
2
3
4
5
6
7
8 vim mailcow.conf
DBNAME=mailcow_db
DBUSER=mailcow_user
SKIP_IP_CHECK=y
SKIP_HTTP_VERIFICATION=y
ALLOW_ADMIN_EMAIL_LOGIN=y
5. 啟動服務
上述設定完成後,接著要用 Docker 啟動服務
1
2 docker compose pull
docker compose up -d
5-1. 服務啟動失敗
啟動服務後,若開啟網頁看到以下錯誤,請不要慌,靜待數秒至幾分鐘後 (依電腦效能),再重新整理,就能看到登入畫面了
5-1. 服務啟動成功
看到以下畫面,代表服務有正常被啟動成功,若仍只看到上述畫面,可以照上面的錯誤訊息,印出 Log 看錯誤訊息
預設帳號 | 預設密碼 |
---|---|
admin | moohoo |
登入後,建議把預設密碼改掉
6. 新增域名
新增我的 domain
操作步驟:E-Mail -> Configuration -> 新增域名
以下是範例
7. DNS 設定
操作步驟:E-Mail -> Configuration -> 找到剛才新增的域名(domain) -> DNS
依照提示去設定 DNS 即可
附上從 Cloudflare 匯出的 DNS 設定
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20;; A Records
mail.riverye.com. 1 IN A 123.45.67.89
;; CNAME Records
autoconfig.riverye.com. 1 IN CNAME mail.riverye.com.
autodiscover.riverye.com. 1 IN CNAME mail.riverye.com.
;; MX Records
riverye.com. 1 IN MX 10 mail.riverye.com.
;; SRV Records
_autodiscover._tcp.riverye.com. 1 IN SRV 10 10 443 mail.riverye.com.
;; TLSA Records
_25._tcp.mail.riverye.com. 1 IN TLSA 3 1 1 af728af706fe3eb0c23ad4387d2d24ad81cfa5811e3821f8fa206452ea52ef32
;; TXT Records
dkim._domainkey.riverye.com. 1 IN TXT "v=DKIM1;k=rsa;t=s;s=email;p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1NRc1H0Ae7+vv//hwsXCKwGDDs6QnU8ZNZ/RbBCPATEMdNkfxrAhlY9Q9x4znQFdoXm6i6P2P39/EF/+PjaKMNR7YKwxe/LDfuZUMitR2/vccRxmRttoJ/FoEO2HimlTliGYE8ertDXHsmyS2Lf3ddxUbS4PZyHm18heWcoSA4IXmsL02JK0Jnt5aotqMAMyZk8m8WGkQkMfHyc3KdhcqfsCdfMBhRMp6HY72qrjRvjKWnQPeyZaB9mqeaasxjCTfZHOoEfi+2qJf04U3SYBOuhs1lv/BJXNJo5iyTHz9mBdPDqGFsn653BHcSpggEW6RXqctIOSMSlypW5/hcp8fQIDAQAB"
_dmarc.riverye.com. 1 IN TXT "v=DMARC1; p=none;"
riverye.com. 1 IN TXT "v=spf1 mx ~all"
Name | Type | Value |
---|---|---|
mail.riverye.com | IN A | 123.45.67.89 |
_25._tcp.mail.riverye.com | IN TLSA 3 1 1 | af728af706fe3eb0c23ad4387... |
riverye.com | IN MX 10 | mail.riverye.com |
autodiscover.riverye.com | IN CNAME | mail.riverye.com |
_autodiscover._tcp.riverye.com | IN SRV 10 10 443 | mail.riverye.com |
autoconfig.riverye.com | IN CNAME | mail.riverye.com |
riverye.com | IN TXT | v=spf1 mx ~all |
_dmarc.riverye.com | IN TXT | v=DMARC1; p=none; |
dkim._domainkey.riverye.com | IN TXT | v=DKIM1;k=rsa;t=s;s=email;p=MIIBIjA... |
設定完成後,等待 DNS 生效後 (快則數秒,慢則數小時),可透過 mailcow 的介面檢查設定是否正確,正確則會有綠色 v
若已經設定好 DNS ,但在 mailcow 介面看仍尚未正確,可以在終端機使用 dig
指令 double check 看是否有輸入錯誤
1
2
3
4
5 想看 SRV Type
dig SRV _autodiscover._tcp.riverye.com
用特定的 DNS 服務查詢,以 Cloudflare 為例
dig @1.1.1.1 SRV _autodiscover._tcp.riverye.com
8. 新增信箱及測試寄信
影片教學
已經新增專屬的信箱後,再來就是要寄到外部,確認能否寄信成功
推薦可以使用 Newsletters spam test by mail-tester.com 進行測試
以下是我的寄信評分
如何綁定 Outlook
以 IMAP 為例,設定如下
名稱 | 伺服器 | 連結埠 | 加密方式 |
---|---|---|---|
內送郵件 | mail.riverye.com | 993 | SSL/TLS |
外送郵件 | mail.riverye.com | 465 | SSL/TLS |
QA.
QA1. 使用「HiNet非固定制固定IP」,並非「固定制」也可以自行架設嗎?
可以的,只差別在 DNS 的 PTR 類型無法設定,常用的信箱 (ex: Gmail、Hotmail、Apple icloud 等) 還是能收到信,但如果是檢查比較嚴格的信箱,則可能會被拒收 (reject),可依照需求評估是否要改用「固定制」。
在建置時,有遇到同樣的設定,使用固定 IP A 可以寄到上述所說的信箱,但換成另一組固定 IP 時,則全都被拒收,好在退信的信件中,有提供申訴的管道,提出申訴後,約等 3-4 小時,就能正常寄給上面的那些外部信箱了。
QA2. 如何讓輸入的網址,連到對應的電腦
關鍵字是「Port Forwarding (通訊埠轉發)」,也有廠商是用「虛擬伺服器」、「虛擬 IP」...等稱呼,指的是同樣的東西。
在 ASUS 的教學文件,寫的很清楚什麼是 Port Forwarding ,以及要如何設定 ASUS 的路由器
[無線路由器]如何在華碩路由器設定虛擬伺服器(Port forwarding)?
ASUS 的設定範例
在 ASUS 中,是在「虛擬伺服器」中設定
Fortinet FortiGate 的設定範例
在 FortiGate 中,是在「虛擬 IP」中設定
防火牆也要記得設定,免得無法將資料正確傳到指定的電腦,其中 NAT 要停用!!!
不然 Server 都只會接收到 Gateway IP Address ,無法知道真實的 IP,進而無法用 Fail2ban
QA3. 路由器已經將 80 或 443 port (埠) 用做其他用途,該怎麼辦?
關鍵字是「Reverse Proxy (反向代理)」,可以使用 Nginx、Apache 來架設 Reverse Proxy
這邊推薦使用 Caddy,比前 2 個更好設定、語法更簡潔、不用處理憑證 (CA)
1
2
3
4
5
6
7
8
9
10
11 /etc/caddy/Caddyfile
假設 Reverse Proxy Server 和 Mail Server 是不同電腦
mail.riverye.com {
reverse_proxy 192.168.1.30
}
假設 Reverse Proxy Server 和 Mail Server 是同一台電腦,且要指定 port 給 Mail Server 使用
mail.riverye.com {
reverse_proxy localhost:9527
}
QA4. 如何看某 port 的流量紀錄?
會特別提到這個,是因為當初沒注意到 Fortinet FortiGate 的 NAT 有啟用,因此用 API 打 mailcow 時,雖然有設定 IP 檢查,卻沒照預期運作。
才會有需要看某 port 的流量紀錄需求,可在終端機中使用 tcpdump
指令。
1
2 想看 443 port
tcpdump -f port 443
QA5. 如何將 mailcow 更新到最新?
1
2 cd /opt/mailcow-dockerized
./update.sh
QA6. 如何避免有人惡意想要嘗試登入後台?
可以使用 Fail2ban, mailcow 的介面,能直接設定
小結
自行架設的過程當中,會學到許多知識,尤其是硬體到軟體都自己弄時,會發現自己不會的東西很多,而不停地去瞭解接觸到的關鍵字,趁記憶猶新時,寫下此篇紀錄,以防之後忘了
參考文件
- mailcow: dockerized documentation
- Install MailCow Server on Ubuntu 22 04 x64
- Debian 11 / Ubuntu 22.04 使用 Docker 安装 Mailcow 自建域名邮箱
- 使用 Mailcow 自建邮件服务器
- Caddy Server 簡介
- 從 Nginx 換到 Caddy
- caddyserver examples
- Fail2ban
- 如何在Ubuntu 20.04上安装和配置Fail2ban
medium 文章連結:https://riverye.medium.com/1d80c469efec
本文同步發布於 小菜的 Blog https://riverye.com/
備註:之後文章修改更新,以個人部落格為主