Azure 仮想マシンを FW と Proxy にする検証環境を Azure CLI で作ってみた

## 背景と目的

顧客環境と同一のネットワーク構成をこちら側に構築して検証したい時がよくあります。厳密には顧客環境で使用しているオンプレの機器と同じものを用意する事は難しいですが、擬似的に Azure 仮想マシンをファイアウォールやプロキシサーバーとして用意して検証しています。それでは、下記のようなネットワーク構成で検証環境を Azure CLI で作成していきます。

![nat-vm.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675885/56fc7f6c-202c-5ea1-5616-54d46c41a41b.png)

## 検証用ネットワークを作成

```bash:bash
# 環境変数をセットします
region=japaneast
prefix=mnrdevnet

# リソースグループを作成します
az group create \
  --name ${prefix}-rg \
  --location $region

# 仮想ネットワークを作成します
az network vnet create \
  --name ${prefix}-vnet \
  --resource-group ${prefix}-rg \
  --address-prefix 10.0.0.0/24

# パブリックサブネット用の NSG を作成します
az network nsg create \
  --resource-group ${prefix}-rg \
  --name ${prefix}-public-nsg

# パブリックサブネットには自分の IP から SSH 接続できるようにします
az network nsg rule create \
  --resource-group ${prefix}-rg \
  --nsg-name ${prefix}-public-nsg \
  --name AllowSSH \
  --priority 100 \
  --source-address-prefixes $(curl -s inet-ip.info/ip) \
  --destination-port-ranges 22 \
  --direction Inbound \
  --access Allow \
  --protocol Tcp

# パブリックサブネットを作成します
az network vnet subnet create \
  --vnet-name ${prefix}-vnet \
  --resource-group ${prefix}-rg \
  --name public-subnet \
  --address-prefix 10.0.0.0/28 \
  --network-security-group ${prefix}-public-nsg

# プライベートサブネット用の NSG を作成します
az network nsg create \
  --resource-group ${prefix}-rg \
  --name ${prefix}-private-nsg

# プライベートサブネットを作成します
az network vnet subnet create \
  --vnet-name ${prefix}-vnet \
  --resource-group ${prefix}-rg \
  --name private-subnet \
  --address-prefix 10.0.0.16/28 \
  --network-security-group ${prefix}-private-nsg
```

## パブリック仮想マシンを作成

```bash:bash
# パブリック IP を作成します
az network public-ip create \
  --name ${prefix}-public-ip \
  --resource-group ${prefix}-rg \
  --allocation-method Static \
  --dns-name ${prefix}

# パブリック用の NIC を作成します
az network nic create \
  --name ${prefix}-public-nic \
  --resource-group ${prefix}-rg \
  --vnet-name ${prefix}-vnet \
  --subnet public-subnet \
  --private-ip-address 10.0.0.4 \
  --public-ip-address ${prefix}-public-ip

# プラウベート用の NIC を IP 転送オンで作成します
az network nic create \
  --name ${prefix}-private-nic \
  --resource-group ${prefix}-rg \
  --vnet-name ${prefix}-vnet \
  --subnet private-subnet \
  --ip-forwarding true \
  --private-ip-address 10.0.0.20

# 仮想マシンを作成します
az vm create \
  --resource-group ${prefix}-rg \
  --name ${prefix}-public \
  --os-disk-name ${prefix}-publicOSDisk \
  --image CentOS \
  --size Standard_B1s \
  --admin-username azureuser \
  --generate-ssh-keys \
  --nics ${prefix}-public-nic ${prefix}-private-nic \
  --storage-sku Standard_LRS
```

## ファイアウォールとプロキシの設定

```bash:bash
# 仮想マシンに SSH 接続します
ssh azureuser@${prefix}.$region.cloudapp.azure.com

# root になります
sudo su -

# Apache をインストールします
yum install -y httpd

# Proxy の設定を作成します
cat <<EOF > /etc/httpd/conf.d/fwproxy.conf
Listen 8080
<IfModule proxy_module>
  ProxyRequests On
  ProxyVia      On
  ProxyTimeout  300

  CustomLog logs/proxy_log combined

  <Proxy *>
    Order deny,allow
    Deny  from all
    Allow from 127.0.0.1
    Allow from 10.0.0.0/24
  </Proxy>
</IfModule>
EOF

# Apache を起動します
systemctl start httpd

# Apache を自動起動設定します
systemctl enable httpd

# Apache のステータスを確認します
systemctl status httpd

# Proxy なしで PIP を確認します
curl https://inet-ip.info

# Proxy 経由のアクセスを確認します
curl -x 127.0.0.1:8080 https://inet-ip.info
curl -x 10.0.0.4:8080 https://inet-ip.info
curl -x 10.0.0.20:8080 https://inet-ip.info

# アクセスログを確認します
tail /var/log/httpd/proxy_log

# FW を起動します
systemctl start firewalld

# Apache を自動起動設定します
systemctl enable firewalld

# Apache のステータスを確認します
systemctl status firewalld

# デフォルトゾーンを external にします
firewall-cmd --set-default-zone=external

# デフォルトゾーンを確認します
firewall-cmd --get-default-zone

# Proxy のポートを許可します
firewall-cmd --zone=external --add-port=8080/tcp

# FW 設定を繁栄します
firewall-cmd --reload

# IP 転送が有効 1 になっているか確認します
cat /proc/sys/net/ipv4/ip_forward

# root から抜けます
exit

# 仮想マシンから抜けます
exit
```

## ルートテーブルを作成

```bash:bash
# ルートテーブルを作成します
az network route-table create \
  --name ${prefix}-private-rt \
  --resource-group ${prefix}-rg \
  --disable-bgp-route-propagation true

# ルートテーブルにルートを作成します
az network route-table route create \
  --route-table-name ${prefix}-private-rt \
  --resource-group ${prefix}-rg \
  --name private-route \
  --address-prefix 0.0.0.0/0 \
  --next-hop-type VirtualAppliance \
  --next-hop-ip-address 10.0.0.20

# ルートテーブルをプライベートサブネットにアタッチします
az network vnet subnet update \
  --resource-group ${prefix}-rg \
  --name private-subnet \
  --vnet-name ${prefix}-vnet \
  --route-table ${prefix}-private-rt
```

## プライベート仮想マシンを作成

```bash:bash
# プライベート仮想マシンを作成します
az vm create \
  --resource-group ${prefix}-rg \
  --name ${prefix}-private \
  --os-disk-name ${prefix}-privateOSDisk \
  --image CentOS \
  --size Standard_B1s \
  --admin-username azureuser \
  --generate-ssh-keys \
  --vnet-name ${prefix}-vnet \
  --subnet private-subnet \
  --nsg "" \
  --public-ip-address "" \
  --storage-sku Standard_LRS

# プライベート仮想マシンに接続するための SSH キーを転送します
scp ~/.ssh/id_rsa azureuser@${prefix}.$region.cloudapp.azure.com:.ssh/
```

## ファイアウォールとプロキシを検証

```bash:bash
# 仮想マシンに SSH 接続します
ssh azureuser@${prefix}.$region.cloudapp.azure.com

# ファイアウォールを検証
ssh 10.0.0.21 "curl -s https://inet-ip.info"

# プロキシを検証
ssh 10.0.0.21 "curl -s -x 10.0.0.20:8080 https://inet-ip.info"
```

## 後片付け

```bash:bash
# 仮想マシンから抜けます
exit

# SSH の known_hosts から削除します
ssh-keygen -R ${prefix}.$region.cloudapp.azure.com

# リソースグループを削除します
az group delete \
  --name ${prefix}-rg \
  --yes
```