こんにちは、やまぐちです。
概要
VPC Lambda から NLB → Proxy (Squid) 経由でインターネットへアクセスするまでを書きます。
構成図は以下のような形です。
やってみる
1. リソース作成
まずは、以下のテンプレートを CloudFormation に流してリソースを作成します。
yaml テンプレート
AWSTemplateFormatVersion: "2010-09-09" Description: "create EC2Instance and NLB" Parameters: KeyName: Type: AWS::EC2::KeyPair::KeyName Description: "Key Pair Name" InstanceType: Type: String Description: "EC2 Instance Type" Default: "t3.micro" ImageId: Type: AWS::EC2::Image::Id Description: "EC2 Image ID" Default: "ami-05a03e6058638183d" Metadata: AWS::CloudFormation::Interface: ParameterGroups: - Label: default: "EC2 Instance Configuration" Parameters: - KeyName - InstanceType - ImageId ParameterLabels: KeyName: default: "Key Pair Name" InstanceType: default: "EC2 Instance Type" ImageId: default: "EC2 Image ID" Resources: VPC: Type: AWS::EC2::VPC Properties: CidrBlock: 10.0.0.0/16 EnableDnsSupport: true EnableDnsHostnames: true Tags: - Key: Name Value: squid-test-vpc PublicSubnet1a: Type: AWS::EC2::Subnet Properties: VpcId: !Ref VPC CidrBlock: 10.0.1.0/24 AvailabilityZone: ap-northeast-1a MapPublicIpOnLaunch: true Tags: - Key: Name Value: squid-test-public-subnet-a PublicSubnet1c: Type: AWS::EC2::Subnet Properties: VpcId: !Ref VPC CidrBlock: 10.0.2.0/24 AvailabilityZone: ap-northeast-1c MapPublicIpOnLaunch: true Tags: - Key: Name Value: squid-test-public-subnet-c PrivateSubnet1a: Type: AWS::EC2::Subnet Properties: VpcId: !Ref VPC CidrBlock: 10.0.3.0/24 AvailabilityZone: ap-northeast-1a Tags: - Key: Name Value: squid-test-private-subnet-a PrivateSubnet1c: Type: AWS::EC2::Subnet Properties: VpcId: !Ref VPC CidrBlock: 10.0.4.0/24 AvailabilityZone: ap-northeast-1c Tags: - Key: Name Value: squid-test-private-subnet-c InternetGateway: Type: AWS::EC2::InternetGateway Properties: Tags: - Key: Name Value: squid-test-igw AttachGateway: Type: AWS::EC2::VPCGatewayAttachment Properties: VpcId: !Ref VPC InternetGatewayId: !Ref InternetGateway PublicRouteTable: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref VPC Tags: - Key: Name Value: squid-test-public-route-table PublicRoute: Type: AWS::EC2::Route DependsOn: AttachGateway Properties: RouteTableId: !Ref PublicRouteTable DestinationCidrBlock: 0.0.0.0/0 GatewayId: !Ref InternetGateway PrivateRouteTable: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref VPC Tags: - Key: Name Value: squid-test-private-route-table AttachPrivateRouteTable1a: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref PrivateSubnet1a RouteTableId: !Ref PrivateRouteTable AttachPrivateRouteTable1c: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref PrivateSubnet1c RouteTableId: !Ref PrivateRouteTable AttachPublicRouteTable1a: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref PublicSubnet1a RouteTableId: !Ref PublicRouteTable AttachPublicRouteTable1c: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref PublicSubnet1c RouteTableId: !Ref PublicRouteTable LambdaSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Security Group with Inbound Rule for Port 3128 VpcId: !Ref VPC Tags: - Key: Name Value: squid-test-lambda-sg EC2InstanceSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Security Group with Inbound Rule for Port 3128 SecurityGroupIngress: - IpProtocol: tcp FromPort: 3128 ToPort: 3128 SourceSecurityGroupId: !Ref LambdaSecurityGroup - IpProtocol: tcp FromPort: 3128 ToPort: 3128 CidrIp: 10.0.3.0/24 - IpProtocol: tcp FromPort: 3128 ToPort: 3128 CidrIp: 10.0.4.0/24 VpcId: !Ref VPC Tags: - Key: Name Value: squid-test-sg VPCLambda: Type: AWS::Lambda::Function Properties: Handler: index.lambda_handler Role: !GetAtt LambdaExecutionRole.Arn FunctionName: squid-test-vpc-lambda Runtime: python3.12 VpcConfig: SubnetIds: - !Ref PrivateSubnet1a - !Ref PrivateSubnet1c SecurityGroupIds: - !Ref LambdaSecurityGroup Code: ZipFile: | import urllib.request import os def lambda_handler(event, context): url = 'https://www.google.com/' with urllib.request.urlopen(url) as response: print(response.getcode()) LambdaExecutionRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: lambda.amazonaws.com Action: sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole EC2Instance: Type: AWS::EC2::Instance Properties: KeyName: !Ref KeyName ImageId: !Ref ImageId InstanceType: t3.micro NetworkInterfaces: - AssociatePublicIpAddress: true DeviceIndex: 0 GroupSet: - !Ref EC2InstanceSecurityGroup SubnetId: !Ref PublicSubnet1a UserData: !Base64 | #!/bin/bash -ex dnf install squid -y systemctl start squid systemctl enable squid sed -i "/network by proxying external TCP connections to unprotected services./a http_access allow localnet" /etc/squid/squid.conf systemctl restart squid Tags: - Key: Name Value: squid-test NLBTargets3128: Type: AWS::ElasticLoadBalancingV2::TargetGroup Properties: HealthCheckTimeoutSeconds: 10 Name: tg-squid-test-nlb-3128 Port: 3128 Protocol: TCP HealthyThresholdCount: 3 UnhealthyThresholdCount: 3 Tags: - Key: Name Value: tg-squid-test-nlb-3128 Targets: - Id: !Ref EC2Instance Port: 3128 TargetType: instance VpcId: !Ref VPC NLB: Type: AWS::ElasticLoadBalancingV2::LoadBalancer Properties: Name: squid-test-nlb Tags: - Key: Name Value: squid-test-nlb Scheme: internal LoadBalancerAttributes: - Key: deletion_protection.enabled Value: false - Key: load_balancing.cross_zone.enabled Value: true Subnets: - !Ref PrivateSubnet1a - !Ref PrivateSubnet1c Type: network NLBListener3128: Type: AWS::ElasticLoadBalancingV2::Listener Properties: DefaultActions: - TargetGroupArn: !Ref NLBTargets3128 Type: forward LoadBalancerArn: !Ref NLB Port: 3128 Protocol: TCP
スタックを作成すると構成図のリソースが作成されます。
EC2 インスタンスの OS は Amazon Linux 2023 にしました。
Squid の詳しい設定については、本ブログでは割愛します。
設定した内容は以下のブログで記載したものと同じで、今回はユーザデータですべての処理を完了させています。
blog.serverworks.co.jp
2. Lambda の実行
では、さっそくテンプレートから作成した VPC Lambda をテスト実行してみます。
上手くいけば、レスポンスコード「200」が返ってくるはずです。
タイムアウトしてしまいました、
VPC からインターネットへアクセスができない状態となっているのがわかるかと思います。
環境変数の設定
ということで、VPC Lambda が プロキシ経由でインターネットへアクセスできるように環境変数を設定します。
「設定」-「環境変数」-「編集」を選択します。
以下のようにhttp_proxy
とhttps_proxy
をキーとする環境変数を追加します。
キー | 値 |
---|---|
http_proxy | http:// NLB の DNS 名:3128 |
https_proxy | http:// NLB の DNS 名:3128 |
NLB の DNS 名はマネジメントコンソールからコピー可能です。
再度 Lambda を実行
ということで、環境変数を設定した状態でもう一度、Lambda を実行します。
「200」が返ってきました!
まとめ
VPC Lambda からプロキシ経由でインターネットへ接続したい場合は、環境変数に設定をしてあげると良い
というだけでした~
それではまたどこかで~