send-mails

メールサーバもお引っ越し。CentOS7からCentOS Stream 8へ。マルチドメインの設定を引っ越して、dovecotのdbox形式に対応する。

先日から何度か紹介したさくらのクラウドからさくらのVPSへの引っ越しでkursanagi 9を導入し、爆速を実現したwebサーバですが、実はこのサーバではマルチドメインのメールサーバとして動いており、このメールサーバも引っ越しました。このエントリではpostfix + dovecotでのマルチドメインのメールサーバ運用のための設定を紹介します。CentOS7で動いていた設定をCentOS Stream 8にお引っ越しします。基本は設定ファイルのコピーだけです。また、Maildirで運用していたメールボックスをdboxに変更します。

send-mails

postfixとdovecotの設定はしっかり切り離されています。そもそも開発元も違いますが、postfixはメールの配送を担当するためのサービスでdovecotは届いたメールを読むためのサービスで役割が全く違うからです。postfixは送信者がポストにメールを放り込む先ポストで、その後インターネット上での配送も担当してくれます。そして送信先の受信箱(サーバ上)に届けるまでがpostfix族(SMTP)の役目で、受信箱に届いたメールを持ってくる(POP)、もしくはそこに置いたまま見る(IMAP)のがdovecotが提供するサービスです。

設定したいこと

まず前提です。やりたいことは以下の通りです。

  • 複数のドメインのメールを受け取れる
  • 一つはLinuxユーザのホームディレクトリにメールボックスを置く
  • 他のドメインはそもそもLinuxにログインすることもないのでメールボックスがどこに置かれていても気にしない
  • Linuxユーザ名とメールアドレスは一致しない(そもそもLinuxユーザが存在しないケースもある)
  • postfix / dovecot ともにSSLで暗号化する
  • dovecotはいにしえの(笑)mboxでもMaildirでもなくてdboxを利用する

くらいでしょうか。それではpostfixの設定から進めます。

postfixの設定ファイル

CentOS7、CentOS Stream 8ともにpostfixの設定ファイルが置いてあるのは /etc/postfix 以下です。

CentOS Stream 8 で /etc/postfix 以下を見てみると以下のファイルがあります。もしかしたらひいらぎやが追加したファイル(virtualdbとか)もあるかもしれませんが初期状態がない…。

[workuser@newserver]$ ls -R /etc/postfix/
postfix/:
access            generic        master.cf        relocated   virtualalias
canonical         header_checks  master.cf.proto  transport
dynamicmaps.cf    main.cf        postfix-files    virtual
dynamicmaps.cf.d  main.cf.proto  postfix-files.d  virtual.db
postfix/dynamicmaps.cf.d:
postfix/postfix-files.d:</pre>

基本的に「設定が必要」なのはmain.cfとmaster.cfです。main.cfはpostfixの全般設定、master.cfはpostfixのmasterプロセスの設定ファイルですが、とりあえずそういう物とおもったほうが早いかも知れません。基本的に設定が必要とかいたのは、転送設定やバーチャルドメインの設定などにtransportやvirutualへの記述が必要になります。

ここでは基本的にCentOS Stream 8のデフォルトの設定ファイルとの差分だけ掲載します。

main.cfの設定

まずはホスト名を設定します。デフォルトではFQDNがはいりますが、いろいろな名前を使い分けていたりするので明示的に指定します。DNSにもこのアドレスをメールサーバとしてmxとして登録したので、ドメイン名をつけてmx.domain1.exampleとしています。

# INTERNET HOST AND DOMAIN NAMES
#
# The myhostname parameter specifies the internet hostname of this
# mail system. The default is to use the fully-qualified domain name
# from gethostname(). $myhostname is used as a default value for many
# other configuration parameters.
#
#myhostname = host.domain.tld
#myhostname = virtual.domain.tld
myhostname = mx.domain1.example

次にメールの送信を受け付けるインタフェイスを指定します。IPアドレスをいくつか持っていたりすると考えることはあるかとは思いますが、このサーバは一本しか外にネットワークインタフェイスをもっていません。内部的につかうlocalhostというアドレスだけに指定することも出来ますがそれでは外部からのメールをうけとれません。単純な構成ですので、allとしています。

# The inet_interfaces parameter specifies the network interface
# addresses that this mail system receives mail on.  By default,
# the software claims all active interfaces on the machine. The
# parameter also controls delivery of mail to user@[ip.address].
#
# See also the proxy_interfaces parameter, for network addresses that
# are forwarded to us via a proxy or network address translator.
#
# Note: you need to stop/start Postfix when this parameter changes.
#
inet_interfaces = all
#inet_interfaces = $myhostname
#inet_interfaces = $myhostname, localhost
#inet_interfaces = localhost

お次はmydestinationを設定します。自分が担当するドメインを記述します。ここでは自サーバ自身($myhostname、localhost.$mydomain, localhost)と自分のドメイン全体($mydomain)を指定しています。$から始まるのは変数です。$mydomainなんて変数指定していない!ということではありますが、$mydomainは、$myhostnameで指定した値の最初の「.」の前までを削った値が入ります。このケースではdomain1.exampleが入っていることになります。

後から出てきますが、mydestinationにバーチャルドメインで指定しようとしているドメインは入れないで下さい。

# The mydestination parameter specifies the list of domains that this
# machine considers itself the final destination for.
#
# These domains are routed to the delivery agent specified with the
# local_transport parameter setting. By default, that is the UNIX
# compatible delivery agent that lookups all recipients in /etc/passwd
# and /etc/aliases or their equivalent.
#
# The default is $myhostname + localhost.$mydomain + localhost.  On
# a mail domain gateway, you should also include $mydomain.
#
# Do not specify the names of virtual domains - those domains are
# specified elsewhere (see VIRTUAL_README).
#
# Do not specify the names of domains that this machine is backup MX
# host for. Specify those names via the relay_domains settings for
# the SMTP server, or use permit_mx_backup if you are lazy (see
# STANDARD_CONFIGURATION_README).
#
# The local machine is always the final destination for mail addressed
# to user@[the.net.work.address] of an interface that the mail system
# receives mail on (see the inet_interfaces parameter).
#
# Specify a list of host or domain names, /file/name or type:table
# patterns, separated by commas and/or whitespace. A /file/name
# pattern is replaced by its contents; a type:table is matched when
# a name matches a lookup key (the right-hand side is ignored).
# Continue long lines by starting the next line with whitespace.
#
# See also below, section "REJECTING MAIL FOR UNKNOWN LOCAL USERS".
#
#mydestination = $myhostname, localhost.$mydomain, localhost
mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain
#mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain,
#       mail.$mydomain, www.$mydomain, ftp.$mydomain

次に信頼するSMTPのクライアントの接続元を指定しています。ここに指定されている範囲から送られてきたメールは無条件で転送します。mynetworksもしくはmynetworks_styleで指定します。mynetworksで指定することが多い気がするのですがあのころのひいらぎやはmynetworks_styleで指定したようです。mynetworks_styleにhostと指定していますが。mynetworksにlocalhostと書いたのと一緒ですね。

# The mynetworks parameter specifies the list of "trusted" SMTP
# clients that have more privileges than "strangers".
#
# In particular, "trusted" SMTP clients are allowed to relay mail
# through Postfix.  See the smtpd_recipient_restrictions parameter
# in postconf(5).
#
# You can specify the list of "trusted" network addresses by hand
# or you can let Postfix do it for you (which is the default).
#
# By default (mynetworks_style = subnet), Postfix "trusts" SMTP
# clients in the same IP subnetworks as the local machine.
# On Linux, this works correctly only with interfaces specified
# with the "ifconfig" command.
#
# Specify "mynetworks_style = class" when Postfix should "trust" SMTP
# clients in the same IP class A/B/C networks as the local machine.
# Don't do this with a dialup site - it would cause Postfix to "trust"
# your entire provider's network.  Instead, specify an explicit
# mynetworks list by hand, as described below.
#
# Specify "mynetworks_style = host" when Postfix should "trust"
# only the local machine.
#
#mynetworks_style = class
#mynetworks_style = subnet
mynetworks_style = host
# Alternatively, you can specify the mynetworks list by hand, in
# which case Postfix ignores the mynetworks_style setting.
#
# Specify an explicit list of network/netmask patterns, where the
# mask specifies the number of bits in the network part of a host
# address.
#
# You can also specify the absolute pathname of a pattern file instead
# of listing the patterns here. Specify type:table for table-based lookups
# (the value on the table right-hand side is not used).
#
#mynetworks = 168.100.189.0/28, 127.0.0.0/8
#mynetworks = $config_directory/mynetworks
#mynetworks = hash:/etc/postfix/network_table

spoolの場所の指定。spoolはメールサーバで受信されたメールが置かれるところです。ユーザが受信する前なので郵便局の中というイメージです。自宅のポストではないです。

これはどこでもいいのですが、なんとなくもともとの設定にspoolというディレクトリが入っていなかったのが(古くからLinuxとかBSDを使っている人からすると)なんとなく気持ち悪くてデフォルトから変更しています。

# The mail_spool_directory parameter specifies the directory where
# UNIX-style mailboxes are kept. The default setting depends on the
# system type.
#
#mail_spool_directory = /var/mail
mail_spool_directory = /var/spool/mail

最後の行が変更した内容。その上の#でコメントアウトしたのがもともとの設定です。ひいらぎやはデフォルトの設定はかならずこのようにコメントアウトして残しています。

次にSSLの鍵を登録します。Let’s Encryptで取得した鍵です。Let’s Encryptでの鍵の取得は多くのサイトで紹介されていますが、そのうちこのサイトでも紹介するかも知れません。上のコメント部分にPEMフォーマットで、そしてフルパスで指定しろとありますので、ご注意下さい。2カ所修正しているところも注意。

# The full pathname of a file with the Postfix SMTP server RSA certificate
# in PEM format. Intermediate certificates should be included in general,
# the server certificate first, then the issuing CA(s) (bottom-up order).
#
#smtpd_tls_cert_file = /etc/pki/tls/certs/postfix.pem
smtpd_tls_cert_file = /etc/letsencrypt/live/XXXX/fullchain.pem
# The full pathname of a file with the Postfix SMTP server RSA private key
# in PEM format. The private key must be accessible without a pass-phrase,
# i.e. it must not be encrypted.
#
#smtpd_tls_key_file = /etc/pki/tls/private/postfix.key
smtpd_tls_key_file = /etc/letsencrypt/live/XXXX/privkey.pem

SMTPクライアントの制限

メール送信したいと接続してきたクライアントからの送信を許可するかどうかです。mynetworksで指定したアドレスから、saslの認証を通過したケースを許可しています。最後のreject_unauth_destinationは、postfix-jpから引用すると

reject_unauth_destination以下のどれか一つに当てはまらない場合に、要求を拒否します:

Postfixがメールを転送する場合: 解決された RCPT TO アドレスが $relay_domains またはその サブドメインにマッチし、送信者指定のルーティング (user@elsewhere@domain) を 含まない場合、

Postfixが最終配送先の場合: 解決された RCPT TO アドレスが $mydestination や $inet_interfaces、 $proxy_interfaces、$virtual_alias_domains、 $virtual_mailbox_domains に マッチし、送信者指定のルーティング (user@elsewhere@domain) を含まない場合。

http://www.postfix-jp.info/trans-2.2/jhtml/postconf.5.html#reject_unauth_destination

転送する場合は$relay_domainsにマッチしない場合はドロップし、最終的に受け取る場合も明示的に指定されていない場合は拒否するという感じですかね。

smtpd_recipient_restrictions = permit_mynetworks,permit_sasl_authenticated,reject_unauth_destination

LMTPの設定をします。LMTPはメールサーバ内でのメール配送です。Local Mail Transport Protocolですね。postfixが保存したメールをそのままdovecotが読めれば必要ないのですが、今回はdovecotのメールフォーマットであるdboxを使うので、dovecotに保存させます。これに使うのがLMTPです。

#LMTP
mailbox_transport = lmtp:unix:private/dovecot-lmtp

次にマルチドメイン運用のためのバーチャルドメインを設定します。先ほどdomain1.exampleの設定をしましたがそれ以外のドメインをここに書きます。ここではdomain2.exampleとdomain3.exampleの2つのバーチャルドメインを指定しています。メールが保存されるフォルダは/var/spool/virtual、そしてこのドメインで利用するアカウント等は/etc/postfix/virtualに書くことにします。ここでも転送にはLMTPを使うことにして、実行uidとgidは1500としています。これはvmailに割り当てられたIDです。postfixはデフォルトでインストールされているはずなのでもともと存在していると思いますが、念のためvmailのidを確認しておくことをお勧めします。”id vmail”と実行すれば良いです。

# Virtual Domains
virtual_mailbox_domains = domain2.example,domain3.example
virtual_mailbox_base = /var/spool/virtual
virtual_mailbox_maps = hash:/etc/postfix/virtual
virtual_transport = lmtp:unix:private/dovecot-lmtp
virtual_uid_maps = static:1500
virtual_gid_maps = static:1500

SASLに関する設定を入れます。SASLの認証はCyrus SASLやdovecotがありますが、今回は受信のために使うdovecotに任せます。

# SASL
smtpd_sasl_auth_enable = yes
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
broken_sasl_auth_clients = yes

master.cfの設定

次にmaster.cfに設定を書いていきます。

まずはsubmissionポートを有効にしてオプションの背邸をしています。います。普通のSMTPは認証がありませんがそこで認証をする機能をつけたのがsubmissionです。587番ポートに接続してお話しすることになりますが使わないのであればコメントアウトのままで良いです。

一緒に記述していますがsmtpsも有効にしています。

submission inet n       -       n       -       -       smtpd
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
smtps     inet  n       -       n       -       -       smtpd
  -o smtpd_tls_wrappermode=yes
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_recipient_restrictions=permit_sasl_authenticated,reject

master.cfはこれだけでした。

virtualを設定する。

virtual_mailbox_maps に指定した、/etc/postfix/virtual にユーザー設定を書きます。ここで注意したいのは、mydestinationに書いたドメインはここでは書いてはいけません。

userA@domain2.example domain2.example/userA/
userB@domain3.example domain3.example/userB/
userC@domain3.example domain3.example/userC/
userD@domain3.example domain3.example/userC/

virtualをハッシュ化しておきます。

[workuser@newserver $] sudo postmap /etc/postfix/virtual

dovecotの設定

SSLの認証はdovecotに任せます。すでに設定ファイルにも出てきました。まずはdovecotをインストールします。

[workuser@newserver $] sudo dnf install dovecot

各種設定を行っていきます。

/etc/dovecot.conf の設定を行います。ここではimapとlmtp妥結買うのでそれだけ活かしています。

# Protocols we want to be serving.
#protocols = imap pop3 lmtp submission
protocols = imap lmtp

次にIPv4でつかうのかIPv6でつかうのかです。さくらのVPSはIPv6も無料で使えるので4と6の双方を有効にしています。*がIPv4で::がIPv6です。このケースでは両方とも指定しています。

# A comma separated list of IPs or hosts where to listen in for connections.
# "*" listens in all IPv4 interfaces, "::" listens in all IPv6 interfaces.
# If you want to specify non-default ports or anything more complex,
# edit conf.d/master.conf.
listen = *, ::

次に/etc/dovecot/conf.d/ 以下にあるファイル群の編集をしていきます。

認証メカニズムの設定です。デフォルトではplainだけでしたが、digest-md5、cram-md5を追加しています。

# Space separated list of wanted authentication mechanisms:
#   plain login digest-md5 cram-md5 ntlm rpa apop anonymous gssapi otp skey
#   gss-spnego
# NOTE: See also disable_plaintext_auth setting.
#auth_mechanisms = plain
auth_mechanisms = digest-md5 cram-md5 plain

そして最後の行にたくさんファイル名が書いてあります。これは別ファイルに書いてある設定を読み込むと言うことですが、以下のファイルを有効にしています。頭の#を消しただけです。

!include auth-system.conf.ext
#!include auth-sql.conf.ext
#!include auth-ldap.conf.ext
!include auth-passwdfile.conf.ext
#!include auth-checkpassword.conf.ext
#!include auth-vpopmail.conf.ext
!include auth-static.conf.ext

ここで有効化した /etc/dovecot/conf.d/auth-passwdfile.conf.ext を編集して以下のようにします。

/etc/dovecot/users というファイルを指定していますがここにユーザのリストが入ります。

passdb {
  driver = passwd-file
  args = scheme=CRYPT username_format=%u /etc/dovecot/users
}
userdb {
  driver = passwd-file
  args = username_format=%u /etc/dovecot/users
  # Default fields that can be overridden by passwd-file
  #default_fields = quota_rule=*:storage=1G
  # Override fields from passwd-file
  #override_fields = home=/home/virtual/%u
}

/etc/dovecot/conf.d/10-master.confを編集します。

頭と後ろ半分はコメントですがunix_listnerから始まる真ん中あたりにある部分を修正します。postfixが指定したソケットを通じてdovecotのLMTPに接続できるよう設定しています。

service lmtp {
  #unix_listener lmtp {
    #mode = 0666
  #}
  unix_listener /var/spool/postfix/private/dovecot-lmtp {
    group = postfix
    mode = 0660
    user = postfix
  }
  # Create inet listener only if you can't use the above UNIX socket
  #inet_listener lmtp {
    # Avoid making LMTP visible for the entire internet
    #address =
    #port =
  #}
}

SMTPで認証の際にdovecotから情報を引き出せるよう設定します。これも同じファイルです。

コメントが長いですが、Postfix smtp-authとかいているところです。先ほどと同じような内容ですね。

service auth {
  # auth_socket_path points to this userdb socket by default. It's typically
  # used by dovecot-lda, doveadm, possibly imap process, etc. Users that have
  # full permissions to this socket are able to get a list of all usernames and
  # get the results of everyone's userdb lookups.
  #
  # The default 0666 mode allows anyone to connect to the socket, but the
  # userdb lookups will succeed only if the userdb returns an "uid" field that
  # matches the caller process's UID. Also if caller's uid or gid matches the
  # socket's uid or gid the lookup succeeds. Anything else causes a failure.
  #
  # To give the caller full permissions to lookup all users, set the mode to
  # something else than 0666 and Dovecot lets the kernel enforce the
  # permissions (e.g. 0777 allows everyone full permissions).
  unix_listener auth-userdb {
    #mode = 0666
    #user =
    #group =
  }
  # Postfix smtp-auth
  unix_listener /var/spool/postfix/private/auth {
    mode = 0660
    user = postfix
    group = postfix
  }
  # Auth process is run as this user.
  #user = $default_internal_user
}

次に10-mail.confを触ります。これもコメントが長いですが載せておきます。mail_locationにsdbox:~/dboxと指定しています。sdboxもしくはmdboxと指定するとdovecotが用意しているフォーマットとなります。sdboxの最初のSはSingleのSでMaildirと同じように1メールを1ファイルして保存します。mdboxとするとmboxのように複数のメールを一つのファイルに足していきます。ただし上限があるのでmboxのようにずっと一つのファイルに書き込まれていくと言うことはありません。ひいらぎやはmdboxにするつもりがなぜかsdboxにしていました…。なぜだ…。

##
## Mailbox locations and namespaces
##
# Location for users' mailboxes. The default is empty, which means that Dovecot
# tries to find the mailboxes automatically. This won't work if the user
# doesn't yet have any mail, so you should explicitly tell Dovecot the full
# location.
#
# If you're using mbox, giving a path to the INBOX file (eg. /var/mail/%u)
# isn't enough. You'll also need to tell Dovecot where the other mailboxes are
# kept. This is called the "root mail directory", and it must be the first
# path given in the mail_location setting.
#
# There are a few special variables you can use, eg.:
#
#   %u - username
#   %n - user part in user@domain, same as %u if there's no domain
#   %d - domain part in user@domain, empty if there's no domain
#   %h - home directory
#
# See doc/wiki/Variables.txt for full list. Some examples:
#
#   mail_location = maildir:~/Maildir
#   mail_location = mbox:~/mail:INBOX=/var/mail/%u
#   mail_location = mbox:/var/mail/%d/%1n/%n:INDEX=/var/indexes/%d/%1n/%n
#
# &lt;doc/wiki/MailLocation.txt&gt;
#
#mail_location =
mail_location = sdbox:~/dbox
#mail_location = maildir:~/Maildir

そしてユーザを作ります。auth-passwdfile.conf.ext で指定した /etc/dovecot/users を編集します。最初がユーザ名とドメイン名というかメールアドレスそのものです。コロンでわけてパスワードを書きます。実はパスワードの後ろにはユーザIDやホームディレクトリを指定することができます。/etc/passwdと同じ書式です。

userA@domain2.example:{CRAM-MD5}ハッシュ化されたパスワード
userB@domain3.example:{CRAM-MD5}ハッシュ化されたパスワード
userC@domain3.example:{CRAM-MD5}ハッシュ化されたパスワード
userD@domain3.example:{CRAM-MD5}ハッシュ化されたパスワード

ここでのパスワードはdoveadmを使って生成します。パスワードが2回きかれるので同じパスワードを入力して下さい。以下ではhogeという(弱い)パスワードでのハッシュ値が出ています。この出力をユーザ毎に貼っていきます。

[workuser@newserver $] sudo doveadm pw -s CRAM-MD5
Enter new password:
Retype new password:
{CRAM-MD5}7aeefbe3e5e957c63e328c53ffa563c26bc08dcd58f605076679216cb4aff6d1

すべてのサーバを再起動する。

設定を有効化するためのすべてのサーバを再起動します。

[workuser@newserver $] sudo systemctl restart postfix dovecot

本当は動作確認のステップをちゃんと踏んだ方がいいのですがそれはまた今度まとめようと思います。これで送受信を試してみましょう。なお、SMTP、IMAPともバーチャルドメインのユーザ名は /etc/dovecot/users で指定したものになります。ユーザ名だけではなくメールアドレスのようにドメインまで指定しているので、このアドレスをメールソフトには設定して下さい。

それとさくらのVPSではデフォルトですべてのポートが外側のFWでブロックされているのでメール関連のポートを空けておいて下さい。このあたりにHTTPの例があります。

kusanagi環境を求めて、さくらのクラウドからさくらのVPSへお引っ越しした話。その4: kusanagiのインストール

関連記事

さてやっとkusanagiの設定です。これまでに、さくらのVPSを契約し、kusanagi on CentOS Stream 8 のテンプレートイメージを導入、Linuxの初期設定を実施しました。これまでの記事は以下に。 [sitec[…]

Software Developing

ひいらぎやのこのサーバ https://www.hiiragiya.net/ がうごいているさくらのVPSはこちらから申し込みできます。

https://vps.sakura.ad.jp/

send-mails
最新情報をチェックしよう!