我无法通过 VPN 将 mysql 客户端连接到 RDS

I can't connect mysql client to RDS through VPN

我一直在努力使用 AWS RDS。所有网络配置的事情真的很痛苦,因为我没有网络技能,我也不喜欢它。

我的目标是在 RDS 上创建我的 mysql 数据库,以便能够通过任何 mysql 客户端连接到它,运行 我的 SQL 脚本来创建数据库并执行我的 lambda 以将数据插入此数据库。

所以,

mysql 客户端 --> RDS (mysql) <-- lambdas

它们都需要相互连接。

经过数周的研究试图了解 AWS 周围的所有网络事物,从一个地方到另一个地方复制示例。

我遇到了以下情况:

我有一个 VPC,public 和私有子网、安全组、EIP、RDS 和 VPN 都在我的云形成模板中。

我可以部署一切正常,似乎一切正常。

我可以连接到我的VPN并ping通我的EIP的私有IP。

但我仍然无法将我的 mysql 客户端连接到我的 RDS。所以,我无法 运行 我的 SQL 脚本,我也无法测试我的 lambda 以查看它们是否真的连接到我的 RDS。

这是我配置的一部分,我猜这可能与问题有关,但正如您想象的那样,我缺乏网络知识使它变得更加困难。

我唯一想到的是 VPN 和 RDS 不属于同一子网。

完整配置:https://gist.github.com/serraventura/ec17d9a09c706e7ace1fd3e3be9972aa

RouteTableDB 始终仅连接到私有子网,而 VPN (ec2) 仅连接到 public 子网。

  SubnetRouteTableAssociationPrivateDB1:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId:
        Ref: RouteTableDB
      SubnetId:
        Ref: SubnetDBPrivate1

  SubnetRouteTableAssociationPrivateDB2:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId:
        Ref: RouteTableDB
      SubnetId:
        Ref: SubnetDBPrivate2

  SubnetRouteTableAssociationPrivate1:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId:
        Ref: RouteTableDB
      SubnetId:
        Ref: SubnetPrivate1

  SubnetRouteTableAssociationPrivate2:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      RouteTableId: !Ref RouteTableDB
      SubnetId: !Ref SubnetPrivate2

RDS、VPN

RDSMySQL:
    Type: AWS::RDS::DBInstance
    Properties:
      AllocatedStorage: ${self:custom.infra.allocatedStorage}
      DBInstanceClass: ${self:custom.infra.dbInstanceClass}
      Engine: ${self:custom.infra.engine}
      DBInstanceIdentifier: ${self:custom.app.dbName}
      DBName: ${self:custom.app.dbName}
      MasterUsername: ${self:custom.app.dbUser}
      MasterUserPassword: ${self:custom.app.dbPass}
      DBSubnetGroupName:
        Ref: myDBSubnetGroup
      MultiAZ: ${self:custom.infra.multiAZ}
      PubliclyAccessible: true
      StorageType: gp2
      VPCSecurityGroups:
        - Ref: RDSSecurityGroup
    DeletionPolicy: Delete

  VPNEIP:
    Type: AWS::EC2::EIP
    Properties:
      InstanceId:
        Ref: VPNEC2Machine
      Domain: vpc

  VPNEC2Machine:
    Type: AWS::EC2::Instance
    Properties:
      KeyName: ${self:custom.infra.ec2KeyPairName.${self:provider.region}}
      ImageId: ${self:custom.infra.openVPNAMI.${self:provider.region}}
      InstanceType: ${self:custom.infra.instanceType}
      AvailabilityZone: ${self:provider.region}a
      Monitoring: true
      SecurityGroupIds:
        - Ref: VPNSecurityGroup
      SubnetId:
        Ref: SubnetPublic1
      Tags:
        - Key: Name
          Value: ${self:custom.companyName} OpenVPN ${self:provider.stage}

  VPNRouteRecordSet:
    Type: AWS::Route53::RecordSet
    DependsOn:
      - VPNEC2Machine
      - VPNEIP
    Properties:
      HostedZoneName: ${self:custom.domains.base}.
      Comment: Record for the VPN subdomain
      Name: vpn-${self:provider.stage}.${self:custom.domains.base}.
      Type: A
      TTL: 60
      ResourceRecords:
        - Ref: VPNEIP

  VPNSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Allow Access From machines to the VPN and Private Network
      VpcId:
        Ref: VPCStaticIP
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: ${self:custom.app.dbPort}
          ToPort: ${self:custom.app.dbPort}
          CidrIp: 0.0.0.0/0
          Description: 'Postgres Port'
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: 0.0.0.0/0
          Description: 'SSH Port'
        - IpProtocol: udp
          FromPort: 1194
          ToPort: 1194
          CidrIp: 0.0.0.0/0
          Description: 'OpenVPN Server Access Port'
        - IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: 0.0.0.0/0
          Description: 'OpenVPN HTTPS Admin Port'
        - IpProtocol: tcp
          FromPort: 943
          ToPort: 943
          CidrIp: 0.0.0.0/0
          Description: 'OpenVPN Server Port'
      Tags:
        - Key: Name
          Value: ${self:custom.companyName} VPN SG ${self:provider.stage}

您的 RDS 实例正在 3306 上接受来自 LambdaSecurityGroup 的入站连接,这对于任何附加了 LambdaSecurityGroup SG 的东西都很好,但您还需要允许来自您的 VPNSecurityGroup 的连接。

将您的 RDSSecurityGroupBlock 更改为如下所示,这应该允许您从 VPN 连接到 RDS:

  RDSSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Allow My SQL access from lambda subnets
      VpcId:
        Ref: VPCStaticIP
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: '3306'
          ToPort: '3306'
          SourceSecurityGroupId:
            Ref: LambdaSecurityGroup
        - IpProtocol: tcp
          FromPort: '3306'
          ToPort: '3306'
          SourceSecurityGroupId:
            Ref: VPNSecurityGroup
      Tags:
        - Key: Name
          Value: RDSSecurityGroup

附带说明一下,VPNSecurityGroup 正在接受来自任何地方的 3306、22、1194、443、943 连接。这可能是有意为之,但考虑到这些是出于管理目的公开的,这不是最佳做法。您应该认真考虑将这些端口的 CidrIp 的范围限定为受信任的 CidrIp 源,以避免任何潜在的不必要的暴露。您还可以考虑从那里一起删除 3306 块,因为似乎没有必要在 VPN 本身上打开该端口。

编辑 根据 OP 的评论,除了上述之外,您还需要将 PubliclyAccessible 更改为 False 以解决问题。

我想给出问题的完整答案,因为标题暗示了 mysql 客户端无法连接 RDS 的问题。

随着@hephalump 的改变,我不得不做更多的两个改变来让我的 lambdas 连接到 RDS,现在我能够连接 mysql 客户端和 lambdas。

我必须为我的 lambda 表达式创建一个新的 IAM 角色

  LambdaRole:
    Type: AWS::IAM::Role
    Properties:
      Path: '/'
      RoleName: LambdaRole
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action: sts:AssumeRole
      Policies:
        - PolicyName: ec2LambdaPolicies
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - ec2:CreateNetworkInterface
                  - ec2:DescribeNetworkInterfaces
                  - ec2:DetachNetworkInterface
                  - ec2:DeleteNetworkInterface
                Resource: "*"
        - PolicyName: 'AllowInvoke'
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: 'Allow'
                Action: 'lambda:InvokeFunction'
                Resource: '*'
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
        - arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole

这里解决问题的重要一点似乎是:

      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
        - arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole

然后我不得不从我的提供商那里删除我的 iamRoleStatements 并添加新角色 role: LambdaRole.

现在我需要将我的 lambda 添加到正确的安全组。

因此,我将供应商上的 VPC 更改为:

  vpc:
    securityGroupIds:
      - Ref: LambdaSecurityGroup
    subnetIds:
      - Ref: SubnetPrivate1

我已经用最新的更改更新了要点。