Kiểm chứng kết nối AWS Site-to-Site VPN (Part 1)

Kiểm chứng kết nối AWS Site-to-Site VPN (Part 1)

avatar

Phong Nguyen

2025.07.01

Bài viết này giúp bạn biết các tạo một trường kiểm chứng kết nối Site-to-Site VPN. Có được môi trường này, chúng ta có thể tự do test kết nối, test truy cập 2 chiều, test truy cập aws service từ on-premise v.v

Giới thiệu

Trước đây mình có tham gia 1 dự án với khách hàng H, khách có nhờ mình tiết lập kết nối Site-To-Site VPN giữa Onpremise phía Client và VPC môi trường AWS.

Khách lên plan trong vòng 2 tuần, mặc dù thời gian mình setting thật sự từ lúc tìm hiểu đến khi setting chỉ mất 2 ngày. Tuy nhiên vấn đề chờ phía CLient cài đặt, tạo tài liệu thiết kế, test v.v không mất nhiều thời gian lắm nhưng cũng kéo đến 2 tuần (người Nhật thường làm chỉnh chu => thời gian cũng kéo dài hơn so với bình thường)

Sau đây là quy trình để thiết lập Site-To-Site VPN cho Client

  • Cloud Engineer: Vai trò Thiết lập phía AWS infrastructure
  • Client A - Network Administrator: Vai trò: Quản lý network on-premise

Quy trình thiết lập Site-To-Site VPN

Phase 1: Planning & Information Gathering

👤 Client A cung cấp cho bạn:

📄 Thông tin cần thiết:
- Public IP của on-premise gateway: 203.113.xxx.xxx
- On-premise network CIDR: Ex 10.0.0.0/22  
- Preferred routing method: Static/BGP
- Contact person cho technical setup

👤 Bạn (AWS Engineer) cung cấp cho Client A:

📄 AWS side information:
- AWS VPC CIDR: Ex 192.168.0.0/22
- Expected timeline
- Technical requirements

Phase 2: AWS Side Configuration

👤 Bạn thực hiện (AWS side):

  • Deploy AWS infrastructure, Config Customer Gateway, Vitual Provate Gateway, Sito-To-Site VPN v.v
  • Lấy VPN configuration

👤 Bạn gửi cho Client A:

📧 VPN Configuration Package:
- Tunnel 1 Public IP: 52.xxx.xxx.xxx
- Tunnel 2 Public IP: 52.yyy.yyy.yyy  
- Pre-shared Key 1: xxxxxxxxxxxx
- Pre-shared Key 2: yyyyyyyyyyyy
- AWS VPC CIDR: Ex 192.168.0.0/22
- IKE/IPsec parameters

Phase 3: Client Side Configuration

👤 Client A Network Admin thực hiện:

  • Cấu hình on-premise gateway: có thể là libreswan
  • Cấu hình routing
  • Firewall configuration

Phase 4: Testing & Validation

👤 Cả hai bên cùng thực hiện:

  • VPN tunnel status check
  • Connectivity testing (ping v.v)
  • Application testing (http, https v.v)

Tại sao bạn cần môi trường để kiểm chứng

Chỉ khi chúng ta có quyền kết nối đến môi trường Onpre phía Client và được quyền thiết lập firewall, hay config vpn vv thì chúng ta mới có thể chủ động trong công việc thiết lập kết nối Site-To-Site

Thêm nữa, nhiều khi môi trường khách đã có sẵn kết nối, muốn thực hiện các công việc như application trên Onpre muốn upload/dowload file trên S3 thông qua Site-To-Site VPN.

Rõ ràng chúng ta không có một môi trường có VPN thật để test tự do, điều này tạo ra rào cản khá cao. Do đó việc tạo một môi trường kiểm chứng là khá quan trọng. Mình đã đặt ra 2 mục tiêu chính như sau:

  1. Sử dụng phần mềm VPN để đảm bảo kết nối VPN hoạt động bình thường
  2. Quản lý toàn bộ môi trường bằng CloudFormation, có thể tạo và xóa một cách dễ dàng

Ngay cả khi không có thiết bị VPN thật, việc kiểm chứng kết nối VPN vẫn có thể thực hiện hoàn toàn trong môi trường AWS. Ngoài ra, bằng cách tận dụng CloudFormation, Chúng ta có thể dễ dàng tạo và dễ quản lý môi trường.

Lab Introduction

  • AWS experience: Intermediate
  • Time to complete: 40 minutes
  • AWS Region: US East (N. Virginia) us-east-1
  • Services used: VPC resource, EC2, IAM, Customer Gateway, Vitual Private Gateway, Site-To-Site VPN

Prerequisites

  • AWS Account với quyền Admin
  • Kiến thức cơ bản về Cloudformation
  • Kiến thức về Site-To-Site VPN
  • SSH để connect vào EC2

Kiến trúc thực tế

  • Môi trường on-premise và AWS sẽ được kết nối thông qua AWS Site-to-Site VPN
  • Thực hiện test kết nối từ on-premise đến AWS và ngược lại

Kiến trúc kiểm chứng

Trong lần kiểm chứng này, mìn sẽ tạo VPC cho môi trường giả lập on-premise và VPC cho môi trường AWS để tái tạo lại môi trường thực tế.

Task Details

  1. Cloudformation Template
  2. Sử dụng Cloudformation tạo resource cho 2 môi trường
  3. Setting VPN
  4. Kiểm tra kết nối
  5. Troublesooting
  6. Clean up

1. Cloudformation Template

Tải file Cloudformation template tại đây

Mình đã sử dụng AI để tạo các CloudFormation template với nội dung dưới đây. Điều này rất tiện lợi vì có thể kiểm tra một phần các lỗi viết sai và tính nhất quán của template dài.

Đặc điểm chung:

  • Cấu hình VPC: Cả hai template đều thiết lập VPC và subnet
  • EC2 Instance: Tạo EC2 instance với Amazon Linux 2023
  • Security Group: Thiết lập security group chỉ cho phép lưu lượng tối thiểu cần thiết
  • IAM Role và VPC Endpoint: Thiết lập IAM role và VPC endpoint cần thiết (SSM, EC2 Messages, SSM Messages) để có thể kết nối đến EC2 instance bằng Systems Manager Session Manager
  • S3 VPC Endpoint: Thiết lập VPC Gateway Endpoint cho S3 để EC2 instance có thể truy cập S3 mà không cần thông qua Internet. Điều này cho phép cài đặt package bằng dnf hoặc yum.
  • Tagging: Gắn tag cho tất cả resource để dễ quản lý. Prefix của tag có thể chỉ định thông qua parameter

Đặc điểm riêng của template môi trường On-premise (Onpre_resource.yaml)

  • Cấu hình Subnet: Tạo cả Public subnet và Private subnet
  • EC2 Instance (Public subnet): EC2 instance đóng vai trò thiết bị VPN (được gán Elastic IP). Tắt tính năng Source / destination checking của network
  • EC2 Instance (Private subnet): EC2 instance đóng vai trò client
  • Routing: Route traffic từ Private subnet thông qua Public EC2 instance (giả lập NAT Gateway)
  • Internet Gateway: Thiết lập Internet Gateway cho Public subnet

Đặc điểm riêng của template môi trường AWS (AWS_resource.yaml)

  • Cấu hình Subnet: Chỉ tạo Private subnet
  • VPN Resources: Tạo Customer Gateway, Virtual Private Gateway, VPN Connection, và VPN Connection Route
  • Parameter: Nhận địa chỉ IP của Customer Gateway thông qua parameter
  • EC2 Instance: Tạo 1 EC2 instance trong Private subnet (đóng vai trò server được truy cập qua VPN)

1.1 Onpre_resource.yaml:

AWSTemplateFormatVersion: '2010-09-09'
Description: 'VPC with Public and Private Subnets, EC2 Instances, SSM access, and S3 Endpoint'

Parameters:
  TagPrefix:
    Type: String
    Default: '00000'
    Description: 'Prefix for resource tags'
  AmazonLinux2023AMI:
    Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
    Default: /aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.1-x86_64

Resources:
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/22
      EnableDnsHostnames: true
      EnableDnsSupport: true
      Tags:
        - Key: Name
          Value: !Sub '${TagPrefix}-VPC'

  InternetGateway:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: !Sub '${TagPrefix}-IGW'

  InternetGatewayAttachment:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      InternetGatewayId: !Ref InternetGateway
      VpcId: !Ref VPC

  PublicSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select [0, !GetAZs '']
      CidrBlock: 10.0.1.0/24
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: !Sub '${TagPrefix}-Public-Subnet'

  PrivateSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select [1, !GetAZs '']
      CidrBlock: 10.0.0.0/24
      MapPublicIpOnLaunch: false
      Tags:
        - Key: Name
          Value: !Sub '${TagPrefix}-Private-Subnet'

  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub '${TagPrefix}-Public-RT'

  PrivateRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub '${TagPrefix}-Private-RT'

  PublicRoute:
    Type: AWS::EC2::Route
    DependsOn: InternetGatewayAttachment
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway

  PrivateRoute:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref PrivateRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      InstanceId: !Ref PublicEC2Instance

  PublicSubnetRouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet
      RouteTableId: !Ref PublicRouteTable

  PrivateSubnetRouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnet
      RouteTableId: !Ref PrivateRouteTable

  PublicSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: !Sub '${TagPrefix}-Public-SG'
      GroupDescription: 'Security group for public EC2 instance'
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: -1
          FromPort: -1
          ToPort: -1
          CidrIp: 10.0.0.0/22
      SecurityGroupEgress:
        - IpProtocol: -1
          FromPort: -1
          ToPort: -1
          CidrIp: 0.0.0.0/0
      Tags:
        - Key: Name
          Value: !Sub '${TagPrefix}-Public-SG'

  PrivateSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: !Sub '${TagPrefix}-Private-SG'
      GroupDescription: 'Security group for private EC2 instance'
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: -1
          FromPort: -1
          ToPort: -1
          SourceSecurityGroupId: !Ref PublicSecurityGroup
      SecurityGroupEgress:
        - IpProtocol: -1
          FromPort: -1
          ToPort: -1
          CidrIp: 0.0.0.0/0
      Tags:
        - Key: Name
          Value: !Sub '${TagPrefix}-Private-SG'

  EndpointSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: !Sub '${TagPrefix}-Endpoint-SG'
      GroupDescription: 'Security group for VPC Endpoints'
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          SourceSecurityGroupId: !Ref PrivateSecurityGroup
        - IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          SourceSecurityGroupId: !Ref PublicSecurityGroup
      Tags:
        - Key: Name
          Value: !Sub '${TagPrefix}-Endpoint-SG'

  PublicEC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      InstanceType: t3.micro
      ImageId: !Ref AmazonLinux2023AMI
      SubnetId: !Ref PublicSubnet
      SecurityGroupIds:
        - !Ref PublicSecurityGroup
      IamInstanceProfile: !Ref EC2InstanceProfile
      SourceDestCheck: false
      Tags:
        - Key: Name
          Value: !Sub '${TagPrefix}-Onpre-Public-EC2'

  PrivateEC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      InstanceType: t3.micro
      ImageId: !Ref AmazonLinux2023AMI
      SubnetId: !Ref PrivateSubnet
      SecurityGroupIds:
        - !Ref PrivateSecurityGroup
      IamInstanceProfile: !Ref EC2InstanceProfile
      Tags:
        - Key: Name
          Value: !Sub '${TagPrefix}-Onpre-Private-EC2'

  PublicEIP:
    Type: AWS::EC2::EIP
    Properties:
      Domain: vpc
      InstanceId: !Ref PublicEC2Instance
      Tags:
        - Key: Name
          Value: !Sub '${TagPrefix}-Public-EIP'

  EC2InstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Path: "/"
      Roles:
        - !Ref EC2SSMRole

  S3Endpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      VpcId: !Ref VPC
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.s3'
      VpcEndpointType: Gateway
      RouteTableIds:
        - !Ref PrivateRouteTable

  EC2SSMRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - ec2.amazonaws.com
            Action:
              - sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
        - arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
      Tags:
        - Key: Name
          Value: !Sub '${TagPrefix}-EC2-SSM-Role'

  SSMEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.ssm'
      VpcId: !Ref VPC
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      SubnetIds:
        - !Ref PrivateSubnet
        - !Ref PublicSubnet
      SecurityGroupIds:
        - !Ref EndpointSecurityGroup

  SSMMessagesEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.ssmmessages'
      VpcId: !Ref VPC
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      SubnetIds:
        - !Ref PrivateSubnet
        - !Ref PublicSubnet
      SecurityGroupIds:
        - !Ref EndpointSecurityGroup

Outputs:
  PublicEC2InstanceId:
    Description: 'Public EC2 Instance ID'
    Value: !Ref PublicEC2Instance
  PrivateEC2InstanceId:
    Description: 'Private EC2 Instance ID'
    Value: !Ref PrivateEC2Instance
  PublicEIP:
    Description: 'Elastic IP for Public EC2 Instance'
    Value: !Ref PublicEIP

1.2 AWS_resource.yaml

AWSTemplateFormatVersion: '2010-09-09'
Description: 'VPC with Private Subnet, EC2 Instance, Site-to-Site VPN, and S3 Endpoint'

Parameters:
  TagPrefix:
    Type: String
    Default: '00000'
    Description: 'Prefix for resource tags'
  CustomerGatewayIp:
    Type: String
    Description: 'Public IP address of your Customer Gateway'
  AmazonLinux2023AMI:
    Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
    Default: '/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.1-x86_64'
    Description: 'Amazon Linux 2023 AMI ID'

Resources:
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 192.168.0.0/22
      EnableDnsHostnames: true
      EnableDnsSupport: true
      Tags:
        - Key: Name
          Value: !Sub '${TagPrefix}-VPC'

  PrivateSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select [0, !GetAZs '']
      CidrBlock: 192.168.0.0/24
      MapPublicIpOnLaunch: false
      Tags:
        - Key: Name
          Value: !Sub '${TagPrefix}-Private-Subnet'

  PrivateRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub '${TagPrefix}-Private-RT'

  PrivateSubnetRouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnet
      RouteTableId: !Ref PrivateRouteTable

  VPNSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: !Sub '${TagPrefix}-VPN-SG'
      GroupDescription: 'Security group for VPN connection and SSM'
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: -1
          FromPort: -1
          ToPort: -1
          CidrIp: 10.0.0.0/22
        - IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: 192.168.0.0/22
      Tags:
        - Key: Name
          Value: !Sub '${TagPrefix}-VPN-SG'

  EC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      InstanceType: t3.micro
      ImageId: !Ref AmazonLinux2023AMI
      SubnetId: !Ref PrivateSubnet
      SecurityGroupIds:
        - !Ref VPNSecurityGroup
      IamInstanceProfile: !Ref EC2InstanceProfile
      Tags:
        - Key: Name
          Value: !Sub '${TagPrefix}-AWS-Private-EC2'

  EC2InstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Path: "/"
      Roles:
        - !Ref EC2SSMRole

  S3Endpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      VpcId: !Ref VPC
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.s3'
      VpcEndpointType: Gateway
      RouteTableIds:
        - !Ref PrivateRouteTable

  EC2SSMRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - ec2.amazonaws.com
            Action:
              - sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
        - arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
      Tags:
        - Key: Name
          Value: !Sub '${TagPrefix}-EC2-SSM-Role'

  CustomerGateway:
    Type: AWS::EC2::CustomerGateway
    Properties:
      Type: ipsec.1
      BgpAsn: 65000
      IpAddress: !Ref CustomerGatewayIp
      Tags:
        - Key: Name
          Value: !Sub '${TagPrefix}-CustomerGateway'

  VirtualPrivateGateway:
    Type: AWS::EC2::VPNGateway
    Properties:
      Type: ipsec.1
      Tags:
        - Key: Name
          Value: !Sub '${TagPrefix}-VPNGateway'

  VPNGatewayAttachment:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref VPC
      VpnGatewayId: !Ref VirtualPrivateGateway

  VPNConnection:
    Type: AWS::EC2::VPNConnection
    DependsOn:
      - VirtualPrivateGateway
      - VPNGatewayAttachment
    Properties:
      Type: ipsec.1
      CustomerGatewayId: !Ref CustomerGateway
      VpnGatewayId: !Ref VirtualPrivateGateway
      StaticRoutesOnly: true
      Tags:
        - Key: Name
          Value: !Sub '${TagPrefix}-VPNConnection'

  VPNConnectionRoute:
    Type: AWS::EC2::VPNConnectionRoute
    DependsOn: VPNConnection
    Properties:
      DestinationCidrBlock: 10.0.0.0/22
      VpnConnectionId: !Ref VPNConnection

  VPNRoute:
    Type: AWS::EC2::Route
    DependsOn: VPNGatewayAttachment
    Properties:
      RouteTableId: !Ref PrivateRouteTable
      DestinationCidrBlock: 10.0.0.0/22
      GatewayId: !Ref VirtualPrivateGateway

  SSMEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      VpcId: !Ref VPC
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.ssm'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      SubnetIds:
        - !Ref PrivateSubnet
      SecurityGroupIds:
        - !Ref VPNSecurityGroup

  EC2MessagesEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      VpcId: !Ref VPC
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.ec2messages'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      SubnetIds:
        - !Ref PrivateSubnet
      SecurityGroupIds:
        - !Ref VPNSecurityGroup

  SSMMessagesEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      VpcId: !Ref VPC
      ServiceName: !Sub 'com.amazonaws.${AWS::Region}.ssmmessages'
      VpcEndpointType: Interface
      PrivateDnsEnabled: true
      SubnetIds:
        - !Ref PrivateSubnet
      SecurityGroupIds:
        - !Ref VPNSecurityGroup

Outputs:
  EC2InstanceId:
    Description: 'EC2 Instance ID'
    Value: !Ref EC2Instance
  CustomerGatewayId:
    Description: 'Customer Gateway ID'
    Value: !Ref CustomerGateway
  VirtualPrivateGatewayId:
    Description: 'Virtual Private Gateway ID'
    Value: !Ref VirtualPrivateGateway
  VPNConnectionId:
    Description: 'VPN Connection ID'
    Value: !Ref VPNConnection

2. Sử dụng Cloudformation tạo resource cho 2 môi trường

Sử dụng CloudShell và AWS CLI để chạy command cho thuận tiện

Open Cloudshell

Upload 2 file Cloudformation template lên CloudShell

Sau khi upload xong 2 file thì kiểm tra xem đã tồn tại chưa

Chạy lần lượt các command sau:

# Thiết lập prefix tag (Tất cả các resource sẽ bắt đầu với Prefix này)
TAGPREFIX=SOA-S2S-VPN

# Triển khai phía On-premise
aws cloudformation deploy \
    --stack-name "VPNtest-Onpre-${TAGPREFIX}" \
    --template-file Onpre_resource.yaml \
    --capabilities CAPABILITY_IAM \
    --parameter-overrides TagPrefix=${TAGPREFIX}

# Đợi đến khi stack create Successfully
# Lấy Global IP của EC2 instance đóng vai trò thiết bị VPN phía On-premise
GLOBALIP=`aws ec2 describe-addresses --query 'Addresses[].PublicIp' --filter "Name=tag:Name,Values=${TAGPREFIX}-Public-EIP" --output text` && echo ${GLOBALIP}

# Triển khai phía AWS
aws cloudformation deploy \
    --stack-name "VPNtest-AWS-${TAGPREFIX}" \
    --template-file AWS_resource.yaml \
    --capabilities CAPABILITY_IAM \
    --parameter-overrides TagPrefix=${TAGPREFIX} CustomerGatewayIp=${GLOBALIP}

Đợi cho đến khi hoàn thành

3. Setting VPN

AWS Site-to-Site VPN cho phép tải xuống mẫu cấu hình cho thiết bị VPN phía on-premise. Phía on-premise sẽ sử dụng phần mềm VPN Libreswan, nhưng do không có mẫu tương ứng nên chúng ta sẽ tải xuống mẫu cấu hình của Openswan tương tự.

3.1 VPN config Download

Console VPC -> Site-to-Site VPN connections

  • Vendor: Openswan
  • Platform: Openswan
  • Software: Openswan 2.6.38+
  • IKE version: ikev1
  • Download

Chúng ta sẽ sử dụng 1 phần trong file này để cấu hình Libreswan

3.2 VPN setting

Đối với kết nối từ Libreswan tới AWS Site-to-Site VPN, mình sẽ chỉ sử dụng 1 tunnel. (Mặc dù có thể cấu hình 2 tunnel, nhưng chỉ là kiểm chứng thôi, không cần phải HA)

Sử dụng AWS Systems Manager Session Manager để đăng nhập vào SOA-S2S-VPN-Onpre-Public-EC2 (giả lập On-premise Customer gateway)

  • Cài đặt Libreswan

    sudo su -
    dnf install -y libreswan
    
  • Sửa đổi các tham số kernel

    echo 'net.ipv4.ip_forward=1' | tee -a /etc/sysctl.d/custom-ip-forwarding.conf
    sysctl -p /etc/sysctl.d/custom-ip-forwarding.conf
    

  • Sửa file /etc/ipsec.conf , Chỉ thêm protostack=netkey ở cuối

    vi /etc/ipsec.conf
    
  • Sửa giống như bên dưới

    # /etc/ipsec.conf - Libreswan 4.0 configuration file
    #
    # see 'man ipsec.conf' and 'man pluto' for more information
    #
    # For example configurations and documentation, see https://libreswan.org/wiki/
    
    config setup
            # If logfile= is unset, syslog is used to send log messages too.
            # Note that on busy VPN servers, the amount of logging can trigger
            # syslogd (or journald) to rate limit messages.
            #logfile=/var/log/pluto.log
            #
            # Debugging should only be used to find bugs, not configuration issues!
            # "base" regular debug, "tmi" is excessive (!) and "private" will log
            # sensitive key material (not available in FIPS mode). The "cpu-usage"
            # value logs timing information and should not be used with other
            # debug options as it will defeat getting accurate timing information.
            # Default is "none"
            # plutodebug="base"
            # plutodebug="tmi"
            #plutodebug="none"
            #
            # Some machines use a DNS resolver on localhost with broken DNSSEC
            # support. This can be tested using the command:
            # dig +dnssec DNSnameOfRemoteServer
            # If that fails but omitting '+dnssec' works, the system's resolver is
            # broken and you might need to disable DNSSEC.
            # dnssec-enable=no
            #
            # To enable IKE and IPsec over TCP for VPN server. Requires at least
            # Linux 5.7 kernel or a kernel with TCP backport (like RHEL8 4.18.0-291)
            # listen-tcp=yes
            # To enable IKE and IPsec over TCP for VPN client, also specify
            # tcp-remote-port=4500 in the client's conn section.
            protostack=netkey # chỉ thêm dòng này
    
    # if it exists, include system wide crypto-policy defaults
    include /etc/crypto-policies/back-ends/libreswan.config
    
    # It is best to add your IPsec connections as separate files
    # in /etc/ipsec.d/
    include /etc/ipsec.d/*.conf
    

  • Trích xuất và dán phần kết nối từ cài đặt VPN đã tải xuống và viết lại nội dung.

    vi /etc/ipsec.d/aws.conf
    
  • Copy nội dung ở file config VPN bạn tải về lúc nãy (IPSEC Tunnel #1 -> Mục 4) ra Editor như Notepad. Chỉnh sửa nội dung và dán vào file /etc/ipsec.d/aws.conf

    conn Tunnel1
      authby=secret
      auto=start
      left=%defaultroute
      leftid=54.221.138.238                 # Giữ nguyên thông tin này
      right=34.204.239.19                   # Giữ nguyên thông tin này
      type=tunnel
      ikelifetime=8h
      keylife=1h
      phase2alg=aes128-sha1;modp2048        # Thay 1024 thành 2048
      ike=aes128-sha1;modp2048              # Thay 1024 thành 2048
      auth=esp                              # Xóa dòng này
      keyingtries=%forever
      keyexchange=ike
      leftsubnet=10.0.0.0/22                # left là phía On-premise, 10.0.0.0/22 như trong Cloudformation
      rightsubnet=192.168.0.0/22            # right là phía AWS, 192.168.0.0/22 như trong Cloudformation
      dpddelay=10
      dpdtimeout=30                         # Xóa dòng này
      retransmit-timeout=30s                # Thêm dòng này
      dpdaction=restart_by_peer
    

  • Dán thông tin secret:

    vi /etc/ipsec.d/aws.secrets
    
  • Copy nội dung ở file config VPN bạn tải về lúc nãy (IPSEC Tunnel #1 -> Mục 5)

  • Khởi động daemon ipsec

    sudo systemctl start ipsec
    sudo systemctl status ipsec
    

3.3 Kiểm tra VPN Tunnel

Confirm status của Site-to-Site VPN Tunnel 1 đã Active chưa.

Up ở Tunnel 1 thôi là Ok rồi!

4. Kiểm tra kết nối

4.1 Confirm IP address

Tại CloudShell, chạy command sau để lấy thông tin IP của các Server

TAGPREFIX=SOA-S2S-VPN
aws ec2 describe-instances \
    --filters "Name=instance-state-name,Values=running" "Name=tag:Name,Values=*${TAGPREFIX}*" \
    --query "Reservations[*].Instances[*].[PrivateIpAddress, Tags[?Key=='Name'].Value | [0]]" \
    --output text

Sử dụng địa chỉ IP trong kết quả của bạn cho các testing sau

4.2 Test Ping

Dùng AWS Systems Manager Session Manager Login vào SOA-S2S-VPN-Onpre-Private-EC2

ping {SOA-S2S-VPN-AWS-Private-EC2 IP}

Ngược lại login vào SOA-S2S-VPN-AWS-Private-EC2

ping {SOA-S2S-VPN-Onpre-Private-EC2 IP}

4.3 Confirm http

Login vào SOA-S2S-VPN-AWS-Private-EC2

Chạy các lệnh sau để run web server

cd
touch iam_aws_private
python3 -m http.server 8000

Login vào SOA-S2S-VPN-Onpre-Private-EC2

curl {SOA-S2S-VPN-AWS-Private-EC2 IP}:8000

5. Troublesooting

Khi gặp vấn đề với kết nối VPN, vui lòng kiểm tra các điểm sau:

  • Cấu hình Security Group
  • Cấu hình Route Table
  • File cấu hình Libreswan
  • VPN logs (sudo journalctl -u ipsec)

6. Clean up resources

Tại CloudShell, tiến hành delete CloudFormation Stack

TAGPREFIX=SOA-S2S-VPN
aws cloudformation delete-stack --stack-name "VPNtest-Onpre-${TAGPREFIX}"
aws cloudformation delete-stack --stack-name "VPNtest-AWS-${TAGPREFIX}"

Challenge (Optional)

  • Tạo resouce cần thiết để có thể từ On-premise truy cập S3 trong môi trường AWS thông qua Interface VPC Endpoint của S3
  • Xem tiếp Phần 2

Tài liệu tham khảo: