Loading
BLOG 開発者ブログ

2020年12月18日

Azure Functionsで送信IPアドレスを固定したい話

今回は、 Azure Functionsで送信IPアドレスを固定する という、業務要件に対応したときの話を書きます。

この記事は アイソルートAdventCalendar2020 18日目の記事です。

こんにちは。
クラウドソリューショングループのimai.kです。

昨日はide.tさんの 【Swift】TableViewに配置したUISwitchのindexPath.rowを取得する でした。
iOS初心者から業務で開発している方まで幅広く役に立つ記事だったのではないでしょうか!

目次


Let’s begin

では、早速進めましょう!

今回の構成

Azure Functionsを利用したシステム構築を行う際、WebサーバーにAzure Functionsからアクセスするとき、
Webサーバー側の制約として、呼び出し元のIPアドレスを固定しないといけない、ということがよくあると思います。

しかし、Azure FunctionsのIPアドレスをマネージドサービスだけで実現することができませんでした。
(Azure NAT Gatewayと組み合わせることで実現可能かと試しましたが、2020年10月時点では上手くできませんでした。)
(2021/8/15 追記 : 現在はPremiumプランのFunctionsでNAT Gatewayを組み合わせることで実現可能です。)

そこで今回は以下のような構成で、Azure Functionsの送信IPアドレスを固定するアプローチを取りました。


Azure Functionsで関数を作成する

まずは、Azure PortalからAzure Functionsの関数アプリを作成しましょう。
プランはPremiumもしくはApp Serviceプランにしてください。
以下のような設定値になっていればOKです。



仮想ネットワークを作成する

仮想ネットワークを作成しましょう。
ここでは、東日本リージョンでサブネットを2つ(subnet1, subnet2)作成しておきます。
以下のような設定値になっていればOKです。



NAT用のインスタンスを作成する

Azure Functionsがインターネットアクセスするときに経由するNAT用のインスタンスを用意します。
今回は簡単のためにSSHのポートを開放しておきます。OSはUbuntu 18.04を使います。

また、NAT用インスタンスは先ほど作成したサブネットの2つめ(subnet2)に配置しておきます。
以下のような設定値になっていればOKです。



NAT用インスタンスが出来上がったら、SSHして以下のコマンドを実行します。

root@nat:~# echo "net.ipv4.ip_forward = 1" | tee -a /etc/sysctl.conf
root@nat:~# systemctl restart systemd-networkd.service
root@nat:~# apt update -y
root@nat:~# apt autoremove -y
root@nat:~# apt install -y firewalld
root@nat:~# systemctl enable firewalld
root@nat:~# systemctl start firewalld.service
root@nat:~# firewall-cmd --set-default-zone=external
root@nat:~# firewall-cmd --reload


関数をVNet統合する

VNet統合の前段階として、ルートテーブルを作成してサブネットにアタッチします。
ルートテーブルのネクストホップIPアドレスは、subnet1におけるNAT用インスタンスのプライベートIPアドレスを設定してください。



作成したルートテーブルをサブネット(subnet1)にアタッチします。



また、NAT用インスタンスの受信ポートの規則(ネットワークセキュリティグループ)に以下を加えます。



Azure Functionsを先ほど作成した仮想ネットワークに接続します。
関数アプリのネットワークからVNet統合を選択し、設定を行います。

以下のように設定できればOKです。



Azure Functionsの全ての送信トラフィックが仮想ネットワーク(subnet1)にルーティングされるように設定します。
関数アプリの構成から以下のアプリケーション設定を追加します。



Webサーバーを用意する

Azure FunctionsからアクセスするWebサーバーを用意します。
NAT用インスタンスとは別の仮想ネットワークを作成し、以下の要領でWebサーバー用のインスタンスを作成しましょう。
また、ネットワークセキュリティグループの設定で、インターネットからの80番ポートアクセスも許可してください。



Webサーバー用のインスタンスが作成できたら、SSHしてApacheをインストールします。

root@webserver:~# apt update -y
root@webserver:~# apt autoremove -y
root@webserver:~# apt install -y apache2


ついでに、アクセスログを出力しておきましょう。

root@webserver:~# tail -f /var/log/apache2/access.log


送信IPが固定されているか試す

では、WebサーバーにHTTPリクエストを実行するAzure Functionsの関数を、トリガーをHTTP triggerに、Authorization LevelをAnonymousにして作成してください。
今回は、C#で処理を書いてみます。

#r "Newtonsoft.Json"
using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;
using System;
using System.Text;
using System.Net.Http;
using System.Net.Http.Headers;
public static async Task Run(HttpRequest req, ILogger log)
{
    var apimUrl = " http://{WebサーバーのパブリックIPアドレス}/";
    HttpClient Client = new HttpClient();
    var response = Client.PostAsync(apimUrl, new StringContent("")).Result;
    return new OkObjectResult("Success");
}


Azure Functionsの「コードとテスト」から実行するか、
関数のURLを叩いてみましょう。

Webサーバー側のアクセスログに、NAT用インスタンスのパブリックIPアドレスが表示されれば成功です。

最後に

以上のようにすればAzure Functionsの送信IPアドレスを固定することができますが、
AWSのLambdaやGCPのCloud Functionsではマネージドサービスの組み合わせにより実現できます。
Microsoft Azureでも可能になると嬉しいです。

また、実運用においてはネットワークセキュリティグループの設定を適切に行う必要があるため、ご注意ください。

明日の記事はmaruoka.nさんによる 【ローコード】勤怠管理アプリを1日で作成です、お楽しみに!

imai.kのブログ