初めてのドメイン名をラズパイに割り当てて、外部ネットワークから接続できるようにしてみた

# Raspberry Piにドメインネームを割り当てる
家のWi-Fiに繋がっている自作IoT機器にアクセスしたり、ちょっとしたウェブサイトを家族、友人、に見てもらったりするために、以前から様々な実験に使っているラズパイにドメイン名を割り当てて、外からでもアクセス可能にしたいと思っていたが、今回の３連休を機会にQiitaデビューも兼ねてやってみようと思います！

## 大まかな流れ
1. ラズパイにごく簡単なサーバを立ち上げる
2. 外部からアクセスができるようにポート転送を設定する
3. ドメイン名を手に入れる
4. ドメイン名と家のルータをつなぐ
5. ルータのIPが変わっても問題が起きないようにDDNSを設定する
6. ラズパイに固定IPを割り当てる

---

## 1. 外部からアクセスするサイトを準備
ひとまずアクセスするサーバをラズパイで立ち上げる。とりあえずDockerでnginxのコンテナでやることにしたんだけど、本当になんでもいいです。
`docker run -it --rm -p 80:80 nginx`

<img width="584" alt="nginx.png" src="https://qiita-image-store.s3.amazonaws.com/0/237915/11f495ae-fc18-b82b-5fbc-e20fff97fed6.png">

画像ではローカルネットワークのコンピューター名でアクセスしたが、IPアドレスを直接打ち込んでもいいです。

LANからアクセスできることを確認した上で次に進もう！

---

## 2. ポート転送の設定
家のネットワークの出入口であるルータにリクエストがきたとき、ラズパイに転送されるように設定をする。

ルータの機種によって細かいところは変わるが、だいたいのことは一緒です。ルータの設定をするために用意されているウェブサイトに移動し、ログインを済ます。分からない場合はルータの機種をググれば上位に出てくるはず。

**ポート転送**の設定を探して、下記のように設定する
<img width="865" alt="portforward.png" src="https://qiita-image-store.s3.amazonaws.com/0/237915/a52bbafe-f028-616c-dd89-b3cb5e4b1e49.png">

* `WAN側ポート` 外部ネットワークからアクセスするときにアクセスするポート（*任意*）
* `LAN側ポート` ラズパイのサーバが使っているポート。HTTPは普通は80を指定する。さっき用意したサーバが違うポートを使っている場合はそのポートを使う。
* `IP Address`ラズパイのローカルネットワークでのIPアドレス。IPアドレスを決めているわけないです。ラズパイがすでに取得したIPを入力しているだけです。

設定を終えてルータを再起動すると外部ネットワークから接続できるようになる！下記のツールにWAN側ポートを入力すると転送されているかどうか確認できる。（転送先が正しいかどうかは次！）

[Open Port Check Tool - Test Port Forwarding on Your Router](https://www.yougetsignal.com/tools/open-ports/)
<img width="816" alt="yougetsignal.png" src="https://qiita-image-store.s3.amazonaws.com/0/237915/7c9227e6-a2d6-be13-d345-18328d3a7039.png">

さて、試してみるか？携帯の*Wi-Fiを切って*からルータの外部アドレスをブラウザーでで訪ねてみよう！ポート番号が80でない場合は指定が必要！
`http://40.30.20.10:3000`みたいな書き方をする。

うまく行けばラズパイのサーバにつながる！

#### ハマったこと
1. 通信会社がポート８０の転送を禁止している場合があるらしい。うまくいかないときは3000とか、高いポート番号を試しましょう。ただ、80を使わない場合はアクセスするURLにダサいポート番号が付いてしまう。
	* ポート８０の場合： `www.hogehoge.com`
	* ポート１２３４の場合：`www.hogehoge.com:1234`
2. 僕のルータではポートを指定するとき範囲で指定しないと行けなかったが、80だけと意味で80-80を入れたとき、エラーは出なかったものの、ポートが転送されなかった。試行錯誤の結果、80-81は80が転送されるが81は転送されない仕様っぽいです。
3. 多くのルータは内部から外部IPでアクセスできないようなので、ポート転送設定を確認するときは携帯なり、パブリックWi-Fiなり、違うネットワークから試す必要がある。
4. ルータを再起動したとき、ラズパイに割り当てられたIPアドレスが変わって、転送設定をやりなおさないといけなかった。まあ、これは想定していた問題だけど、対策は後半で打つから、とりあえず手直しして進もう。

---

## 3. ドメイン名の取得

無料で手に入るサイトもあるみたいだけど、[NameCheap](https://www.namecheap.com/)で100円程度で買えちゃうから、今日は自販機でプチ節約して初めてのドメインを買うことにした！

<img width="150" alt="namecheap.png" src="https://qiita-image-store.s3.amazonaws.com/0/237915/1b1fd8ba-55b3-3732-3d85-eaa7392e6060.png">

よし、これで行こう！

手続きは案外楽だった。メールで本人確認を済ましてすぐに使える状態になった。ルータと連携してみよう！

---

## 4. ドメイン名とルータのIPをつなぐ

これも期待以上に楽だった。

<img width="1371" alt="namecheap-dashboard.png" src="https://qiita-image-store.s3.amazonaws.com/0/237915/2318f1cb-7153-0820-d373-80dc5b0d16ed.png">

管理のページから新しく購入したドメイン名のManageボタンをまず見つける。

<img width="1064" alt="namecheap-static-ip.png" src="https://qiita-image-store.s3.amazonaws.com/0/237915/4145e201-c518-b969-e977-4cdb22bd0716.png">

上記の図のように編集する。
* `A Record`を設定すると`Host`+`nihongoheta.club`に行ったとき、`Value`に指定したIPに辿り着くようになる。
* `CNAME Record`はアリアス的なもので、`nihongoheta.club`に行ったとき、`www.nihongoheta.club`と同じ扱いになる。
* Hostに好きなサブドメインを指定することができる。例えば、`sugoi.nihongoheta.club`などが作れる！中々楽しいですな！

設定を保存してから反映されるまで３０分くらいかかるらしいです。一息休憩でもしようか？

**経過時間15分**

また携帯のWi-Fiを切って、`nihongoheta.club`と`www.nihongoheta.club`を試してみたが、ラズパイのnginxサーバがあっさり表示された！

---

#### ここで終わり？
実験的にしか使わない、安定性を求めない場合、ここでよしとしてもかもしれない。一方、長く使いたい、アップタイムを重視する場合はまだまだ仕事が残っている。なぜ？

通信会社会社が家のルータ割り当てるIPアドレスと、ルータがラズパイに割り当てるIPアドレスは可変だからです。しばらくしたらルータとラズパイのIPアドレスがそれぞれ変わって、先ほどせっかく連携したドメイン名と違うIPになってしまう。

この問題を解決するために、DDNS（Dynamic Domain Name Server)というものが存在する。簡単に説明すると、ラズパイのIPが変わったとき、ラズパイが新しいIPをNameCheapに通知を出す仕組みです。

---

## 5. ルータのIPが変わっても問題が起きないようにDDNSを設定する
### NameCheapでDDNSを有効にする
さっきのAdvanced DDNSメニューで下の方に行くとDDNSを有効にできるスイッチがあるので、ポッチっと。

パスワードが表示されるのだけど、次のステップで使う！

<img width="1065" alt="namecheap-ddns.png" src="https://qiita-image-store.s3.amazonaws.com/0/237915/1cd13416-ab41-7b08-12b7-cb4c5666aa3a.png">

### ラズパイにddclientをインストール

ddclientは背景でIPアドレスを見張り、変わったときはNameCheapに通知をだして更新をさせるdaemonです。（個人の勝手な解釈）無論、NameCheap以外のサイトも対応している。ラズパイの方で下記を実行。

```
sudo apt install ddclient
```

インストールが終了したらちょっと怖い設定画面が出るんだけど、設定は後で上書きするから適当にやっちゃっていいです。

好みのエディッターで`/etc/ddclient.conf`を編集。VIM万歳！

```
use=web, web=checkip.dyndns.com/, web-skip='IP Address'
ssl=yes
protocol=namecheap
server=dynamicdns.park-your-domain.com
login=nihongoheta.club
password=<機密情報>
www
```

* 一行目：現在のIPアドレスを取得する方法を指定
* ssl: NameCheapに通知をだすとき、パスワードなどを暗号化
* protocol: 利用する会社の規定
* server: DNSサーバ
* login: NameCheapの場合はドメイン名そのもの
* password: 先程NameCheapで表示されたパスワード
* www 更新するホスト

*注意点*: `park-your-domain`に自分のドメイン名を代入したくなるかもしれないが、あれはName CheapのDNSサーバの本当の名前みたいです。誤解を招く名前をつけてくれたな。

保存しておくと終わりです！

### 動作確認
でもdaemonだと本当に動いているかどうか不安だよね？どうやって確実に確かめられるだろう？

`sudo service ddclient status`で状態とログを確認できる。定期的に通知を出していることがわかるんですね。

```
● ddclient.service - LSB: Update dynamic domain name service entries
   Loaded: loaded (/etc/init.d/ddclient; bad; vendor preset: enabled)
   Active: active (exited) since Sun 2018-02-11 08:09:56 EST; 13h ago
     Docs: man:systemd-sysv-generator(8)

Feb 11 08:09:56 bitbuster systemd[1]: Starting LSB: Update dynamic domain name service entries...
Feb 11 08:09:56 bitbuster systemd[1]: Started LSB: Update dynamic domain name service entries.
Feb 11 08:25:45 bitbuster systemd[1]: Started LSB: Update dynamic domain name service entries.
Feb 11 20:01:11 bitbuster systemd[1]: Started LSB: Update dynamic domain name service entries.
Feb 11 20:10:13 bitbuster systemd[1]: Started LSB: Update dynamic domain name service entries.
Feb 11 20:14:45 bitbuster systemd[1]: Started LSB: Update dynamic domain name service entries.
Feb 11 20:53:09 bitbuster systemd[1]: Started LSB: Update dynamic domain name service entries.
```

でも、受け取る側でエラー起きたりしていないかな？
それを試すためには、一回`A Record`のIPアドレスを無効なIP（1.1.1.1とか）に書き換えて、ddclientを動かして、更新されたかチェックすればいいです。

下記のコマンドはddclientをdaemonとしてではなくて、一回だけ呼んで、コンソールに成否が分かるdebug情報を残す。
`sudo ddclient -daemon=0 -noquiet -debug -verbose`

これでルータのIPが変わっても、問題ないはず！
でもラズパイのLANでのIPが変わる可能性はまだ残っているよね？せっかく家のルータまできたリクエストがラズパイでないところに転送されたかもしれない！

## 6. ラズパイに固定IPを割り当てる

もう少し頑張ろう！ルータもHPに戻って、ラズパイに固定IPを指定する。
ラズパイのMACアドレスが必要になるので、ルータの機器一覧で見つけたり、ラズパイのターミナルで取得したりして、以下のように設定する。

<img width="1064" alt="namecheap-static-ip.png" src="https://qiita-image-store.s3.amazonaws.com/0/237915/fe254d2f-64cb-b6ef-288a-d3c9ce07afd5.png">


メーカーによって、固定IPは割当IPの範囲外のアドレスにしないといけない仕様のものもあるが、僕のルータは範囲内出ないとエラーになる

ポート転送設定の更新を忘れないように気をつけましょう！

<img width="1030" alt="portforward-update.png" src="https://qiita-image-store.s3.amazonaws.com/0/237915/ddc00999-fe28-92bc-b2a0-3332b92db0cf.png">

ルータを再起動し、試しておこう！
外部ネットワークから接続するのがポイントです！

<img width="827" alt="success.png" src="https://qiita-image-store.s3.amazonaws.com/0/237915/0a00c796-6d73-a849-b69d-864b27e4ad10.png">

よしゃ！成功！

## お疲れ様です！

今度はHTTPSに挑戦したいと思いますが、今日はこれまでにしよう！
お茶でも飲んで三連休の残りをゆっくり過ごしましょう。