2022 June 13

Quick Individual Security for AWS EC2 Instances

Below I'm going to show you how I add some simple protection to a server so that only an authorized user can access it.

Step 1 VPC

Make a vpc with one subnet and an internet gateway.

aws ec2 create-vpc --cidr-block # gives us vpc-id vpc-08978c6622c0cdde2 aws ec2 create-subnet --vpc-id vpc-08978c6622c0cdde2 --cidr-block # gives us subnet-id subnet-088dade0383f32827 aws ec2 create-internet-gateway # gives us igw igw-08d28c1aeb68cc9b1 aws ec2 attach-internet-gateway --internet-gateway-id igw-08d28c1aeb68cc9b1 --vpc-id vpc-08978c6622c0cdde2 aws ec2 describe-route-tables --filters Name=vpc-id,Values=vpc-08978c6622c0cdde2 # gives us rout table rtb-0f582e7a508bf0a55

In the route tables we see that our new vpc has no way to get traffic from our servers to the internet. and should have a rule like this in "Routes."

aws ec2 create-route --route-table-id rtb-0f582e7a508bf0a55 --destination-cidr-block --gateway-id igw-08d28c1aeb68cc9b1 { "Return": true }

So what we've done is create a public subnet inside a vpc. This is where our server(s) are going to live. To make sure only we can access it we're going too setup a security group next.

Step 2 Security Group

Before we make our new group, you may have noticed in the aws dashboard that this vpc already has a security group associated with it. We're going to make a new one and ignore the default one (you can use the default one if you like though).

aws ec2 create-security-group --vpc-id vpc-08978c6622c0cdde2 --group-name secgrp --description "Secure your machines" { "GroupId": "sg-06e38dc4737441021" } aws ec2 authorize-security-group-ingress --group-id sg-06e38dc4737441021 --protocol tcp --port 22 --cidr { "Return": true, "SecurityGroupRules": [ { "SecurityGroupRuleId": "sgr-07bd6d9923cfe26af", "GroupId": "sg-06e38dc4737441021", "GroupOwnerId": "XXX", "IsEgress": false, "IpProtocol": "tcp", "FromPort": 22, "ToPort": 22, "CidrIpv4": "" } ] }

This will create a security group that allows connections from the ip address, your ip will be different and you'll need to look it up and use it instead. You will need to update this rule when you want to connect with whatever your current ip is. A convenient option is to purchase a static ip from your internet service or vpn provider. If your ip is temporary it's best practice to remove the rule after finishing your work.

So when you're done working do it like this:

aws ec2 revoke-security-group-ingress --group-id sg-06e38dc4737441021 --protocol tcp --port 22 --cidr { "Return": true }

Step 3 Instance

Next you'll want to setup an instance. You will need to create a key on aws, and download the private part. This can be any standard ssh rsa key. I created one called "blog_ex" and put it in the blog_ex.cer file in my .ssh folder and ran `chmod 600 blog_ex.cer`.

aws ec2 run-instances --image-id ami-0ee8244746ec5d6d4 --count 1 --instance-type t2.micro --key-name blog_ex --security-group-ids sg-06e38dc4737441021 --subnet-id subnet-088dade0383f32827 aws ec2 allocate-address { "PublicIp": "", "AllocationId": "eipalloc-085246c43ea152122", "PublicIpv4Pool": "amazon", "NetworkBorderGroup": "us-west-2", "Domain": "vpc" } aws ec2 associate-address --instance-id i-0652e96652e97eb93 --public-ip { "AssociationId": "eipassoc-0efc13dedcc08c3f8" }

I won't post the result of `run-instances` but it's a big long json object with the instance id and ample information about your new instance.

If you try to ping the instance at this ip it should timeout:

ping PING ( 56 data bytes Request timeout for icmp_seq 0 Request timeout for icmp_seq 1 Request timeout for icmp_seq 2 Request timeout for icmp_seq 3

This is because we haven't allowed connections ICMP (internet control message protocol) but only TCP. Factoid: ICMP does not use any port as it operates at the network layer and not the transport layer.

Step 4 SSH to Instance

This will allow you to work in your instance with some peace of mind. Make sure to put whatever the name of your keyfile is instead.

ssh ubuntu@ -i ~/.ssh/blog_ex.cer

Even though you are the only one that can connect, this server can still make outward requests to download software or data, and received responses.


When I'm done I deallocate the servers, vpc, ip, and igw.

# instances aws ec2 terminate-instances --instance-ids i-097f5af615257e460 { "TerminatingInstances": [ { "CurrentState": { "Code": 32, "Name": "shutting-down" }, "InstanceId": "i-0652e96652e97eb93", "PreviousState": { "Code": 16, "Name": "running" } } ] } # sec groups aws ec2 delete-security-group --group-id sg-06e38dc4737441021 # route tables/rules aws ec2 delete-route --route-table-id rtb-0f582e7a508bf0a55 --destination-cidr-block # subnets aws ec2 delete-subnet --subnet-id subnet-088dade0383f32827 # gateways aws ec2 detach-internet-gateway --internet-gateway-id igw-08d28c1aeb68cc9b1 --vpc-id vpc-08978c6622c0cdde2 # finally the vpc aws ec2 delete-internet-gateway --internet-gateway-id igw-08d28c1aeb68cc9b1 aws ec2 delete-vpc --vpc-id vpc-08978c6622c0cdde2


This security setup is meant to provide basic security for solo users who otherwise would have none. There is, however, a principle in computer security called "defense in depth" the idea is to create multiple layers of protection to secure your servers. As your team grows you may find that you need more depth to your security.

Other layers of protection:

sshd config changes ssh bastion host/proxy aws acl rules 2fa for ssh

If you see an issue in this blog, message me so we can fix it together. I like to work with others. If you have a project or you want help or advice you can hire me.


Difference Between ACL, SG

Signup For More