【裏技】Lambda の固定IP化にまだ NatGateway 使ってるの？

2023/12/25 ... 【追記】アリ

# 背景
顔のイボやイボ痔を治療中で、年内に X のフォロワー1000人を目指している [@\_\_\_nix___](https://twitter.com/___nix___)  です。

以前から大人気の Lambda ですが、APIのコンピューティング部分で使うことも一般的になっています。
例えば外部決済システムとやり取りをするような場合に決済システム側から「接続元IPを制限しているのでGWのIPをご連絡ください」と言われるケースが少なくありません。

こんな時に今までは当たり前のようにやってきたやり方、実はそれ以外にも方法があったのでご紹介したいと思います。


# 現状
はい、この構成が Lambda を固定IP化する最も有名な方法です。
Lambda を VPC 内に配置し、（お高い）NatGateway 経由でアクセスすることで接続元IPを固定にする方法です。
![](https://storage.googleapis.com/zenn-user-upload/b1c821cb2474-20231222.png)

ただ、たったこれだけ？の為に VPC 構築して（お高い）NatGateway を設置するのにいつも罪悪感というか、手数増えるなぁという感想を持ってました。

# 気づき
そんなある日、こんな記事を見かけました。

https://zenn.dev/counterworks/articles/e942f58ddb1abf

ふむふむ、読み込んでいくと気になる一文が...。

> Lambda は実は EIP をアサインできる
あまり知られていませんが、Lambda Function は Public VPC に配置し、直接 Elastic IP をアタッチ出来ます。 これだけで任意の Lambda 関数の Outbound アクセスは固定IPになります。

(。´･ω･)え?


# 目指す構成
Lambda を PublicSubnet に配置、NetworkInterface に EIP をアタッチして外部にアクセスする経路を構築してみます。
![](https://storage.googleapis.com/zenn-user-upload/9e99ea1cc2de-20231222.png)

# 裏技
確かに Lambda を VPC の PublicSubnet に配置すると NetworkInterface が自動で生成されています。
※「インターフェイスのタイプ = lambda」で検索すればヒットします。
![](https://storage.googleapis.com/zenn-user-upload/a5e16a11fb2e-20231222.png)

では実際にこの NetworkInterface に EIP をアタッチしてみます。

```shell
$ aws ec2 associate-address \
--allocation-id eipalloc-xxxxxxxxxxxxxxxxx \
--network-interface-id eni-xxxxxxxxxxxxxxxxx
{
    "AssociationId": "eipassoc-xxxxxxxxxxxxxxxxx"
}
```

お、普通にできました。
では実際にどこかのURLにアクセスする関数を書いて実行してみましょう。

（この辺りのプロセスは省略します）

本当にできた...。
接続元IPはまさしく `eipalloc-xxxxxxxxxxxxxxxxx` の EIP でアクセスしてます。


# 何故？
なんだ、楽勝じゃ無いか。
（お高い）NatGateway なんてさようなら。

...
でも何故 AWS はこのような構成を事例紹介しないのだろう。
きっと何らかの理由があるはずです。

と言うわけで更に調査を進めましたが、結果としてこの裏技は「使っても良いけど挙動の理解が必要」だと結論付けました。
※この点については後述する【追記】も併せてご覧ください。


# 調査結果
Lambda を VPC に配置する際に Subnet を選択します。
例えば構成図に書いたような状態だとすると AZ で冗長化させて設定することが多いと思いますが、この条件によって自動生成される NetworkInterface が変わります。具体的には以下のような組み合わせで生成されます。

`セキュリティグループの組み合わせ` x `VPC の AZ`

例えば Lambda を 1a の PublicSubnet のみに配置し、セキュリティグループ A をアタッチして VPC 内に設定した場合、次のような NetworkInterface が生成されるということです。

|NetworkInterfase|AZ|SG|
|---|---|---|
|Lambda-1a-A|1a|A|

【その他の例1】
Lambda1 を 1a と 1c の PublicSubnet に配置し、セキュリティグループ A をアタッチ

|NetworkInterfase|AZ|SG|
|---|---|---|
|Lambda1-1a-A|1a|A|
|Lambda1-1c-A|1c|A|

【その他の例2】
Lambda1 を 1a と 1c の PublicSubnet に配置し、セキュリティグループ A と B をアタッチ

|NetworkInterfase|AZ|SG|
|---|---|---|
|Lambda1-1a-AB|1a|A,B|
|Lambda1-1c-AB|1c|A,B|

ここまでは「ふーん(・ω・)」で良いのです。

では【その他の例2】の構成がある状態で同じ VPC 内に Lambda2 を 1a と 1c の PublicSubnet に配置し、セキュリティグループ A と B をアタッチします。

|NetworkInterfase|AZ|SG|
|---|---|---|
|Lambda1-1a-AB|1a|A,B|
|Lambda1-1c-AB|1c|A,B|

あれ？
NetworkInterface が増えません。

はい、ここが分かり難い点ですが、上で書いたように `セキュリティグループの組み合わせ` x `VPC の AZ` の組み合わせであれば **共有される** という点に注意するようにしてください。

# 実験
Lambda が自動生成してくれるけど、それなら「インターフェイスのタイプ = lambda」を手動で作成してしまえば良いのでは？

やってみた。

```shell
$ aws ec2 create-network-interface \
--subnet-id subnet-xxxxxxxxxxxxxxxxx \
--description "manual" \
--groups sg-xxxxxxxxxxxxxxxxx \
--interface-type lambda

An error occurred (InvalidParameterValue) when calling the CreateNetworkInterface operation: invalid value for parameter interface-type: lambda
```

ダメでした... orz

https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ec2/create-network-interface.html
> - `-interface-type` (string)
> The type of network interface. The default is interface .
> The only supported values are `interface` , `efa` , and `trunk` .
> Possible values:
> - `efa`
> - `branch`
> - `trunk`

確かに AWS CLI では制限されてました。
こういうバッドノウハウ的な実験好きな人っていますよねw

# まとめ
この裏技を使うことで、Lambda を固定IP化する際に PrivateSubnet、（お高い）NatGateway が不要になりますので構成がシンプル且つ、（お高い）NatGateway による固定資産税と従量課金のコストに悩む必要が無くなります。

最初は凄くビックリしたのですが、周りではそれ程慌ただしくならないので拍子抜けしてしまってますが、裏技としては非常に面白いだけでなくコスト削減にも繋がるので適材適所でご活用ください。

# 編集後記
この記事を書くにあたり、参照させて頂いた記事の筆者である [@\_\_swordfish](https://twitter.com/__swordfish) さんには多大なる感謝をしております。
ありがとうございました。

※この記事を公開した後に一言ご挨拶させて頂く予定です。

では、この記事を気に入って頂けた方はフォローをお待ちしております♪


# 【追記】

[nak2k](https://zenn.dev/nak2k)さんよりコメントを頂きました。
（この場をお借りして感謝申し上げます！）

以下の2つの点は確かにこの挙動を知っていないと大きな事故に繋がりますので注意しましょう！

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/foundation-networking.html#foundation-nw-eni-man

> 各 Hyperplane ENI は最大 65,000 個の接続/ポートをサポートします。接続数が 65,000 を超えると、Lambda は新しい Hyperplane ENI を作成して、追加の接続を提供します。

> Lambda 関数が連続した複数週の間アイドル状態のままである場合、Lambda は未使用の Hyperplane ENI を回収し、関数の状態をアイドルに設定します