VLANで区切られたネットワークにおけるサーバーの構築

# はじめに
この記事では、以下の要件を満たすシステムを構築します。

- WebサーバーAとクライアント、WebサーバーB、DNS (Domain Name System) サーバーが存在し、それぞれ異なるVLAN (Virtual Local-Area-Network) に属する
- クライアントからWebサーバーにアクセスし、Webサイトを表示できる
- クライアントからDNSサーバーに問い合わせて名前解決できる

すなわち、図「システム概要」に示すようなシステムを構築することが目的です。

システム概要
![topology_abstract.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3894442/965f9728-95e8-2cc4-67a7-252cf5ce371d.jpeg)


この記事では、システムを構築するにあたり、

- 作業前のシステムの状態
- 作業後のシステム構成
- システムが要件を満たすことの確認

について説明します。また、最初にVLANの概要を説明します。サーバー側では以下の作業が必要となりますが、この記事では扱いません。

- ホストとL2スイッチの接続
- ホスト側ネットワークインタフェースにIPアドレスの設定
- WebサーバーおよびDNSサーバーのアプリケーション導入

# VLAN
## 概要
VLANとは、OSI参照モデルにおける第2層、データリンク層において、論理的にネットワークを分割する技術です。通常、ネットワークの範囲はネットワークの物理的な構成により決定されます。すなわち、L2スイッチで相互に接続された範囲が1つのネットワークとなり、ルータによりネットワークは分割されます。VLANを用いることで、物理的な構成に依存せず、論理的にネットワークを分割することが可能です。

より正確には、L2スイッチで相互に接続された範囲を **ブロードキャストドメイン** と呼びます。これは、イーサネットにおけるブロードキャストフレームの到達する範囲が、L2スイッチで相互に接続されたネットワーク内であるためです。

VLANによりブロードキャストドメインを分割する例を示します。図「元のネットワーク」にVLANで分割する前のネットワークを、図「VLANによる分割」にVLANで分割したネットワークを示します。元のネットワークでは、クライアントC1, C2, サーバーS1, S2がそれぞれ相互に通信可能です。分割後のネットワークでは、VLAN 1に属するC1, S1間、VLAN 2に属するC2, S2間では通信可能です。一方、VLAN 1とVLAN 2の間では通信できず、ブロードキャストドメインが分割されています。

元のネットワーク
![VLAN_before.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3894442/a0898401-bb7e-6846-c41d-776039a995be.jpeg)

VLANによる分割
![VLAN_after.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3894442/cc16289f-beb4-3a2b-23fd-701d9d1ec440.jpeg)

VLANを用いることにより、物理的な構成にとらわれずネットワークを構成可能です。例えば、クライアントがオフィスに、サーバーがサーバールームにある場合でも、上図のように、C1とS1を同一ネットワークに、C2とS2をまた別のネットワークに含めることができます。

## VLAN間ルーティング
異なるVLAN間で通信する場合は、異なるネットワーク間で通信するときと同様、レイヤ3でルーティングする必要があります。図「VLAN間ルーティング」に示すように、VLANに重ねてサブネットを割り振り、そのサブネット間でルーティングを行います。

VLAN間ルーティング
![VLAN_routing.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3894442/be765503-2758-4534-c967-f5a6edfa6783.jpeg)

# 作業前の状態
図「作業前の状態」に、作業前の状態を示します。L2スイッチとL3スイッチが存在し、以下のように設定されています。実際には、今回のシステムはVMWare ESXi上の仮想環境に構築します。そのため、機器間のリンクや、スイッチのポートは仮想的です。また、L3スイッチはルータとして使用します。

- **L2スイッチ**: 3つのアクセスポートにそれぞれVLAN ID 20 - 22 が設定されている。L3スイッチとトランクリンクで接続されている
- **L3スイッチ**: L2スイッチと接続するインタフェースは、3つのサブインタフェースを持ち、それぞれID 20 - 22のVLANをカプセル化する。サブインタフェースにはIP (Internet Protocol) アドレスが設定され、それぞれ異なるサブネットに属する

作業前の状態
![topology_before.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3894442/4ce7bb5c-fc5d-0c25-3aca-fccaf4bbfed8.jpeg)

# ネットワーク構成
図「ネットワーク構成図」に、今回構成するシステムのネットワーク構成を示します。クライアントと各サーバーは、L2スイッチと接続するインタフェースに、構成図に従ったIPアドレスを設定します。またデフォルトゲートウェイとして各サブネットのルータのIPアドレスを、DNSサーバーに`192.168.22.1`を設定します。

ネットワーク構成図
![topology_anonymised.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3894442/cfa414f1-bf89-edd1-0326-e6a3b73e315b.jpeg)

このような、ネットワークにルータが1つの接続を持つ構成は、router on a stickといい、VLAN間のルーティングにしばしば用いられます。トランクポートに設定されたルータ側インタフェースに、リンクを通過するVLANそれぞれに対応するサブインタフェースを設定し、それらのサブインタフェースにIPアドレスとサブネットを設定します。VLAN間のルーティングは、これらのサブネット間のルーティングとして行われます。

# 構成の確認
構成したシステムが要件を満たしていることを、クライアントから確認します。digを用いてDNSサーバーに問い合わせることで名前解決を、curlを用いてHTTP (Hyper Text Transfer Protocol) リクエストをWebサーバーに送信することでWebサーバーへのアクセスを確認します。

DNSを用いた名前解決を確認するログを「名前解決の確認」に示します。192.168.22.1に3つのドメインを問い合わせ、そのIPアドレスがANSWERセクションに含まれていることから、DNSサーバーは正しく設定されています。

digはDNSサーバーに問い合わせるツールです。引数に名前解決したいドメインを与えます。`+noall +answer`オプションで回答のANSWERセクションのみを表示し、`@192.168.22.1`で問い合わせるサーバーーを指定しています。
``` :名前解決の確認
$ dig +noall +answer @192.168.22.1 www1.internal. www2.internal. ns.internal.
www1.internal.          28800   IN      A       192.168.20.1
www2.internal.        28800   IN      A       192.168.21.1
ns.internal.            28800   IN      A       192.168.22.1
```

Webサーバーの動作を確認するログを「Webサーバーの確認」に示します。curlでWebサーバーに送信したリクエストに対し、ステータス200番のレスポンスが返ってきていることから、Webサーバーは正しく設定されています。レスポンスボディは、ubuntu上のApache HTTP Serverのデフォルトページです。Webブラウザで表示した画像を「Webページの表示例」に示します。

curlはURL (Uniform Resource Locator) を用いてファイルの送受信を行うツールです。引数には通信したいURLを与えます。
`-s`, `--silent`オプションは、プログレスバーやエラーを表示しないようにします。
`-D`, `--dump-header`オプションは、通信プロトコルとしてHTTPかFTP (File Transfer Protocol) を用いるとき、レスポンスヘッダを引数で指定したファイルに出力します。ここでは、引数として`-`を与え、標準出力にヘッダを出力しています。
`-o`, `--output`オプションは、受信したデータ（のヘッダを除くペイロード）を、引数に指定したファイルに出力します。
``` :Webサーバーの確認
$ curl -sD - http://www1.internal -o index.html
HTTP/1.1 200 OK
Date: Wed, 25 Sep 2024 04:59:44 GMT
Server: Apache/2.4.52 (Ubuntu)
Last-Modified: Tue, 17 Sep 2024 02:11:37 GMT
ETag: "29af-62247359d4dd7"
Accept-Ranges: bytes
Content-Length: 10671
Vary: Accept-Encoding
Content-Type: text/html
```
Webページの表示例
![Webページの表示例](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3894442/e1103637-59ee-cfd4-fa29-bee0c95831b8.png)

## (補足) ポートフォワードによる内部サーバーへのアクセス
外部から各ホストへの接続はSSHのみだったため、Webページをブラウザで表示するにあたり、SSHのポートフォワードによりローカルのブラウザからWebサーバーにアクセスしました。すなわち 
`ssh -L 8080:www1.internal:80 -p PORT USER@EXT_IP_ADDR`
を実行し、ブラウザから `http://localhost:8080` にアクセスしました。ただし `PORT` はリモートホストでSSHが待ち受けるポート番号、 `USER` はユーザ名、 `EXT_IP_ADDR` はリモートホストのインターネット側IPアドレスです。

`-L port:host:hostport` はSSHでポートフォワードを行うオプションです。SSHで接続するリモートホストを経由して、`port` に指定したローカルポートを、`host` の `hostport` に指定したポートへ転送します。上述の例では、ローカルでの `localhost:8080` へのアクセスが、検証環境のクライアントを通して、`www1.internal:80` に転送されます。

```
[localhost]8080 == [SSH-remote] ==> 80[www1.internal]
```

# まとめ
この記事では、VLANで区切られたネットワークにおいて、WebサーバーやDNSサーバーが動作するシステムについて説明しました。router on a stickと呼ばれるネットワーク構成によりVLAN間のルーティングを実現しました。最後に、構成後のシステムに対し、digやcurlといったツールを用いて、実際にサーバの提供するサービスを利用することで、正しく設定されていることを確認しました。