1. はじめに
前回、IBM Cloud: VPCで透過的ファイアーウォールを作る方法(1)という記事で、透過的ファイアーウォールの構成を示したが、この構成には色々と不満がある。最大の不満はVNFがシングル構成であることだ。これでは、VNF障害の時に通信が止まってしまう。
Custom RouteのDestinationとして複数のVNFのIPアドレスを指定することはできるが、その場合はECMPでアクセスされてしまうので、仮に一方のVNFに障害が発生していても割り振り続けてしまう。
以下は、IBM Cloud docsからの引用。
The implicit router performs equal-cost multi-path (ECMP) routing (multiple routes with the same destination, but different next hop addresses) with the following limitations:
- This only applies to routes with an action of deliver.
- Only two identical destination routes are permitted per zone, and each must have different next hop addresses.
- When ECMP is used, the return path might not take the same path.
というので、VNFに割り振る際には、ヘルスチェックをして正常なVNFにだけそのままパケットを転送する機能が必要となるのだが、それを解決するのがNLBのroute modeだ。これにより、通常のNLBのようなIPアドレス変換が実施されることなく、透過的ファイアーウォールをHA構成で実現できる。
NLB(デフォルト) | NLB route mode | |
---|---|---|
DNAT | 実施される (バックエンドサーバーからの戻りにおいては、HypervisorでNLBのIPアドレスを付与することでDirect Server Returnを実現する) | 実施されない(単にVNFにパケットをアドレス変換なしにそのままフォワードする。) |
利用できるプロトコル | TCP/UDP | TCP/UDP(NLB route modeでもICMPはサポートされてない) |
Public or Private | PublicとPrivateを両方サポート | Privateのみサポート |
Listenするポート番号 | - 複数のListenerを作成することで、複数のポートを指定可能。 - Publicの時は1つのListnerでポート番号をrange(最小値/最大値)で指定可能。 |
1つのNLBに対してListnerは1つしか作成できず、1-65535 というrangeのみが選択可能。 |
バックエンドプールに登録するサーバー | ターゲットサーバー。 | 典型的にはVNF(VNFでセキュリティーチェックなどを実施した後に、VNFからターゲットサーバーに転送されるような構成にすることが多い)。 |
配置上の制約 | - - primary intefaceにしか割り振れない。 |
- バックエンドサーバーはNLBと同一Subnetに存在する必要がある。 - 必ずCustom Routeと組み合わせて利用する。 - primary intefaceにしか割り振れない。 |
HA構成 | 単一のIPアドレスが利用可能であり、メンテナンスによってそのIPアドレスが変更されることはない。そのため、アプリケーションではそのIPアドレスを固定して使い続けることが可能である。 | Active/StandbyのそれぞれのIPアドレスが割り当てられているが、Custom Routeではnext hopとして現在Activeである方のIPアドレスを指定しておけばよい。NLBにメンテナンスが発生した場合は、ActiveであるIPアドレスがnext hopになるように自分のVPC内部にあるRoute tableが自動的に更新される。 (元々Custom routeのnext hopではホスト名を指定できないが、逆に言えばこの挙動のためにnext hopでホスト名を指定する必要もない。) |
参考docs
https://cloud.ibm.com/docs/vpc?topic=vpc-nlb-vnf&interface=ui
https://cloud.ibm.com/docs/vpc?topic=vpc-nlb-limitations&interface=ui
これにより、以下のような構成が可能になる。custom routeにおけるdestinationではNLB(route mode)を指定する。
2. route modeのNLBの作成と構成。
2-1. route modeのNLBの注文
NLBの注文画面
- NLBの選択
- type/routing mode/subnetの選択
- Direct Link経由でアクセスするので、TypeはPrivateを選択する(というか、Privateでないと
route mode
は選択できない)。 -
routing mode
を有効化 - VNFと同じsubnetを選択
- Direct Link経由でアクセスするので、TypeはPrivateを選択する(というか、Privateでないと
- BackendPoolの構成
- ヘルスチェックのポート番号は空にしているとメンバーポートでヘルスチェックされてしまうため、今回はSSHポートでヘルスチェックするように22番を指定した(本来はVNFが提供するサービスに対してヘルスチェックした方が良いが、今回VNFとして見立てているサーバーは単にパケット転送を実施するLinuxサーバーにしか過ぎないので、他にヘルスチェックをさせるべきサービスが存在していません)。
- Session StickinessはNoを選択する(本稿執筆時点では、有効化すると動かないというバグがありました)
- BackendServer(VNF)の追加。
- vnfを2台追加する。
- ポート番号はここでは80としているが何でも良い(ヘルスチェックには、BackendPoolで設定したHeatlch Checkポートが使われるので。もしそこでHealth Checkポートを定義していないのであれば、このポート番号がヘルスチェックに使われる。)
- FrontEnd Listnerの構成
作成されると、以下のようにType=Private(Routing)
と表示される。
2-2. route modeのNLBの確認
NLBのIPアドレスを控えておく(NLBのIPアドレスは変更されない)
$ dig +short xxxxxxxx-jp-tok.lb.appdomain.cloud
172.16.0.13
2-3. Custom Routeの構成
(なお、NLBに障害が発生した場合は、このCustom Routeが自動的に更新されてfailoverしたNLBのIPアドレスにパケットが届くように更新される。)
3. Direct Link経由でのテスト
3-1. 80番ポートへのアクセス
bash-4.3# curl -I 10.4.0.19
HTTP/1.1 200 OK
Date: Fri, 22 Oct 2021 07:03:32 GMT
Server: Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips
Last-Modified: Fri, 01 Oct 2021 23:43:55 GMT
ETag: "d-5cd5322eda505"
Accept-Ranges: bytes
Content-Length: 13
Content-Type: text/html; charset=UTF-8
2回ずつ同様のパケットが表示されているのは、VNFに入ってくるものと出ていくものをカウントしているから。
06:40:20.978901 IP 192.168.50.223.51958 > 10.4.0.19.80: Flags [S], seq 3309025527, win 65535, options [mss 8960,nop,wscale 3,nop,nop,TS val 1638976899 ecr 0], length 0
06:40:20.978961 IP 192.168.50.223.51958 > 10.4.0.19.80: Flags [S], seq 3309025527, win 65535, options [mss 8960,nop,wscale 3,nop,nop,TS val 1638976899 ecr 0], length 0
06:40:20.979389 IP 10.4.0.19.80 > 192.168.50.223.51958: Flags [S.], seq 686757678, ack 3309025528, win 28960, options [mss 1460,nop,nop,TS val 1752332962 ecr 1638976899,nop,wscale 7], length 0
06:40:20.979398 IP 10.4.0.19.80 > 192.168.50.223.51958: Flags [S.], seq 686757678, ack 3309025528, win 28960, options [mss 1460,nop,nop,TS val 1752332962 ecr 1638976899,nop,wscale 7], length 0
06:40:20.980764 IP 192.168.50.223.51958 > 10.4.0.19.80: Flags [.], ack 1, win 32761, options [nop,nop,TS val 1638976899 ecr 1752332962], length 0
06:40:20.980769 IP 192.168.50.223.51958 > 10.4.0.19.80: Flags [.], ack 1, win 32761, options [nop,nop,TS val 1638976899 ecr 1752332962], length 0
06:40:20.980775 IP 192.168.50.223.51958 > 10.4.0.19.80: Flags [P.], seq 1:74, ack 1, win 32761, options [nop,nop,TS val 1638976899 ecr 1752332962], length 73: HTTP: GET / HTTP/1.1
06:40:20.980777 IP 192.168.50.223.51958 > 10.4.0.19.80: Flags [P.], seq 1:74, ack 1, win 32761, options [nop,nop,TS val 1638976899 ecr 1752332962], length 73: HTTP: GET / HTTP/1.1
06:40:20.981106 IP 10.4.0.19.80 > 192.168.50.223.51958: Flags [.], ack 74, win 227, options [nop,nop,TS val 1752332964 ecr 1638976899], length 0
06:40:20.981111 IP 10.4.0.19.80 > 192.168.50.223.51958: Flags [.], ack 74, win 227, options [nop,nop,TS val 1752332964 ecr 1638976899], length 0
06:40:20.981439 IP 10.4.0.19.80 > 192.168.50.223.51958: Flags [P.], seq 1:274, ack 74, win 227, options [nop,nop,TS val 1752332964 ecr 1638976899], length 273: HTTP: HTTP/1.1 200 OK
06:40:20.981443 IP 10.4.0.19.80 > 192.168.50.223.51958: Flags [P.], seq 1:274, ack 74, win 227, options [nop,nop,TS val 1752332964 ecr 1638976899], length 273: HTTP: HTTP/1.1 200 OK
06:40:20.982996 IP 192.168.50.223.51958 > 10.4.0.19.80: Flags [F.], seq 74, ack 274, win 32761, options [nop,nop,TS val 1638976899 ecr 1752332964], length 0
06:40:20.983000 IP 192.168.50.223.51958 > 10.4.0.19.80: Flags [F.], seq 74, ack 274, win 32761, options [nop,nop,TS val 1638976899 ecr 1752332964], length 0
06:40:20.983240 IP 10.4.0.19.80 > 192.168.50.223.51958: Flags [F.], seq 274, ack 75, win 227, options [nop,nop,TS val 1752332966 ecr 1638976899], length 0
06:40:20.983245 IP 10.4.0.19.80 > 192.168.50.223.51958: Flags [F.], seq 274, ack 75, win 227, options [nop,nop,TS val 1752332966 ecr 1638976899], length 0
06:40:20.984473 IP 192.168.50.223.51958 > 10.4.0.19.80: Flags [.], ack 275, win 32761, options [nop,nop,TS val 1638976899 ecr 1752332966], length 0
06:40:20.984477 IP 192.168.50.223.51958 > 10.4.0.19.80: Flags [.], ack 275, win 32761, options [nop,nop,TS val 1638976899 ecr 1752332966], length 0
3-2. 8080番ポートへのアクセス
bash-4.3# curl -I 10.4.0.19:8080
HTTP/1.1 200 OK
Date: Fri, 22 Oct 2021 07:03:58 GMT
Server: Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips
Last-Modified: Fri, 01 Oct 2021 23:43:55 GMT
ETag: "d-5cd5322eda505"
Accept-Ranges: bytes
Content-Length: 13
Content-Type: text/html; charset=UTF-8
2回ずつ同様のパケットが表示されているのは、VNFに入ってくるものと出ていくものをカウントしているから。
06:59:21.149722 IP 192.168.50.223.52218 > 10.4.0.19.8080: Flags [S], seq 2644742540, win 65535, options [mss 8960,nop,wscale 3,nop,nop,TS val 1638979180 ecr 0], length 0
06:59:21.149761 IP 192.168.50.223.52218 > 10.4.0.19.8080: Flags [S], seq 2644742540, win 65535, options [mss 8960,nop,wscale 3,nop,nop,TS val 1638979180 ecr 0], length 0
06:59:21.150182 IP 10.4.0.19.8080 > 192.168.50.223.52218: Flags [S.], seq 29432477, ack 2644742541, win 28960, options [mss 1460,nop,nop,TS val 1753473141 ecr 1638979180,nop,wscale 7], length 0
06:59:21.150190 IP 10.4.0.19.8080 > 192.168.50.223.52218: Flags [S.], seq 29432477, ack 2644742541, win 28960, options [mss 1460,nop,nop,TS val 1753473141 ecr 1638979180,nop,wscale 7], length 0
06:59:21.151710 IP 192.168.50.223.52218 > 10.4.0.19.8080: Flags [.], ack 1, win 32761, options [nop,nop,TS val 1638979180 ecr 1753473141], length 0
06:59:21.151715 IP 192.168.50.223.52218 > 10.4.0.19.8080: Flags [.], ack 1, win 32761, options [nop,nop,TS val 1638979180 ecr 1753473141], length 0
06:59:21.151721 IP 192.168.50.223.52218 > 10.4.0.19.8080: Flags [P.], seq 1:79, ack 1, win 32761, options [nop,nop,TS val 1638979180 ecr 1753473141], length 78: HTTP: GET / HTTP/1.1
06:59:21.151723 IP 192.168.50.223.52218 > 10.4.0.19.8080: Flags [P.], seq 1:79, ack 1, win 32761, options [nop,nop,TS val 1638979180 ecr 1753473141], length 78: HTTP: GET / HTTP/1.1
06:59:21.152086 IP 10.4.0.19.8080 > 192.168.50.223.52218: Flags [.], ack 79, win 227, options [nop,nop,TS val 1753473143 ecr 1638979180], length 0
06:59:21.152090 IP 10.4.0.19.8080 > 192.168.50.223.52218: Flags [.], ack 79, win 227, options [nop,nop,TS val 1753473143 ecr 1638979180], length 0
06:59:21.152981 IP 10.4.0.19.8080 > 192.168.50.223.52218: Flags [P.], seq 1:274, ack 79, win 227, options [nop,nop,TS val 1753473144 ecr 1638979180], length 273: HTTP: HTTP/1.1 200 OK
06:59:21.152986 IP 10.4.0.19.8080 > 192.168.50.223.52218: Flags [P.], seq 1:274, ack 79, win 227, options [nop,nop,TS val 1753473144 ecr 1638979180], length 273: HTTP: HTTP/1.1 200 OK
06:59:21.154530 IP 192.168.50.223.52218 > 10.4.0.19.8080: Flags [F.], seq 79, ack 274, win 32761, options [nop,nop,TS val 1638979180 ecr 1753473144], length 0
06:59:21.154534 IP 192.168.50.223.52218 > 10.4.0.19.8080: Flags [F.], seq 79, ack 274, win 32761, options [nop,nop,TS val 1638979180 ecr 1753473144], length 0
06:59:21.154797 IP 10.4.0.19.8080 > 192.168.50.223.52218: Flags [F.], seq 274, ack 80, win 227, options [nop,nop,TS val 1753473145 ecr 1638979180], length 0
06:59:21.154801 IP 10.4.0.19.8080 > 192.168.50.223.52218: Flags [F.], seq 274, ack 80, win 227, options [nop,nop,TS val 1753473145 ecr 1638979180], length 0
06:59:21.156246 IP 192.168.50.223.52218 > 10.4.0.19.8080: Flags [.], ack 275, win 32761, options [nop,nop,TS val 1638979180 ecr 1753473145], length 0
06:59:21.156250 IP 192.168.50.223.52218 > 10.4.0.19.8080: Flags [.], ack 275, win 32761, options [nop,nop,TS val 1638979180 ecr 1753473145], length 0
3-3. pingでのアクセス
bash-4.3# ping 10.4.0.19
(通信できず)
VNFにもパケットは現れず。これはNLBがTCPしか対応していないから仕方がない。
3-4. UDPでのアクセス。
あれ、UDPでも動いてるけど、、、これは想定とは違う挙動でありバグとのことです。本稿検証時点では機能していますが、今後動かなくなる可能性があります。
bash-4.3# nmap -sU 10.4.0.19 -p 30000
[root@transfw1 ~]# tcpdump -i any not port 22 -nn
07:12:30.824031 IP 192.168.50.223.64175 > 10.4.0.19.30000: UDP, length 0
07:12:30.824069 IP 192.168.50.223.64175 > 10.4.0.19.30000: UDP, length 0