EC2 includes a security feature that allows you to define groups with a set of firewall rules to restrict access. These groups are called security groups. As of now these firewall rules can be a set of ACCEPT rules for all incoming packets on TCP, UDP and ICMP ports. These rules can be applied to internal traffic from other EC2 instances as well as to traffic from the internet. Whenever an instance is launched, it has to be associated with a security group. By default a security group of “default” is assigned to the instance, if you don’t assign one yourself. Once an instance is launched, its security group cannot be changed. However, you can add new rules to the security group which will be applied to all instances running in that group immediately.
In the next sections of this blog post, I will be using EC2 command line tools, if you don’t already have them installed, this link is a good guide to get you up and running.
Listing the groups and rules
You can get a list of all the defined security groups with the rules using the command
ec2-describe-group. Suppose we have a group called Apache which allows traffics on ports 22 and 80, then it will be listed by the above command as follows:
GROUP sg-44a9695e 923486498713 Apache Apache web server PERMISSION 923486498713 Apache ALLOWS tcp 22 22 FROM CIDR 0.0.0.0/0 ingress PERMISSION 923486498713 Apache ALLOWS tcp 80 80 FROM CIDR 0.0.0.0/0 ingress
The first line of the listing gives the security group definition:
sg-44a9695e is the unique id of the security group
923486498713 is the AWS account number
Apache is the name of the security group
Apache web server is the description of the security group
The following two lines are the actual filtering rules, that allow incoming traffic on TCP ports 22 and 80 from anywhere. Notice that the IP addresses are specified in CIDR notation (0.0.0.0/0 is most unrestrictive and matches every IP address).
Creating a security group
Creating a new security group is pretty easy and can be accomplished by using the command
ec2-create-group. Following is how you would add a security group named Apache
ec2-create-group Apache -d Apache web server
Adding a firewall rule
Firewall rules can be added to limit access on any TCP, UDP and ICMP ports, and as I mentioned above the IP address have to be specified in the CIDR notation. You can read more about the CIDR notation here. Firewall rules can be added using the
Let’s add a rule to allow http traffic on TCP port 80 from anywhere to all machines in the security group named Apache
ec2-authorize Apache -P tcp -p 80 -s 0.0.0.0/0
That was pretty easy. But what if I want the source to be more restrictive. Suppose I have a MySQL instance that I have to open up access for, on port 3306, but I want the port 3306 to be only accessible from the Apache instance. If the apache instance has the IP 10.106.10.102/32, I can easily add a rule like below:
ec2-authorize MySQL -P tcp -p 3306 -s 10.106.10.102/32
But that’s not very scalable, what if I have more than one Apache instances all connecting to the MySQL instance, and also the fact that I have no control over the EC2 private IP, whenever an instance is restarted its private IP changes. Just for these kind of situations, you can also specify the source as another security group instead of a CIDR IP address. Suppose all your Apache instances belong to the security group Apache. Then we can easily modify the above rule to only allow access from instances in the Apache group:
ec2-authorize MySQL -P tcp -p 3306 -u AWS_ACCOUNT_NUMBER -o Apache
Now we can keep on adding new instances, making sure they belong to the Apache security group, and they would be able to access the MySQL instance on port 3306.
Deleting a firewall rule
Firewall rules can deleted as easily as they were added. The command that would accomplish that is
ec2-revoke. Suppose you want to delete the firewall rule allowing access to instances in Apache security group over port 80:
ec2-revoke Apache -P tcp -p 80 -s 0.0.0.0/0
EC2 security groups is a very underestimated feature, but one that can be very powerful. The best thing is that it allows role based filtering to be applied which is very neat and which allows for easy scaling. You can think of security groups as roles, and its very easy as I showed above to allow role based access, for example, allowing instances in the Apache group to access instances in the MySQL group.