初回VCN作成をサクッとできるOracle Cloud Infrastructure Virtual Networking Quickstart & 仮想ファイアウォール設定の理解

# TL;DR

* [Oracle Cloud Free Tier（Always Free）](https://www.oracle.com/jp/cloud/free/)がリリースされて利用者が増えた
* Oracle Cloud Infrastructureのネットワーク設定は最初のハードル
* [Virtual networking quickstart](https://docs.cloud.oracle.com/iaas/releasenotes/changes/3856e7e4-7862-4dfe-9262-f2ca6ed26f0e/)が2019/12/4にリリースされてネットワークの設定が簡単になった
* それでも仮想ファイアウォール（セキュリティ・ルール）の設定を理解するのは少し大変
 
# 動作環境

* Oracle Cloud Infrastructure Compute
* Oracle Linux 7 / CentOS 7 で検証しているが何でもよい

# 1. Virtual Networking Quickstartとは

[Oracle Cloud Free Tier（Always Free）](https://www.oracle.com/jp/cloud/free/)がリリースされてから、Oracle Cloud Infrastructureを使う人が多くなったようだ。

はじめのハマりどころは、次の二つではないだろうか。

* **<font color="red">確認用コードの送信先電話番号（先頭のゼロを取る必要あり）</font>**
* **<font color="red">ネットワークの設定（特にセキュリティ・ルールとルートテーブル）</font>**

電話番号の件は海外電話の常識と考えればいいとしても（とはいえ先頭のゼロを取れというインストラクションくらいあってもいい）、ネットワークは奥が深い。

そんなこともあり2019/12/4に新機能[Virtual networking quickstart](https://docs.cloud.oracle.com/iaas/releasenotes/changes/3856e7e4-7862-4dfe-9262-f2ca6ed26f0e/)がリリースされた。この機能を利用するとウィザード形式で簡単に初期ネットワークを作成できる。

「簡単」と言いつつも、いくつか注意事項があるので説明する。

# 2. Virtual Networking Quickstartでネットワークを作成する

[Virtual Networking Quickstart](https://docs.cloud.oracle.com/iaas/Content/Network/Tasks/quickstartnetworking.htm)では、次の2種類のネットワークを作成できる。通常利用するのは「VCN with Internet Connectivity」だ。

* <font color="blue">VCN with Internet Connectivity</font>
* <font color="blue">VCN with VPN Connect and Internet Connectivity</font>

VCN with Internet Connectivityを使うと、下図のように二つのサブネットと各ゲートウェイを作成できる。実際の手順を説明する。
![nwquick02.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266049/4ec4d341-4e1e-b2e8-b9d9-844882f64a66.png)

1. 管理コンソールにログインして、表示言語を英語に変更する。日本語表示のまま作成すると、サブネット名が**「パブリック・サブネット-＜VCN名＞」**のようになりかっこ悪い。

![nwquick00.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266049/29847dae-a964-cbc7-d6a3-4e8f07c58208.png)

2.Quick Startページにアクセスするには次の2つの方法がある。

* トップページの「Quick Actions」から「Set up a networking a wizard」をクリックする
* ナビゲーション・メニューで「Networking」-「Virtual Cloud Networks」を選択し、「Start VCN Wizard」をクリックする

![nwquick00-1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266049/dd5cea41-fd44-7c30-6141-fa6f1015c6b7.png)

3.「Start Workflow」をクリックする。
![nwquick00-2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266049/4e476e5b-129c-6794-fe4e-2ea1c88d161c.png)

4.VCN名と各CIDRブロックを入力する。<font color="red">なお、事前にコンパートメント作成を推奨。</font>
![nwquick01.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266049/941220af-7d49-04f9-ab0c-d72a2a357422.png)
**VCN NAME：**：VCNの名前
**COMPARTMENT：**作成先のコンパートメント

**VCN CIDR：**VCNのCIDR。あとで変更できないので/16などが推奨
**PUBLIC SUBNET CIDR：**パブリック・サブネット用のCIDRを指定する。DMZと考えてもよい。VCNのCIDR内の範囲を指定
**PRIVATE SUBNET CIDR：**プライベート・サブネット用のCIDRを指定する。パブリック・サブネットとかぶらない範囲を指定

5.「Next」をクリックすると、作成するオブジェクトの一覧が表示される。問題が無かったら「Create」をクリックして作成する。
![nwquick03-1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266049/016ac192-80f8-a943-64f9-8eb92fafdcae.png)

6.作成が完了すると、パブリックとプライベートの二つのサブネットが作成される。次にセキュリティ・リストをカスタマイズしよう。


# 3. 作成したネットワークをカスタマイズする

QuickStartで作成したネットワークでは、ssh接続やインターネットへのアウトバウンド接続など基本的な通信はできる。ただしWebサーバーやDBサーバーを使用するには、追加作業が必要だ。

作成したネットワークを確認しながら、必要な設定を追加してみよう。

### 3-1. 作成したネットワークを確認する

下図のように二つのサブネットと、それぞれに関連付けたセキュリティ・リストが作成されている。

**作成されたサブネット**

* Public Subnet-＜VCN名＞
* Private Subnet-＜VCN名＞

**作成されたセキュリティ・リスト**

* Default Security List for ＜VCN名＞：パブリック・サブネットに関連付け
* Security List for Private Subnet-＜VCN名＞：プライベート・サブネットに関連付け

![nwquick03.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266049/f1d4597a-4001-bbe9-a68a-21c3e9283813.png)
複数のルールが定義されているなかで、重要なのは以下の設定だ。
**パブリック・サブネット**
・インターネットを含むすべてのネットワークからssh接続できる（Ingress）

**プライベート・サブネット**
・VCN内からssh接続できる（Ingress）

### 3-2. セキュリティ・ルールをカスタマイズする（基本）

以下のようなネットワークを想定してセキュリティ・ルールをカスタマイズする。追加要件は以下のとおり。

* VCN内のpingを有効にする
* 踏み台サーバーはインターネットからの80/443を許可する
* DBサーバーはパブリック・サブネットから1521を許可する

![nwquick05.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266049/0f7022f1-1313-83be-bafd-41d84184f1a7.png)
追加するルールは以下のとおり。いずれもIngressルールだ。
**Default Security List for ＜VCN名＞**

| Source | Protocol | Type/Dest Port |
|:-:|:-:|:-:|
| 0.0.0.0.0/0 | TCP | 80 |
| 0.0.0.0.0/0 | TCP | 443 |
| 192.168.0.0/16  | ICMP  | 8 |

**Security List for Private Subnet-＜VCN名＞**

| Source | Protocol | Type/Dest Port |
|:-:|:-:|:-:|
| 192.168.0.0/24 | TCP | 1521 |
| 192.168.0.0/16  | ICMP  | 8 |

この設定が終わればクラウドレイヤの設定は終わりだ。次にOSのファイアウォール設定を変更する。

### 3-3. OSのファイアウォールを設定する

Oracle Cloud Infrastructure Compute/DatabaseではOS上のファイアウォール（firewalld/iptables）がデフォルトで有効化されている。無効化してもよいが、Oracle Cloud Infrastructureではdenyルールを記述できないため、トレーニングのためにfirewalldを使ってみよう。

踏み台サーバーとDBサーバーのそれぞれでファイアウォール設定を追加する。

* [An Introduction to Firewalld](https://www.liquidweb.com/kb/an-introduction-to-firewalld/)
* [RHEL:セキュリティガイド（FIREWALLD の現在のステータスおよび設定の表示）](https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html/security_guide/sec-viewing_current_status_and_settings_of_firewalld#sec-Viewing_Current_firewalld_Settings)
* [最低限firewalldを操作するためのチートシート](https://qiita.com/usagisystem/items/c5d05ca24fa1388ff412)


```shell-session:参考：firewalldを停止＆無効化する
systemctl disable firewalld -now
```

#### 3-3-1. 踏み台サーバー

踏み台サーバーでファイアウォールを設定する。

1.デフォルトではsshとDHCPクライアントだけが有効になっている。

```shell-session
# firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: ens3
  sources:
  services: dhcpv6-client ssh
  ports:
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:
```

2.ポート80と443を開ける。ポート番号も指定できるが、よく使用するポートは`/usr/lib/firewalld/services`配下の定義ファイルも利用できる。

```shell-session
firewall-cmd --add-service=http --permanent --zone=public
firewall-cmd --add-service=https --permanent --zone=public
```

3.リロードして有効化する。

```shell-session
firewall-cmd --reload
```

4.設定を確認すると、http（80）とhttps（443）が有効になっている。

```shell-session
# firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: ens3
  sources:
  services: dhcpv6-client http https ssh ★追加されている
  ports:
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:
```

#### 3-3-2. DBサーバー

次にDBサーバーで実行する。

1.Oracle Net用のポート1521を開ける。

```shell-session
firewall-cmd --add-port=1521/tcp --permanent --zone=public
```

2.リロードして有効化する。

```shell-session
firewall-cmd --reload
```

3.設定を確認すると、1521が有効になっている。

```shell-session
# firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: ens3
  sources:
  services: dhcpv6-client ssh
  ports: 1521/tcp ★追加されている
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:
```

### 3-4. 疎通確認する

WebサーバやDBサーバーが起動していれば、すぐに疎通確認できる。しかし、構築前だと確認できない。そんなときに便利なのがncコマンドだ。接続先サーバーとポートを指定して、疎通の可否を確認できる。

ncコマンドは問題の切り分けにも使えるので、ぜひインストールしておきたいところ。

* [ネットワーク診断の現場から（netcat編・その1）](http://www.intellilink.co.jp/article/column/security-net01.html)

1. 踏み台サーバーにncをインストールする。

```shell-session
yum install nc -y
```

2.踏み台サーバーからDBサーバーにncコマンドで疎通確認する。`-z`オプションはゼロI/Oモードで、サーバープログラムに接続しないで接続ステータスだけを確認できる。

Syntax：`nc 接続先ホストのIPアドレス ポート番号 -z`

```shell-session
# nc 192.168.1.2 1521 -z
# ★すぐにプロンプトが表示されたときは疎通に成功している。
```

3.試しに1520で実行すると、ポートが閉じているのでプロンプトが戻ってこない。

```shell-session
# nc 192.168.1.2 1520 -z
★疎通できないときはプロンプトが戻ってこない。
```

### 3-5. セキュリティ・ルールをカスタマイズする（ホワイトリスト）

これまでの設定ではインターネットのどこからでも**「踏み台兼Webサーバー」**に接続できた。接続元を、社内ネットワークや自宅だけに制限したいときにはホワイトリストで実現できる。

インターネットにはNAT経由で接続することがほとんどなので、NATで使用するパブリックIPをホワイトリストとして指定する。社内ネットワークの場合、ネットワーク部門に聞くのがいいだろう。また以下のサイトでも簡単に現在のパブリックIPを確認できる。

https://www.whatismyip.com/
https://www.cman.jp/network/support/go_access.cgi
![nwquick06.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266049/11d71368-f2ec-b1b1-79c7-ecc62fc3ac61.png)

自宅の場合、契約プランにもよるが固定のグローバルIPを持っていないことがほとんどだ。プロバイダが公開していない場合、こまめに追加するのがいいだろう。

変更箇所は以下のとおり。変更しないところは省略している。
**Default Security List for ＜VCN名＞**
<font color="blue">変更前</font>

| Source | Protocol | Type/Dest Port |
|:-:|:-:|:-:|
| 0.0.0.0.0/0 | TCP | 22 |
| 0.0.0.0.0/0 | TCP | 80 |
| 0.0.0.0.0/0 | TCP | 443 |

<font color="blue">変更後</font>
単一のIPアドレスを指定するときは/32、複数のアドレスを指定するときはCIDRブロックも指定できる。

| Source | Protocol | Type/Dest Port |
|:-:|:-:|:-:|
| NATしているパブリックIP/32 or CIDRブロック | TCP | 22 |
| NATしているパブリックIP/32 or CIDRブロック | TCP | 80 |
| NATしているパブリックIP/32 or CIDRブロック | TCP | 443 |

**<font color="blue">ヒント：OCIからのアクセスをホワイトリストに設定するには</font>**

「他のOCIテナント」や「相互接続していないVCN」からインターネット経由（パブリックIP利用）のアクセスを許可したいことがある。単一のIPアドレスだけなら「パブリックIP/32」で使用すればよい。

しかし、ざっくりと「OCIの東京リージョンからはOK」のような場合は、Oracle社が公開しているリージョンごとのパブリックIPレンジを利用できる。定期的に追加されるので注意すること。

* [IP Address Ranges](https://docs.cloud.oracle.com/iaas/Content/General/Concepts/addressranges.htm)

### 3-6. セキュリティ・ルールをカスタマイズする（同一サブネット内）

OCIのネットワークで戸惑うのがオンプレミスとの違いである。オンプレミスの場合、同一サブネット内の通信はfirewalld等で拒否しない限り、すべて疎通できる。

ところがOCIでは同じサブネットに属していても明示的に許可しない限り疎通できない。理由は、セキュリティ・ルールはインスタンス単位で評価するからだ。

例えば下図のように開発サーバー（DEV）を追加しても、DBサーバーとは1521ポートで疎通できない。
![nwquick07.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266049/cadad887-6197-5450-0c50-65172a5e1abb.png)

疎通するにはプライベート・サブネットのセキュリティ・ルールに以下のルールを追加する必要がある。

| Source | Protocol | Type/Dest Port |
|:-:|:-:|:-:|
| 192.168.1.0/24 | TCP | 1521 |

もしくは以下のように、サブネット内はすべての通信を許可してもいいだろう。

| Source | Protocol | Type/Dest Port |
|:-:|:-:|:-:|
| 192.168.1.0/24 | all | all |


# 4. おわりに

これまでQuickstartで作成されたセキュリティ・ルールをカスタマイズしてきた。しかしセキュリティ・ルールの設定方法は以下の二通りの方法がある。

* セキュリティ・リスト
* ネットワーク・セキュリティ・グループ（NSG）

両者の詳細はマニュアルを読んでもらうとして、前者がサブネットにヒモ付けるのに対し、後者はインスタンスのVNICにヒモ付ける。Quickstartではセキュリティ・リストを使用しているが、今後本格的に使用するならネットワーク・セキュリティ・グループが推奨である。

またインスタンスには複数のセキュリティ・リスト／ネットワーク・セキュリティ・グループを関連付けできる（最大5個）。これらの機能を理解し、うまく活用することで設定の効率化も考えたほうがいいだろう。

また今回はまったく説明していないがルートテーブルも重要だ。マニュアルを読んで、それぞれ理解を深めて欲しい。

参考：

* [OCIマニュアル：セキュリティ・ルール](https://docs.oracle.com/cd/E97706_01/Content/Network/Concepts/securityrules.htm)
* [OCIマニュアル：ルートテーブル](https://docs.oracle.com/cd/E97706_01/Content/Network/Tasks/managingroutetables.htm)
* [OCI Manual: Security Rules](https://docs.cloud.oracle.com/iaas/Content/Network/Concepts/securityrules.htm)
* [OCI Manual: Route Tables](https://docs.cloud.oracle.com/iaas/Content/Network/Tasks/managingroutetables.htm)