BIG-IPで送信元IPに基づいてアクセスするVirtual Serverを分ける

#はじめに
この記事は、DevCentralの次の記事に触発されて書いたものです。

[DevCentral: The Power of Source Address](https://devcentral.f5.com/articles/https-devcentralf5com-articles-the-power-of-source-address-29315-29315)

記事を読んで「これならこういうことができそうだ」という想像と、軽い検証程度で作成しました。実際の使用（商用利用）経験に基づく情報ではありませんのでご注意ください。

## 環境
この記事で紹介する設定は、BIG-IP v12.1.2で動作を確認してます。

#本題
## Source Address設定について
BIG-IPのVirtual Serverの設定にある**Source Address**という設定。

<img width="620" alt="Virtual_Server_Souce_Address.png" src="https://qiita-image-store.s3.amazonaws.com/0/157891/22c20498-ed7a-50dd-8d78-7720a0c6bc8d.png">


いつの頃からか（v11.3かららしいです）BIG-IPのVirtual Serverの設定画面に、このような欄が追加されてました。Virtual Serverに対する簡易ACLのようなものかと思っていましたが、どうやらもっと便利な機能でした。

----

BIG-IPに求められるよくある機能として「**ひとつのVirtual Server(Virtual Address)に対して、特定の送信元からの通信の場合と、それ以外の場合で振る舞いを切り替えてほしい**」というものがあります。

例えば「192.168.0.0/25からのアクセスはPool_Internalに、それ以外からのアクセスは、Pool_Publicに振り分ける」という要件があるとします。

これを実装するには、多くの場合、次のようなiRuleを使います。

```text
when CLIENT_ACCEPTED {
    if {[IP::addr [IP::client_addr] equals 192.168.0.0/255.255.255.0 ]} {
        pool Pool_Internal
    }
    else {
        pool Pool_Public
    }
}

```

このようなiRuleを一つのVirtual Serverに適用することで、送信元アドレスに基づいて宛先Poolを切り替えます。

しかし、Source Address設定を使うことで、Virtual Address, Portの重複する、複数の異なるVirtual Serverを設定することができるようになりました。つまり、次のような設定が可能になりました。

![souce_address_pic1.png](https://qiita-image-store.s3.amazonaws.com/0/157891/433d8bb1-3224-f559-3206-b9a11cdd174d.png)

このイメージを機器の設定で表すと次のようになります。（説明と関係ない部分は適当です。）

```text
ltm virtual vs_internal {
    destination 203.0.113.1:http
    ip-protocol tcp
    mask 255.255.255.255
    pool Pool_Internal
    profiles {
        http { }
        tcp { }
    }
    source 192.168.0.0/24
    translate-address enabled
    translate-port enabled
    vs-index 21
}
ltm virtual vs_public {
    destination 203.0.113.1:http
    ip-protocol tcp
    mask 255.255.255.255
    pool Pool_Public
    profiles {
        http { }
        tcp { }
    }
    source 0.0.0.0/0
    translate-address enabled
    translate-port enabled
    vs-index 22
}

```

Virtual Serverの受付となる**destination**の設定が、重複していることがわかります。これで送信元IPアドレスに基づき、受けつけるVirtual Serverを変更するができます。

### Virtual Serverの決定について
**Destination（宛先IP:Port）設定の値が同一で、Souce Address設定の値が異なるの複数のVirtual Serverへのアクセスは、アクセス時の送信元IPアドレスに基づいて選択されます。この際の決定は、送信元IPアドレスに対するロンゲストマッチで行われます**。したがって、上記に加えて「192.168.0.100/32からのアクセスは、また別のVirtual Serverへのアクセスにする」といったことも可能です。

もし、BIG-IPで**VLAN and Tunnel Traffic** (vlans-enabled)設定を使われたことがあるならば、Source Address設定は、よく似ているとすぐわかります。VLAN and Tunnel Traffic設定は、どのVLANやTunnelからの通信かに基づいて通信を処理するVirtual Serverを決定します。有効とするVLANやTunnelが異なれば、同一の宛先のVirtaul Serverを複数作成できます。Source Address設定は、そのL3版と言えると思います。

## 本機能のメリット・デメリット

### メリット
iRuleで実装する場合と比べて、Virtual Serverレベルで分割できるので、Pool以外の要素（例えばprofileやirule）を、送信元IP毎に個別に指定することが可能です。

例えば「特定のIPアドレスからの通信は開発用のVirtual Serverへ、また別の特定IPアドレスからの通信はステージング用のVirtual Serverへ、それ以外はプロダクション用Virtual Serverへ」など、同じアドレスへの通信を行いながら、実際のサーバへのアクセスを切り替えることができます。そして、Virtual Serverに紐づける様々な設定、例えばiRuleやProfileなども分割させることができるため、開発用Virtual Serverに適用するiRuleについては、多くのデバッグログを出力させる、といった利用が可能です。

![souce_address_pic2.png](https://qiita-image-store.s3.amazonaws.com/0/157891/e11b982a-43bc-0578-f67b-22dde7b55e4d.png)


### デメリット
1つのVirtual Serverにおいて、Source Addressは一つのネットワークアドレスしか指定できないので、上記の絵の「特定の送信元」が、複数の異なるネットワークアドレスとなる場合、その数だけVirtual Serverを作らないといけないため、常に有効な方法とは言えません。

# 補足事項
 - 文頭で紹介したDevCentralの記事では、Source Addressの機能を使うことで、既存のSNAT（global SNATと記載されてます。SNAT Listのことだと思います）を代替する使い方について述べられています。CGNで使われてるそうです。興味のある方は、是非参照してください。