ニフクラ ブログ

ニフクラやクラウドの技術について、エンジニアが語るブログです。

起動時スクリプトを使用してメールサーバーの構築を自動化してみた

こんにちは、ニフクラテクニカルアカウントチームです。
ニフクラのエンジニアリングパーツ(PaaS)として提供しているDNSサービスでは、ドメイン名を取得する機能があります。その機能を使ってメールサーバー(CentOS)を構築することができます。
今回は、メールサーバーの設定について、サーバー起動時スクリプトを使用した作成方法をご紹介します。 サーバー起動時スクリプト(以降:起動時スクリプト)を使用することで、面倒なメールサーバー構築を自動化してみましょう。

前提条件

本ブログは、以下の前提知識がある方を想定しています。

  • ニフクラの基本的なコントロールパネルの操作、サービスを利用する知識
    (サーバー作成など)
  • 基本的なサーバーOSを構築する知識
  • DNSの基礎的な知識
  • メールサーバーについての基本的な知識

検証概要

本検証では、端末間のメール送受信のためのSMTPサーバーおよびPOPサーバーの構築を目的としています。
構築対象は、端末Aが使用するメールサーバーA(SMTP、POPサーバー)となります。
メールサーバーBについては、既存のメールサーバーを使用するため、詳細は割愛します。

検証の流れとしては、
①ドメインの登録(ニフクラのDNS)
②サーバー作成(起動時スクリプト)
③レコードの登録(ニフクラのDNS)
④メールアカウントを作成
⑤オープンリレーの確認(外部サイト)
⑥メールソフトの設定
⑦メール送受信(メールサーバーAB間は転送)の確認
となります。

以下の構成で検証を実施しています。
f:id:TechnicalAccountEngineer:20190117190459p:plain

利用リソース

今回の検証を実施するにあたり、利用したニフクラのリソースやツールのバージョン情報に関して以下に記載します。
※ 各リソースのアクセス制限に関しては、ニフクラのファイアウォール等を用いて適切に設定を行った上で実施しています。

リソース 数量
仮想サーバー(サーバーOS:CentOS7.4) 1
DNSドメイン 1
DNSレコード(A、MX、PTR) 3
ツール名 バージョン
certbot 0.26.1-2
Postfix 2.10.1-6
Dovecot 2.2.10-8

検証内容

環境準備

①ドメインの登録(ニフクラのDNS)

DNSの登録については下記ブログを参照して下さい。
ドメイン名の取得とDNSの設定方法

②サーバー作成(起動時スクリプト)

ここでは、コントロールパネルでサーバーを作成する際に起動時スクリプトを指定し Let's Encrypt、Postfix、Dovecotを導入します。
サーバーの作成については、クラウドヘルプ(サーバーの作成)を参照してください。

起動時スクリプトの設定項目は以下になります。

■OSの設定およびメールサーバーの設定に必要な情報を入力
■スクリプト実行ログの出力設定
■ホスト名の設定
■EPELリポジトリのインストール
■certbotのインストール
■Postfixのインストール
■Dovecotのインストール
■証明書の取得
■証明書の自動更新
■Postfixの設定
※本検証で主に留意した点を記載します。
1. メールリレーの設定として下記の定義を追記
 ・mynetworksで有効にしたネットワークからのメールは
  転送許可
 ・認証を通過したものは転送許可
 ・permit_mynetworks以外からのネットワークからの
  転送を拒否
2. SASL認証を有効化
3. 転送先のメールサーバーが対応していれば暗号化
4. TLS使用時のみSMTP認証を使用
5. /etc/postfix/master.cf を変更しSMTPSとSTARTTLSを有効化
■Dovecotの設定
 ・POP3Sを有効にしてPOP3とIMAPを無効
■rootにメールボックスを作成
■自動でメールボックスを作成
■各サービスの起動と自動起動の設定
■認証ソケットファイルの確認
■スクリプトの実行時間の表示

※今回利用した起動時スクリプトの詳細な設定内容は「起動時スクリプト ソースコード」を参照してください。

③レコード登録

レコードの登録については、クラウドヘルプ(DNS:レコード設定)を参照してください。

各レコードの設定値は以下の通りです。

タイプ レコード TTL
A test.example.com 60 XX.XX.XX.XX
(作成したメールサーバーの
グローバルIPアドレス)
MX @ 60 test.example.com
PTR XX.XX.XX.XX
(作成したメールサーバーの
グローバルIPアドレス)
60 test.example.com

※ test.example.com は実際に取得したレコード名とは異なります。

④メールアカウント作成

作成したメールサーバーにログインし、メール送受信を行うOSユーザーを作成します。
(本検証では「testuser」を作成しています。)

# useradd <ユーザー名>
# passwd <作成したユーザー名>
Changing password for user testuser.
New password: <任意のパスワード>
# usermod -s /sbin/nologin <作成したユーザー名>

⑤オープンリレーの確認

オープンメールリレーは、ニフクラの禁止事項に定められており、これに抵触しないようにするため、またセキュリティレベルの確認のために、こちらの外部サイトを使用してチェックします。

  1. 「Mail Server」の入力欄に作成したメールサーバー(ホスト名)を入力し、「Test Email Server」をクリックします。
  2. オープンリレーの設定が適切であれば、「SMTP Open Relay」の項目が「OK - Not an open relay」となります。
1
f:id:TechnicalAccountEngineer:20190116085509p:plain
2
f:id:TechnicalAccountEngineer:20190117174018p:plain

⑥メールソフトの設定

ここでは、端末AにThunderbird(メールソフト)をインストールし設定します。
※メールソフトのダウンロードはここでは割愛します。

・ メール受信(POP3S)設定

下記設定値を入力します。

設定項目 設定値
サーバー名 test.example.com
ポート 995
ユーザー名 testuser
接続の保護 SSL/TLS
認証方式 通常のパスワード認証

f:id:TechnicalAccountEngineer:20190116085519p:plain

・ メール送信(SMTPS)設定

「追加」をクリックして、下記設定値を入力します。
メール送信については、2パターン実施しています。

項目 設定値(SMTPS) 設定値(STARTTLS)
サーバー名 test.example.com
ポート 465 587
ユーザー名 testuser
接続の保護 SSL/TLS STARTTLS
認証方式 通常のパスワード認証

f:id:TechnicalAccountEngineer:20190117174010p:plain

※STARTTLSについては設定値(ポート、接続の保護)を読み替えてください。

動作確認

⑦メール送受信

ここでは、端末A・Bからメールを送信し、正常に送受信されることを確認します。確認パターンとして受信、送信(2パターン)を実施します。

・ メール受信(POP3S)

  1. 端末Bのメールソフトを使用し端末Aへメールを送信します。
  2. 端末Aのメールソフトの受信トレイを確認し、メールの差出人、件名、本文が一致している事を確認します。
1
f:id:TechnicalAccountEngineer:20190116085530p:plain
2
f:id:TechnicalAccountEngineer:20190116085534p:plain

・ メール送信(SMTPS)

  1. 端末Aのメールソフトを使用し端末Bへメールを送信します。
  2. 端末Bのメールソフトの受信トレイを確認し、メールの差出人、件名、本文が一致している事を確認します。
1
f:id:TechnicalAccountEngineer:20190116085538p:plain
2
f:id:TechnicalAccountEngineer:20190116085543p:plain

・ メール送信(STARTTLS)

  1. 端末Aのメールソフトを使用し端末Bへメールを送信します。
  2. 端末Bのメールソフトの受信トレイを確認し、メールの差出人、件名、本文が一致している事を確認します。
1
f:id:TechnicalAccountEngineer:20190116085546p:plain
2
f:id:TechnicalAccountEngineer:20190116085550p:plain

正常にメールの送受信が行えました。
以上で本検証は終了となります。

まとめ

作成に時間がかかるメールサーバーの構築も、起動時スクリプトを使用して自動化する事により、構築時間を短縮できました。
また、今回は実施しませんでしたが、メールアカウントの作成も起動時スクリプトに組み込むことで、一度もメールサーバーにログインせずに、ニフクラのコントロールパネル上の操作だけで構築することも可能です。
これからメールサーバーを作成する際に、少しでも本記事が参考になれば幸いです。

注意事項について

  • メールサーバーを作成する場合は、ニフクラの禁止事項にもあるように、オープンリレーにならないよう細心の注意を払ってください。
  • 大量配信用途のメール配信システムを個別構築すると該当サーバーのIPアドレスがブラックリストに乗る可能性があります。 そのような用途の場合はESS(メール配信)の利用もご検討ください
  • 本記事については検証結果の1つとなります。実際に検討される場合は、事前にそれぞれの要件を鑑みて実装するか確認してください。
  • 本記事ではOS上の操作についても記載していますが、ニフクラではOS以上はご利用者様の責任範囲となりますのでご留意ください。

※起動時スクリプト ソースコード

本検証では、以下の設定とします。
※ test.example.com は実際に取得したレコード名とは異なります。

項目 設定値
HOST_NAME test.example.com
DOMAIN_NAME example.com
LOGFILE /var/tmp/`date +%Y%m%d`.log
MY_MAIL xxxxx@xxxxxxx.co.jp
#!/bin/bash -x

### Config
#=========================================
HOST_NAME="<任意のホスト名>"
DOMAIN_NAME="<ドメイン名>"
LOGFILE="<スクリプト実行ログの出力先>"
MY_MAIL="<Let,s encript用のメールアドレス>"
#=========================================

### LogOutput Configuration
SECONDS=0
exec > ${LOGFILE}
exec 2>&1

### Hostname Configuration
/bin/hostname ${HOST_NAME}
/bin/sed -i".org" -e "s/localhost.localdomain/${HOST_NAME}/" /etc/hostname
/bin/diff /etc/hostname /etc/hostname.org

### Check Install Package
pkgs="epel-release certbot postfix dovecot"
for pkg in ${pkgs}
do
  rpm -qa ${pkg} | grep -q ${pkg}
  if [ $? -eq 0 ]; then
    echo "${pkg} Already Install"
  else
    yum -y install ${pkg}
  fi
done

### Acquire certificate
certbot certonly --standalone -d ${HOST_NAME} -m ${MY_MAIL} --agree-tos -n
ls -l /etc/letsencrypt/live/${HOST_NAME}

### Certificate automatic update
echo "00 05 01 * * /bin/certbot renew" >> /var/spool/cron/root

### Postfix Configuration
/bin/sed -i".org" -e "s/#myhostname = host.domain.tld/myhostname = ${HOST_NAME}/g" /etc/postfix/main.cf
/bin/sed -i -e "s/#mydomain = domain.tld/mydomain = ${DOMAIN_NAME}/g" /etc/postfix/main.cf
/bin/sed -i -e "s/#myorigin = \$mydomain/myorigin = \$mydomain/g" /etc/postfix/main.cf
/bin/sed -i -e "s/#mynetworks = 168.100.189.0\/28, 127.0.0.0\/8/mynetworks = 127.0.0.0\/8/g" /etc/postfix/main.cf
/bin/sed -i -e "s/inet_interfaces = localhost/inet_interfaces = all/g" /etc/postfix/main.cf
/bin/sed -i -e "s/mydestination = \$myhostname, localhost.\$mydomain, localhost/mydestination = \$myhostname, localhost.\$mydomain, localhost, \$mydomain/g" /etc/postfix/main.cf
/bin/sed -i -e "s/#local_recipient_maps = proxy:unix:passwd.byname \$alias_maps/local_recipient_maps = proxy:unix:passwd.byname \$alias_maps/g" /etc/postfix/main.cf
/bin/sed -i -e "s/#relay_domains = \$mydestination/relay_domains = /g" /etc/postfix/main.cf
/bin/sed -i -e "s/#relayhost = \[an.ip.add.ress\]/relayhost = /g" /etc/postfix/main.cf
/bin/sed -i -e "s/#home_mailbox = Maildir\//home_mailbox = Maildir\//g" /etc/postfix/main.cf
/bin/sed -i -e "s/#smtpd_banner = \$myhostname ESMTP \$mail_name/smtpd_banner = \$myhostname ESMTP/g" /etc/postfix/main.cf
cat << EOF >> /etc/postfix/main.cf
disable_vrfy_command = yes
smtpd_recipient_restrictions = permit_mynetworks,permit_sasl_authenticated,reject_unauth_destination
smtpd_sasl_auth_enable = yes
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
broken_sasl_auth_clients = yes
smtpd_tls_security_level = may
smtpd_tls_auth_only = yes
smtpd_tls_cert_file = /etc/letsencrypt/live/${HOST_NAME}/fullchain.pem
smtpd_tls_key_file = /etc/letsencrypt/live/${HOST_NAME}/privkey.pem
smtpd_tls_loglevel = 1
smtpd_tls_session_cache_database = btree:/var/lib/postfix/smtpd_scache
smtpd_tls_session_cache_timeout = 3600s
smtp_tls_security_level = may
smtp_tls_loglevel = 1
smtp_tls_session_cache_database = btree:/var/lib/postfix/smtp_scache
smtp_tls_session_cache_timeout = 3600s
EOF
/bin/diff /etc/postfix/main.cf /etc/postfix/main.cf.org
/bin/sed -i".org" -e "s/^#submission/submission/g" /etc/postfix/master.cf
/bin/sed -i -e "s/^#smtps/smtps/g" /etc/postfix/master.cf
/bin/sed -i -e "s/#\(  -o smtpd_tls_wrappermode=yes\)/\1/g" /etc/postfix/master.cf
/bin/sed -i -e "s/#\(  -o smtpd_sasl_auth_enable=yes\)/\1/g" /etc/postfix/master.cf
/bin/sed -i -e "s/#\(  -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject\)/\1/g" /etc/postfix/master.cf
/bin/diff /etc/postfix/master.cf /etc/postfix/master.cf.org
postfix check

### Dovecot Configuration
/bin/sed -i".org" -e "s/#protocols = imap pop3 lmtp/protocols = pop3/g" /etc/dovecot/dovecot.conf
/bin/sed -i".org" -e "s/    #port = 143/    port = 0/g" /etc/dovecot/conf.d/10-master.conf
/bin/sed -i -e "s/    #port = 110/    port = 0/g" /etc/dovecot/conf.d/10-master.conf
/bin/sed -i -e "s/    #port = 995/    port = 995/g" /etc/dovecot/conf.d/10-master.conf
/bin/sed -i -e "42,45 s/    #ssl = yes/    ssl = yes/g" /etc/dovecot/conf.d/10-master.conf
/bin/sed -i -e "s/  #unix_listener /var/spool/postfix/private/auth {/  unix_listener /var/spool/postfix/private/auth {/g" /etc/dovecot/conf.d/10-master.conf
/bin/sed -i -e "96,100 s/  #}/  }/g" /etc/dovecot/conf.d/10-master.conf
/bin/sed -i -e "s/  #\(unix_listener \/var\/spool\/postfix\/private\/auth {\)/  \1/g" /etc/dovecot/conf.d/10-master.conf
/bin/sed -i -e "s/  #  mode = 0666/    mode = 0660/g" /etc/dovecot/conf.d/10-master.conf
/bin/sed -i -e "/    mode = 0660/a\    user = postfix" /etc/dovecot/conf.d/10-master.conf
/bin/sed -i -e "/    user = postfix/a\    group = postfix" /etc/dovecot/conf.d/10-master.conf
/bin/sed -i".org" -e "s/#disable_plaintext_auth = yes/disable_plaintext_auth = no/g" /etc/dovecot/conf.d/10-auth.conf
/bin/sed -i -e "s/auth_mechanisms = plain/auth_mechanisms = plain login/g" /etc/dovecot/conf.d/10-auth.conf
/bin/sed -i".org" -e "s/ssl = required/ssl = yes/g" /etc/dovecot/conf.d/10-ssl.conf
/bin/sed -i -e "s/ssl_cert = <\/etc\/pki\/dovecot\/certs\/dovecot.pem/ssl_cert = <\/etc\/letsencrypt\/live\/${HOST_NAME}\/fullchain.pem/g" /etc/dovecot/conf.d/10-ssl.conf
/bin/sed -i -e "s/ssl_key = <\/etc\/pki\/dovecot\/private\/dovecot.pem/ssl_key = <\/etc\/letsencrypt\/live\/${HOST_NAME}\/privkey.pem/g" /etc/dovecot/conf.d/10-ssl.conf
/bin/sed -i".org" -e "s/#mail_location = /mail_location = maildir:~\/Maildir/g" /etc/dovecot/conf.d/10-mail.conf
/bin/sed -i".org" -e "s/#log_path = syslog/log_path = syslog/g" /etc/dovecot/conf.d/10-logging.conf

### root create mailbox
mkdir -p ~/Maildir/{new,cur,tmp}
chmod -R 700 ~/Maildir/

### Automatically create mailbox
mkdir -p /etc/skel/Maildir/{new,cur,tmp}
chmod -R 700 /etc/skel/Maildir/

### Service Startup and Automatic Startup Setting
systemctl status postfix
systemctl restart postfix
systemctl enable postfix
systemctl status postfix
systemctl status dovecot
systemctl restart dovecot
systemctl enable dovecot
systemctl status dovecot

ls -F /var/spool/postfix/private/auth

echo "[INFO] Script time is ${SECONDS}sec."