AWS Step-by-Step
Best Practices for EC2 Security Groups
Any time that you create a new instance in AWS EC2, AWS gives you the opportunity to either create a new security group or to reuse an existing one. In doing so, AWS makes this process almost completely frictionless and super simple. Even so, there are some best practices that should be followed with regard to security groups in an effort to avoid security problems and management headaches.
The All or Nothing Approach
One of the first best practices that I want to talk about is to avoid what I like to call the "all or nothing" approach to security group creation. In practice, this means that you should avoid creating one single security group that handles all of your instances, while at the same time avoiding creating a brand new security group for each instance. The single security group approach can expose your instances to security threats since that group probably has a variety of open ports due to the needs of the various instances that it protects. At the same time, creating a new security group for each instance can cause you to end up with an overwhelming number of security groups (especially if you forget to delete them when you remove an instance), which can become impossible to manage.
A much better approach involves creating security groups by role. As an example, you might create one security group for Web servers, another security group for database servers, and still another security group for bastion hosts. This approach results in the creation of a small and very manageable number of reusable and purpose built security groups. These security groups contain exactly the rules that are required by the servers that the group is designed to protect, and nothing more.
Defense in Depth
As you no doubt know, security groups are essentially firewalls that are designed to protect EC2 instances. Even so, there is one subtle, but important distinction between a security group and a "real firewall." That distinction is that security groups do not allow for the creation of deny rules. You can only create allow rules. So in other words, a security group can be used to open ports for communications with an instance, but there is no provision for actively blocking various ports (although not opening a port essentially denies access to the port). This being the case, it's a good idea to practice defense in depth by using security groups in conjunction with operating system level and VPC level firewalls, not as a replacement for them.
Another mistake that is sometimes made, especially by smaller organizations, is that of placing too much confidence in security groups and therefore being lax with security in other areas. As an example, an organization might assume that because a security group prevents traffic from the outside world, there is no need to stay up to date with security patches inside of their instances.
The problem with this idea is that even if the security group does its job and blocks all Internet traffic, the instance is presumably still able to communicate with other resources within its own VPC. Hence, if another instance (protected by a different security group) were to become compromised, the attacker may be able to move laterally and attack the outdated instance from the compromised instance rather than trying to access it directly from the Internet.
Be Selective with Your Ports
It probably goes without saying, but you should never open a security group port to 0.0.0.0/0 unless it is absolutely necessary. Typically, this should be reserved for public facing Web servers.
Similarly, if you need to open Port 22 (SSH) or Port 3389 (RDP), limit access to a specific IP address, or at the very least to an IP address range associated with your corporate VPN. That way, instances can only be remotely managed from specific locations. Other options include using Session Manager (which doesn't require SSH at all) or setting up bastion hosts with restricted access.
While I am on the subject of ports, AWS security groups are configured by default to allow all outbound traffic. However, it's a good idea to figure out which ports are actually needed for outbound traffic and create rules that only allow outbound traffic on those ports. This will help to prevent the exfiltration of data in the event that an instance becomes compromised. This can also help to prevent certain types of ransomware from "phoning home."
Document Everything
Finally, when creating security groups, it's important to document each rule and why that rule exists, as well as why the security group itself exists. It's equally important to periodically review these rules in case changes need to be made. You may occasionally find rules that can be deleted or modified as a result of a port that is no longer being used or an IP address that has been retired.
About the Author
Brien Posey is a 22-time Microsoft MVP with decades of IT experience. As a freelance writer, Posey has written thousands of articles and contributed to several dozen books on a wide variety of IT topics. Prior to going freelance, Posey was a CIO for a national chain of hospitals and health care facilities. He has also served as a network administrator for some of the country's largest insurance companies and for the Department of Defense at Fort Knox. In addition to his continued work in IT, Posey has spent the last several years actively training as a commercial scientist-astronaut candidate in preparation to fly on a mission to study polar mesospheric clouds from space. You can follow his spaceflight training on his Web site.