WindowsのVirtualBox 7でUbuntu Server 22.04.3 LTSを動かしてSSHするまでの手順(備忘)

タイトルに書いてあることをしたので手順を残します。


## 環境
Windows 10 22H2
VirtualBox 7.0.10
Ubuntu Server 22.04.3 LTS


## 更新履歴
2023/10/7 記事を投稿
2023/10/15 全体的に書き直し(最初に記事を書いた時の問題が別環境では起きない事を確認できたため)


## 経緯
ローカルにLinuxサーバーを立てたくて調べながら行いました。
仮想マシンの選択肢は`VirtualBox`，`VMware Workstation Player`，`WSL2`などがありましたが，OSSの方が良いと思い`VirtualBox`にしました。(あとWSL2は上手く行かない部分があったので断念しました)
Linuxディストリビューションは仕事では`RedHat系`を使っていますが，世界的にシェアが高い`Ubuntu`が気になっていたので`Ubuntu Server`にしました。


## 参考にした記事
https://note.com/_chibisuke/n/n89d110e74241

https://qiita.com/HirMtsd/items/225c20b77a7cd5194834

https://zenn.dev/hatotk/articles/install-ubuntu-server-20-04-lts


## VirtualBoxをインストール

公式サイトからVirtualBox 7.0.10のWindows用インストーラーをダウンロードする。

https://www.virtualbox.org/wiki/Downloads

設定は特にデフォルトから変えずインストールできる。

途中で"**Missing Dependencies Python Core / win32api**"という警告が出るが無視してよさそう。


## Ubuntuをダウンロード

公式サイトからUbuntuのISOをダウンロードする。

https://ubuntu.com/download/server

Ubuntu DesktopとUbuntu Serverがあるが，GUIは不要なのでServerにした。
LTSである22.04.3を選ぶ。

オプションは
Option 1 - Manual server installation
でよさそう。(他のを選ぶと面倒そうな画面になった)


## VirtualBoxで仮想マシンを作成

VirtualBoxで「新規」を開きUbuntuのISOファイルを選ぶ。

メモリは4GBにした。(デフォルトは2GB)
CPUは1にした。
ストレージはデフォルトの25GBにした。

（ちなみに最初にストレージを2GBにしたら，Ubuntuのインストールで失敗した。要求スペックはちゃんと確認しよう）

必要な設定をしてポチポチすると仮想マシンが起動する。


## Ubuntuのインストール
仮想マシンが起動すると，Ubuntuのインストールメニューが表示される。

以下を設定した。

- 言語は**English**。（日本語は無いっぽい）
- JIS配列のキーボードを使っているのでキーボードレイアウトは**Japanese**。(US配列ならEnglish(US)。間違った設定を選んでパスワード設定するとひどい目に遭う)
- Storage configurationで**ボリュームを最大**にする。**ubuntu-lv**のSizeをMAXになるように設定してfree spaceの部分が無くなればOK。(忘れても後述の手順(※1)でリカバリーできる)
- サーバー名，ユーザー名，パスワードを設定。この設定をSSHの際に使用する。
- **Install OpenSSH server**にチェック。WindowsからSSHするのに必要となる。

これ以外の設定はデフォルトで差し支えない。(IPアドレスは後から設定できる)

インストールして画面内でRebootするとログインできるようになる。


## 仮想マシンのネットワークの設定1(NAT)

仮想マシンの設定でネットワークを開く。
アダプター1には最初から「NAT」が設定されている。
特にいじらなくてよい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2447309/962484a9-0527-4d74-7d5f-dd33047419c7.png)

これでゲストOSからインターネットへのアクセスは問題無く可能。


## 仮想マシンのネットワークの設定2(ホストオンリーアダプター)

WindowsからSSHしたいので，
アダプター2を有効化し，「ホストオンリーアダプター」を設定する。
(仮想マシンを落としておかないと設定変更できない)

これはホストOSとゲストOSの間だけで通信できるネットワークをとなる。
(他のホストからもアクセスしたい場合は「ブリッジアダプター」が選択肢となる)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2447309/d277c36e-e1e4-5457-f99c-d096a232a44e.png)

ホストアダプターにおけるWindowsのIPアドレスは，VirtualBox マネージャー>ツール>Networkで設定する。
デフォルトは192.168.56.1/24だったが私は10.0.1.1/24に変更した。

どのようなIPアドレスが適切かは環境に依るので，Windowsで`route print`してプライベートIPアドレスの範囲で空いてそうなネットワークセグメントを探そう。
192.168.56.0/24のIPアドレスが使われていない環境であればデフォルトで良い。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2447309/3d09795e-adae-40cf-1f62-08f120725f7c.png)

ちなみに不要なのでDHCPサーバーは無効にした。


## UbuntuでのIPアドレスの設定

UbuntuでIPアドレスを設定する。
VirtualBoxのどのアダプターがUbuntuのどのインターフェースに対応するかはMACアドレスで確認できる。

```bash:Ubuntu
ip a #現在設定されているインターフェース，MACアドレス，IPアドレスを確認
```

enp0s3: アダプター1(NAT) 10.0.2.15/24
enp0s8: アダプター2(ホストオンリーアダプター)
になっていた。

/etc/netplan/01-netcfg.yaml
を書くことでIPアドレスを設定できる。

```bash:Ubuntu
sudo vim /etc/netplan/01-netcfg.yaml #ファイルを編集してIPアドレスを設定する
```

UbuntuのIPアドレスは10.0.1.101/24とした。
(Windowsのホストオンリーアダプターと同じネットワークセグメントにしよう)

設定ファイルの書き方はGPT4に教わった。

```vim:01-netcfg.yaml
network:
  version: 2
  renderer: networkd
  ethernets:
    enp0s8:
      dhcp4: no
      addresses: [10.0.1.101/24]
```

以下のコマンドを実行すると設定が反映される。

```bash:Ubuntu
sudo netplan apply #設定を反映
```

IPアドレスが設定できた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2447309/fe46713c-8bf5-c2bb-065e-cf1c8510d74c.png)


## SSHクライアント
Windowsで使うSSHクライアントは何でもいいが，とりあえず`PowerShell`を使った。

https://learn.microsoft.com/ja-jp/powershell/scripting/install/installing-powershell-on-windows?view=powershell-7.3


## SSHする

Windowsから10.0.1.101宛にSSHができるようになる。

```Windows
PS C:\> ssh ryosuke@10.0.1.101
The authenticity of host '10.0.1.101 (10.0.1.101)' can't be established.
ECDSA key fingerprint is SHA256:MWKqldbCL5sXswvtqW/u1ww80G6ddjzClENA2bjECgQ.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.0.1.101' (ECDSA) to the list of known hosts.
ryosuke@10.0.1.101's password:
Welcome to Ubuntu 22.04.3 LTS (GNU/Linux 5.15.0-86-generic x86_64)
```

**これで目的は無事に果たされた！**

## おわりに
難なく仮想マシンが動かせる世界と先人達の知恵に感謝しかありません。

以降はトラブルシューティングの記録などを残します。


## ※1 ストレージ容量の修正

```bash:Ubuntu
df -h #ディスク容量を確認
```
したら容量が19GBしかないように見えた。
Storage configurationでSIZEを指定する操作を知らずに忘れたのがダメだったらしい。

以下で後から拡張できた。

```bash:Ubuntu
lsbulk #使い切れていないボリュームを確認
lvdisplay #マウントされているパスを確認 -> /dev/ubuntu-vg/ubuntu-lv だった
sudo lvextend -l +100%FREE /dev/ubuntu-vg/ubuntu-lv #論理ボリュームを拡張
df -T #Typeを確認 -> ext4だった
sudo resize2fs /dev/ubuntu-vg/ubuntu-lv #ext4でファイルシステムの容量を拡張するコマンド
```

無事に仮想マシンの容量30GBを全て使えるようになった。

## ※2 アダプター1(NAT)からSSHする方法
VPNを使っている環境ではホストオンリーアダプターが機能しない場合がある。

これは，VPNクライアントがルーティングを強制的に制限しているためである。
(社内ネットワークで好き勝手な通信をさせないための機能だろう)

その場合は設定を加えてアダプター1(NAT)で通信することができる。

仮想マシンにポートフォワーディング設定をする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2447309/069a46d6-6950-8a7e-1753-42cf74b4c159.png)

プロトコル: TCP
ホストポート: 2222
ゲストポート: 22

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2447309/bba014bf-fcdc-cc9b-a5b1-4c3191f63501.png)

設定を閉じると設定が反映される。(Windowsの警告が出たら許可をする)
これでWindowsからlocalhostの2222にアクセスするとUbuntuの22に通信できる。

```powershell:Windows
ssh -p 2222 ユーザー名@localhost
```

で無事にSSHできた。

他に使いたいポートがあったら都度設定が必要となる。

とても不便なので環境が許すなら「ホストオンリーアダプター」か「ブリッジアダプター」でIPアドレスを1つ割り当てる方が良い。

ちなみにWindowsが自動で使うポート番号はEphemeral Portsといい，デフォルトでは49152～65535になっている。
この範囲はアプリケーションが自動で使う可能性があるので避けた。


## ※3 VPN環境で起きた事象
VPN環境では「ホストオンリーアダプター」「ブリッジアダプター」を適切に設定しても通信ができなかった。

事象としては**WindowsかからゲストOSのIPアドレスにpingが通らない**というものになる。
(当然，SSHもできない)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2447309/d08e4571-5503-e249-4406-6bf4a6a3412e.png)

Windowsのルーティングテーブルを確認すると奇妙なことになっていた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2447309/b6e30764-fbae-f3dc-572b-44147ea9cd38.png)

Ubuntu宛のパケットがVPNの仮想アダプターのゲートウェイにルーティングされている。

Windows(10.0.1.1/24)とUbuntu(10.0.1.101)は同一のネットワークセグメントにいるので，ルーティングなど関係無しで通信できると思っていたが，VPNクライアントが許してくれないようだ。
(※4の手順でL2レベルの疎通ができていることを確認したが，VPNクライアントの機能はそれよりも強いらしい)

VPNを切ると問題なく通信できる場合はVPNが原因と言える。

(参考)

https://forums.virtualbox.org/viewtopic.php?t=69214

*Normal operation as the VPN is rejecting all other routes when active. You would need to set the VPN software up to allow for local routes to work.*


## ※4 ネットワークの確認観点
VPN環境でホストオンリーアダプターが機能しなかった時に色々と調べたので，確認観点を残しておく。

### WindowsのIPアドレスとMACアドレス
VirtualBoxでWindowsに設定したIPアドレスが反映されているかは`ipconfig`で確認できる。
また，`ipconfig -all`でWindows側のMACアドレスも確認することができる。

```:Windows
PS C:\> ipconfig

Windows IP 構成
(中略)
イーサネット アダプター イーサネット 3:
(中略)
   説明. . . . . . . . . . . . . . . . .: VirtualBox Host-Only Ethernet Adapter
   物理アドレス. . . . . . . . . . . . .: 0A-00-27-00-00-28
(中略)
   IPv4 アドレス . . . . . . . . . . . .: 10.0.1.1(優先)
   サブネット マスク . . . . . . . . . .: 255.255.255.0
(後略)
```


### 仮想マシンのMACアドレス
仮想マシンの設定ウインドウで仮想マシン側のMACアドレスを確認できる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2447309/3bafd9b7-f0c0-db46-7bfd-ac1674a0a5c7.png)


### UbuntuのMACアドレス
```bash:Ubuntu
ip a
```
でUbuntuが認識している仮想マシンのMACアドレスを確認できる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2447309/e63bb1c7-b226-7e67-f247-d5431f903870.png)


### Ubuntuが認識しているWindowsのMACアドレス
Ubuntuでarpをするためには以下のツールをインストールする。
```bash:Ubuntu
sudo apt install net-tools
```

通信を試みた後に`arp -a`でUbuntuが認識しているWindowsのMACアドレスが確認可能である。

```:Ubuntu
ryosuke@myubuntu:~$ arp -a
_gateway (10.0.2.2) at 52:54:00:12:35:02 [ether] on enp0s3
? (10.0.1.1) at 0a:00:27:00:00:28 [ether] on enp0s8
```


### Windowsが認識しているUbuntuのMACアドレス
WindowsからpingやSSHで通信を試みてから`arp -a`で確認できる。

```:Windows
PS C:\> arp -a
(中略)
インターフェイス: 10.0.1.1 --- 0x28
  インターネット アドレス 物理アドレス           種類
  10.0.1.101            08-00-27-82-f7-06     動的
  10.0.1.255            ff-ff-ff-ff-ff-ff     静的
  255.255.255.255       ff-ff-ff-ff-ff-ff     静的
```

## ※5 Windowsでのルーティング設定の追加
VPNの影響で通信できない問題はスタックオーバーフローにも投稿されていた。

https://ja.stackoverflow.com/questions/61867/vpn%E6%8E%A5%E7%B6%9A%E3%81%99%E3%82%8B%E3%81%A8virtualbox%E3%81%AEvm%E3%81%AB%E6%8E%A5%E7%B6%9A%E3%81%A7%E3%81%8D%E3%81%AA%E3%81%8F%E3%81%AA%E3%82%8B#comment67440_61867

この投稿では`route add`で解決したらしい。
(私の環境では解決しなかった)

`route add`では特定のIPアドレス宛のルーティングで送出するインターフェースを指定できる。
インターフェースのインデックス番号は`route print`で確認できる。