Providing Internet Connectivity to Private Subnet through NAT Gateway

Akashdeep Gupta
Analytics Vidhya

--

Previously deployed Webserver on AWS using VPC in which running WordPress server in the public subnet and MySql database in the private subnet(link of that article given just below). As MySql launched in the private subnet means that it does not have internet connectivity which is good but in the case of updating software, making some changes, fixing bugs or patches, it might prove to a major security threat.

In that case, we are going to provide internet connectivity to our database server using NAT gateway. We are also going to launch one instance known as bastion host that will be used to ping inside MySql instance and can also do tasks like updating and fixing bugs.

*Terminologies that going to be used in this task

NAT Gateway

NAT Gateway is a highly available AWS managed service that makes it easy to connect to the Internet from instances within a private subnet in an Amazon Virtual Private Cloud (Amazon VPC). Previously, you needed to launch a NAT instance to enable NAT for instances in a private subnet.

EIP

Elastic IP address is a reserved public IP address that you can assign to any EC2 instance in a particular region, until you choose to release it. To allocate an Elastic IP address to your account in a particular region, see Allocating an Elastic IP Address.

Bastion Host

Bastion host is a server whose purpose is to provide access to a private network from an external network, such as the Internet. Because of its exposure to potential attacks, a bastion host must minimize the chances of penetration.

Security groups are essential for maintaining tight security and play a big part in making bastion host solution work.

*Solution of the task

  • Before creating a NAT gateway we have to create EIP for that.
# — Creating EIPresource “aws_eip” “task4-eip” {
vpc = “true”
}

Simple as simple nothing to explain.

EIP
  • Creating NAT gateway.
# — Creating NAT gatewayresource “aws_nat_gateway” “task4-ngw” {
allocation_id = “${aws_eip.task4-eip.id}
subnet_id = “${aws_subnet.public-subnet-1a.id}”

tags = {
Name = “task4-ngw”
}

Assigning this NAT gateway to the public subnet.

NAT Gateway
  • Creating a route table for NAT gateway and its association to private subnet for having internet connectivity.
# — Create route table for nat gatewayresource “aws_route_table” “task4-route-ngw” {
depends_on = [ aws_nat_gateway.task4-ngw,
]
vpc_id = “${aws_vpc.task4-vpc.id}”
route {
cidr_block = “0.0.0.0/0”
gateway_id = “${aws_nat_gateway.task4-ngw.id}”
}
tags = {
Name = “task4-route-ngw”
}
}
# — Subnet Association for nat gatewayresource “aws_route_table_association” “subnet-1b-asso” {
subnet_id = “${aws_subnet.public-subnet-1b.id}”
route_table_id = “${aws_route_table.task4-route-ngw.id}”
}
Route Table
  • Creating a key pair for bastion host.
# — Creating Key Pairs for bastion hostresource “tls_private_key” “key7” {
algorithm = “RSA”
rsa_bits = 4096
}
resource “local_file” “key8” {
content = “${tls_private_key.key7.private_key_pem}”
filename = “bastion_key.pem”
file_permission = 0400
}
resource “aws_key_pair” “key9” {
key_name = “bastion_key”
public_key = “${tls_private_key.key7.public_key_openssh}”
}
  • Creating a security group for bastion host.
# — Creating Security Groups for bastion hostresource “aws_security_group” “sg-bs” {
name = “bastion-sg”
description = “Allow TLS inbound traffic”
vpc_id = “${aws_vpc.task4-vpc.id}”
ingress {
description = “SSH”
from_port = 22
to_port = 22
protocol = “tcp”
cidr_blocks = [ “0.0.0.0/0” ]
}
egress {
from_port = 0
to_port = 0
protocol = “-1”
cidr_blocks = [“0.0.0.0/0”]
}
tags = {
Name = “bastion-sg”
}
}

Allowing only ssh to bastion host.

sg-bastion
  • Creating a security group for MySql for allowing only bastion host security group for doing ssh.
# — Creating Security Groups for mySql for having connectivity with only bastion_host instanceresource “aws_security_group” “sg-db2” {
depends_on = [
aws_security_group.sg-bs,
]
name = “mySql-sg2”
description = “Allow TLS inbound traffic”
vpc_id = “${aws_vpc.task4-vpc.id}”
ingress {
description = “SSH”
from_port = 22
to_port = 22
protocol = “tcp”
security_groups = [ “${aws_security_group.sg-bs.id}” ]
}
egress {
from_port = 0
to_port = 0
protocol = “-1”
cidr_blocks = [“0.0.0.0/0”]
}
tags = {
Name = “mySql-sg2”
}
}
sg-mysql
  • Launching bastion host instance.
# — Creating Ec2 instance for bastion_hostresource “aws_instance” “bash_host” {
ami = “ami-0732b62d310b80e97”
subnet_id = “${aws_subnet.public-subnet-1a.id}”
availability_zone = “${data.aws_availability_zones.zones.names[0]}”
instance_type = “t2.micro”
root_block_device {
volume_type = “gp2”
delete_on_termination = true
}
key_name = “${aws_key_pair.key9.key_name}”
vpc_security_group_ids = [ “${aws_security_group.sg-bs.id}” ]
associate_public_ip_address = true

tags = {
Name = “Bastion_host”
}
}
instances

Now, using this bastion host we can log in inside private subnet in our case MySql instance and can do ssh using its key pairs.

For key pair look into the local repository where you created the project, and through WindSCP send it to the bastion host instance from your repository.

Bastion host Public IP: 13.232.65.1
MySql Private IP: 192.168.1.109
# sudo su - root# cd /home/ec2-user
Note:- As going to this loction as a have copied the key(mySql)to this location
# ssh -i mysql_key.pem -l ec2-user 192.168.1.109# ping goo.gl# sudo su - root# now install any software or fix bugs.

Thanks for reading!!

Feel free to give suggestions and having any query then DM me.

Github repo for help and also for entire code

--

--