BIG-IP on EC2でSource NATを行わずに通信してみた

BIG-IP on EC2でSource NATを行わずに通信してみた

どうしてもSource NATを行いたくない場合に
Clock Icon2025.07.18

X-Fowarding-ForヘッダーでクライアントのIPアドレスを知るのではなく、直接クライアントIPアドレスを知る必要がある

こんにちは、のんピ(@non____97)です。

皆さんはX-Fowarding-ForヘッダーでクライアントのIPアドレスを知るのではなく、直接クライアントIPアドレスを知る必要がある場面に遭遇したことはありますか? 私はあります。

ALBの場合はターゲット側にはソースIPアドレスがALBのIPアドレスとして見えます。要するにSource NATをしているということです。

NLBでも送信元IPアドレスを維持することが可能です。ただし、NLBではホスト名やパスで振り分け先を変えたりといった高度なルーティングができません。

既存でSource NATが可能なロードバランサーを使っている場合はどうしても機能不足と感じてしまうこともあるでしょう。

BIG-IPではSource NATを行わずに後段のリソースに通信を流すことが可能です。

https://www.f5.com/ja_jp/glossary/secure-network-address-translation-snat

ということで、BIG-IPでSource NATを行わずに通信をしてみます。

いきなりまとめ

  • BIG-IPではSource NATをせずに後段のリソースに通信を流すことが可能
  • BIG-IPのCloud Failover Extentionを使用すれば、フェイルオーバーをトリガーに指定したルートテーブルのルートを書き換えが可能
  • インターネットに面しているシステムの場合は後段のリソースが属するサブネットのルートテーブルでデフォルトゲートウェイをBIG-IPに向ける必要がある
    • そのため、フォワードプロキシを用意しなければ、インターネットへアウトバウンドリクエストをすることはできない

やってみた

検証環境

検証環境は以下のとおりです。

フェイルオーバー前.png

以下記事のものから構成の変更は加えていません。

https://dev.classmethod.jp/articles/big-ip-multi-az-ha-cluster-cloudformation/

なお、上述の記事から再作成をしたため、EIPは変わっています。

現在のアクセスログ

まず、現在のアクセスログを確認します。

適当に繰り返しアクセスをします。

$ curl http://98.80.114.203
big-ip-application1-01

$ curl http://98.80.114.203
big-ip-application1-02

$ curl http://98.80.114.203
big-ip-application1-01

$ curl http://98.80.114.203
big-ip-application1-01

この時のアクセスログは以下のとおりです。

big-ip-application1-01の/var/log/nginx/access.log
10.0.0.11 - - [16/Jul/2025:08:09:11 +0000] "GET / HTTP/1.1" 200 23 "-" "curl/8.14.1" "-"

10.0.0.11というのは現在ActiveとなっているBIG-IP AのExternal ENIのプライマリIPアドレスです。

X-Fowarding-Forヘッダーを追加した場合

まずはX-Fowarding-Forヘッダーを追加した場合を確認します。

今回は既存のHTTP用のプロファイルにX-Fowarding-Forヘッダー追加の瀬亭を行います。

httpプロファイルをクリックします。

1.Profile.png

Insert X-Forwarding-ForEnabledに変更して更新をします。

2.Insert X-Forwarded-For.png

これだけです。

再度アクセスをして、アクセスログを確認しましょう。

big-ip-application1-01の/var/log/nginx/access.log
10.0.0.11 - - [16/Jul/2025:08:26:37 +0000] "GET / HTTP/1.1" 200 23 "-" "curl/8.14.1" "104.28.243.105"

クライアントのIPアドレスである104.28.243.105が返ってきました。

個人的には少しみづらいので、アクセスログをJSON Linesで出力するように変更します。

/etc/nginx/nginx.confを以下のようにしました。

/etc/nginx/nginx.conf
.
.
(中略)
.
.
http {
    log_format json_combined escape=json
    '{'
        '"time_local":"$time_local",'
        '"remote_addr":"$remote_addr",'
        '"remote_user":"$remote_user",'
        '"request":"$request",'
        '"status": $status,'
        '"body_bytes_sent": $body_bytes_sent,'
        '"request_time": $request_time,'
        '"http_referrer":"$http_referer",'
        '"http_user_agent":"$http_user_agent",'
        '"http_x_forwarded_for":"$http_x_forwarded_for"'
    '}';

    access_log  /var/log/nginx/access.log  json_combined;
.
.
(中略)
.
.
}

Nginxのサービスを再起動後、再度アクセスします。

この時のログは以下のとおりです。

big-ip-application1-01の/var/log/nginx/access.log
{"time_local":"16/Jul/2025:08:36:31 +0000","remote_addr":"10.0.4.11","remote_user":"","request":"GET /","status": 200,"body_bytes_sent": 23,"request_time": 0.001,"http_referrer":"","http_user_agent":"","http_x_forwarded_for":""}
{"time_local":"16/Jul/2025:08:36:34 +0000","remote_addr":"10.0.0.11","remote_user":"","request":"GET / HTTP/1.1","status": 200,"body_bytes_sent": 23,"request_time": 0.000,"http_referrer":"","http_user_agent":"curl/8.14.1","http_x_forwarded_for":"104.28.243.105"}

いい感じですね。

Source NATを行わない場合

それでは本題のSource NATを行わない場合を試します。

Source NATが必須ではないことはF5公式ドキュメントにも記載があります。

Is SNAT required?¶

SNAT is not required if your application server’s default route points through the BIG-IPs NICs. If you are using SNAT in AWS HA Across AZ, please see Define the Failover Addresses in AWS.

Frequently Asked Questions (FAQ)

Virtual ServerでSource Address TranslationAuto MapからNoneに変更します。

3.Source Address TranslationをNoneに変更.png

変更後アクセスを行います。

$ curl http://3.214.127.249/ -I
HTTP/1.1 502 Bad Gateway
Cache-Control: private, max-age=0, no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Referrer-Policy: same-origin
Expires: Thu, 01 Jan 1970 00:00:01 GMT
Proxy-Status: Cloudflare-Proxy;error=http_response_incomplete
Cf-Team: 28b3fda0b40000af9a886b2400000001
Content-Length: 10160
Date: Wed, 16 Jul 2025 08:40:46 GMT

はい、エラーになってしまいました。

アクセスログを確認しても当該ログは記録されていないです。

これは、以下の複数の要因があります。

  • Virtual Serverの送信先であるWebサーバーのセキュリティグループで0.0.0.0/0からのTCP/80へのアクセスを許可するルールがなく、通信できないため
  • BIG-IPのExternalのENIで送信元/送信先チェックが有効であり、レスポンスの通信において自身のIPアドレスが送信先IPアドレスとなっていないがために、パケットをドロップしてしまうため
  • Virtual Serverの送信先であるWebサーバーが属するサブネットのルートテーブルにて、デフォルトゲートウェイがNAT Gatewayを向いており、レスポンスの通信がBIG-IPを通らないDirect Server Return(DSR)となっているため

一つ一つ対応をします。

まずは、WebサーバーにアタッチしているセキュリティグループでExternalのENIからのTCP/80へのアクセスを許可しましょう。0.0.0.0/0からでも良いですが、あまりよろしくないでしょう。

また、BIG-IPのExternalのENIで送信元/送信先チェックを無効化します。こちらも両方のBIG-IPインスタンスについて行います。

最後にWebサーバーが属するサブネットのルートテーブルで0.0.0.0/0への通信はBIG-IPのExternalのENIにルーティングするように設定します。

4.ルートテーブルの変更.png

設定変更完了後、再度アクセスを行います。

$ curl http://98.80.114.203
big-ip-application1-01

$ curl http://98.80.114.203
big-ip-application1-02

$ curl http://98.80.114.203
big-ip-application1-01

$ curl http://98.80.114.203
big-ip-application1-02

$ curl http://98.80.114.203
big-ip-application1-02

$ curl http://98.80.114.203
big-ip-application1-01

正常にアクセスできましたね。

アクセスログを確認すると、remote_addrhttp_x_forwarded_forが一致している = Source NATを行わずにWebサーバーに到達していることを確認できました。

big-ip-application1-01の/var/log/nginx/access.log
{"time_local":"17/Jul/2025:15:29:52 +0000","remote_addr":"104.28.236.107","remote_user":"","request":"GET / HTTP/1.1","status": 200,"body_bytes_sent": 23,"request_time": 0.000,"http_referrer":"","http_user_agent":"curl/8.14.1","http_x_forwarded_for":"104.28.236.107"}
{"time_local":"17/Jul/2025:15:29:54 +0000","remote_addr":"104.28.236.107","remote_user":"","request":"GET / HTTP/1.1","status": 200,"body_bytes_sent": 23,"request_time": 0.000,"http_referrer":"","http_user_agent":"curl/8.14.1","http_x_forwarded_for":"104.28.236.107"}
{"time_local":"17/Jul/2025:15:29:55 +0000","remote_addr":"10.0.0.11","remote_user":"","request":"GET /","status": 200,"body_bytes_sent": 23,"request_time": 0.001,"http_referrer":"","http_user_agent":"","http_x_forwarded_for":""}
{"time_local":"17/Jul/2025:15:29:56 +0000","remote_addr":"10.0.4.11","remote_user":"","request":"GET /","status": 200,"body_bytes_sent": 23,"request_time": 0.001,"http_referrer":"","http_user_agent":"","http_x_forwarded_for":""}
{"time_local":"17/Jul/2025:15:29:56 +0000","remote_addr":"104.28.236.107","remote_user":"","request":"GET / HTTP/1.1","status": 200,"body_bytes_sent": 23,"request_time": 0.000,"http_referrer":"","http_user_agent":"curl/8.14.1","http_x_forwarded_for":"104.28.236.107"}
{"time_local":"17/Jul/2025:15:29:59 +0000","remote_addr":"104.28.236.107","remote_user":"","request":"GET / HTTP/1.1","status": 200,"body_bytes_sent": 23,"request_time": 0.000,"http_referrer":"","http_user_agent":"curl/8.14.1","http_x_forwarded_for":"104.28.236.107"}

Cloud Failover Extentionsでフェイルオーバールートの設定を追加した場合

めでたしめでたし

ではありません。

このままではBIG-IP Bにフェイルオーバーすると、以降Webサーバーから正常に応答を受け取ることができません。

なぜなら、デフォルトゲートウェイがBIG-IP AのExternal ENIに向いていているため、Webサーバーのレスポンス通信をBIG-IP Aに返そうとしてしまうからです。

つまりは、フェイルオーバーのタイミングで指定したルートテーブルのルートを書き換える必要があります。

こちらはCloud Failover Extentions(以降CFE)で制御が可能です。

現在の定義や状態は以下のとおりです。

BIG-IP A
>  curl \
    -sku admin:$admin_password \
    -X GET https://23.20.172.35/mgmt/shared/cloud-failover/declare \
    | jq .
{
  "message": "success",
  "declaration": {
    "schemaVersion": "1.0.0",
    "class": "Cloud_Failover",
    "environment": "aws",
    "controls": {
      "class": "Controls",
      "logLevel": "silly"
    },
    "externalStorage": {
      "encryption": {
        "serverSide": {
          "enabled": true,
          "algorithm": "AES256"
        }
      },
      "scopingTags": {
        "f5_cloud_failover_label": "bigip_high_availability_solution"
      }
    },
    "failoverAddresses": {
      "enabled": true,
      "scopingTags": {
        "f5_cloud_failover_label": "bigip_high_availability_solution"
      },
      "requireScopingTags": false
    }
  }
}

>  curl \
    -sku admin:$admin_password \
    -X GET https://23.20.172.35/mgmt/shared/cloud-failover/inspect \
    | jq .
{
  "instance": "i-055fd78af29715fbf",
  "addresses": [
    {
      "publicIpAddress": "23.20.172.35",
      "privateIpAddress": "10.0.1.11",
      "networkInterfaceId": "eni-026bb5fe081900500"
    },
    {
      "publicIpAddress": "",
      "privateIpAddress": "10.0.2.11",
      "networkInterfaceId": "eni-0812e390d83655675"
    },
    {
      "publicIpAddress": "34.198.64.199",
      "privateIpAddress": "10.0.0.11",
      "networkInterfaceId": "eni-0603a4992d0579540"
    },
    {
      "publicIpAddress": "98.80.114.203",
      "privateIpAddress": "10.0.0.101",
      "networkInterfaceId": "eni-0603a4992d0579540"
    }
  ],
  "routes": [],
  "hostName": "failover01.www.non-97.net",
  "deviceStatus": "active",
  "trafficGroup": [
    {
      "name": "/Common/traffic-group-1"
    }
  ]
}
BIG-IP B
> curl \
    -sku admin:$admin_password \
    -X GET https://3.227.198.100/mgmt/shared/cloud-failover/declare \
    | jq .
{
  "message": "success",
  "declaration": {
    "schemaVersion": "1.0.0",
    "class": "Cloud_Failover",
    "environment": "aws",
    "controls": {
      "class": "Controls",
      "logLevel": "silly"
    },
    "externalStorage": {
      "encryption": {
        "serverSide": {
          "enabled": true,
          "algorithm": "AES256"
        }
      },
      "scopingTags": {
        "f5_cloud_failover_label": "bigip_high_availability_solution"
      }
    },
    "failoverAddresses": {
      "enabled": true,
      "scopingTags": {
        "f5_cloud_failover_label": "bigip_high_availability_solution"
      },
      "requireScopingTags": false
    }
  }
}

>  curl \
    -sku admin:$admin_password \
    -X GET https://3.227.198.100/mgmt/shared/cloud-failover/inspect \
    | jq .
{
  "instance": "i-061cbb31a5158ad30",
  "addresses": [
    {
      "publicIpAddress": "3.227.198.100",
      "privateIpAddress": "10.0.5.11",
      "networkInterfaceId": "eni-01d04904d876f5924"
    },
    {
      "publicIpAddress": "34.226.159.140",
      "privateIpAddress": "10.0.4.11",
      "networkInterfaceId": "eni-04bec0335a47b26c3"
    },
    {
      "publicIpAddress": "",
      "privateIpAddress": "10.0.4.101",
      "networkInterfaceId": "eni-04bec0335a47b26c3"
    },
    {
      "publicIpAddress": "",
      "privateIpAddress": "10.0.6.11",
      "networkInterfaceId": "eni-097a6bb7971ecceb4"
    }
  ],
  "routes": [],
  "hostName": "failover02.www.non-97.net",
  "deviceStatus": "standby",
  "trafficGroup": [
    {
      "name": "/Common/traffic-group-1"
    }
  ]
}

特にフェイルオーバーをしたタイミングでルートを変更するような設定は組み込まれていません。

フェイルオーバーをしたタイミングでルートを変更するようなCFEの定義を用意します。

cfe-snat-none.json
{
  "schemaVersion": "1.0.0",
  "class": "Cloud_Failover",
  "environment": "aws",
  "controls": {
    "class": "Controls",
    "logLevel": "silly"
  },
  "externalStorage": {
    "encryption": {
      "serverSide": {
        "enabled": true,
        "algorithm": "AES256"
      }
    },
    "scopingTags": {
      "f5_cloud_failover_label": "bigip_high_availability_solution"
    }
  },
  "failoverAddresses": {
    "enabled": true,
    "scopingTags": {
      "f5_cloud_failover_label": "bigip_high_availability_solution"
    },
    "requireScopingTags": false
  },
  "failoverRoutes": {
    "enabled": true,
    "routeGroupDefinitions": [
      {
        "scopingName": "rtb-060adeaa8fe5b2bbb",
        "scopingAddressRanges": [
          {
            "range": "0.0.0.0/0"
          }
        ],
        "defaultNextHopAddresses": {
          "discoveryType": "static",
          "items": [
            "10.0.0.101",
            "10.0.4.101"
          ]
        }
      }
    ]
  }
}

追加したのはfailoverRoutesのブロックです。

各プロパティの値は以下をさしています。

  • rtb-060adeaa8fe5b2bbb : WebサーバーのサブネットのルートテーブルID
  • 10.0.0.11 : BIG-IP AのExternal ENIのプライマリIPアドレス
  • 10.0.4.11 : BIG-IP BのExternal ENIのプライマリIPアドレス

IPアドレスは必ずENIのプライマリIPアドレスである必要があります。VIPを紐づけているセカンダリIPアドレスを指定しても、正常に動作しません。

用意した定義で更新をします。

>  curl \
    -sku admin:$admin_password \
    -X POST -d @cfe-snat-none.json https://23.20.172.35/mgmt/shared/cloud-failover/declare \
    | jq .
{
  "message": "success",
  "declaration": {
    "schemaVersion": "1.0.0",
    "class": "Cloud_Failover",
    "environment": "aws",
    "controls": {
      "class": "Controls",
      "logLevel": "silly"
    },
    "externalStorage": {
      "encryption": {
        "serverSide": {
          "enabled": true,
          "algorithm": "AES256"
        }
      },
      "scopingTags": {
        "f5_cloud_failover_label": "bigip_high_availability_solution"
      }
    },
    "failoverAddresses": {
      "enabled": true,
      "scopingTags": {
        "f5_cloud_failover_label": "bigip_high_availability_solution"
      },
      "requireScopingTags": false
    },
    "failoverRoutes": {
      "enabled": true,
      "routeGroupDefinitions": [
        {
          "scopingName": "rtb-060adeaa8fe5b2bbb",
          "scopingAddressRanges": [
            {
              "range": "0.0.0.0/0"
            }
          ],
          "defaultNextHopAddresses": {
            "discoveryType": "static",
            "items": [
              "10.0.0.11",
              "10.0.4.11"
            ]
          }
        }
      ]
    }
  }
}

>  curl \
    -sku admin:$admin_password \
    -X GET https://23.20.172.35/mgmt/shared/cloud-failover/inspect \
    | jq .
{
  "instance": "i-055fd78af29715fbf",
  "addresses": [
    {
      "publicIpAddress": "23.20.172.35",
      "privateIpAddress": "10.0.1.11",
      "networkInterfaceId": "eni-026bb5fe081900500"
    },
    {
      "publicIpAddress": "",
      "privateIpAddress": "10.0.2.11",
      "networkInterfaceId": "eni-0812e390d83655675"
    },
    {
      "publicIpAddress": "34.198.64.199",
      "privateIpAddress": "10.0.0.11",
      "networkInterfaceId": "eni-0603a4992d0579540"
    },
    {
      "publicIpAddress": "98.80.114.203",
      "privateIpAddress": "10.0.0.101",
      "networkInterfaceId": "eni-0603a4992d0579540"
    }
  ],
  "routes": [
    {
      "routeTableId": "rtb-060adeaa8fe5b2bbb",
      "routeTableName": null,
      "networkId": "vpc-0287f01407d1276f0"
    }
  ],
  "hostName": "failover01.www.non-97.net",
  "deviceStatus": "active",
  "trafficGroup": [
    {
      "name": "/Common/traffic-group-1"
    }
  ]
}

更新されましたね。routesに参照しているルートテーブルの情報が追加されました。

BIG-IP B側にも設定が同期されていることを確認します。

>  curl \
    -sku admin:$admin_password \
    -X GET https://3.227.198.100/mgmt/shared/cloud-failover/declare \
    | jq .
{
  "message": "success",
  "declaration": {
    "schemaVersion": "1.0.0",
    "class": "Cloud_Failover",
    "environment": "aws",
    "controls": {
      "class": "Controls",
      "logLevel": "silly"
    },
    "externalStorage": {
      "encryption": {
        "serverSide": {
          "enabled": true,
          "algorithm": "AES256"
        }
      },
      "scopingTags": {
        "f5_cloud_failover_label": "bigip_high_availability_solution"
      }
    },
    "failoverAddresses": {
      "enabled": true,
      "scopingTags": {
        "f5_cloud_failover_label": "bigip_high_availability_solution"
      },
      "requireScopingTags": false
    },
    "failoverRoutes": {
      "enabled": true,
      "routeGroupDefinitions": [
        {
          "scopingName": "rtb-060adeaa8fe5b2bbb",
          "scopingAddressRanges": [
            {
              "range": "0.0.0.0/0"
            }
          ],
          "defaultNextHopAddresses": {
            "discoveryType": "static",
            "items": [
              "10.0.0.11",
              "10.0.4.11"
            ]
          }
        }
      ]
    }
  }
}

>  curl \
    -sku admin:$admin_password \
    -X GET https://3.227.198.100/mgmt/shared/cloud-failover/inspect \
    | jq .
{
  "instance": "i-061cbb31a5158ad30",
  "addresses": [
    {
      "publicIpAddress": "3.227.198.100",
      "privateIpAddress": "10.0.5.11",
      "networkInterfaceId": "eni-01d04904d876f5924"
    },
    {
      "publicIpAddress": "34.226.159.140",
      "privateIpAddress": "10.0.4.11",
      "networkInterfaceId": "eni-04bec0335a47b26c3"
    },
    {
      "publicIpAddress": "",
      "privateIpAddress": "10.0.4.101",
      "networkInterfaceId": "eni-04bec0335a47b26c3"
    },
    {
      "publicIpAddress": "",
      "privateIpAddress": "10.0.6.11",
      "networkInterfaceId": "eni-097a6bb7971ecceb4"
    }
  ],
  "routes": [],
  "hostName": "failover02.www.non-97.net",
  "deviceStatus": "standby",
  "trafficGroup": [
    {
      "name": "/Common/traffic-group-1"
    }
  ]
}

Standby側にはroutes内のオブジェクトは追加されないようです。

最後に、下準備としてルートテーブルにf5_cloud_failover_label:bigip_high_availability_solutionのタグを付与します。

こちらを付与しなければ、正常に動作しませんでした。

また、BIG-IP BのENIで送信元/送信先チェックを無効にしていない場合は、無効にしておきましょう。Virtual ServerのSNATをNoneにすることも忘れずに。

現在のWebサーバーが属するサブネットのルートテーブルは以下のとおりです。

6.フェイルオーバー前ルートテーブル.png

フェイルオーバーを実施します。

5.フェイルオーバー.png

加えて、裏側でフェイルオーバー前から0.1秒間隔でアクセスをさせます。

$ while true; do
    start_time=$(date +%s.%N)
    response=$(curl -s --max-time 5 "http://98.80.114.203/index.html")
    end_time=$(date +%s.%N)
    elapsed=$(echo "$end_time - $start_time" | bc)

    echo "$response | Response time: ${elapsed}s"
    sleep 0.1
done
.
.
(中略)
.
.
big-ip-application1-02 | Response time: .459180000s
big-ip-application1-01 | Response time: .469168000s
big-ip-application1-02 | Response time: .412991000s
big-ip-application1-01 | Response time: .448568000s
 | Response time: 5.062852000s
 | Response time: 5.072382000s
 | Response time: 5.046399000s
 | Response time: 5.050259000s
 | Response time: 5.065631000s
 | Response time: 5.061009000s
 | Response time: 5.057728000s
 | Response time: 5.056672000s
 | Response time: 5.059115000s
 | Response time: 5.060330000s
 | Response time: 5.075265000s
 | Response time: 5.082781000s
 | Response time: 5.057507000s
 | Response time: 5.060536000s
 | Response time: 5.066528000s
 | Response time: 5.048013000s
 | Response time: 5.050280000s
 | Response time: 5.039236000s
 | Response time: 5.048934000s
 | Response time: 5.055705000s
 | Response time: 5.053175000s
 | Response time: 5.073154000s
 | Response time: 5.088465000s
 | Response time: 5.053167000s
 | Response time: 5.052180000s
 | Response time: 5.100696000s
big-ip-application1-02 | Response time: .400236000s
big-ip-application1-02 | Response time: .458778000s
big-ip-application1-01 | Response time: .435870000s
big-ip-application1-02 | Response time: .437336000s
.
.
(以下略)
.
.

フェイルオーバーを実施してから130秒ほどダウンタイムがありましたが、以降は正常にレスポンスが返ってくるようになりました。

アクセスログにも記録されています。

big-ip-application1-01の/var/log/nginx/access.log
{"time_local":"17/Jul/2025:15:41:01 +0000","remote_addr":"104.28.236.107","remote_user":"","request":"GET /index.html HTTP/1.1","status": 200,"body_bytes_sent": 23,"request_time": 0.000,"http_referrer":"","http_user_agent":"curl/8.14.1","http_x_forwarded_for":"104.28.236.107"}
{"time_local":"17/Jul/2025:15:41:02 +0000","remote_addr":"104.28.236.107","remote_user":"","request":"GET /index.html HTTP/1.1","status": 200,"body_bytes_sent": 23,"request_time": 0.000,"http_referrer":"","http_user_agent":"curl/8.14.1","http_x_forwarded_for":"104.28.236.107"}
{"time_local":"17/Jul/2025:15:41:03 +0000","remote_addr":"104.28.236.107","remote_user":"","request":"GET /index.html HTTP/1.1","status": 200,"body_bytes_sent": 23,"request_time": 0.000,"http_referrer":"","http_user_agent":"curl/8.14.1","http_x_forwarded_for":"104.28.236.107"}
{"time_local":"17/Jul/2025:15:41:04 +0000","remote_addr":"104.28.236.107","remote_user":"","request":"GET /index.html HTTP/1.1","status": 200,"body_bytes_sent": 23,"request_time": 0.000,"http_referrer":"","http_user_agent":"curl/8.14.1","http_x_forwarded_for":"104.28.236.107"}

フェイルオーバー後のルートテーブルを確認すると、デフォルトゲートウェイがBIG-IP BのExternal ENIになっていました。

7.フェイルオーバー後ルートテーブル.png

この時、S3バケットに出力されたf5cloudfailoverstate.jsonは以下のとおりです。

f5cloudfailoverstate.json
{
  "taskState": "SUCCEEDED",
  "message": "Failover Complete",
  "timestamp": "2025-07-17T15:38:42.875Z",
  "instance": "failover02.www.non-97.net",
  "failoverOperations": {
    "addresses": {
      "publicAddresses": {
        "98.80.114.203": {
          "current": {
            "PrivateIpAddress": "10.0.0.101",
            "AssociationId": "eipassoc-018c90df9cc912b36"
          },
          "target": {
            "PrivateIpAddress": "10.0.4.101",
            "NetworkInterfaceId": "eni-04bec0335a47b26c3"
          },
          "AllocationId": "eipalloc-0814e2bbaf002a2bc"
        }
      },
      "interfaces": {
        "disassociate": [
          {
            "networkInterfaceId": "eni-0603a4992d0579540",
            "addresses": []
          },
          {
            "networkInterfaceId": "eni-0812e390d83655675",
            "addresses": []
          }
        ],
        "associate": [
          {
            "networkInterfaceId": "eni-04bec0335a47b26c3",
            "addresses": []
          },
          {
            "networkInterfaceId": "eni-097a6bb7971ecceb4",
            "addresses": []
          }
        ]
      },
      "loadBalancerAddresses": {}
    },
    "routes": {
      "operations": [
        {
          "routeTableId": "rtb-060adeaa8fe5b2bbb",
          "networkInterfaceId": "eni-04bec0335a47b26c3",
          "routeAddress": "0.0.0.0/0",
          "nextHopAddress": "10.0.4.11",
          "ipVersion": "4"
        }
      ]
    }
  }
}

failoverOperations.routes.operationsにどのような操作をしたのかの情報が記載されていますね。

REST APIでCFEの現在の状態を確認します。

>  curl \
    -sku admin:$admin_password \
    -X GET https://23.20.172.35/mgmt/shared/cloud-failover/inspect \
    | jq .
{
  "instance": "i-055fd78af29715fbf",
  "addresses": [
    {
      "publicIpAddress": "23.20.172.35",
      "privateIpAddress": "10.0.1.11",
      "networkInterfaceId": "eni-026bb5fe081900500"
    },
    {
      "publicIpAddress": "",
      "privateIpAddress": "10.0.2.11",
      "networkInterfaceId": "eni-0812e390d83655675"
    },
    {
      "publicIpAddress": "34.198.64.199",
      "privateIpAddress": "10.0.0.11",
      "networkInterfaceId": "eni-0603a4992d0579540"
    },
    {
      "publicIpAddress": "",
      "privateIpAddress": "10.0.0.101",
      "networkInterfaceId": "eni-0603a4992d0579540"
    }
  ],
  "routes": [],
  "hostName": "failover01.www.non-97.net",
  "deviceStatus": "standby",
  "trafficGroup": [
    {
      "name": "/Common/traffic-group-1"
    }
  ]
}

>  curl \
    -sku admin:$admin_password \
    -X GET https://3.227.198.100/mgmt/shared/cloud-failover/inspect \
    | jq .
{
  "instance": "i-061cbb31a5158ad30",
  "addresses": [
    {
      "publicIpAddress": "3.227.198.100",
      "privateIpAddress": "10.0.5.11",
      "networkInterfaceId": "eni-01d04904d876f5924"
    },
    {
      "publicIpAddress": "34.226.159.140",
      "privateIpAddress": "10.0.4.11",
      "networkInterfaceId": "eni-04bec0335a47b26c3"
    },
    {
      "publicIpAddress": "98.80.114.203",
      "privateIpAddress": "10.0.4.101",
      "networkInterfaceId": "eni-04bec0335a47b26c3"
    },
    {
      "publicIpAddress": "",
      "privateIpAddress": "10.0.6.11",
      "networkInterfaceId": "eni-097a6bb7971ecceb4"
    }
  ],
  "routes": [
    {
      "routeTableId": "rtb-060adeaa8fe5b2bbb",
      "routeTableName": null,
      "networkId": "vpc-0287f01407d1276f0"
    }
  ],
  "hostName": "failover02.www.non-97.net",
  "deviceStatus": "active",
  "trafficGroup": [
    {
      "name": "/Common/traffic-group-1"
    }
  ]
}

BIG-IP B(failover02.www.non-97.net)がActiveになっていることを確認できました。

再度フェイルオーバーを行います。

フェイルオーバー時のタイムアウトは今回も130秒ほどでしたが、以降は正常にアクセスできています。

.
.
(中略)
.
.
big-ip-application1-02 | Response time: .416088000s
big-ip-application1-01 | Response time: .467229000s
big-ip-application1-02 | Response time: .432712000s
big-ip-application1-02 | Response time: .448970000s
big-ip-application1-01 | Response time: .429122000s
big-ip-application1-01 | Response time: .439792000s
 | Response time: 5.055961000s
 | Response time: 5.054471000s
 | Response time: 5.038379000s
 | Response time: 5.026982000s
 | Response time: 5.041893000s
 | Response time: 5.037498000s
 | Response time: 5.042279000s
 | Response time: 5.038285000s
 | Response time: 5.036910000s
 | Response time: 5.037413000s
 | Response time: 5.034680000s
 | Response time: 5.038419000s
 | Response time: 5.041508000s
 | Response time: 5.034251000s
 | Response time: 5.033083000s
 | Response time: 5.027898000s
 | Response time: 5.068765000s
 | Response time: 5.033541000s
 | Response time: 5.034379000s
 | Response time: 5.027906000s
 | Response time: 5.040967000s
 | Response time: 5.027580000s
 | Response time: 5.029461000s
 | Response time: 5.031077000s
 | Response time: 5.038569000s
 | Response time: 5.038713000s
big-ip-application1-02 | Response time: .384456000s
big-ip-application1-01 | Response time: .399939000s
big-ip-application1-02 | Response time: .396850000s
big-ip-application1-02 | Response time: .414267000s
big-ip-application1-01 | Response time: .390396000s
big-ip-application1-02 | Response time: .400357000s
big-ip-application1-01 | Response time: .415856000s
big-ip-application1-01 | Response time: .417045000s
.
.
(以下略)
.
.

この時、S3バケットに出力されたf5cloudfailoverstate.jsonは以下のとおりです。

{
  "taskState": "SUCCEEDED",
  "message": "Failover Complete",
  "timestamp": "2025-07-17T15:47:13.982Z",
  "instance": "failover01.www.non-97.net",
  "failoverOperations": {
    "addresses": {
      "publicAddresses": {
        "98.80.114.203": {
          "current": {
            "PrivateIpAddress": "10.0.4.101",
            "AssociationId": "eipassoc-05f74050aa51b1297"
          },
          "target": {
            "PrivateIpAddress": "10.0.0.101",
            "NetworkInterfaceId": "eni-0603a4992d0579540"
          },
          "AllocationId": "eipalloc-0814e2bbaf002a2bc"
        }
      },
      "interfaces": {
        "disassociate": [
          {
            "networkInterfaceId": "eni-097a6bb7971ecceb4",
            "addresses": []
          },
          {
            "networkInterfaceId": "eni-04bec0335a47b26c3",
            "addresses": []
          }
        ],
        "associate": [
          {
            "networkInterfaceId": "eni-0812e390d83655675",
            "addresses": []
          },
          {
            "networkInterfaceId": "eni-0603a4992d0579540",
            "addresses": []
          }
        ]
      },
      "loadBalancerAddresses": {}
    },
    "routes": {
      "operations": [
        {
          "routeTableId": "rtb-060adeaa8fe5b2bbb",
          "networkInterfaceId": "eni-0603a4992d0579540",
          "routeAddress": "0.0.0.0/0",
          "nextHopAddress": "10.0.0.11",
          "ipVersion": "4"
        }
      ]
    }
  }
}

問題なく動作していますね。

どうしてもSource NATを行いたくない場合に

BIG-IP on EC2でSource NATを行わずに通信してみました。

ALB/NLBで実装が難しい要素の対応をする場合はお世話になりそうですね。

一方で、個人的にはSource NATを行わないことは積極的にはやりたくはありません。

理由はSource NATを行わずに通信を投げる先のルーティングの自由度がなくなるためです。

インターネットに面しているシステムの場合は後段のリソースが属するサブネットのルートテーブルでデフォルトゲートウェイをBIG-IPに向ける必要があります。

そのため、フォワードプロキシを用意しなければ、インターネットへアウトバウンドリクエストをすることはできません。

これにより、例えばTransit Gatewayを用いて、AWS Network Firewallを挟んだり、アウトバウンド通信をNAT Gatewayで集約したりといったことができなくなります。

出口集約をする かつ SNATをしない場合.png

SNATをする場合についてはTransit Gatewayによる出口集約も簡単に行えます。

出口集約をする かつ SNATをする場合.png

アプリケーションの改修が可能なのであれば、可能な限りそちらで対応したいところです。

この記事が誰かの助けになれば幸いです。

以上、クラウド事業本部 コンサルティング部の のんピ(@non____97)でした!

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.