Seeking review, comments, point out issues, link to available tested, better solution…
This idea is to provide secure remote access into EC2 instances and allow backend instances to reach internet when required for update, install packages, etc. I just started to pickup AWS on my own and had no prior experience with AWS. I learned the method to secure remote access (like SSH) is to restrict the SSH source IP, create jump/bastion hosts, then internet access for backend/private subnet would be NAT instance/gateway or proxy. For a small setup of <20 servers, 1 to 2 admins.. looked overkilled.
I think of using AWS CLI, security groups and network ACLs to provide “just enough” protection for small setup. No need to open SSH to public when not required, or restricting to only specific IP, extra instances or pay for NAT Gateway per AZ. I searched a little but can’t seem to find what in mind and so I did a little scripts to test. My scripting experience is extremely low, more of a GUI guy.. so please bear with me.
Test setup; 1 Public subnet, security group allow http, https & ssh from all IP. ACL allow ingress of http/https & ephemeral ports, and outbound to all. Auto assign public IP.
1 Private/backend subnet, security group allow required ports from Public subnet and ssh from all IP. ACL allow traffic from VPC’s CIDR, ephemeral, and outbound to all. Don’t assign public IP. Routing table to allow both subnets to reach internet.
Laptop configured with AWS CLI and access keys. Predefined scripts to add SSH rule in ACL to allow current public IP to access specific subnet.
aws ec2 create-network-acl-entry --network-acl-id acl-public/backend --ingress --rule-number 801 --protocol tcp --port-range From=22,To=22 --cidr-block “$(curl http://checkip.amazonaws.com)”/32 --rule-action allow
To list current instances and IP;
aws ec2 describe-instances --output text --query 'Reservations[*].Instances[*].[InstanceId,NetworkInterfaces[*].Association.PublicIp,Tags[?Key==`Name`].Value]' --filters "Name=network-interface.subnet-id,Values=subnet-backend"
To access backend instance and allow it internet access; I copy and paste the InstanceId from above as script parameter.
if [ ! -n "$1" ]
then
echo "need InstanceID"
exit
fi
#Get a EIP
aws ec2 allocate-address --domain vpc --output text > $1.txt
#read variables
read eip d ip < $1.txt
#Associate Ip to instance
echo "issuing instance "$eip " with ip "$ip
aws ec2 associate-address --output text --instance-id $1 --allocation-id $eip > $1"EIP".txt
#ssh to instance
echo "ssh to "$ip
ssh ec2-user@$ip -i Vrigina-private-key.pem
#remove EIP
read asid < $1"EIP".txt
aws ec2 disassociate-address --association-id $asid
aws ec2 release-address --allocation-id $eip
echo "removed eip"
cat $1.txt $1"EIP".txt > $1"-"`date +"%Hh-%Mm-%d-%b-%y"`.txt
rm $1.txt $1"EIP".txt
Then another script to remove the SSH allow rule in the ACL. Public subnet instances, just need to add SSH and remove the rule will do.
There are rooms for improvement; like automate the selection of instances, automatic daily check (maybe use AWS config/Lambda) and alert if there is still backend instance public IP and ACL SSH rule not removed. Script lack error checking, no MFA (no idea how), etc..
I did not test with a webserver and DB setup, not sure will there be service interruption.
Issue? Too much effort? During the duration when the backend instance gained access to the internet, SG and ACL do block incoming traffic. Private network ACL can be configured to Deny SSH from public subnet instance. So it look OK..
Regards.