FreeBSD 12 で自宅サーバ作成　メールサーバ編

## はじめに
FreeBSD 12を使用した自宅サーバの構築を行った。FreeBSD 12はリリースされて間もない状態ですが、カーネルに標準でVIMAGEが取り込まれDNSの外向きと、内向きを別々のシステム（jail+VIMAGE）が同一ホストで構築できることから採用することにしました。その時の構築手順を備忘録の意味も含め、具体的にいくつかに渡り説明する。

* [基本システム編その１](https://qiita.com/Chun3/items/2f891e5993c91b58ae5c)
	- 背景
	- 基本のインストール
	- 日本語環境の設定
* [基本システム編その２](https://qiita.com/Chun3/items/1e8fe5071c4a78d37e66)
	- セキュリティ
	- ftpサーバ
* [基本システム編その３](https://qiita.com/Chun3/items/e5cc6a69542153649dc0)
	- jail
	- 基本システム編おわり
* [jail内基本システム編](https://qiita.com/Chun3/items/4b11b9acdd080ecdab6c)
	- 基本の設定（jail1・jail2共通）
* [DNS編](https://qiita.com/Chun3/items/95ad3113202d111ee53c)
 	- DNSの構築におけるこれまでの問題
 	- bind9インストール
 	- NTPサーバ
* [Let's Encrypt編](https://qiita.com/Chun3/items/4814c25c09756690133f)
 	- Let's Encryptについて
 	- certbotのインストール
 	- 各種設定
 	- 証明書の取得
* [Webサーバ編](https://qiita.com/Chun3/items/286e567952cd9faf279f)
 	- インストール（apache2.4・webalizer・php7.3・postgresql11.2・mysql8.0）
 	- 設定
* [メールサーバ編](https://qiita.com/Chun3/items/dc0e176c9de4f6b4bfb8)（この記事）
 	- インストール（cyrus-sasl・postfix・dovecot・procmail・pflogsumm・policyd-spf）
 	- 設定・起動
 	- spfレコード送信設定
* [ファイルサーバ編](https://qiita.com/Chun3/items/356b7fadd7aa5280ec65)
 	- sambaの選択
 	- samba3のインストール
* [メールサーバ編その2](https://qiita.com/Chun3/items/4c15ee889b052df67bbd)
 	- 概要
 	- OpenDKIM
 	- OpenDMARC
 	- ClamAV (clamav-milter)
 	- Spamassasin (spamass-milter)

## インストール（cyrus-sasl・postfix・dovecot・procmail・pflogsumm）
### cyrus-saslのインストール
SMTP認証にsasl認証を使用する。

```
jail1 /root # pkg install cyrus-sasl cyrus-sasl-saslauthd
Updating FreeBSD repository catalogue...
[jail1] Fetching meta.txz: 100%    944 B   0.9kB/s    00:01
[jail1] Fetching packagesite.txz: 100%    6 MiB 139.5kB/s    00:48
Processing entries: 100%
FreeBSD repository update completed. 32016 packages processed.
All repositories are up to date.
Updating database digests format: 100%
The following 2 package(s) will be affected (of 0 checked):

New packages to be INSTALLED:
        cyrus-sasl: 2.1.27
        cyrus-sasl-saslauthd: 2.1.27_1

Number of packages to be installed: 2

The process will require 8 MiB more space.
（以下省略）
```

### postfixのインストール
オプション変更を伴うためportsからインストールする。

```
jail1 /root # portinstall postfix
[Updating the portsdb <format:bdb_btree> in /var/db/pkg ... - 32801 port entries found .........1000.........2000.........3000.........4000.........5000.........6000.........7000.........8000.........9000.........10000.........11000.........12000.........13000.........14000.........15000.........16000.........17000.........18000.........19000.........20000.........21000.........22000.........23000.........24000.........25000.........26000.........27000.........28000.........29000.........30000.........31000.........32000........ ..... done]
[Reading data from pkg(8) ... - 141 packages found - done]
--->  Installing 'postfix-3.3.2_1,1' from a port (mail/postfix)
--->  Building '/usr/ports/mail/postfix'
===>  Cleaning for postfix-3.3.2_1,1
（途中省略　以下の用にmailer.confを作成するか聞いてくるがどちらでも可能。何れ書くことになるので'y'とした）
Would you like to activate Postfix in /usr/local/etc/mail/mailer.conf [n]? y
Activate Postfix in /usr/local/etc/mail/mailer.conf
（以下省略）
```

追加するオプションは、BLACKLISTDとSASLである。
![postfix.png](https://qiita-image-store.s3.amazonaws.com/0/233460/a7dceb74-d3e6-c3ba-a8fe-d56969be0a1d.png)

pkgでアップグレードしないようにロックを掛ける

```
jail1 /root # pkg lock postfix
Locking postfix-3.3.2_1,1
```

### dovecotのインストール
オプション追加がないのでpkgでインストールする。

```
jail1 /root # pkg install dovecot
Updating FreeBSD repository catalogue...
FreeBSD repository is up to date.
All repositories are up to date.
Updating database digests format: 100%
The following 1 package(s) will be affected (of 0 checked):

New packages to be INSTALLED:
        dovecot: 2.3.4.1

Number of packages to be installed: 1

The process will require 21 MiB more space.
4 MiB to be downloaded.
[jail1] [1/1] Fetching dovecot-2.3.4.1.txz: 100%    4 MiB 173.9kB/s    00:23
Checking integrity... done (0 conflicting)
[jail1] [1/1] Installing dovecot-2.3.4.1...
===> Creating groups.
Creating group 'dovecot' with gid '143'.
Creating group 'dovenull' with gid '144'.
===> Creating users
Creating user 'dovecot' with uid '143'.
Creating user 'dovenull' with uid '144'.
[jail1] [1/1] Extracting dovecot-2.3.4.1: 100%
Message from dovecot-2.3.4.1:
```

### procmail のインストール

```
jail1 /root # pkg install procmail
Updating FreeBSD repository catalogue...
FreeBSD repository is up to date.
All repositories are up to date.
The following 1 package(s) will be affected (of 0 checked):

New packages to be INSTALLED:
        procmail: 3.22_10

Number of packages to be installed: 1

139 KiB to be downloaded.
[jail1] [1/1] Fetching procmail-3.22_10.txz: 100%  139 KiB  71.0kB/s    00:02
Checking integrity... done (0 conflicting)
[jail1] [1/1] Installing procmail-3.22_10...
[jail1] [1/1] Extracting procmail-3.22_10: 100%
```

### pflogsumm のインストール
ログファイルの集計をインストールする。

```
jail1 /root # pkg install pflogsumm
Updating FreeBSD repository catalogue...
FreeBSD repository is up to date.
All repositories are up to date.
The following 4 package(s) will be affected (of 0 checked):

New packages to be INSTALLED:
        pflogsumm: 1.1.5,1
        p5-Date-Calc: 6.4
        p5-Bit-Vector: 7.4
        p5-Carp-Clan: 6.07

Number of packages to be installed: 4

The process will require 1 MiB more space.
355 KiB to be downloaded.
（以下省略）
```

### policyd-spfのインストール

```
jail1 /root # pkg install py36-postfix-policyd-spf-python
Updating FreeBSD repository catalogue...
FreeBSD repository is up to date.
All repositories are up to date.
The following 4 package(s) will be affected (of 0 checked):

New packages to be INSTALLED:
        py36-postfix-policyd-spf-python: 2.0.2
        py36-pyspf: 2.0.12_4
        py36-authres: 1.1.1
        py36-py3dns: 3.2.0

Number of packages to be installed: 4

142 KiB to be downloaded.
```

## 設定・起動
### 使用宣言
sendmailの停止は、元々jailでは停止されているのでsendmail_xxxは既に設定されている。

```sh:/etc/rc.conf
#mail
saslauthd_enable="YES"
saslauthd_flags="-a sasldb"
postfix_enable="YES"
dovecot_enable="YES"
sendmail_enable="NO"
sendmail_submit_enable="NO"
sendmail_outbound_enable="NO"
sendmail_msp_queue_enable="NO"
```

### postfixの設定
/etc/mail/mailer.confに優先されるので/etc/mail/mailer.confはデフォルトの状態で残したほうがOSのupgradeしやすい。なお、インストール時に作成の問い合わせに'y'で回答しているので既に設定されている。

```/usr/local/etc/mail/mailer.conf
#
# Execute the Postfix sendmail program, named /usr/local/sbin/sendmail
#
sendmail        /usr/local/sbin/sendmail
send-mail       /usr/local/sbin/sendmail
mailq           /usr/local/sbin/sendmail
newaliases      /usr/local/sbin/sendmail
```

### main.cfの設定
#### コンパチブル設定・パスの設定はデフォルトのまま

```sh:/usr/local/etc/postfix/main.cf
compatibility_level = 2
# LOCAL PATHNAME INFORMATION
queue_directory = /var/spool/postfix
command_directory = /usr/local/sbin
daemon_directory = /usr/local/libexec/postfix
data_directory = /var/db/postfix
mail_owner = postfix
```

#### ホスト名などの設定
```sh:/usr/local/etc/postfix/main.cf
# INTERNET HOST AND DOMAIN NAMES
myhostname = mail.example.jp
mydomain = example.jp
# SENDING MAIL
myorigin = $mydomain
# RECEIVING MAIL
inet_interfaces = all
mydestination = $myhostname, localhost.$mydomain, localhost, jail1.$mydomain, jail1, $mydomain
# REJECTING MAIL FOR UNKNOWN LOCAL USERS
unknown_local_recipient_reject_code = 550
# TRUST AND RELAY CONTROL
mynetworks = 111.222.333.100, 111.222.333.200, 127.0.0.0/8, 192.168.1.0/24
relay_domains = $mydestination
# ALIAS DATABASE
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
# DELIVERY TO MAILBOX
home_mailbox = Maildir/
mailbox_command = /usr/local/bin/procmail
```

#### その他
smtpでユーザが存在するかを問い合わせるvrfyコマンドに応答しないようにする（3/16追加）。

```sh:/usr/local/etc/postfix/main.cf
disable_vrfy_command = yes
# DEBUGGING CONTROL
debug_peer_level = 2
debugger_command =
         PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin
         ddd $daemon_directory/$process_name $process_id & sleep 5
# INSTALL-TIME CONFIGURATION INFORMATION
sendmail_path = /usr/local/sbin/sendmail
newaliases_path = /usr/local/bin/newaliases
mailq_path = /usr/local/bin/mailq
setgid_group = maildrop
html_directory = /usr/local/share/doc/postfix
manpage_directory = /usr/local/man
sample_directory = /usr/local/etc/postfix
readme_directory = /usr/local/share/doc/postfix
inet_protocols = ipv4
meta_directory = /usr/local/libexec/postfix
shlib_directory = /usr/local/lib/postfix
```

#### 追加部分（sasl関連）
```sh:/usr/local/etc/postfix/main.cf
# Cyrus-SASL configuration
smtpd_sasl_auth_enable = yes
smtpd_sasl_local_domain = $mydomain
smtpd_sasl_security_options = noanonymous
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination
#broken_sasl_auth_clients = yes
# TLS configuration
smtpd_use_tls = yes
smtpd_tls_cert_file = /usr/local/etc/letsencrypt/live/example.jp/fullchain.pem
smtpd_tls_key_file = /usr/local/etc/letsencrypt/live/example.jp/privkey.pem
smtpd_tls_session_cache_database = btree:/usr/local/etc/postfix/smtpd_scache
```

####サービスオプション

```sh:/usr/local/etc/postfix/master.cf
# ==========================================================================
# service type  private unpriv  chroot  wakeup  maxproc command + args
#               (yes)   (yes)   (no)    (never) (100)
# ==========================================================================
smtp      inet  n       -       n       -       -       smtpd
#smtp      inet  n       -       n       -       1       postscreen
#smtpd     pass  -       -       n       -       -       smtpd
#dnsblog   unix  -       -       n       -       0       dnsblog
#tlsproxy  unix  -       -       n       -       0       tlsproxy
submission inet n       -       n       -       -       smtpd
#  -o syslog_name=postfix/submission
#  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
#  -o smtpd_tls_auth_only=yes
#  -o smtpd_reject_unlisted_recipient=no
#  -o smtpd_client_restrictions=$mua_client_restrictions
#  -o smtpd_helo_restrictions=$mua_helo_restrictions
#  -o smtpd_sender_restrictions=$mua_sender_restrictions
#  -o smtpd_recipient_restrictions=
  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING
smtps     inet  n       -       n       -       -       smtpd
  -o syslog_name=postfix/smtps
  -o smtpd_tls_wrappermode=yes
  -o smtpd_sasl_auth_enable=yes
#  -o smtpd_reject_unlisted_recipient=no
#  -o smtpd_client_restrictions=$mua_client_restrictions
#  -o smtpd_helo_restrictions=$mua_helo_restrictions
#  -o smtpd_sender_restrictions=$mua_sender_restrictions
#  -o smtpd_recipient_restrictions=
#  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
#  -o milter_macro_daemon_name=ORIGINATING
#628       inet  n       -       n       -       -       qmqpd
pickup    unix  n       -       n       60      1       pickup
cleanup   unix  n       -       n       -       0       cleanup
qmgr      unix  n       -       n       300     1       qmgr
#qmgr     unix  n       -       n       300     1       oqmgr
tlsmgr    unix  -       -       n       1000?   1       tlsmgr
rewrite   unix  -       -       n       -       -       trivial-rewrite
bounce    unix  -       -       n       -       0       bounce
defer     unix  -       -       n       -       0       bounce
trace     unix  -       -       n       -       0       bounce
verify    unix  -       -       n       -       1       verify
flush     unix  n       -       n       1000?   0       flush
proxymap  unix  -       -       n       -       -       proxymap
proxywrite unix -       -       n       -       1       proxymap
smtp      unix  -       -       n       -       -       smtp
relay     unix  -       -       n       -       -       smtp
        -o syslog_name=postfix/$service_name
#       -o smtp_helo_timeout=5 -o smtp_connect_timeout=5
showq     unix  n       -       n       -       -       showq
error     unix  -       -       n       -       -       error
retry     unix  -       -       n       -       -       error
discard   unix  -       -       n       -       -       discard
local     unix  -       n       n       -       -       local
virtual   unix  -       n       n       -       -       virtual
lmtp      unix  -       -       n       -       -       lmtp
anvil     unix  -       -       n       -       1       anvil
scache    unix  -       -       n       -       1       scache
```

### saslの設定
readmeにはsaslauthdとなっているが、マニュアルではauxpropとなっている。ここでは、一番シンプルなauxpropとする。

```/usr/local/lib/sasl2/Sendmail.conf
pwcheck_method: auxprop
```
### dovecotの設定
#### サンプル設定をコピー

```
jail1 /root # cd /usr/local/etc/dovecot
jail1 /usr/local/etc/dovecot # cp -Rp example-config/ .
```

#### 基本設定
IPV6で 『Address family not supported by protocol』のログを残し起動できないことが発生し以下の通りlisten行を追加しIPV6パケットを読まないようにした(2022/4/7追記)。
```/usr/local/etc/dovecot/dovecot.conf
# Protocols we want to be serving.
listen = *
protocols = imap pop3
dict {
}
!include conf.d/*.conf
!include_try local.conf
```
#### SSL設定

```/usr/local/etc/dovecot/conf.d/10-ssl.conf
ssl = yes
ssl_cert = </usr/local/etc/letsencrypt/live/example.jp/fullchain.pem
ssl_key = </usr/local/etc/letsencrypt/live/example.jp/privkey.pem
```

#### master設定
imapとpop3は使用せず、imapsとpop3sを使用する
Postfix smtp-authを使用する

```/usr/local/etc/dovecot/conf.d/10-master.conf
service imap-login {
  inet_listener imap {
    port = 0
  }
  inet_listener imaps {
    port = 993
    ssl = yes
  }
}

service pop3-login {
  inet_listener pop3 {
    port = 0
  }
  inet_listener pop3s {
    port = 995
    ssl = yes
  }
}

service imap {
  #vsz_limit = $default_vsz_limit
  #process_limit = 1024
}

service pop3 {
  #process_limit = 1024
}

service auth {
  unix_listener auth-userdb {
    #mode = 0666
    #user =
    #group =
  }

  # Postfix smtp-auth
  unix_listener /var/spool/postfix/private/auth {
    mode = 0666
        user = postfix
        group = postfix
  }
}

service auth-worker {
  #user = root
}

service dict {
  unix_listener dict {
    #mode = 0600
    #user =
    #group =
  }
}
```

#### 認証
SSLを使用するのでplaintext認証にする

```/usr/local/etc/dovecot/conf.d/10-auth.conf
disable_plaintext_auth = no
auth_mechanisms = plain login
!include auth-system.conf.ext
```

#### maildir

```/usr/local/etc/dovecot/conf.d/10-mail.conf
mail_location = maildir:~/Maildir
namespace inbox {
  inbox = yes
}
protocol !indexer-worker {
}
```

### policyd-spfの設定
master.cfに以下追加

```/usr/local/etc/postfix/master.cf
policyd-spf  unix  -       n       n       -       0       spawn
   user=nobody argv=/usr/local/bin/policyd-spf
```

main.cfに以下追加
smtpd_recipient_restrictionsの設定にミスがあり追加（2019/3/8）
設定内容の意味は以下の通りで、先にローカルユーザと外部接続で認証されたユーザについて許可した後にSPFポリシーを確認する
<dl>
  <dt>permit_mynetworks</dt>
    <dd>クライアントのIPアドレスが、mynetworksにリストされているネットワークまたはネットワークアドレスと一致する場合許可</dd>
  <dt>permit_sasl_authenticated</dt>
    <dd>クライアントがRFC 4954（AUTH）プロトコルを介して正常に認証されたときに許可</dd>
  <dt>reject_unverified_recipient</dt>
    <dd>RCPT TOアドレスへのメールがバウンスすることがわかっている場合、または受信者アドレスの宛先に到達できない場合拒否</dd>
  <dt>reject_unauth_destination</dt>
    <dd>メールフォワーダ：解決されたRCPT TOドメインはrelay_domainsまたはそのサブドメインに一致、または最終宛先：解決されたRCPT TOドメインはmydestination、inet_interfaces、proxy_interfaces、virtual_alias_domains、またはvirtual_mailbox_domainsと一致する場合を除き拒否</dd>
  <dt>check_policy_service unix:private/policyd-spf</dt>
    <dd>指定されたポリシーサーバーを照会する</dd>
</dl>

```/usr/local/etc/postfix/main.cf
policyd-spf_time_limit = 3600
smtpd_recipient_restrictions =
	permit_mynetworks,
	permit_sasl_authenticated,
	reject_unverified_recipient,
	reject_unauth_destination,
	check_policy_service unix:private/policyd-spf
# smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination
```

サンプルをコピーして、設定ファイルを以下とする。

```
jail1 /usr/local/etc/postfix-policyd-spf-python # cp policyd-spf.conf.sample policyd-spf.conf
```

```/usr/local/etc/postfix-policyd-spf-python/policyd-spf.conf
#  For a fully commented sample config file see policyd-spf.conf.commented
debugLevel = 1
defaultSeedOnly = 1
HELO_reject = SPF_Not_Pass
Mail_From_reject = Fail
PermError_reject = False
TempError_Defer = False
skip_addresses = 127.0.0.0/8,::ffff:127.0.0.0/104,::1/128
```

### メールディレクトリの作成
#### 既存ユーザhogeのディレクトリを作成

```
jail1 /root # mkdir -p /home/hoge/Maildir/{cur,new,tmp}
jail1 /root # chmod -R 700 /home/hoge/Maildir
jail1 /root # chown -R hoge:hoge /home/hoge/Maildir
```

#### 今後ゆーざ作成用にデフォルト値を作成

```
jail1 /root # mkdir -p /usr/share/skel/Maildir/{cur,new,tmp}
jail1 /root # chmod -R 700 /usr/share/skel/Maildir/
```

### procmail の設定

```sh:/usr/local/etc/procmailrc
SHELL=/bin/sh
PATH=/bin:/usr/bin:/usr/local/bin
DROPPRIVS=yes
MAILDIR=$HOME/Maildir
DEFAULT=$MAILDIR/
#LOGFILE=$MAILDIR/procmail.log

#remove sexy
:0
* ^Subject: .*sexy.*
/dev/null
```

### pflogsumm の設定
昨日もメールログから整理する

```sh:/etc/crontab
# Mail log
30  0   *   *   *   root    zcat /var/log/maillog.0.bz2 | /usr/local/bin/pflogsumm -d yesterday
```

### SMTPユーザの追加
追加

```
jail1 /root # saslpasswd2 -c -u example.jp hoge
Password:
Again (for verification):
```

確認

```
jail1 /root # sasldblistusers2
hoge@example.jp: userPassword
```

### 起動

```
jail1 /root # service saslauthd start
Starting saslauthd.
jail1 /root # service postfix start
postfix/postfix-script: starting the Postfix mail system
jail1 /root # service dovecot start
Starting dovecot.
```

## spfレコード送信設定
以下のようにspf1プロトコルのTXTレコードをゾーンファイルに設定する

```/usr/local/etc/namedb/master/example.jp.zone
                IN  TXT "v=spf1 +mx +ip4:111.222.333.100 ~all"
```