How to Whitelist Specific IP Addresses in an EC2 Security Group
You've stood up an EC2 instance and now you need to lock down port 443 to a single office IP — not the entire internet. Adding a specific CIDR block like 203.0.113.0/32 as an inbound rule is the right move, but getting the Security Group rule syntax wrong means either locking yourself out or leaving the port wide open. Here's exactly how to do it correctly.
TL;DR — Whitelist a Specific IP in a Security Group
| Step | Action |
|---|---|
| 1 | Identify your Security Group ID (e.g., sg-0abc123def456) |
| 2 | Confirm the exact public IP or CIDR block to whitelist |
| 3 | Add an inbound rule: TCP port 443, source = 203.0.113.0/32 |
| 4 | Verify the rule is applied and test connectivity |
How Security Group Inbound Rules Work
A Security Group acts as a stateful instance-level firewall. 'Stateful' means return traffic for an allowed inbound connection is automatically permitted — you don't need a matching outbound rule for responses. Rules are evaluated collectively: if any rule matches the incoming traffic, the connection is allowed. There is no explicit deny at the Security Group level — traffic not matching any rule is implicitly dropped.
A /32 CIDR block means exactly one IPv4 address. 203.0.113.0/32 allows only that single IP. Using 0.0.0.0/0 would allow any IPv4 address — which is what you're trying to avoid.
- Office Client initiates HTTPS traffic from IP
203.0.113.0. - Security Group evaluates inbound rules. The rule permitting TCP 443 from
203.0.113.0/32matches. - Traffic reaches the EC2 Instance on port 443.
- Any other source IP hits no matching rule and is silently dropped.
Step 1: Find Your Security Group ID
Before adding a rule, confirm which Security Group is attached to your instance. It's easy to add a rule to the wrong group — especially if the instance has multiple Security Groups attached.
aws ec2 describe-instances \
--instance-ids i-0123456789abcdef0 \
--query 'Reservations[*].Instances[*].SecurityGroups' \
--output table
This returns the Security Group name and ID for every group attached to the instance. Note the GroupId — you'll need it in the next step. If multiple groups are listed, identify which one controls inbound HTTPS access.
Step 2: Add the Inbound Rule to Whitelist a Specific IP on Port 443
With the Security Group ID confirmed, add the inbound rule using authorize-security-group-ingress. The --cidr value is your office IP in CIDR notation.
aws ec2 authorize-security-group-ingress \
--group-id sg-0abc123def456 \
--protocol tcp \
--port 443 \
--cidr 203.0.113.0/32
If the command succeeds, it returns a JSON object with Return: true and the rule details. If the rule already exists, AWS returns a InvalidPermission.Duplicate error — not a silent no-op. That error is actually useful: it confirms the rule was already present.
Think of a /32 CIDR like a guest list with exactly one name on it. A /24 is a whole neighborhood. A /0 is 'anyone who shows up.' You want the one-name list.
Step 3: Verify the Rule Was Applied Correctly
Adding a rule and confirming it landed correctly are two different things. Describe the Security Group's current inbound rules to verify — don't assume the CLI success response is enough.
aws ec2 describe-security-groups \
--group-ids sg-0abc123def456 \
--query 'SecurityGroups[*].IpPermissions' \
--output json
Look for an entry with FromPort: 443, ToPort: 443, IpProtocol: tcp, and an IpRanges entry containing CidrIp: 203.0.113.0/32. If you see 0.0.0.0/0 in the same port range from a previous rule, that prior rule still allows all traffic — the new specific rule doesn't override it.
Step 4: Remove an Overly Permissive Rule if One Exists
This is where most engineers stop too early. If there's already a rule allowing 0.0.0.0/0 on port 443, your new specific rule does nothing useful — traffic from any IP still matches the broad rule. You need to revoke the permissive rule explicitly.
aws ec2 revoke-security-group-ingress \
--group-id sg-0abc123def456 \
--protocol tcp \
--port 443 \
--cidr 0.0.0.0/0
After revoking, re-run the describe command from Step 3 to confirm only the 203.0.113.0/32 rule remains for port 443. This is the step that actually closes the exposure.
Doing This via the AWS Console
If you prefer the console over CLI:
- Navigate to EC2 → Security Groups and select your group.
- Click the Inbound rules tab, then Edit inbound rules.
- Click Add rule. Set Type to HTTPS (auto-fills port 443), Protocol to TCP.
- In the Source field, select Custom and enter
203.0.113.0/32. - Optionally add a description like
Office IP - HTTPS only. - Click Save rules.
The console will also show you all existing rules in the same view — use that to spot and delete any 0.0.0.0/0 rules on port 443 at the same time.
A Real Failure Pattern: The Rule That Did Nothing
The symptom: you add the specific IP rule, test from a different IP, and the connection still succeeds. You check the Security Group and see your new rule is there. What's wrong?
The misdiagnosis: the new rule must not have saved correctly, or the instance needs to be restarted for rules to take effect.
The actual cause: there was already a rule allowing 0.0.0.0/0 on port 443 — added months ago during initial setup and forgotten. Security Groups are additive. Adding a restrictive rule doesn't cancel a permissive one. Both rules exist simultaneously, and any traffic matching either rule is allowed.
The fix: always audit existing rules before and after adding a new one. The describe command in Step 3 is not optional housekeeping — it's the actual verification step.
Security Group rules don't have priority order. There's no 'deny wins.' Every allow rule is evaluated independently, and a match on any one of them lets the traffic through.
IAM Permissions Required for These Operations
The CLI commands above require the following IAM permissions. Apply these to the role or user running the commands, scoped to the specific Security Group where possible.
🔽 Click to expand — IAM policy for Security Group rule management
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:DescribeSecurityGroups",
"ec2:AuthorizeSecurityGroupIngress",
"ec2:RevokeSecurityGroupIngress",
"ec2:DescribeInstances"
],
"Resource": "*"
}
]
}
Note: ec2:DescribeSecurityGroups and ec2:DescribeInstances are read actions that require Resource: * — they do not support resource-level restrictions. AuthorizeSecurityGroupIngress and RevokeSecurityGroupIngress can be scoped to a specific Security Group ARN in some configurations, but verify against the AWS Service Authorization Reference for your exact use case.
Wrap-Up: Whitelisting Specific IPs in Security Groups
Restricting port 443 to a single office IP is a two-part operation: add the specific CIDR rule, then remove any existing permissive rules covering the same port. Skipping the second part leaves the exposure intact. The CLI workflow above handles both, and the describe step in between is what confirms the intended state actually matches the configured state.
For dynamic office IPs that change periodically, consider using Security Group rule descriptions to track when each IP was added, and review them on a schedule. AWS also supports referencing another Security Group as a source instead of a CIDR — useful when your office traffic exits through a known AWS resource.
Official reference: AWS EC2 Security Group Rules documentation.
Glossary
| Term | Definition |
|---|---|
| Security Group | A stateful, instance-level virtual firewall that controls inbound and outbound traffic for EC2 instances. |
| CIDR Block | A notation for specifying IP address ranges (e.g., 203.0.113.0/32 = single IP, 10.0.0.0/24 = 256 addresses). |
| /32 prefix | A CIDR prefix length indicating exactly one IPv4 address — the most restrictive single-host notation. |
| Inbound Rule | A Security Group rule controlling traffic arriving at the instance. Stateful — return traffic is automatically allowed. |
| Implicit Deny | Security Group default behavior: traffic not matching any allow rule is silently dropped, with no explicit deny rule required. |
Related Posts
- 📄 EC2 SSH Connection Timeout: Which Security Group Rules to Check
- 📄 Connecting to AWS RDS MySQL from Your Local Machine: Public Access, Security Groups, and Safer Alternatives
- 📄 How to Use AWS Config to Detect Non-Compliant Security Group Rules
- 📄 Security Group vs Network ACL: Stateful vs Stateless Traffic Filtering in AWS VPC
- 📄 Connecting Two VPCs with VPC Peering: Route Tables, Security Groups, and Private IP Communication
Comments
Post a Comment