Vagrantでウェルノウンポートをフォワードする


# 目的

スマートフォン端末から、Mac OS XのVagrant(Virtualbox)上で動作するCentOSに、HTTP/HTTPSで http://example.com や https://example.com など、特別なポート番号を指定せずにアクセスできるようにします。

そのために、Vagrantをroot権限で起動し、ホスト上のウェルノウンポート(80, 443)をゲストの同ポートにフォワードします。

![ゴール](http://i.imgur.com/OKiAGEP.jpg)

# 手順

## 鍵ファイルを設置する

`vagrant up`で仮想マシンを起動する際、以下のような挙動になります。

- `vagrant`コマンドのどれかを実行すると`~/.vagrant.d/insecure_private_key`が生成される
- boxの`authorized_keys`には、予め`insecure_private_key`が登録されている
- `vagrant up`を実行すると、`insecure_private_key`を使って仮想マシンに接続する
- 鍵ファイルの所有者は`vagrant up`を実行したユーザである必要がある(SSHの仕様)


今回は、ファイルに一切の変更を加えないために`vagrant status`を使って鍵ファイルを生成し、rootのホームディレクトリである`/var/root`にこの鍵をコピーします。

```bash
# 鍵を生成
$ vagrant status

# 鍵を設置
$ sudo mkdir /var/root/.vagrant.d
$ sudo cp ~/.vagrant.d/insecure_private_key /var/root/.vagrant.d/insecure_private_key
$ sudo chown root:wheel /var/root/.vagrant.d/insecure_private_key
```

## 仮想マシンを起動する

通常とは異なり、`/var/root/.vagrant.d/insecure_private_key`を使って仮想マシンに接続するので、その設定を記述した`Vagrantfile`で仮想マシンを起動します。

```ruby:Vagrantfile
# -*- mode: ruby -*-
# vi: set ft=ruby :

# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  # Box
  config.vm.box = "centos_6.5"
  config.vm.box_url = "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_centos-6.5_chef-provisionerless.box"

  # Key
  config.ssh.private_key_path = "/var/root/.vagrant.d/insecure_private_key"

  # Network
  config.vm.network "forwarded_port", guest: 80 , host: 80
  config.vm.network "forwarded_port", guest: 443, host: 443
end
```

```bash
$ sudo vagrant up
$ sudo vagrant ssh
```

## 確認する

仮想マシンにApacheなどをインストールし、ホストOSのブラウザで http://127.0.0.1 に接続してindexファイルが閲覧できればフォワードは成功です。

## インターネット共有を有効にする

`システム環境設定 > 共有 > インターネット共有`と進み、インターネット共有を有効にします。
スマートフォン端末からアクセスするため、IPアドレスを確認して下さい。デフォルトでは192.168.2.1/24になるはずです。

![インターネット共有](http://i.imgur.com/1L5bP8t.png)

```bash
$ ifconfig bridge0
```

## 確認する

スマートフォン端末で、キャリアの回線をOFFにし、インターネット共有のネットワークに参加した状態で http://192.168.2.1 (上記で確認したアドレス)にアクセスしてindexファイルが閲覧できればインターネット共有は成功です。

## DNSサーバを立てる

このままでも仮想マシンにアクセスできますが、ホスト名でアクセスするために[unbound](http://unbound.net/)を使ってMac OS XをDNSサーバにします。

```bash
# インストール
$ brew install unbound

# バックアップ
$ cp /usr/local/etc/unbound/unbound.conf /usr/local/etc/unbound/unbound.conf.org

# 上書き
$ vim /usr/local/etc/unbound/unbound.conf
$ cat /usr/local/etc/unbound/unbound.conf
server:
	username: nobody
	interface: 0.0.0.0
	access-control: 192.168.2.0/24 allow 
	local-data: "example.com A 192.168.2.1"

# 起動
$ sudo unbound -v -d -c /usr/local/etc/unbound/unbound.conf
```

## 確認する

スマートフォン端末から http://example.com にアクセスしてindexファイルが閲覧できればDNSサーバの設定は成功です。

# 補足

## Vagrant Shareについて

Vagrant 1.5で追加された[Vagrant Share](https://www.vagrantup.com/blog/feature-preview-vagrant-1-5-share.html)を使えば外部からアクセス可能なURLが生成されます。
しかし、開発用にURLを固定する必要がある場合など、対応できない場合もあるのでこの方法が役に立つときもあるはず…。

## root権限での起動について

Vagrantの[公式ドキュメント](https://docs.vagrantup.com/v2/networking/forwarded_ports.html)では非推奨となっており、多くのチュートリアルもウェルノウンポート以外でフォワードしている場合が多いです。
しかし、とりあえず方法を残しておけば役に立つときもあるはず…。

	host (int) - The port on the host that you want to use to access the port on the guest. This must be greater than port 1024 unless Vagrant is running as root (which is not recommended).

## DNSキャッシュについて

DNSの設定に失敗した状態で1度アクセスに失敗すると、スマートフォン端末にDNSのキャッシュが残ってしまい、以後アクセスに失敗し続ける可能性があります。

以下の手順でDNSキャッシュを削除して再度アクセスを試してください。

1. 機内モードをONにする
2. 機内モードをOFFにする