VLAN の中で IP Forwarding を設定する (Akamai）

Akamai クラウド・コンピューティング・サービス の Virtual LAN (VLAN) を使うと、プライベートネットワークを組むことができます。本記事は VLAN を設定した後に必要となるルーティング設定について記載します。VLAN については下記の記事を参照ください。

https://qiita.com/110hideki/items/aead6f2bc9ff1563641c


# IP Forwarding が有効なケース
VLAN を使うことで、DMZ に配置されたインスタンスの保護が強化されます。しかし、運用を開始すると、パッチを当てる必要があったり、[Longview](https://www.linode.com/ja/blog/linode/linode-longview/) や Datadog のような監視エージェントを入れたり、といった目的でVLAN内のインスタンスから外部に接続したいときがあります。


![VLAN NAT.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264188/fe2f1b05-85f8-21a0-1054-f1ab44c6e3c3.png)

そのようなときに、IP Forwarding を使ったルーティングの設定をすると運用が楽になります。手順としては大きく分けて２つのことを実施します。
1. パブリックインターネットに接続しているインスタンスで、 IP Fowarding の設定を行いルーターとして動作させる
3. DMZ に配置されたインスタンスで、ゲートウエイの設定を行い、ルーター経由でパブリックインターネットに接続できるようにする


![VLAN IP Forwarding.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264188/6a7c9af2-a79a-3973-5484-aa2116ebe35d.png)

# はじめに
この設定は VLAN のネットワークが組まれていることが前提ですので、まずは[先に紹介した記事](https://qiita.com/110hideki/items/aead6f2bc9ff1563641c)を参考に VLAN を設定してください。

参考となるドキュメントは以下になります。本記事は ``Ubuntu 22.10`` で実際に実行したときのノウハウになります。

:::note info
本番環境を想定するなら、Long term support である、22.04 LTS などにすることを推奨します。
:::

::: note warn
執筆時点では、Ubuntu 22.10 で Longview (監視ツール) のインストールスクリプトは動作しません。
:::

https://www.linode.com/docs/guides/linux-router-and-ip-forwarding/#define-the-gateway

シナリオは、先に紹介した記事と同様になります。インスタンスが２つあります。パブリック IP で公開するフロントサーバー (linode-ap-south-01-front) と VLAN でのみ動作する DMZ 内を想定したサーバー (linode-ap-south-02-dmz) です。今回、フロントサーバーにルーターの機能を設定します。VLAN の中では、ルーターとなるサーバーの IP は ``10.0.0.1``、DMZ に配置されているサーバーの IP は ``10.0.0.2`` を想定しています。

最初の疎通状況を確認します。VLAN の中で通信が出来ていることを確認します。
```
linode-ap-south-02-dmz # ping 10.0.0.1
PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.
64 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=0.480 ms
64 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=0.474 ms
64 bytes from 10.0.0.1: icmp_seq=3 ttl=64 time=0.495 ms
```
次に DMZ から外のネットワークに通信できるかを確認します。次のようなエラーがでます。DNS の設定が正しくない場合は次のようなエラーになるかと思います。
```
linode-ap-south-02-dmz # ping linode.com
ping: linode.com: Temporary failure in name resolution
```
DNS の設定が正しい場合でも、次のように疎通ができないことが確認できます。
```
linode-ap-south-02-dmz # ping linode.com
ping: connect: Network is unreachable
```

本記事では、最終的に疎通ができるようになるまでが目標です。

# ルーターの設定 (パブリックIPに配置されたインスタンス)

## IP Forwarding の設定
IPフォワーディングは、ルーターの基本的な機能です。ルーターがあるネットワークインターフェイスから別のネットワークインターフェイスにトラフィックを転送するための機能です。ルーターは、あるネットワーク上のコンピューターが別のネットワーク上のコンピューターに到達できるようにします。

多くの Linux では、IP フォワーディングは無効となっていますので、有効にする必要があります。具体的には``/etc/sysctl.conf`` のパラメータを変更します。

現在の設定を確認します。
```
sudo sysctl net.ipv4.ip_forward
```
次のように値が ``0`` の場合は設定が無効になっていることを意味します。
```
net.ipv4.ip_forward = 0
```

``/etc/sysctl.conf`` では次のように設定がコメントアウトされています。
```
# Uncomment the next line to enable packet forwarding for IPv4
#net.ipv4.ip_forward=1
```
この設定を次のようにコメントを取った行を作ります。
```
#net.ipv4.ip_forward=1
net.ipv4.ip_forward=1
```

同様に IPv6 の設定もありますので、次のようにコメントを外します。
```
# Uncomment the next line to enable packet forwarding for IPv6
#  Enabling this option disables Stateless Address Autoconfiguration
#  based on Router Advertisements for this host
#net.ipv6.conf.all.forwarding=1
net.ipv6.conf.all.forwarding=1
```
次にファイルの変更内容を有効化します。
```
sudo sysctl -p
```

この状態で再度設定を確認すると値が ``1`` になっていることを確認できます。
```
linode-ap-south-02-dmz # sudo sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1
```
```
linode-ap-south-02-dmz # sudo sysctl net.ipv6.conf.all.forwarding
net.ipv6.conf.all.forwarding = 1
```

## ルーティングの設定
同じくルーターとして動作する ``10.0.0.1`` のインスタンス側の作業となります。基本的なルーターとして機能するようにiptablesを設定します。iptablesユーティリティは、ファイアウォール（デフォルトのフィルターテーブルを使用）としても、ルーター（natテーブルを使用する場合など）としても機能します。

最初に現在の iptables を確認します。

```
iptables-save
```
何も出力されていなければ、設定がされていません。インスタンスを作成した直後は、何も表示されないと思いますが、もし出力された場合は慎重に設定内容を確認してください。今回は何も出力されなかったことを前提に進みます。

最初にポートフォワーディングを有効にします。
```
iptables -A FORWARD -j ACCEPT
```
次に、iptables で ``NAT``(ネットワークアドレス変換)を設定します。これは、ネットワークパケットのIPアドレスの詳細を変更し、VLAN上のすべてのシステムがルーターの同じパブリックIPアドレスを共有することを可能にします。今回の VLAN のサブネットは ``10.0.0.0/24`` なので、次の iptables ルールを追加します。
```
iptables -t nat -s 10.0.0.0/24 -A POSTROUTING -j MASQUERADE
```

最後に設定内容が反映されているかを確認します。
```
iptables-save
```
次のように設定が反映されたことが確認できます。
```
# Generated by iptables-save v1.8.7 on Wed Apr  5 06:28:40 2023
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A FORWARD -j ACCEPT
COMMIT
# Completed on Wed Apr  5 06:28:40 2023
# Generated by iptables-save v1.8.7 on Wed Apr  5 06:28:40 2023
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -s 10.0.0.0/24 -j MASQUERADE
-A POSTROUTING -j MASQUERADE
COMMIT
# Completed on Wed Apr  5 06:28:40 2023
```


# ゲートウェイの設定 (DMZに配置されたインスタンス)

次に実際にパブリック IP に通信したい DMZ の中のインスタンスの設定をします。次の設定を行います。
1. Network Helper を無効化する
2. インスタンスにログインする
3. プライベート VLAN インタフェースのコンフィグファイルを変更する
4. ネットワークインタフェースを再起動する

この手順だけでは正常に動作しなかったので、追加で以下の作業を行います。
5. ルーティングテーブルを更新する
6. DNS を解決する

実際には私の勘違いで 3. の設定の仕方を間違えたから、5. の作業が必要になったのですが、どのように修正したかについても参考までに記述します。

## Network Helper を無効化する
Akamai クラウド・コンピューティング・サービスのポータルである Cloud Manager にログインしてインスタンスに有効化されている Network Helper を無効化します。

Network Helperは、VM のネットワーク設定を容易にするオプションツールで標準では有効となっています。各システムの起動時に、ディストリビューションに適した内部ネットワーク設定ファイルを自動的に調整します。これにより、これらのファイルを手動で設定する必要がなく、すぐにインスタンスを使用開始できます。

Network Helper は便利な機能ですが、今回は手動でファイル設定をするので、無効にする必要があります。まずは、Cloud Manager にログインして、設定した VM インスタンスの Configuratrions から設定を行います。

![dmz-config.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264188/aef58f6d-39ad-f287-4c53-83f7e8d654fc.jpeg)

該当する Network Interfaces を編集します。
![dmz-config-edit.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264188/e6d44411-cb16-8d5e-dea3-b16fc5b2c5c9.jpeg)

編集ボタンを押すとページの下のほうに次のようなトグルがあります。
![dmz-auto-configure-network.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264188/f1207afa-1aeb-d8a1-5dff-70ae117f786d.jpeg)

Auto-configure networking が該当する設定になりますので、こちらをオフにします。
![dmz-auto-configure-network-disabled.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264188/636abfb6-89b0-419c-feaa-361e51e0ea61.jpeg)

これで Network Helper をオフにすることができました。

## プライベート VLAN インタフェースのコンフィグファイルを変更する

``/etc/network/interfaces`` ファイルに以下のように追記します。

```
iface eth0 inet static
    address 10.0.0.2/24
    gateway 10.0.0.1
```

``10.0.0.1`` がゲートウェイのアドレスで、ルーターとして設定したインスタンスの VLAN 内の IP アドレスになります。``10.0.0.2`` は自分自身のアドレスになります。

設定を有効化するには systemctl コマンドを利用します。
```
sudo systemctl restart systemd-networkd
```

## ネットワークインタフェースを再起動します
公式ドキュメントでは以下のコマンドを実行するように書かれています。
```
sudo ifdown eth0 && sudo ip addr flush eth0 && sudo ifup eth0
```
ssh 経由で別のサーバーからログインしている場合は、ssh のプロセスも切れてしまって、ゾンビの shell が動いてしまう可能性もあるので、一旦 ssh をログアウトして、Cloud Manager からインスタンスを再起動すると良いです。

ここで、``ping`` を実行すると動くはずです。
```
ping linode.com
```
動かない場合は、設定を見直す必要があります。実際自分の場合は設定を見直す必要がありました。

ルーティングテーブルを確認します。

```
linode-ap-south-02-dmz # ip route show
10.0.0.0/24 dev eth0 proto kernel scope link src 10.0.0.2
```
本来は、ゲートウェイ（ルーター）の設定が見えるはずですが見えていません。次の作業ではルーティングテーブルを修正します。

## ルーティングテーブルを更新する
ルーターの IP をデフォルトで設定するようにします。``10.0.0.1`` がルーターの IP アドレスになります。
```
sudo ip route add default via 10.0.0.1
```

ルーティングテーブルを再確認します。
```
linode-ap-south-02-dmz # ip route show
default via 10.0.0.1 dev eth0
10.0.0.0/24 dev eth0 proto kernel scope link src 10.0.0.2
```
ようやくルーターへのルーティングが登録されました。

``route`` コマンドでは次のように見えます。
```
linode-ap-south-02-dmz # route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         _gateway        0.0.0.0         UG    0      0        0 eth0
10.0.0.0        0.0.0.0         255.255.255.0   U     0      0        0 eth0
```

``ping``を実施して名前解決できない場合は、DNS の設定をする必要があります。
```
linode-ap-south-02-dmz # ping linode.com
ping: linode.com: Temporary failure in name resolution
```

## DNS を解決する
``/etc/systemd/resolved.conf`` を確認します。

```
[Resolve]
# Some examples of DNS servers which may be used for DNS= and FallbackDNS=:
# Google:     8.8.8.8#dns.google 8.8.4.4#dns.google 2001:4860:4860::8888#dns.google 2001:4860:4860::8844#dns.google
# Quad9:      9.9.9.9#dns.quad9.net 149.112.112.112#dns.quad9.net 2620:fe::fe#dns.quad9.net 2620:fe::9#dns.quad9.net
#DNS=
#FallbackDNS=
#Domains=
#DNSSEC=no
#DNSOverTLS=no
#MulticastDNS=no
#LLMNR=no
#Cache=no-negative
#CacheFromLocalhost=no
#DNSStubListener=yes
#DNSStubListenerExtra=
#ReadEtcHosts=yes
#ResolveUnicastSingleLabel=no
```

8.8.8.8 を DNS サーバーとして使う場合は次のように設定します。
```
DNS=8.8.8.8
```

最終的に ping で名前解決を確認しました。
```
linode-ap-south-02-dmz # ping linode.com
PING linode.com (72.14.191.202) 56(84) bytes of data.
64 bytes from www-loadbal3.linode.com (72.14.191.202): icmp_seq=1 ttl=48 time=193 ms
64 bytes from www-loadbal3.linode.com (72.14.191.202): icmp_seq=2 ttl=48 time=194 ms
64 bytes from www-loadbal3.linode.com (72.14.191.202): icmp_seq=3 ttl=48 time=194 ms
```

これで、apt で必要なモジュールもダウンロードできるようになりました。
```
linode-ap-south-02-dmz # apt install traceroute
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
traceroute is already the newest version (1:2.1.0-3).
0 upgraded, 0 newly installed, 0 to remove and 16 not upgraded.
```

# トラブルシューティング
手動でルーティングテーブルを修正して外部のネットワークに接続できましたが、毎回リブートする度に修正するのも手間になります。``/etc/network/interfaces``の設定が反映されていない原因を探ります。

```
# cat /etc/network/interfaces
# ifupdown has been replaced by netplan(5) on this system.  See
# /etc/netplan for current configuration.
# To re-enable ifupdown on this system, you can run:
#    sudo apt install ifupdown
iface eth0 inet static
    address 10.0.0.2/24
    gateway 10.0.0.1
```
``ipupdown`` が ``netplan`` にリプレースされたと記述があります。

```
# ls -l /etc/netplan
total 8
-rw-r--r-- 1 root root 275 Apr  6 10:40 01-netcfg.yaml
```

``01-netcfg.yaml`` に default のゲートウェイアドレスを記入します。
```
# cat 01-netcfg.yaml
# This file describes the network interfaces available on your system
# For more information, see netplan(5).
network:
  version: 2
  renderer: networkd
  ethernets:
    eth0:
      routes:
        - to: default
          via: 10.0.0.1
      addresses:
        - 10.0.0.2/24
```
設定を反映します。
```
netplan apply
```

設定は反映されているようですが、この設定では動作しませんでした。
```
# netplan get
network:
  version: 2
  renderer: networkd
  ethernets:
    eth0:
      addresses:
      - "10.0.0.2/24"
      routes:
      - to: "default"
        via: "10.0.0.1"
```
記述の``renderer: networkd`` は systemd-networkd を利用することを意味しています。実際のインスタンスの中でプロセスを見ると、 ``systemd-networkd`` デーモンが動いていることが分かります。
```
# ps aux| egrep network
systemd+    7794  0.0  0.3  17376  3256 ?        Ss   Apr06   0:00 /lib/systemd/systemd-networkd
```

``systemd-networkd`` のステータスを確認します。
```
# systemctl status systemd-networkd
● systemd-networkd.service - Network Configuration
     Loaded: loaded (/lib/systemd/system/systemd-networkd.service; enabled-runtime; preset: enabled)
     Active: active (running) since Wed 2023-04-05 06:59:51 UTC; 9s ago
TriggeredBy: ● systemd-networkd.socket
       Docs: man:systemd-networkd.service(8)
   Main PID: 1213 (systemd-network)
     Status: "Processing requests..."
      Tasks: 1 (limit: 1020)
     Memory: 1.4M
        CPU: 95ms
     CGroup: /system.slice/systemd-networkd.service
             └─1213 /lib/systemd/systemd-networkd

Apr 05 06:59:51 systemd[1]: Starting Network Configuration...
Apr 05 06:59:51 systemd-networkd[1213]: eth0: Link UP
Apr 05 06:59:51 systemd-networkd[1213]: eth0: Gained carrier
Apr 05 06:59:51 systemd-networkd[1213]: lo: Link UP
Apr 05 06:59:51 systemd-networkd[1213]: lo: Gained carrier
Apr 05 06:59:51 systemd-networkd[1213]: eth0: Gained IPv6LL
Apr 05 06:59:51 systemd-networkd[1213]: Enumeration completed
Apr 05 06:59:51 systemd[1]: Started Network Configuration.
Apr 05 06:59:51 systemd-networkd[1213]: eth0: found matching network '/etc/systemd/network/05-eth0.network', base>
Apr 05 06:59:51 systemd-networkd[1213]: eth0: Configuring with /etc/systemd/network/05-eth0.network.
```

``systemd-networkd`` は ``/etc/systemd/network/05-eth0.network`` を参照していることが分かりました。

```
# cat /etc/systemd/network/05-eth0.network
# Generated by Linode Network Helper
# Wed Apr  5 12:03:52 2023 UTC
#
# This file is automatically generated on each boot with your Linode's
# current network configuration. If you need to modify this file, please
# first disable the 'Auto-configure networking' setting within your Linode's
# configuration profile:
#  - https://cloud.linode.com/linodes/41868256/configurations
#
# For more information on Network Helper:
#  - https://www.linode.com/docs/guides/network-helper/
#
# A backup of the previous config is at /etc/systemd/network/.05-eth0.network.linode-last
# A backup of the original config is at /etc/systemd/network/.05-eth0.network.linode-orig
#
# /etc/systemd/network/05-eth0.network

[Match]
Name=eth0

[Network]
DHCP=no

Domains=members.linode.com
IPv6PrivacyExtensions=false

Address=10.0.0.2/24
Gateway=10.0.0.1
```
ファイルの最後に Gateway アドレスを登録しています。
```
Gateway=10.0.0.1
```

``systemd-netword`` をリスタートします。
```
sudo systemctl restart systemd-networkd
```
ルーティングテーブルに反映されました。リブート後も同様にゲートウェイが設定されることも確認しました。
```
# ip r
default via 10.0.0.1 dev eth0 proto static
10.0.0.0/24 dev eth0 proto kernel scope link src 10.0.0.2
```

公式ドキュメントには、それぞれの Linux ディストリビューションの設定ファイルが整理されています。

https://www.linode.com/docs/products/compute/compute-instances/guides/manual-network-configuration/

ドキュメントはちゃんと読みましょうという話でした。
![network-files.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264188/4528b23f-808c-02f1-c955-53376b83ccdf.jpeg)


# まとめ
VLAN を使うと、プライベートネットワークを組むことができます。今回のように IP フォワーディングや NAT の設定をすることで、運用も楽になるかと思います。必要に応じてルーティングテープルを有効にしたり無効にして運用してください。