VPCE(VPC Endpoint Service) Realtime(Private Link).
Steps:
Please refer the below script before start the activity
#!/bin/bash
# Set variables
VPC_CIDR="10.0.0.0/16"
PUBLIC_SUBNET_CIDR="10.0.1.0/24"
PRIVATE_SUBNET_CIDR="10.0.2.0/24"
REGION="us-east-1"
KEY_NAME="test"
INSTANCE_TYPE="t2.micro"
AMI_ID="ami-0182f373e66f89c85" # Amazon Linux 2 AMI for the region
VPC_NAME="PrivateLinkVPC-Prod"
IGW_NAME="IGW-Prod"
PUBLIC_SUBNET_NAME="PublicSubnet-Prod"
PRIVATE_SUBNET_NAME="PrivateSubnet-Prod"
RT_PUBLIC_NAME="PublicRT-Prod"
RT_PRIVATE_NAME="PrivateRT-Prod"
SEC_GROUP_NAME="WebSG-Prod"
INSTANCE_PRIVATE_NAME="PrivateWebServer-Prod"
INSTANCE_PUBLIC_NAME="PublicWebServer-Prod"
VPCE_NAME="VPCE-Prod"
NAT_GW_NAME="NATGW-Prod"
EIP_NAME="ElasticIP-Prod"
# Create a VPC
echo "Creating VPC..."
VPC_ID=$(aws ec2 create-vpc \
--cidr-block $VPC_CIDR \
--region $REGION \
--query 'Vpc.VpcId' \
--output text)
echo "VPC ID: $VPC_ID"
# Assign a name to the VPC
aws ec2 create-tags --resources $VPC_ID --tags Key=Name,Value=$VPC_NAME
echo "VPC named: $VPC_NAME"
# Enable DNS support and DNS hostnames
aws ec2 modify-vpc-attribute --vpc-id $VPC_ID --enable-dns-support
aws ec2 modify-vpc-attribute --vpc-id $VPC_ID --enable-dns-hostnames
# Create a public subnet
echo "Creating public subnet..."
PUBLIC_SUBNET_ID=$(aws ec2 create-subnet \
--vpc-id $VPC_ID \
--cidr-block $PUBLIC_SUBNET_CIDR \
--availability-zone ${REGION}a \
--query 'Subnet.SubnetId' \
--output text)
echo "Public Subnet ID: $PUBLIC_SUBNET_ID"
# Tag the public subnet
aws ec2 create-tags --resources $PUBLIC_SUBNET_ID --tags Key=Name,Value=$PUBLIC_SUBNET_NAME
echo "Public Subnet named: $PUBLIC_SUBNET_NAME"
# Create a private subnet
echo "Creating private subnet..."
PRIVATE_SUBNET_ID=$(aws ec2 create-subnet \
--vpc-id $VPC_ID \
--cidr-block $PRIVATE_SUBNET_CIDR \
--availability-zone ${REGION}a \
--query 'Subnet.SubnetId' \
--output text)
echo "Private Subnet ID: $PRIVATE_SUBNET_ID"
# Tag the private subnet
aws ec2 create-tags --resources $PRIVATE_SUBNET_ID --tags Key=Name,Value=$PRIVATE_SUBNET_NAME
echo "Private Subnet named: $PRIVATE_SUBNET_NAME"
# Create an Internet Gateway and attach it to the VPC
echo "Creating Internet Gateway..."
IGW_ID=$(aws ec2 create-internet-gateway \
--query 'InternetGateway.InternetGatewayId' \
--output text)
aws ec2 attach-internet-gateway --vpc-id $VPC_ID --internet-gateway-id $IGW_ID
echo "Internet Gateway ID: $IGW_ID"
# Tag the Internet Gateway
aws ec2 create-tags --resources $IGW_ID --tags Key=Name,Value=$IGW_NAME
echo "Internet Gateway named: $IGW_NAME"
# Create a route table for the public subnet and associate it
echo "Creating route table for public subnet..."
PUBLIC_ROUTE_TABLE_ID=$(aws ec2 create-route-table \
--vpc-id $VPC_ID \
--query 'RouteTable.RouteTableId' \
--output text)
aws ec2 create-route --route-table-id $PUBLIC_ROUTE_TABLE_ID --destination-cidr-block 0.0.0.0/0 --gateway-id $IGW_ID
aws ec2 associate-route-table --subnet-id $PUBLIC_SUBNET_ID --route-table-id $PUBLIC_ROUTE_TABLE_ID
echo "Public Route Table ID: $PUBLIC_ROUTE_TABLE_ID"
# Tag the public route table
aws ec2 create-tags --resources $PUBLIC_ROUTE_TABLE_ID --tags Key=Name,Value=$RT_PUBLIC_NAME
echo "Public Route Table named: $RT_PUBLIC_NAME"
# Create a security group for the web server
echo "Creating security group..."
SECURITY_GROUP_ID=$(aws ec2 create-security-group \
--vpc-id $VPC_ID \
--group-name $SEC_GROUP_NAME \
--description "Security group for web server in production" \
--query 'GroupId' \
--output text)
echo "Security Group ID: $SECURITY_GROUP_ID"
# Tag the security group
aws ec2 create-tags --resources $SECURITY_GROUP_ID --tags Key=Name,Value=$SEC_GROUP_NAME
echo "Security Group named: $SEC_GROUP_NAME"
# Allow inbound SSH and HTTP traffic
aws ec2 authorize-security-group-ingress --group-id $SECURITY_GROUP_ID --protocol tcp --port 22 --cidr 0.0.0.0/0
aws ec2 authorize-security-group-ingress --group-id $SECURITY_GROUP_ID --protocol tcp --port 80 --cidr 0.0.0.0/0
# Create an Elastic IP for the NAT Gateway
echo "Creating Elastic IP for NAT Gateway..."
EIP_ALLOC_ID=$(aws ec2 allocate-address --query 'AllocationId' --output text)
echo "Elastic IP Allocation ID: $EIP_ALLOC_ID"
# Tag the Elastic IP
aws ec2 create-tags --resources $EIP_ALLOC_ID --tags Key=Name,Value=$EIP_NAME
echo "Elastic IP named: $EIP_NAME"
# Create a NAT Gateway in the public subnet
echo "Creating NAT Gateway in public subnet..."
NAT_GW_ID=$(aws ec2 create-nat-gateway \
--subnet-id $PUBLIC_SUBNET_ID \
--allocation-id $EIP_ALLOC_ID \
--query 'NatGateway.NatGatewayId' \
--output text)
echo "NAT Gateway ID: $NAT_GW_ID"
# Tag the NAT Gateway
aws ec2 create-tags --resources $NAT_GW_ID --tags Key=Name,Value=$NAT_GW_NAME
echo "NAT Gateway named: $NAT_GW_NAME"
# Wait for the NAT Gateway to become available
echo "Waiting for NAT Gateway to become available..."
aws ec2 wait nat-gateway-available --nat-gateway-ids $NAT_GW_ID
echo "NAT Gateway is available."
# Create a route table for the private subnet and associate it
echo "Creating route table for private subnet..."
PRIVATE_ROUTE_TABLE_ID=$(aws ec2 create-route-table \
--vpc-id $VPC_ID \
--query 'RouteTable.RouteTableId' \
--output text)
aws ec2 associate-route-table --subnet-id $PRIVATE_SUBNET_ID --route-table-id $PRIVATE_ROUTE_TABLE_ID
echo "Private Route Table ID: $PRIVATE_ROUTE_TABLE_ID"
# Tag the private route table
aws ec2 create-tags --resources $PRIVATE_ROUTE_TABLE_ID --tags Key=Name,Value=$RT_PRIVATE_NAME
echo "Private Route Table named: $RT_PRIVATE_NAME"
# Add a route to the private route table for internet traffic via the NAT Gateway
echo "Creating route in private route table for internet access via NAT Gateway..."
aws ec2 create-route --route-table-id $PRIVATE_ROUTE_TABLE_ID --destination-cidr-block 0.0.0.0/0 --nat-gateway-id $NAT_GW_ID
echo "Route to NAT Gateway added in private route table."
# Launch an EC2 instance in the public subnet
echo "Launching EC2 instance in public subnet..."
INSTANCE_PUBLIC_ID=$(aws ec2 run-instances \
--image-id $AMI_ID \
--instance-type $INSTANCE_TYPE \
--key-name $KEY_NAME \
--subnet-id $PUBLIC_SUBNET_ID \
--security-group-ids $SECURITY_GROUP_ID \
--associate-public-ip-address \
--query 'Instances[0].InstanceId' \
--output text)
echo "Public EC2 Instance ID: $INSTANCE_PUBLIC_ID"
# Tag the private EC2 instance
aws ec2 create-tags --resources $INSTANCE_PUBLIC_ID --tags Key=Name,Value=$INSTANCE_PUBLIC_NAME
echo "Private EC2 instance named: $INSTANCE_PUBLIC_NAME"
# Launch an EC2 instance in the private subnet
echo "Launching EC2 instance in private subnet..."
INSTANCE_PRIVATE_ID=$(aws ec2 run-instances \
--image-id $AMI_ID \
--instance-type $INSTANCE_TYPE \
--key-name $KEY_NAME \
--subnet-id $PRIVATE_SUBNET_ID \
--security-group-ids $SECURITY_GROUP_ID \
--query 'Instances[0].InstanceId' \
--output text)
echo "Private EC2 Instance ID: $INSTANCE_PRIVATE_ID"
# Tag the private EC2 instance
aws ec2 create-tags --resources $INSTANCE_PRIVATE_ID --tags Key=Name,Value=$INSTANCE_PRIVATE_NAME
echo "Private EC2 instance named: $INSTANCE_PRIVATE_NAME"
Step-1:
Open cloudshell by searching in search button of aws portal:
Copy the variable's content like below.
# Set variables
VPC_CIDR="10.0.0.0/16"
PUBLIC_SUBNET_CIDR="10.0.1.0/24"
PRIVATE_SUBNET_CIDR="10.0.2.0/24"
REGION="us-east-1"
KEY_NAME="test"
INSTANCE_TYPE="t2.micro"
AMI_ID="ami-0182f373e66f89c85" # Amazon Linux 2 AMI for the region
VPC_NAME="PrivateLinkVPC-Prod"
IGW_NAME="IGW-Prod"
PUBLIC_SUBNET_NAME="PublicSubnet-Prod"
PRIVATE_SUBNET_NAME="PrivateSubnet-Prod"
RT_PUBLIC_NAME="PublicRT-Prod"
RT_PRIVATE_NAME="PrivateRT-Prod"
SEC_GROUP_NAME="WebSG-Prod"
INSTANCE_PRIVATE_NAME="PrivateWebServer-Prod"
INSTANCE_PUBLIC_NAME="PublicWebServer-Prod"
VPCE_NAME="VPCE-Prod"
NAT_GW_NAME="NATGW-Prod"
EIP_NAME="ElasticIP-Prod"
Step-2:
Verify the variables:
[cloudshell-user@ip-10-134-46-239 ~]$ echo $VPC_NAME
PrivateLinkVPC-Prod
Step-3:
Create a vpc:
# Create a VPC
echo "Creating VPC..."
VPC_ID=$(aws ec2 create-vpc \
--cidr-block $VPC_CIDR \
--region $REGION \
--query 'Vpc.VpcId' \
--output text)
echo "VPC ID: $VPC_ID"
# Assign a name to the VPC
aws ec2 create-tags --resources $VPC_ID --tags Key=Name,Value=$VPC_NAME
echo "VPC named: $VPC_NAME"
# Enable DNS support and DNS hostnames
aws ec2 modify-vpc-attribute --vpc-id $VPC_ID --enable-dns-support
aws ec2 modify-vpc-attribute --vpc-id $VPC_ID --enable-dns-hostnames
Step-4:
Create a subnets(Private & Public):
# Create a public subnet
echo "Creating public subnet..."
PUBLIC_SUBNET_ID=$(aws ec2 create-subnet \
--vpc-id $VPC_ID \
--cidr-block $PUBLIC_SUBNET_CIDR \
--availability-zone ${REGION}a \
--query 'Subnet.SubnetId' \
--output text)
echo "Public Subnet ID: $PUBLIC_SUBNET_ID"
# Tag the public subnet
aws ec2 create-tags --resources $PUBLIC_SUBNET_ID --tags Key=Name,Value=$PUBLIC_SUBNET_NAME
echo "Public Subnet named: $PUBLIC_SUBNET_NAME"
# Create a private subnet
echo "Creating private subnet..."
PRIVATE_SUBNET_ID=$(aws ec2 create-subnet \
--vpc-id $VPC_ID \
--cidr-block $PRIVATE_SUBNET_CIDR \
--availability-zone ${REGION}a \
--query 'Subnet.SubnetId' \
--output text)
echo "Private Subnet ID: $PRIVATE_SUBNET_ID"
# Tag the private subnet
aws ec2 create-tags --resources $PRIVATE_SUBNET_ID --tags Key=Name,Value=$PRIVATE_SUBNET_NAME
echo "Private Subnet named: $PRIVATE_SUBNET_NAME"
Create IGW & public route tables & SG's
# Create an Internet Gateway and attach it to the VPC
echo "Creating Internet Gateway..."
IGW_ID=$(aws ec2 create-internet-gateway \
--query 'InternetGateway.InternetGatewayId' \
--output text)
aws ec2 attach-internet-gateway --vpc-id $VPC_ID --internet-gateway-id $IGW_ID
echo "Internet Gateway ID: $IGW_ID"
# Tag the Internet Gateway
aws ec2 create-tags --resources $IGW_ID --tags Key=Name,Value=$IGW_NAME
echo "Internet Gateway named: $IGW_NAME"
# Create a route table for the public subnet and associate it
echo "Creating route table for public subnet..."
PUBLIC_ROUTE_TABLE_ID=$(aws ec2 create-route-table \
--vpc-id $VPC_ID \
--query 'RouteTable.RouteTableId' \
--output text)
aws ec2 create-route --route-table-id $PUBLIC_ROUTE_TABLE_ID --destination-cidr-block 0.0.0.0/0 --gateway-id $IGW_ID
aws ec2 associate-route-table --subnet-id $PUBLIC_SUBNET_ID --route-table-id $PUBLIC_ROUTE_TABLE_ID
echo "Public Route Table ID: $PUBLIC_ROUTE_TABLE_ID"
# Tag the public route table
aws ec2 create-tags --resources $PUBLIC_ROUTE_TABLE_ID --tags Key=Name,Value=$RT_PUBLIC_NAME
echo "Public Route Table named: $RT_PUBLIC_NAME"
# Create a security group for the web server
echo "Creating security group..."
SECURITY_GROUP_ID=$(aws ec2 create-security-group \
--vpc-id $VPC_ID \
--group-name $SEC_GROUP_NAME \
--description "Security group for web server in production" \
--query 'GroupId' \
--output text)
echo "Security Group ID: $SECURITY_GROUP_ID"
# Tag the security group
aws ec2 create-tags --resources $SECURITY_GROUP_ID --tags Key=Name,Value=$SEC_GROUP_NAME
echo "Security Group named: $SEC_GROUP_NAME"
# Allow inbound SSH and HTTP traffic
aws ec2 authorize-security-group-ingress --group-id $SECURITY_GROUP_ID --protocol tcp --port 22 --cidr 0.0.0.0/0
aws ec2 authorize-security-group-ingress --group-id $SECURITY_GROUP_ID --protocol tcp --port 80 --cidr 0.0.0.0/0
Step-6:
Create NAT with EIP & Private route tables:
# Create an Elastic IP for the NAT Gateway
echo "Creating Elastic IP for NAT Gateway..."
EIP_ALLOC_ID=$(aws ec2 allocate-address --query 'AllocationId' --output text)
echo "Elastic IP Allocation ID: $EIP_ALLOC_ID"
# Tag the Elastic IP
aws ec2 create-tags --resources $EIP_ALLOC_ID --tags Key=Name,Value=$EIP_NAME
echo "Elastic IP named: $EIP_NAME"
# Create a NAT Gateway in the public subnet
echo "Creating NAT Gateway in public subnet..."
NAT_GW_ID=$(aws ec2 create-nat-gateway \
--subnet-id $PUBLIC_SUBNET_ID \
--allocation-id $EIP_ALLOC_ID \
--query 'NatGateway.NatGatewayId' \
--output text)
echo "NAT Gateway ID: $NAT_GW_ID"
# Tag the NAT Gateway
aws ec2 create-tags --resources $NAT_GW_ID --tags Key=Name,Value=$NAT_GW_NAME
echo "NAT Gateway named: $NAT_GW_NAME"
# Wait for the NAT Gateway to become available
echo "Waiting for NAT Gateway to become available..."
aws ec2 wait nat-gateway-available --nat-gateway-ids $NAT_GW_ID
echo "NAT Gateway is available."
# Create a route table for the private subnet and associate it
echo "Creating route table for private subnet..."
PRIVATE_ROUTE_TABLE_ID=$(aws ec2 create-route-table \
--vpc-id $VPC_ID \
--query 'RouteTable.RouteTableId' \
--output text)
aws ec2 associate-route-table --subnet-id $PRIVATE_SUBNET_ID --route-table-id $PRIVATE_ROUTE_TABLE_ID
echo "Private Route Table ID: $PRIVATE_ROUTE_TABLE_ID"
# Tag the private route table
aws ec2 create-tags --resources $PRIVATE_ROUTE_TABLE_ID --tags Key=Name,Value=$RT_PRIVATE_NAME
echo "Private Route Table named: $RT_PRIVATE_NAME"
# Add a route to the private route table for internet traffic via the NAT Gateway
echo "Creating route in private route table for internet access via NAT Gateway..."
aws ec2 create-route --route-table-id $PRIVATE_ROUTE_TABLE_ID --destination-cidr-block 0.0.0.0/0 --nat-gateway-id $NAT_GW_ID
echo "Route to NAT Gateway added in private route table."
Create an Bastion Ec2 machine:
# Launch an EC2 instance in the public subnet
echo "Launching EC2 instance in public subnet..."
INSTANCE_PUBLIC_ID=$(aws ec2 run-instances \
--image-id $AMI_ID \
--instance-type $INSTANCE_TYPE \
--key-name $KEY_NAME \
--subnet-id $PUBLIC_SUBNET_ID \
--security-group-ids $SECURITY_GROUP_ID \
--associate-public-ip-address \
--query 'Instances[0].InstanceId' \
--output text)
echo "Public EC2 Instance ID: $INSTANCE_PUBLIC_ID"
# Tag the private EC2 instance
aws ec2 create-tags --resources $INSTANCE_PUBLIC_ID --tags Key=Name,Value=$INSTANCE_PUBLIC_NAME
echo "Private EC2 instance named: $INSTANCE_PUBLIC_NAME"
SSH into the Bastion.
shiva@BhagathSingh MINGW64 ~/Downloads
$ ssh -i test.pem ec2-user@54.234.109.58
before performing any activity we need private subnet machine.
Keypair: Choose your key pair
Ensure network configuration is same like below
Access the private machine from bastion:
Before we need to configure the keypair in bastion machine
touch test.pem + vi test.pem(Paste the content in this file) + wq!
chmod 400 test.pem
Setup a webserver for testing.
[ec2-user@ip-10-0-2-192 ~]$ sudo systemctl status httpd
● httpd.service - The Apache HTTP Server
Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; preset: disabled)
Active: active (running) since Thu 2024-09-05 18:25:02 UTC; 5s ago
Docs: man:httpd.service(8)
Main PID: 25806 (httpd)
Status: "Started, listening on: port 80"
Tasks: 177 (limit: 1112)
Memory: 12.9M
CPU: 65ms
CGroup: /system.slice/httpd.service
├─25806 /usr/sbin/httpd -DFOREGROUND
├─25807 /usr/sbin/httpd -DFOREGROUND
├─25808 /usr/sbin/httpd -DFOREGROUND
├─25809 /usr/sbin/httpd -DFOREGROUND
└─25810 /usr/sbin/httpd -DFOREGROUND
Sep 05 18:25:02 ip-10-0-2-192.ec2.internal systemd[1]: Starting httpd.service - The Apache HTTP Server...
Sep 05 18:25:02 ip-10-0-2-192.ec2.internal systemd[1]: Started httpd.service - The Apache HTTP Server.
Sep 05 18:25:02 ip-10-0-2-192.ec2.internal httpd[25806]: Server configured, listening on: port 80
[ec2-user@ip-10-0-2-192 ~]$ history
1 yum install httpd
2 sudo yum install httpd
3 sudo systemctl enable httpd
4 sudo systemctl start httpd
5 sudo systemctl status httpd
From public machine try to access private ip of private subnet machine it should work like below
[root@ip-10-0-1-165 ~]# curl 10.0.2.192
Private link demo
[root@ip-10-0-1-165 ~]#
Step-11:
Create a target group for NLB:
Click on create TG
Now Create NLB:
Create VPCE(Private link):
Copy the VPCE Service Name
Create VPC Endpoint:
Now lunch a machine in VPC2 to access the endpoint service securely.
Ensure you can lunch a new machine in VPC2
Step-14:
Finally test private communication
Copy the DNS name go to the VPC2 machine and curl the private dns name which you copied
0 Comments