在家架設一台郵件伺服器的全套過程記錄

Why

明明有各種免費的企業郵局,為什麼還要自建郵件服務器?

因為我域名太多了。另外我精力旺盛。自建一個屬於自己的郵件伺服器是我從小的夢想。(並不是)

為什麼安裝iRedMail?

因為配置簡單。

為什麼需要配置SSH tunnel轉發端口?(更新:不再使用SSH tunnel轉發SMTP數據了,轉向使用ISP提供給我的郵件中轉服務器

因為雖然我家有固定IP,但是我並不能設置出口IP的反向 PTR 記錄(Reverse PTR record / IP反解),所以只能曲線救國,找一台有公網IP並且可以設定PTR記錄的伺服器中轉郵件服務器的流量。而Vultr最便宜的VPS一個月只需要$5,並且有IPv4和IPv6,也可以免費設定PTR記錄所以我選擇使用Vultr的VPS作為跳板。

所以我選擇使用Vultr的VPS作為跳板。

既然都用Vultr來做中轉了,為何不直接在雲端上部署iRedMail?

因為我窮。iRedMail至少需要2GB的RAM。而Vultr之類的VPS提供商運行一個符合最低配置的實例一個月的費用比付家裏那台服務器的電費要貴,貴很多。

實施環境

我家有一台運行WIndows的伺服器,我使用Hyper-V創建了一個運行ubuntu 18.04的虛擬機,安裝OS時,選取了同時安裝Openssh的選項,FQDN設定為mx。FQDN設定為ISP分配給我的域名的主機名。

這個虛擬機通過虛擬網路卡接入我家的路由器,通過DHCP和DHCPv6分別獲取了一個192.168.0.x的IPv4地址和一個IPv6的公網地址。

我為這個虛擬機啟動時分配了2048MB的運行內存,我開啟了動態內存功能。

我在Vultr新建了一個512MB RAM的實例,在東京機房。我開啟了IPv6的支援,安裝ubuntu 18.04,沒有開啟Vultr的防火牆。

我使用的是自稱世界最快的家用光纖網絡nuro,下行速率最高2Gbps,上行最高1Gbps。封鎖了25連接埠(OP25B)。

安裝iRedMail

請參考官方的安裝教學 https://docs.iredmail.org/install.iredmail.on.debian.ubuntu-zh_CN.html

首先按照官方教學,需要手動修改一下 /etc/hosts ,把完整的FQDN寫上,比如mx.domain.com fpaxxxxxxx.oskixxx.ap.nuro.jp

需要重新啟動虛擬機器才能生效。

因為我覺得我可能會用上,所以安裝時我額外勾選了安裝「SOGo Groupware」的選項。這個組件非常吃RAM,如果不需要就不要選了。

資料庫我選了SQL系的MySQL,因為我比較熟悉這個。

設定連接埠(端口)轉發(廢棄)

因為郵件伺服器需要設定Reverse PTR Record才能比較理想地工作,而我用的是家用網路,我暫時還沒有聽說過家用網路可以自己設定Reverse PTR record的,有的話請告訴我。而我現在用的那個ISP就不提供這個服務,所以只能曲線救國,將本地郵件伺服器的數據轉發到遠端擁有公網IP位址而且還能設定Reverse PTR Record的伺服器上。

Vultr是一個好選擇。它性價比高:不單可以設定IPv4的反向PTR,而且願意解除25連接埠的限制

你可能需要發工單提出你需要解除25連接埠的限制。Vultr的staff可能會需要你提供一個你打算發送的郵件的模板,這裡你就妥善處理就好了,解除限制後,你需要重新啟動一次VPS。

然後回到本地伺服器,安裝autossh並且手動連接一次Vultr機器的SSH

然後根據 iRedMail官方手冊裡面有關連接埠的那一頁裡面提到的需要暴露給公網的連接埠妥善設定好Vultr的防火牆,現在用ufw可以很容易做到。

需要中轉的連接埠列表:https://docs.iredmail.org/network.ports.html

比如這樣:

autossh -M 23001 -fNR 25:localhost:25 [email protected]
autossh -M 23001 -fNR 587:localhost:587 [email protected]
autossh -M 23001 -fNR 110:localhost:110 [email protected]
autossh -M 23001 -fNR 995:localhost:995 [email protected]
autossh -M 23001 -fNR 143:localhost:143 [email protected]
autossh -M 23001 -fNR 993:localhost:993 [email protected]
autossh -M 23001 -fNR 80:localhost:80 [email protected]
autossh -M 23001 -fNR 443:localhost:443 [email protected]

這裡的23001是我隨便選的一個連接埠,這是一個autossh用來判斷是否可以和遠端通訊的端口,這裡可以設定為0,也就是關閉這個功能,用openssh的ClientAliveInterval參數達到類似的功能:編輯/etc/ssh/sshd_config設定檔。修改下面的兩個變量,類似這樣:

ClientAliveInterval 3
ClientAliveCountMax 2

記得重新啟動一次sshd,讓設定生效。

我這裡的參數設定得比較激進,各位可以按照自己的網路狀況適當調整。

在Vultr的那台機器上輸入netstat -lnp看看相應的連接埠是不是被正常中轉了。

這裡可能會遇到一個問題,就是那個端口監聽在了127.0.0.1上面,不能被公網訪問。

這個時候需要編輯/etc/ssh/sshd_config設定檔,將GatewayPorts參數設定為yes

像這樣:

GatewayPorts yes

這裡也是要重新啟動sshd才能讓設定生效。

用瀏覽器確認連接埠轉發沒有問題後,讓autossh在每次重新啟動本地伺服器後也能自動重新設定連接埠轉發是比較理想的,所以我們在本地伺服器上新建一個腳本文件,比如我把它放在/root/目錄下,名字就叫start.sh吧:

touch /root/start.sh

然後我們編輯它:

vim /root/start.sh

它的內容應該是類似這樣的:

autossh -M 23001 -fNR 25:localhost:25 [email protected]
autossh -M 23001 -fNR 587:localhost:587 [email protected]
autossh -M 23001 -fNR 110:localhost:110 [email protected]
autossh -M 23001 -fNR 995:localhost:995 [email protected]
autossh -M 23001 -fNR 143:localhost:143 [email protected]
autossh -M 23001 -fNR 993:localhost:993 [email protected]
autossh -M 23001 -fNR 80:localhost:80 [email protected]
autossh -M 23001 -fNR 443:localhost:443 [email protected]

保存它。然後給它增加執行的權限:

chmod +x /root/start.sh

然後我們再編輯/etc/rc.local

vim /etc/rc.local

裡面寫上剛才那個腳本的路徑:

/root/start.sh

然後保存。

連接埠轉發就設定好了。

使用ISP提供的郵件伺服器作為發信中繼

因為我現在用的ISP封鎖了25端口。(https://support.so-net.ne.jp/supportsitedetailpage?id=000012073

所以通過將ISP提供的郵件伺服器設定為全局的中繼伺服器繞過封鎖。

在申請nuro的網絡的時候,會收到一張明信片,上面寫了自己的電子郵件帳戶的帳號和密碼,需要注意的是雖然用來登入會員頁面的帳號看起來也是一個郵件地址,但是那個帳號並不能用來登入郵箱⋯⋯

nuro的發信伺服器主機地址是:mail.so-net.ne.jp

連接埠:587

所以按照iRedMail的官方文件設定好reply host就好。

https://docs.iredmail.org/relayhost.html

利用Certbot,通過Cloudflare的API增加(修改)TXT記錄申請一個Wildcard證書

我這邊通過增加官方certbot的PPA源之後安裝到的certbot版本也只有0.31(現時點最新穩定版本為0.39),原因不明,因為適配Cloudflare的那個plugin需要最新版本的certbot,我混亂了,所以我選擇安裝certbot-auto⋯⋯

certbot-auto通過設定一個python的虛擬環境,免疫了各種奇怪的問題。

切換操作目錄到certbot-auto的安裝目錄下:

cd /opt/eff.org/certbot/venv

切換到python虛擬環境:

source bin/activate

安裝 certbot-dns-cloudflare plugin:

pip install certbot-dns-cloudflare

確認plugin正確安裝:

certbot-auto plugins

離開python虛擬環境:

deactivate

獲取Wildcard證書:

certbot-auto certonly --preferred-challenges dns-01 -m [email protected] --agree-tos --dns-cloudflare --dns-cloudflare-credentials ~/.secrets/certbot/cloudflare.ini --manual-public-ip-logging-ok --server https://acme-v02.api.letsencrypt.org/directory -d *.你的域名 -d 你的域名 --dry-run

如果沒有問題,去掉--dry-run後再次運行。

這樣就拿到了對應的Wildcard證書檔。

按照iRedMail的官方文檔設定好證書:

https://docs.iredmail.org/letsencrypt.html

然後我們讓證書自動續期(renew):

crontab -e

比如按照官方給出的設定增加這一句後保存:

1   3   *   *   *   certbot renew --post-hook 'service postfix restart; service nginx restart; service dovecot restart'

在路由器上開放必要的連接埠

根據iRedMail的官方文件所說,需要開放的連接埠分別是 2558711014399399544380

在路由器的設定頁面將上面的幾個連接埠轉發到安裝有iRedMail的伺服器上。

訪問郵件伺服器的網頁默認打開SOGo

iRedMail默認是訪問伺服器IP後跳轉到RoundCube,相比RoundCube我更喜歡SOGo的介面,SOGo看起來更美觀,功能也更佳豐富(除了郵件功能,還有行事曆和通訊錄)。

修改 Nginx 的默認伺服器的主頁文件即可達到目的:

~# vim /var/www/html/index.html

改成這樣:

<html><head><meta HTTP-EQUIV="REFRESH" content="0; url=/SOGo/"></head></html>

保存即可。

更換LOGO,美化SOGo的登錄介面

原來的SOGo的介面的LOGO我覺得太大了,而且LOGO的padding也不是特別合適,讓我很難受,所以我決定給我自己的郵件服務做一個新的LOGO替換上去。

打開Adobe Illustrator

因為是自己內部用的,所以隨便做一個簡單的就可以了,畫布尺寸我參考了SOGo原來的那個的尺寸(320×175),我特意給我的LOGO四周留了足夠的間隔。

然後我們創建一個SOGo的登錄頁面的模板副本,這樣我們就可以優雅地修改SOGo的介面,更新SOGo也不會將我們的修改覆蓋掉。

創建一個放模板文件的資料夾:

mkdir -p ~sogo/GNUstep/Library/SOGo/Templates/MainUI

將現在的登錄界面的模板文件複製過來:

cp /usr/lib*/GNUstep/SOGo/Templates/MainUI/SOGoRootPage.wox \
    ~sogo/GNUstep/Library/SOGo/Templates/MainUI

然後我們修改~sogo/GNUstep/Library/SOGo/Templates/MainUI/SOGoRootPage.wox 定位到LOGO的那部分,比如我就修改成這樣了:

<div class="sg-logo" flex-gt-md="50">
        <div layout="row" class="md-padding">
          <div class="md-flex hide show-gt-md"><!-- push logo to the right on larger screens --></div>
          <!-- <img const:alt="*" class="md-margin" rsrc:src="img/sogo-full.svg"/> -->
          <img const:alt="*" class="md-margin" rsrc:src="img/ox-LOGO_SOGo.svg"/>
        </div>
      </div>

然後將新的LOGO文件放在這裡:/usr/lib/GNUstep/SOGo/WebServerResources/img/

然後restart一下sogo讓我們的修改生效:

systemctl restart sogo.service

另外,SOGo在CJK環境下,頂部的日期會錯位,這是一個令人惱火的小問題,我雖然已經提交了一個解決這個bug的pr也merge了,但在下一個release發布前,沒必要因此重新下載源碼編譯,所以可以手動修改/usr/lib/GNUstep/SOGo/WebServerResources/css/styles.css

定位到.sg-date-group選擇器,修改為這樣即可:

.sg-date-group{font-size:14px;line-height:1;text-transform:uppercase;word-break:keep-all}

新增了一個word-break屬性,並且將值指定為keep-all

修改後效果如圖:

以上就是在家架設一台郵件伺服器的大概流程,此文暫告一段落。(2019/10/19)

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *