Amazon Web Services ブログ

AWS IoT ボタンによる、ジャストインタイムの VPN アクセス

AWS コミュニティヒーローである Teri Radichel による寄稿。Teri Radichel は、彼女の会社である 2nd Sight Lab を通じてサイバーセキュリティ評価、ペネトレーションテスト、調査サービスを提供しています。また、彼女は AWS Architects Seattle Meetup の創設者でもあります。

クラウドセキュリティのトレーニングを行うために旅行している間、私はホテルの部屋でも、教室でも VPN を使用して Wi-Fi ネットワークに接続します。ほとんどの企業は、リモート VPN エンドポイントをインターネット全体に公開しています。そこで、必要な場所にだけネットワークアクセスを許可するために AWS IoT ボタンを使用できるという仮説を思いつきました。VPN ユーザーがクリックするとアクセスできるようになり、ネットワークルールが起動され、ダブルクリックすると再びネットワークトラフィックが許可されなくなるとしたらどうでしょうか。 このアイディアを試したところ、以下の結果が分かります。

なぜ、VPN をリモートクラウド管理に使用するのか、疑問に思われるかもしれません。なぜ、ノートパソコンやモバイルアプリケーションではなくて AWS IoT ボタンなのでしょうか? それについての詳細は、私のクラウドセキュリティに関するブログをご覧ください。

最初は、デバイスで使用される証明書を組織が管理できるので、AWS IoT エンタープライズボタンを使用したいと考えていました。また Wi-Fi も使用し、ネットワークアクセスを許可するためにボタンの IP アドレスを取得することを望んでいました。そのためには、ラップトップと同じ IP アドレスをボタンが Wi-Fi ネットワークから受け取ったことを証明できなければなりませんでした。残念ながら、一部のワイヤレスネットワークで使用されるキャプティブポータルのために、一部の場所でボタンを接続するのに問題がありました。

次に、AT&T LTE-M ボタンを試しました。このボタンを今回のユースケースのために機能させることはできましたが、必要とされるほどユーザーフレンドリーではありませんでした。このボタンは、ホテルの部屋で VPN に接続するために使用している Wi-Fi ではなく、セルラーネットワークにあるため、IP アドレスを自動的に判断することができないのです。AWS IoT モバイルアプリケーションを使用して手動で設定しなければなりません。

もう一つの問題は VPN 接続の後で、一部のネットワークが Wi-Fi クライアントのパブリック IP アドレスを変更することです。変更前と変更後の IP アドレスは常に同じネットワークブロック内にありますが、一貫性はありません。単一の IP アドレスを使用する代わりに、ユーザーはどの IP 範囲がボタンに渡されるかを特定する方法を理解する必要があります。この概念実証の実装はうまく動作しますが、ネットワークに精通していないユーザーにとっては理想的なソリューションではありません。

幸いなことに、管理者権限で自分の AWS アカウントにログインして、ネットワーク設定を変更したり、自分の場所から VPN エンドポイントへのアクセスを許可したりする必要はありません。アクセスを許可する AWS Lambda 関数のロールと同様に、AWS IoT ボタンのユーザーのアクセス許可は制限されています。AWS IoT ボタンは、多要素認証の一種です。

Lambda 関数を使ったボタンの設定

注意: これは完全にテストされた、または本番稼働可能なソリューションではなく、管理エンドポイントへのオンデマンドのネットワークアクセスの実装に関するいくつかのアイデアを得るための出発点です。ボタンと Lambda 関数の役割は、概念実証の実装で使用したものよりもはるかに制限があります。

1.VPN エンドポイントを設定します (設定に関する指示はこの記事の範囲を超えています)。OpenVPN や、リモートアクセス用の VPN を作成できるようにする AWS Marketplace のオプションなどを使用できます。

2.Jeff Barr が、Lambda 関数を使用して AWS IoT ボタンを設定する方法に関する最も優れた記事をすでに書いています。そのプロセスは簡単です。

3.ボタンでネットワークを変更できるようにするには、Lambda のロールがネットワーク ACL エントリを置き換える機能を追加します。このロールにより、割り当てられたリソースはアカウント内の任意のルールを更新できます。ただし、推奨されません! さらにこれを特定のネットワーク ACL に制限します。また、ユーザーが編集できるのは、割り当てられた自分のボタンのプレイスメント属性だけであることを確認します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "ec2:ReplaceNetworkAclEntry",
            "Resource": "*"
        }
    ]
}

4.コードを書きます。

私のテストでは、ボタンに付属していたデフォルトコードを編集して、自分がやろうとしていたことがうまくいくことを証明しました。テキストメッセージを送信する行を残しましたが、ネットワーク変更の後です。そのため、エラーが発生した場合、ユーザーは SNS メッセージを受信しません。

さらに、必ず、必ず、必ずクライアントから任意のアプリケーションに送信されたすべての入力を検証する必要があります。それを追加できる場所を示すためにログの行を追加しました。環境に合わせて次の変数を変更します: vpcid、nacl、rule。ルールパラメータは、ボタンアプリケーションで提供された IP アドレスを使用するように更新された、ネットワーク ACL 内のルールです。

from __future__ import print_function

import boto3
import json
import logging

logger = logging.getLogger()
logger.setLevel(logging.INFO)

sns = boto3.client('sns')

def lambda_handler(event, context):

    logger.info('Received event: ' + json.dumps(event))

    attributes = event['placementInfo']['attributes']

    phone_number = attributes['phoneNumber']
    message = attributes['message']
    ip = attributes['ip']

    logger.info("Need code here to validate this is a valid IP address")
    logger.info("Need code here to validate the message")
    logger.info("Need code here to validate the phone number")

    for key in attributes.keys():
        message = message.replace('{{%s}}' % (key), attributes[key])
    message = message.replace('{{*}}', json.dumps(attributes))

    dsn = event['deviceInfo']['deviceId']
    click_type = event['deviceEvent']['buttonClicked']['clickType']
  
    vpcid = 'vpc-xxxxxxxxxxxxxxxx'
    nacl = 'acl-xxxxxxxxxxxxxxx'
    rule = 200
    
    cidr =  ip + '/32'
    
    message = message + " " + cidr
    
    client = boto3.client('ec2')

    response = client.replace_network_acl_entry(
        NetworkAclId=nacl,
        CidrBlock=cidr,
        DryRun=False,
        Egress=False,
        PortRange={
            'From': 500,
            'To': 500
        },
        Protocol="17",
        RuleAction="allow",
        RuleNumber=rule
    )
    
    sns.publish(PhoneNumber=phone_number, Message=message)

    logger.info('SMS has been sent to ' + phone_number)

 

5.ネットワークアクセスを削除する、ダブルクリックの場合のコードを書きます。このコードは、読者のための演習として残しました。前の手順でネットワーク ACL を編集する方法を理解していれば、RuleAction = “allow” という行を RuleAction = “deny” に変更して、トラフィックを許可しないダブルクリックの機能を作成できます。これで、リモートユーザーが VPN に接続できるようにするネットワークポートへのアクセスがブロックされました。

ボタンのテスト

1.https://whatismyip.com などのサイトにアクセスして、現在のネットワークのパブリック IP アドレスを取得します。

この記事では、必要な IP アドレスは 1 つだけであるとします。ただし、上記のコードを変更して、代わりに IP の範囲 (つまり CIDR ブロック) を許可することもできます。

2.ボタンのモバイルアプリにログインします。

3.[Projects] を選択し、ボタンのプロジェクトを選択します。ここでは、「vpn2」と名前を付けました。

4.ボタンに割り当てた Lambda 関数に関連付けられているプロジェクトには、以下のプレイスメント属性が必要です。
message: ネットワークが更新されました!
phoneNumber: テキストを受信する電話番号。
ip: whatismyip.com からの IP アドレス。

5.既存の属性を選択して変更するか、[+ Add Placement Attribute] を選択して新しく追加します。

6.AWS IoT ボタンを押して、Lambda 関数を起動します。エラーなしで実行された場合は、入力した IP アドレスを含むテキストメッセージが届きます。

7.VPC ネットワークの ACL ルールをチェックして、正しい IP アドレスに変更されていることを確認します。

8.VPN に接続できることを確認します。

9.アクセスを無効にするダブルクリック機能を実装した場合は、ボタンをダブルクリックすると、ネットワーク ACL ルールを「allow」ではなく「deny」に変更します。

これで、AWS IoT ボタンを使用してネットワークルールをオンデマンドで変更する方法が分かりました。できれば、この記事が AWS VPN と管理エンドポイントにさらにセキュリティの層を追加するためのいくつかのアイデアを刺激できることを期待しています!