VirtualBox上ゲストOSにssh接続する＆ゲストOSからインターネット接続できるようにする。

## 目標
VirtualBox上OSで作業するとき、ホストOSとの画面の切り替えがめんどくさかったり、ゲストOS内でブラウザの処理が遅かったり、言語などのOS設定のカスタマイズが必要だったり、案外手間が多い。そこで、VirtualBoxからはバックグラウンドでOSを立ち上げ、puttyなどでゲストOSに接続する方法を紹介する。その際、ゲストOSがインターネット接続可能な設定を行う。また、最後に、ゲストOSを jupyter notebook のサーバとして動作させる例を挙げる。

## 設定の概略
ホストOS-ゲストOS間に二つのネットワーク設定を構築する．一つは，ホストOSからゲストOSにssh接続する用のネットワーク "Host-Only Adapter" ，もう一つは，ゲストOSからインターネットに接続するためのネットワーク "NAT" である．本ブログではこれらの設定の仕方を解説する．

## 実行環境
- ホストOS: Windows 10
- ゲストOS: Ubuntu18
- VirtualBox version 5.2.7
※　今回はUbuntで設定しましたが，Linux系OS であればほぼ同様の操作で同じことができるはずです．


##  VirtualBox上の設定

(i) まず，VirtualBoxマネージャーの画面から，「ファイル」->「環境設定」->「ネットワーク」とたどり，"ホストオンリーネットワーク" のタブを開き，既に存在する "VirtualBox Host-only Ethernet Adapter" を右クリックし，「ホストオンリーネットワークを編集」を選択する．もし，存在しない場合は，右のアイコンから新しく作っておく．
（追記）新しい Virtual Box のバージョンでは，マネージャーを立ち上げて，右上のグローバルツールからホストネットワークマネージャーを開く．

<img width="487" alt="host-network-manager.png" src="https://qiita-image-store.s3.amazonaws.com/0/139085/a8444451-da14-e35f-2763-d22f69f008c4.png">


次の二つの操作を行う．
1. 「アダプター」タブの "IPv4" のアドレスをメモしておく．また， "IPv4 ネットマスク" が "255.255.255.0" になっていることを確認する．
2. 「DHCPサーバ」タブを開き，「サーバーを有効化」のチェックを外す．これはゲストOSのネットワーク設定を手動で設定するときに，DHCPで設定されたIPアドレスと被ることを防止するために一応設定しておく．


(ii) 次に，VirtualBox でゲストOSのネットワーク設定を開く．Adapter 1のタブを開き，"NAT"にする．

<img width="526" alt="VM-nat.png" src="https://qiita-image-store.s3.amazonaws.com/0/139085/221c318c-cd96-54ef-1fbd-2f7218949159.png">


(iii) 次に，Adapter 2のタブを開き， "ホストオンリーアダプター" に設定する。"高度" の項目は特に変更を加えていない。

<img width="526" alt="VM-host.png" src="https://qiita-image-store.s3.amazonaws.com/0/139085/9069c98e-55cc-b69a-6048-39d5435e9f83.png">


## ゲストOS上の設定
まずは，VirtualBox上で設定した二つのネットワークにつながっているゲストOS上のネットワークアダプタの名前を知る必要がある．
`$ ip a`コマンドでネットワークデバイスの情報を確認する．

<img width="539" alt="ip-a.png" src="https://qiita-image-store.s3.amazonaws.com/0/139085/b966255f-ce5f-7720-ff51-7a4df6d098ae.png">


"enp0sx" のようなアダプタが二つあり，番号の若いほうが "NAT" で，大きいほうが"ホストオンリーアダプタ"と思ってよい．次は "ホストオンリーアダプタ" である "enp0s8" の設定を変更する．

今回は設定を変更する方法を三つ紹介する．どれかひとつをやればよい．
1. GUI を使ってサクッと変更する．
2. Ubuntu のバージョン16 以下の設定方法(/etc/network/interfaces)
3. Ubuntu のバージョン17 以上の設定方法(/etc/systemd/network/nep0s8.network)
CentOSでは "/etc/sysconfig/network-scripts/ifcfg-enp0s8" を編集する方法があるらしい．

---

#### 1: GUI でホストオンリーネットワーク設定
Ubuntu の場合，右上のメニューからネットワークインターフェース （この例ではenp0s8）を選択して，Address を変更する．Gateway は空で，DNS はホストネットワークマネージャーで見たアドレスにする．

<img width="500" alt="enp0s8.png" src="https://qiita-image-store.s3.amazonaws.com/0/139085/a17afcbc-3670-77bf-cd6c-70b5e0fb1095.png">

設定を反映するためネットワークを再起動する．

`$ sudo service networking restart # centOS の場合はsystemctl restart network.service `

`ip a`でネットワーク設定を確認してみて，まだ変わってない場合はシステムごと再起動する．

#### 2: GUI 使わないでUbuntu 16 以上の設定

"/etc/network/interfaces" を次のように変更する．

<img width="500" alt="interfaces.png" src="https://qiita-image-store.s3.amazonaws.com/0/139085/403cc56b-8ad2-3349-72a3-ccd64c27edf3.png">


ここでポイントとなるのは，
1. address に設定したい IP アドレスを指定すること
1. dns-nameservers にホストネットワークマネージャーでみたアドレスを設定すること
2. gateway はあえて設定しない．デフォルトゲートウェイは NAT のenp0s3 の方を使いたいから．
2. 他は適切に設定する

設定を反映するためネットワークを再起動する．

`$ sudo service networking restart # centOS の場合はsystemctl restart network.service `

`ip a`でネットワーク設定を確認してみて，まだ変わってない場合はシステムごと再起動する．

#### 3: GUI 使わないでUbuntu 17 以上の設定
"/etc/systemd/network/enp0s8.network" というファイルを作り，次のように記入する．

```
[Match]
enp0s8

[Network]
Address=192.168.151.100
DNS=192.168.151.1

```

設定を反映するためネットワークを再起動する．

`$ sudo service networking restart # centOS の場合はsystemctl restart network.service `

`ip a`でネットワーク設定を確認してみて，まだ変わってない場合はシステムごと再起動する．

## ネットワークが正しく設定できているか確認
最後にネットワークの設定を確認してみる．`route` コマンドで，デフォルトゲートウェイが "NAT" ネットワークに接続している "eth03"のみになっていることを確認する．もしデフォルトゲートウェイが二つ以上ある場合，（特にeth08に設定されている場合）間違ったルーティングでパケットを送信してしまうため，インターネット接続が確立できない場合がある．

<img width="600" alt="route.png" src="https://qiita-image-store.s3.amazonaws.com/0/139085/93286f4e-4489-c6c1-9fcc-6952ffa5f2cd.png">


## インターネット接続を試してみる．
` ping google.com ` 等で接続を試す．ネットワークがつながってない場合，NAT 側のルーティングに問題があることが考えられる．

## ssh 接続できるか試してみる．
Tera Term などの ssh アプリケーションでログインを試してみる．
ログイン先は，ネットワーク設定で変更したアドレスで，上の例では 192.168.151.100 に当たる．

<img width="361" alt="teraterm.png" src="https://qiita-image-store.s3.amazonaws.com/0/139085/5a054496-478e-c4f2-a550-db99e07c694f.png">



## もしもssh接続できない場合
- openssh-serverをインストールしてあるか確認する。
- SELinuxを無効にし，ファイアウォールの設定を無効にしてあるか確認する．下の「鍵認証で"refused"される場合」を参照
- ゲストOSのsshの認証設定（鍵認証orパスワード認証）が認識とあっているか確認する．


## おまけ：鍵認証で"refused"される場合
puttyで鍵認証ログインするとき、正しく公開鍵を設定したにもかかわらず拒否される場合がある。`getenforce`コマンドで`Enforcing`となっている場合、SELinuxが原因となっている可能性がある。`setenforce 0`コマンドでSELinuxを一時的に無効にしたり、

```
# vi /etc/selinux/config
SELINUX=disabled
```

で永続的に無効にしたりすると治る。
（参考：https://eng-entrance.com/linux-selinux、http://next49.hatenadiary.jp/entry/20140620/p1）

## おまけ：ゲストOSをバックグラウンドで立ち上げる方法

ゲストOSはssh経由で操作するため、ゲストOSの画面は使わない。画面を起動するだけむだにグラフィック処理が走る。そこで、VirtualBoxでゲストOSの画面を立ち上げずにバックグラウンドでゲストOSを起動する。

「起動」の脇のメニューから、「ヘッドレス起動」を選択することで、バックグラウンドでOSを立ち上げることができる。
<img width="619" alt="vm07.png" src="https://qiita-image-store.s3.amazonaws.com/0/139085/e80494b5-156d-7baa-de86-5de06545f10f.png">

## おまけ：Jupyter notebook を使う例
ゲストOSでjupyter notebook のサーバを立ち上げて、ホストOSのウェブブラウザから表示することができる。
まず、ゲストOS上で、8888ポートからの接続を受け付けるようにFireWallの設定を変更する必要がある。

```
$ sudo firewall-cmd --add-port=8888/tcp --zone=public --permanent
success
$ sudo firewall-cmd --reload
success
```
また，SELinuxをオフにすれば，FireWallもオフのままになるはず．基本的にオフっておけ．

ゲストOSでjupyter サーバを立ち上げる。

```
jupyter notebook --ip=[IP Address] --no-browser
```

すると、ホストOSから、http://[IP Address]:8888で接続できる。