webエンジニアが実践しておきたいネットワークプロトコル

世の中便利なもので自分でサーバを立てることも最近では無くなってアプリケーションの開発に集中することが出来るようになりました。
ただ、どんなに便利になっても使うためには設定が必ず必要になるわけで、知識がなくてはパラメータの名前や内容をどんなふうに設定したら良いかあたりをつける事もままなりません。
独断と偏見ですがweb系エンジニアにも深い関わりのあるネットワークプロトコルを２つピックアップして、サーバ構築の手順を書き留めたので、冬休みの余興にでもどうぞ。

# DNS

## DNSサーバを作成する
DNSサーバを作るのにAWSのEC2インスタンスを利用します。
外からのアクセスを許可するため、名前解決に利用される53番ポートのTCP/UDPアクセス可能にしてください。
インスタンス作成時のSecurityGroupに53番ポートのTCP/UDPを付与すれば大丈夫です。

この記事ではブラウザでwww.yahoo.co.jpにアクセスするとgoogle.co.jpにアクセスされるようにDNSを設定します。
ただしchrootなどのセキュリティ対策は行っていないため、この設定のまま運用するのはやめた方が良いです。

## 参考にさせていただいたサイト

[DNSサーバー構築(BIND)](http://centossrv.com/bind.shtml "DNSサーバー構築(BIND)")

[EC2上で内部向けDNSを構築してみる](http://qiita.com/mechamogera/items/574de60310fb19e088ca "EC2上で内部向けDNSを構築してみる")

### 必要な物をインストール

#### bind
bindはDNSサーバとリゾルバなどの各種ライブラリが入ってます。
DNSサーバにはIPアドレスとドメインのセットを保持しており、リゾルバがDNSサーバに問い合わせを行い名前解決を行います。

```
$ sudo yum -y install bind
```

bindの設定ファイルを作成

```
$ sudo cp /etc/named.conf{,.org}
$ sudo vim /etc/named.conf
```

```config:/etc/named.conf
//
// named.conf
//
// Provided by Red Hat bind package to configure the ISC BIND named(8) DNS
// server as a caching only nameserver (as a localhost DNS resolver only).
//
// See /usr/share/doc/bind*/sample/ for example named configuration files.
//

options {
        # 自身のリクエストから応答出来るようにするため
		 # listen on portにEC2のプライベートIPを追加
        listen-on port 53 { 127.0.0.1; XXX.XXX.XXX.XXX;};
        listen-on-v6 port 53 { ::1; };
        directory       "/var/named";
        dump-file       "/var/named/data/cache_dump.db";
        statistics-file "/var/named/data/named_stats.txt";
        memstatistics-file "/var/named/data/named_mem_stats.txt";
        # 外からの要求に答えられるようにするためanyに変更
        allow-query     { any; };
        recursion yes;

        dnssec-enable yes;
        dnssec-validation yes;
        dnssec-lookaside auto;
        # 自分では名前解決出来なかった時にフォワードするDNSサーバのIPアドレス
        # 8.8.8.8はGoogleが提供するDNS
        forwarders {  8.8.8.8; 8.8.4.4; };
        forward only;

        /* Path to ISC DLV key */
        bindkeys-file "/etc/named.iscdlv.key";

        managed-keys-directory "/var/named/dynamic";
};

logging {
        channel default_debug {
                file "data/named.run";
                severity dynamic;
        };
};

zone "." IN {
        type hint;
        file "named.ca";
};

# yahoo.co.jpの問い合わせをmaster.yahoo.co.jpの中に記述されたIPで返却する
zone "yahoo.co.jp" IN {
  type master;
  file "master.yahoo.co.jp";
};

include "/etc/named.rfc1912.zones";
include "/etc/named.root.key";
```

yahoo.co.jpへの名前解決の内容を記述

```
$ sudo vi /var/named/master.yahoo.co.jp
```

```config:/var/named/master.yahoo.co.jp
$TTL 43200
yahoo.co.jp.     IN      SOA    help.yahoo.co.jp. ns01.yahoo.co.jp. (
                         1
                         21600
                         7200
                         1209600
                         43200)

yahoo.co.jp.            NS      ns01.yahoo.co.jp.
ns01                    A       216.58.220.206 # google.co.jpのIP
www                     A       216.58.220.206 # google.co.jpのIP
```

起動と自動起動を有効化

```
$ sudo /etc/init.d/named start
$ sudo chkconfig named on
```

DNSリゾルバの向き先を自身のDNSサーバに変更する

```
$ sudo cp /etc/resolv.conf{,.org}
$ sudo vi /etc/resolv.conf
$ cat /etc/resolv.conf
; generated by /sbin/dhclient-script
search ap-northeast-1.compute.internal
nameserver 127.0.0.1
```

```
$ sudo vi /etc/sysconfig/network-scripts/ifcfg-eth0
```

```/etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
BOOTPROTO=dhcp
ONBOOT=yes
TYPE=Ethernet
USERCTL=yes
# DHCPでIPを取得時にyesだと/etc/resolv.confの値が更新されてしまう
PEERDNS=no
IPV6INIT=no
PERSISTENT_DHCLIENT=yes
```

これでDNSサーバの設定は終わりで、PCのDNSの向き先を作成したEC2インスタンスのPublicIPを指定してブラウザにyahoo.co.jpと入力します。
うまく行っていればgoogle.co.jpが表示されます。

# SMTP POP3
SMTPとPOP3はメールの送受信に使われるプロトコルです。
SMTPは送信、POP3は受信を担当しています。
使用するポートはSMTPが25番 POP3が110番です。

## メールサーバ

### 必要なもの

1. サーバ
メールを送受信するのに必要です。

2. ドメイン
受信の必要があるなら必須です。

### サーバの用意
送信にはPostfix 受信はDevecotを使います、例ではAmazonLinuxを使用しています。
作成するEC2インスタンスのSecurityGroupには25と110のポートのインバウンドを許可しておいてください。
EC2からローカルに対してのメールでもポートが空いてないと送受信が出来ません。
自宅サーバならばルータの設定も25と110番のポートを利用出来るようにしておいてください。

#### Dovecot

##### インストール

```shell:shell
sudo yum -y install dovecot
sudo service dovecot start # 起動
$ sudo chkconfig dovecot on # 自動起動有効
```

#### Postfix

##### インストール

```shell:shell
# 下記コマンドを打つと質問に回答する必要があるので、
# 用途については「インターネットサイト」、システムメール名は「了解」を選択
$ sudo yum -y install postfix mailx
$ sudo service postfix start # 起動
$ sudo chkconfig postfix on # 自動起動有効

# postfixと同じくPOP3を提供するsendmailからpostfixをデフォルトにする
$ sudo /etc/rc.d/init.d/sendmail stop # 停止
$ sudo chkconfig sendmail off # 自動起動を無効
$ sudo alternatives --config mta # alternativesコマンドでmtaをpostfixに変更する 2を入力してエンター
2 プログラムがあり 'mta' を提供します。

  選択       コマンド
-----------------------------------------------
*  1           /usr/sbin/sendmail.sendmail
 + 2           /usr/sbin/sendmail.postfix
```

##### postfixの設定ファイルを書き換える

```config:/etc/postfix/main.cf
# メールを送る時の@以降の文字列
myhostname = mail.example.comなど

# ドメイン名
mydomain = example.com

# コメントになっているので#を外す
myorigin = $mydomain

# localhostだとローカル内からのメールの受信のみ可能なので全てのメールを受信可能にする
inet_interfaces = all

# ipv6を許可すると環境によってはエラーになるらしい
inet_protocols = ipv4

# $mydomainを追加する
# mtaが@以降のドメインをmydestinationの値と比較して自分が受信するべきか判定に使うため、
# 設定されていないと受信出来ない
mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain

home_mailbox = Maildir/ # コメントになっているので#を外す
```

#####

```shell:shell
# test@mail.example.com宛は /home/test/Maildir/new以下に保存される

# ユーザ作成時のデフォルトのディレクトリ構成を設定
$ sudo mkdir -p /etc/skel/Maildir/{new,cur,tmp}
$ sudo chmod -R 700 /etc/skel/Maildir/
$ sudo useradd test
$ sudo passwd test
$ su - test
```


#### 実行
```shell:shell
# 送れたかどうか /var/log/mail.log と /var/log/mail.errをtailしておくとわかりやすい
# さきほど作成したdovcotで送るには以下のコマンドを実行
echo "Hello" | mail ec2-user@localhost
```

```実行結果
# 確認 Helloという内容が追加されていれば成功
sudo cat /var/mail/ec2-user

From ec2-user@ip-XXX-XXX-XXX-XXX.ap-northeast-1.compute.internal  Sun Nov 29 18:38:38 2015
Return-Path: <ec2-user@ip-XXX-XXX-XXX-XXX.ap-northeast-1.compute.internal>
Received: from ip-XXX-XXX-XXX-XXX.ap-northeast-1.compute.internal (localhost [127.0.0.1])
	by ip-XXX-XXX-XXX-XXX.ap-northeast-1.compute.internal (8.14.4/8.14.4) with ESMTP id tATIccSd031046
	for <ec2-user@ip-XXX-XXX-XXX-XXX.ap-northeast-1.compute.internal>; Sun, 29 Nov 2015 18:38:38 GMT
Received: (from ec2-user@localhost)
	by ip-XXX-XXX-XXX-XXX.ap-northeast-1.compute.internal (8.14.4/8.14.4/Submit) id tATIccjD031045
	for ec2-user@localhost; Sun, 29 Nov 2015 18:38:38 GMT
From: EC2 Default User <ec2-user@ip-XXX-XXX-XXX-XXX.ap-northeast-1.compute.internal>
Message-Id: <201511291838.tATIccjD031045@ip-XXX-XXX-XXX-XXX.ap-northeast-1.compute.internal>
Date: Sun, 29 Nov 2015 18:38:38 +0000
To: ec2-user@ip-XXX-XXX-XXX-XXX.ap-northeast-1.compute.internal
User-Agent: Heirloom mailx 12.4 7/29/08
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Hello

```

ほい、ローカルからの送受信は割りとすんなり出来ました。

##### DNSの設定を行う
外部からメールを受信するためには、@以降のドメインから今作成したサーバのIPが引けるようにならなければいけません。
なので、ネームサーバにMXレコードとAレコードを登録する必要がありますが、お名前.comであれば設定する事が可能です。
あるいはネームサーバをAWSのRoute53に変更し、登録します。

1. Aレコード
Aレコードはドメインに対応するIPアドレスを設定するレコード
その他にはCNAMEレコードなどが有り、CNAMEレコードはドメインに対して別のドメインを指定することが出来る

2. MXレコード
メールの宛先をAレコードで指定したドメイン名をMXレコードのVALUEに記述する。

設定が反映されるには少し時間がかかるので、しばらくしたらdigコマンド(windowsであればnslookup)を使って設定が波及されたか確認してみる。

```
# ANSWER SECTIONに先ほどの設定が出ていればOK
# MXレコードが波及されたか確認するのは dig mail.example.com mx で確認出来る
$ dig mail.example.com

; <<>> DiG 9.8.3-P1 <<>> mail.example.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 26357
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 4, ADDITIONAL: 6

;; QUESTION SECTION:
;mail.example.com.			IN	A

;; ANSWER SECTION:
mail.example.com.		3600	IN	A	XXX.XXX.XXX.XXX

;; AUTHORITY SECTION:
example.com.		86265	IN	NS	03.dnsv.jp.
example.com.		86265	IN	NS	02.dnsv.jp.
example.com.		86265	IN	NS	04.dnsv.jp.
example.com.		86265	IN	NS	01.dnsv.jp.

;; ADDITIONAL SECTION:
01.dnsv.jp.		19035	IN	A	XXX.XXX.XXX.XXX
02.dnsv.jp.		15489	IN	A	XXX.XXX.XXX.XXX
03.dnsv.jp.		15390	IN	A	XXX.XXX.XXX.XXX
03.dnsv.jp.		12191	IN	AAAA	2400:8500:3000::53
04.dnsv.jp.		13134	IN	A	XXX.XXX.XXX.XXX
04.dnsv.jp.		48160	IN	AAAA	2400:8500:3fff::53

;; Query time: 36 msec
;; SERVER: 192.168.11.1#53(192.168.11.1)
;; WHEN: Sat Dec  5 12:31:33 2015
;; MSG SIZE  rcvd: 243

```

##### 送受信をしてみる

まずは受信をしてみるので、Gmailなどのメーラからtest@mail.example.comに向けてメールを送ってみる。
するとtestユーザのMaildir/newに新規メールが届いているはず...!

同じようにmailコマンドで外部ドメインに対しても送る事が可能です。

```shell:shell
echo "送信テスト" | mail "example@gmail.com"
```

## 外部サービス

これまでは自身でサーバを作成するところまでを説明しましたが、以下のサービスはこれまでの苦労を代理で行ってくれる物です。
自分で作る機会があるときは本当に自分で作る必要があるのか判断し、その中でもサービスごとに特色が異なるので慎重に選択すると幸せになれるかもしれません。

1. SES
AWSが提供するメールサービス 安いから個人でも使いやすい。
アカウント作成時などの純粋にメールを送るだけの場合はこれで十分、ただ送信リストなどの顧客管理ちっくなことまで求めると辛い。

2. ブレインメール
国内ではかなり実績がありそう。
メールアドレスに対してリスト化したり予約送信など行う事が可能なので、メルマガ系のサービスやる場合はこれが良いかも。
ただ他のメールサービスと比べて送信数ではなく、送信先として登録しているメールアドレスの数によって変わってきて値段は決して安くない。

3. Mandril
APIが充実している...らしい。値段もSESと張るくらい安い。