2023-07-19 10:07:22 +08:00
{
"AWSTemplateFormatVersion" : "2010-09-09" ,
"Mappings" : {
"OS" : {
"Ubuntu2004" : {
2023-07-19 12:32:45 +08:00
"HelperInstallationCommands" : "export DEBIAN_FRONTEND=noninteractive\napt-get -yq update\napt-get -yq install python3-pip\npython3 -m pip install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-py3-latest.tar.gz\n"
2023-07-19 10:07:22 +08:00
} ,
2023-07-21 11:23:09 +08:00
"Ubuntu2204" : {
"HelperInstallationCommands" : "export DEBIAN_FRONTEND=noninteractive\napt-get -yq update\napt-get -yq install python3-pip\npython3 -m pip install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-py3-latest.tar.gz\n"
} ,
"Debian10" : {
"HelperInstallationCommands" : "export DEBIAN_FRONTEND=noninteractive\napt-get -yq update\napt-get -yq install python3-pip\npython3 -m pip install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-py3-latest.tar.gz\n"
} ,
"Debian11" : {
"HelperInstallationCommands" : "export DEBIAN_FRONTEND=noninteractive\napt-get -yq update\napt-get -yq install python3-pip\npython3 -m pip install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-py3-latest.tar.gz\n"
} ,
"Debian12" : {
"HelperInstallationCommands" : "export DEBIAN_FRONTEND=noninteractive\nrm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED\napt-get -yq update\napt-get -yq install python3-pip\npython3 -m pip install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-py3-latest.tar.gz\n"
} ,
2023-07-19 10:07:22 +08:00
"CentOS7" : {
2023-07-19 12:32:45 +08:00
"HelperInstallationCommands" : "yum -y install python3 wget\npython3 -m pip install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-py3-latest.tar.gz\n"
2023-07-19 10:07:22 +08:00
} ,
"AmazonLinux2" : {
2023-07-19 12:32:45 +08:00
"HelperInstallationCommands" : "export PATH=\"$PATH:/opt/aws/bin\"\n"
2023-07-19 10:07:22 +08:00
}
}
} ,
2023-07-20 18:15:12 +08:00
"Metadata" : { } ,
2023-07-19 10:07:22 +08:00
"Resources" : {
"VpnVpc" : {
"Type" : "AWS::EC2::VPC" ,
"Properties" : {
"CidrBlock" : "10.0.0.0/24"
} ,
2023-07-20 18:15:12 +08:00
"Metadata" : { }
2023-07-19 10:07:22 +08:00
} ,
"VpnSubnet" : {
"Type" : "AWS::EC2::Subnet" ,
"Properties" : {
"VpcId" : {
"Ref" : "VpnVpc"
} ,
"CidrBlock" : "10.0.0.0/24" ,
"MapPublicIpOnLaunch" : true ,
"AvailabilityZone" : {
"Fn::Select" : [
"0" ,
{
"Fn::GetAZs" : ""
}
]
}
} ,
2023-07-20 18:15:12 +08:00
"Metadata" : { } ,
2023-07-19 10:07:22 +08:00
"DependsOn" : [
"VpnVpc" ,
"VpcInternetGateway"
]
} ,
"VpnRouteTable" : {
"Type" : "AWS::EC2::RouteTable" ,
"Properties" : {
"VpcId" : {
"Ref" : "VpnVpc"
}
} ,
2023-07-20 18:15:12 +08:00
"Metadata" : { } ,
2023-07-19 10:07:22 +08:00
"DependsOn" : [
"VpnSubnet"
]
} ,
"PublicInternetRoute" : {
"Type" : "AWS::EC2::Route" ,
"Properties" : {
"DestinationCidrBlock" : "0.0.0.0/0" ,
"RouteTableId" : {
"Ref" : "VpnRouteTable"
} ,
"GatewayId" : {
"Ref" : "VpcInternetGateway"
}
} ,
2023-07-20 18:15:12 +08:00
"Metadata" : { } ,
2023-07-19 10:07:22 +08:00
"DependsOn" : [
"VpnRouteTable" ,
"VpcInternetGateway" ,
"InternetGatewayAttachment"
]
} ,
"VpnInstance" : {
"Type" : "AWS::EC2::Instance" ,
"CreationPolicy" : {
"ResourceSignal" : {
"Timeout" : "PT15M"
}
} ,
"Properties" : {
"UserData" : {
"Fn::Base64" : {
"Fn::Join" : [
"" ,
[
"#!/bin/bash -xe\n" ,
"trap 'cfn-signal -e 1 " ,
" --stack " ,
{
"Ref" : "AWS::StackName"
} ,
" --resource VpnInstance " ,
" --region " ,
{
"Ref" : "AWS::Region"
} ,
"' ERR\n" ,
"sleep 60\n" ,
{
"Fn::FindInMap" : [
"OS" ,
{
"Ref" : "OS"
} ,
"HelperInstallationCommands"
]
} ,
"export VPN_IPSEC_PSK='" ,
{
"Ref" : "VpnIpsecPsk"
} ,
"'\n" ,
"export VPN_USER='" ,
{
"Ref" : "VpnUser"
} ,
"'\n" ,
"export VPN_PASSWORD='" ,
{
"Ref" : "VpnPassword"
} ,
"'\n" ,
2023-07-19 12:32:45 +08:00
"wget -t 3 -T 30 -nv -O vpn.sh https://github.com/hwdsl2/setup-ipsec-vpn/raw/master/vpnsetup.sh\n" ,
2023-07-19 10:07:22 +08:00
"sh vpn.sh\n" ,
"cfn-signal -e 0 " ,
" --stack " ,
{
"Ref" : "AWS::StackName"
} ,
" --resource VpnInstance " ,
" --region " ,
{
"Ref" : "AWS::Region"
} ,
"\n"
]
]
}
} ,
"SecurityGroupIds" : [
{
"Fn::GetAtt" : [
"VpnSecurityGroup" ,
"GroupId"
]
}
] ,
"SubnetId" : {
"Ref" : "VpnSubnet"
} ,
"AvailabilityZone" : {
"Fn::Select" : [
"0" ,
{
"Fn::GetAZs" : ""
}
]
} ,
"InstanceType" : {
"Ref" : "InstanceType"
} ,
"KeyName" : {
"Fn::GetAtt" : [
"KeyPairInfo" ,
"KeyName"
]
} ,
"ImageId" : {
"Fn::GetAtt" : [
"AMIInfo" ,
"AMIId"
]
}
} ,
2023-07-20 18:15:12 +08:00
"Metadata" : { } ,
2023-07-19 10:07:22 +08:00
"DependsOn" : [
"VpnRouteTable" ,
"VpnServerVolume" ,
"KeyPairCreation" ,
"AMIInfoFunction" ,
"VpnSecurityGroup"
]
} ,
"VpnSecurityGroup" : {
"Type" : "AWS::EC2::SecurityGroup" ,
"Properties" : {
"GroupDescription" : "The VPN Security Group, allowing ingress UDP traffic at port 4500 and 500." ,
"GroupName" : "VpnSecurityGroup" ,
"VpcId" : {
"Ref" : "VpnVpc"
} ,
"SecurityGroupIngress" : [
{
"CidrIp" : "0.0.0.0/0" ,
"IpProtocol" : "tcp" ,
"FromPort" : 22 ,
"ToPort" : 22
} ,
{
"CidrIp" : "0.0.0.0/0" ,
"IpProtocol" : "udp" ,
"FromPort" : 500 ,
"ToPort" : 500
} ,
{
"CidrIp" : "0.0.0.0/0" ,
"IpProtocol" : "udp" ,
"FromPort" : 4500 ,
"ToPort" : 4500
}
] ,
"SecurityGroupEgress" : [
{
"CidrIp" : "0.0.0.0/0" ,
"IpProtocol" : -1
}
]
} ,
2023-07-20 18:15:12 +08:00
"Metadata" : { }
2023-07-19 10:07:22 +08:00
} ,
"VpnServerVolume" : {
"Type" : "AWS::EC2::Volume" ,
"Properties" : {
"AvailabilityZone" : {
"Fn::Select" : [
"0" ,
{
"Fn::GetAZs" : ""
}
]
} ,
"Size" : 8
} ,
2023-07-20 18:15:12 +08:00
"Metadata" : { }
2023-07-19 10:07:22 +08:00
} ,
"VpcInternetGateway" : {
"Type" : "AWS::EC2::InternetGateway" ,
"Properties" : { } ,
2023-07-20 18:15:12 +08:00
"Metadata" : { } ,
2023-07-19 10:07:22 +08:00
"DependsOn" : [
"VpnVpc"
]
} ,
"EC2SRTA4VJU5" : {
"Type" : "AWS::EC2::SubnetRouteTableAssociation" ,
"Properties" : {
"RouteTableId" : {
"Ref" : "VpnRouteTable"
} ,
"SubnetId" : {
"Ref" : "VpnSubnet"
}
} ,
2023-07-20 18:15:12 +08:00
"Metadata" : { }
2023-07-19 10:07:22 +08:00
} ,
"KeyPairCreation" : {
"Type" : "AWS::Lambda::Function" ,
"Properties" : {
"Handler" : "index.handler" ,
"Runtime" : "python3.7" ,
"Role" : {
"Fn::GetAtt" : [
"LambdaExecutionRole" ,
"Arn"
]
} ,
"Timeout" : 30 ,
"Code" : {
"ZipFile" : {
"Fn::Join" : [
"\n" ,
[
"import boto3" ,
"import cfnresponse" ,
"import string" ,
"import random" ,
"'''" ,
"This python program should be embedded into its designated cloudformation" ,
"template as the inline code of one of the lambda functions." ,
"'''" ,
"def handler(event, context):" ,
" try:" ,
" keyName = 'setup-ipsec-vpn-' + ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits) for _ in range(10))" ,
" region = event['ResourceProperties']['Region']" ,
" ec2 = boto3.client('ec2',region)" ,
" response = ec2.create_key_pair(" ,
" KeyName=keyName" ,
" )" ,
" keyMaterial = response['KeyMaterial']" ,
" cfnresponse.send(event, context, cfnresponse.SUCCESS, {'KeyMaterial':keyMaterial, 'KeyName':keyName}, 'KeyPairInfo')" ,
" except Exception:" ,
" cfnresponse.send(event, context, cfnresponse.FAILED, {})"
]
]
}
}
} ,
2023-07-20 18:15:12 +08:00
"Metadata" : { } ,
2023-07-19 10:07:22 +08:00
"DependsOn" : [
"LambdaExecutionRole"
]
} ,
"AMIInfo" : {
"Type" : "Custom::AMIInfo" ,
"Properties" : {
"Region" : {
"Ref" : "AWS::Region"
} ,
"ServiceToken" : {
"Fn::GetAtt" : [
"AMIInfoFunction" ,
"Arn"
]
} ,
"Distribution" : {
"Ref" : "OS"
}
} ,
2023-07-20 18:15:12 +08:00
"Metadata" : { } ,
2023-07-19 10:07:22 +08:00
"DependsOn" : [
"AMIInfoFunction"
]
} ,
"AMIInfoFunction" : {
"Type" : "AWS::Lambda::Function" ,
"Properties" : {
"Handler" : "index.handler" ,
"Runtime" : "python3.7" ,
"Role" : {
"Fn::GetAtt" : [
"LambdaExecutionRole" ,
"Arn"
]
} ,
"Code" : {
"ZipFile" : {
"Fn::Join" : [
"\n" ,
[
"import boto3" ,
"import cfnresponse" ,
"'''" ,
"This python script should be embeded into its designated cloudformation template." ,
"Its function is to sort out the correct AMI image to use for each of the distribution options available." ,
"'''" ,
"def creation_date(e):" ,
" return e['CreationDate']" ,
"" ,
"def handler(event, context):" ,
" try:" ,
" regionName = event['ResourceProperties']['Region']" ,
" distribution = event['ResourceProperties']['Distribution']" ,
" ec2 = boto3.client('ec2',regionName)" ,
" AMIName = {" ,
" 'Ubuntu2004': 'ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*'," ,
2023-07-21 11:23:09 +08:00
" 'Ubuntu2204': 'ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*'," ,
" 'Debian10': 'debian-10-amd64-*'," ,
" 'Debian11': 'debian-11-amd64-*'," ,
" 'Debian12': 'debian-12-amd64-*'," ,
2023-07-19 10:07:22 +08:00
" 'CentOS7': 'CentOS 7.9.2009 x86_64'," ,
" 'AmazonLinux2': 'amzn2-ami-hvm-*.*-x86_64-gp2'," ,
" }[distribution]" ,
2023-07-21 11:23:09 +08:00
" response = ec2.describe_images(Filters=[{'Name':'name', 'Values':[AMIName]}], Owners=['099720109477', '136693071363', '125523088429', 'amazon'])" ,
2023-07-19 10:07:22 +08:00
" images = response['Images']" ,
" images.sort(key=creation_date,reverse=True)" ,
" AMIId = images[0]['ImageId']" ,
" cfnresponse.send(event, context, cfnresponse.SUCCESS, {'AMIId':AMIId}, 'AMIInfo')" ,
" except Exception:" ,
" cfnresponse.send(event, context, cfnresponse.FAILED, {})"
]
]
}
} ,
"Timeout" : 30
} ,
2023-07-20 18:15:12 +08:00
"Metadata" : { } ,
2023-07-19 10:07:22 +08:00
"DependsOn" : [
"LambdaExecutionRole"
]
} ,
"LambdaExecutionRole" : {
"Type" : "AWS::IAM::Role" ,
"Properties" : {
"AssumeRolePolicyDocument" : {
"Version" : "2012-10-17" ,
"Statement" : [
{
"Effect" : "Allow" ,
"Principal" : {
"Service" : "lambda.amazonaws.com"
} ,
"Action" : [
"sts:AssumeRole"
]
} ,
{
"Effect" : "Allow" ,
"Principal" : {
"Service" : [
"ec2.amazonaws.com"
]
} ,
"Action" : [
"sts:AssumeRole"
]
}
]
} ,
"Path" : "/" ,
"Policies" : [
{
"PolicyName" : "root" ,
"PolicyDocument" : {
"Version" : "2012-10-17" ,
"Statement" : [
{
"Effect" : "Allow" ,
"Action" : "*" ,
"Resource" : "*"
}
]
}
}
]
} ,
2023-07-20 18:15:12 +08:00
"Metadata" : { }
2023-07-19 10:07:22 +08:00
} ,
"KeyPairInfo" : {
"Type" : "Custom::KeyPairInfo" ,
"Properties" : {
"Region" : {
"Ref" : "AWS::Region"
} ,
"ServiceToken" : {
"Fn::GetAtt" : [
"KeyPairCreation" ,
"Arn"
]
}
} ,
2023-07-20 18:15:12 +08:00
"Metadata" : { } ,
2023-07-19 10:07:22 +08:00
"DependsOn" : [
"KeyPairCreation"
]
} ,
"InternetGatewayAttachment" : {
"Type" : "AWS::EC2::VPCGatewayAttachment" ,
"Properties" : {
"InternetGatewayId" : {
"Ref" : "VpcInternetGateway"
} ,
"VpcId" : {
"Ref" : "VpnVpc"
}
} ,
2023-07-20 18:15:12 +08:00
"Metadata" : { }
2023-07-19 10:07:22 +08:00
} ,
"EC2VA41EUF" : {
"Type" : "AWS::EC2::VolumeAttachment" ,
"Properties" : {
"Device" : "/dev/sdh" ,
"VolumeId" : {
"Ref" : "VpnServerVolume"
} ,
"InstanceId" : {
"Ref" : "VpnInstance"
}
} ,
2023-07-20 18:15:12 +08:00
"Metadata" : { }
2023-07-19 10:07:22 +08:00
}
} ,
"Parameters" : {
"VpnUser" : {
"Type" : "String" ,
"Description" : "Your VPN username"
} ,
"VpnIpsecPsk" : {
"Type" : "String" ,
"Description" : "Your VPN IPsec PSK (pre-shared key)"
} ,
"VpnPassword" : {
"Type" : "String" ,
"Description" : "Your VPN password"
} ,
"OS" : {
"Type" : "String" ,
2023-07-21 11:43:29 +08:00
"Description" : "The OS of your VPN server. Default: Ubuntu 22.04" ,
"Default" : "Ubuntu2204" ,
2023-07-19 10:07:22 +08:00
"AllowedValues" : [
"Ubuntu2004" ,
2023-07-21 11:23:09 +08:00
"Ubuntu2204" ,
"Debian10" ,
"Debian11" ,
"Debian12" ,
2023-07-19 10:07:22 +08:00
"CentOS7" ,
"AmazonLinux2"
]
} ,
"InstanceType" : {
"Type" : "String" ,
"Description" : "The instance type of your VPN server. Using t2.micro may qualify for the AWS Free Tier." ,
"AllowedValues" : [
"t2.micro" ,
"t3.nano" ,
"m5.large" ,
"t3.micro" ,
"t3.small" ,
"t2.nano" ,
"t2.small" ,
"t3a.nano" ,
"t3a.micro" ,
"t3a.small" ,
"m5a.large" ,
"t1.micro"
] ,
"Default" : "t2.micro"
}
} ,
"Outputs" : {
"VPNAddress" : {
"Description" : "This is the public IP of your newly-launched VPN server." ,
"Value" : {
"Fn::GetAtt" : [
"VpnInstance" ,
"PublicIp"
]
}
} ,
"VPNUsername" : {
"Description" : "Your VPN username" ,
"Value" : {
"Ref" : "VpnUser"
}
} ,
"VPNPassword" : {
"Description" : "Your VPN password" ,
"Value" : {
"Ref" : "VpnPassword"
}
} ,
"VPNKey" : {
"Description" : "Your VPN IPsec PSK (pre-shared key)" ,
"Value" : {
"Ref" : "VpnIpsecPsk"
}
} ,
"EC2PrivateKeyMaterial" : {
"Description" : "The content of your private key for accessing the VPN server via SSH. Save it as a file for use when connecting." ,
"Value" : {
"Fn::GetAtt" : [
"KeyPairInfo" ,
"KeyMaterial"
]
}
} ,
"NextStep" : {
"Description" : "Learn how to configure VPN clients." ,
"Value" : "https://github.com/hwdsl2/setup-ipsec-vpn#next-steps"
2023-07-21 11:23:09 +08:00
} ,
"WarningForDebianUsers" : {
"Description" : "Please be noted that due to Debian images on AWS EC2 using cloud kernels, you are unable to use IPSec/L2TP mode if your server is running Debian. For more information, please refer to the link to the left." ,
"Value" : "https://github.com/hwdsl2/setup-ipsec-vpn/blob/master/docs/clients.md#debian-kernel"
2023-07-19 10:07:22 +08:00
}
}
}