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

StepAction
1Identify your Security Group ID (e.g., sg-0abc123def456)
2Confirm the exact public IP or CIDR block to whitelist
3Add an inbound rule: TCP port 443, source = 203.0.113.0/32
4Verify 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.

graph LR OfficeClient["Office Client 203.0.113.0"] OtherClient["Other Client 198.51.100.5"] SG["Security Group Inbound Rule: TCP 443 Source: 203.0.113.0/32"] EC2["EC2 Instance Port 443"] Dropped["Traffic Dropped (implicit deny)"] OfficeClient -->|"TCP 443 - matches rule"| SG SG -->|"allowed"| EC2 OtherClient -->|"TCP 443 - no matching rule"| Dropped
  1. Office Client initiates HTTPS traffic from IP 203.0.113.0.
  2. Security Group evaluates inbound rules. The rule permitting TCP 443 from 203.0.113.0/32 matches.
  3. Traffic reaches the EC2 Instance on port 443.
  4. 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:

  1. Navigate to EC2 → Security Groups and select your group.
  2. Click the Inbound rules tab, then Edit inbound rules.
  3. Click Add rule. Set Type to HTTPS (auto-fills port 443), Protocol to TCP.
  4. In the Source field, select Custom and enter 203.0.113.0/32.
  5. Optionally add a description like Office IP - HTTPS only.
  6. 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

TermDefinition
Security GroupA stateful, instance-level virtual firewall that controls inbound and outbound traffic for EC2 instances.
CIDR BlockA notation for specifying IP address ranges (e.g., 203.0.113.0/32 = single IP, 10.0.0.0/24 = 256 addresses).
/32 prefixA CIDR prefix length indicating exactly one IPv4 address — the most restrictive single-host notation.
Inbound RuleA Security Group rule controlling traffic arriving at the instance. Stateful — return traffic is automatically allowed.
Implicit DenySecurity Group default behavior: traffic not matching any allow rule is silently dropped, with no explicit deny rule required.

Related Posts

Comments

Popular posts from this blog

AWS SNS Email Alerts Not Arriving? The Subscription Confirmation Trap Explained

S3 Public Access Denied: Why Your Public Object URL Still Returns 403

EC2 No Internet Access in Custom VPC: Fix Internet Gateway and Route Table