Introduction
Security groups act as virtual firewalls for EC2 instances. When traffic is blocked, instances can't receive inbound connections or send outbound traffic despite network routes being correct. The security group rules don't match your traffic requirements.
Symptoms
Application-level:
$ curl http://10.0.1.50:8080
curl: (7) Failed to connect to 10.0.1.50 port 8080: Connection timed outSSH connection:
$ ssh ec2-user@ec2-1-2-3-4.compute-1.amazonaws.com
ssh: connect to host ec2-1-2-3-4.compute-1.amazonaws.com port 22: Connection refusedDatabase connection:
Error: Can't connect to MySQL server on '10.0.2.100' (110)
Connection timed outHealth check failures:
```bash $ aws elbv2 describe-target-health --target-group-arn arn:aws:elasticloadbalancing:...
"TargetHealth": { "State": "unhealthy", "Description": "Target failed health checks" } ```
Common Causes
- 1.Missing inbound rule - No ingress rule for the required port/protocol
- 2.Wrong source CIDR - Rule exists but source IP range doesn't include client
- 3.Missing outbound rule - Egress blocked, instance can't respond
- 4.Rule priority confusion - Multiple rules, wrong one matching
- 5.Security group not attached - Instance doesn't have the security group
- 6.Network ACL overriding - NACL blocking before security group
- 7.Wrong protocol - TCP rule when UDP needed, or vice versa
- 8.Port range incorrect - Single port when range needed
Step-by-Step Fix
- 1.Check logs for specific error messages
- 2.Verify configuration settings
- 3.Test network connectivity
- 4.Review recent changes
- 5.Apply corrective action
- 6.Verify the fix
Step 1: Identify Instance Security Groups
```bash # Get instance's security groups aws ec2 describe-instances --instance-ids i-abc123 \ --query 'Reservations[*].Instances[*].SecurityGroups[*].[GroupId,GroupName]'
# Or by name aws ec2 describe-instances --filters Name=tag:Name,Values=my-server \ --query 'Reservations[*].Instances[*].SecurityGroups[*].GroupId' ```
Step 2: Review Security Group Rules
```bash # Get all inbound rules (ingress) aws ec2 describe-security-groups --group-ids sg-12345 \ --query 'SecurityGroups[*].IpPermissions'
# Get all outbound rules (egress) aws ec2 describe-security-groups --group-ids sg-12345 \ --query 'SecurityGroups[*].IpPermissionsEgress'
# Get rules in formatted table aws ec2 describe-security-groups --group-ids sg-12345 \ --query 'SecurityGroups[*].IpPermissions[*].[FromPort,ToPort,IpProtocol,IpRanges[*].CidrIp]' \ --output table ```
Step 3: Test Connectivity from Source
```bash # Test from outside AWS (your local machine) curl -v --connect-timeout 5 http://INSTANCE_PUBLIC_IP:8080
# Test from another EC2 instance in same VPC aws ec2 describe-instances --instance-ids i-test123 --query 'Reservations[*].Instances[*].PrivateIpAddress'
# SSH to test instance and try connection ssh test-instance curl -v http://10.0.1.50:8080
# Check what source IP you're connecting from curl http://checkip.amazonaws.com ```
Step 4: Check for Missing Inbound Rule
bash
# Check if specific port is open
aws ec2 describe-security-groups --group-ids sg-12345 \
--query 'SecurityGroups[*].IpPermissions[?FromPort==8080`]'
# Check if port 22 (SSH) is allowed
aws ec2 describe-security-groups --group-ids sg-12345 \
--query 'SecurityGroups[*].IpPermissions[?FromPort==22 && IpProtocol==tcp]'
# If missing, add the rule aws ec2 authorize-security-group-ingress \ --group-id sg-12345 \ --protocol tcp \ --port 8080 \ --cidr 10.0.0.0/16 # Or specific source IP ```
Step 5: Verify Source CIDR Matches
```bash # Get your source IP SOURCE_IP=$(curl -s http://checkip.amazonaws.com)/32
# Check if your IP is in any rule's CIDR range aws ec2 describe-security-groups --group-ids sg-12345 \ --query "SecurityGroups[*].IpPermissions[*].IpRanges[*].CidrIp"
# If your IP isn't covered, add specific rule aws ec2 authorize-security-group-ingress \ --group-id sg-12345 \ --protocol tcp \ --port 22 \ --cidr $SOURCE_IP
# Or add broader range aws ec2 authorize-security-group-ingress \ --group-id sg-12345 \ --protocol tcp \ --port 22 \ --cidr 203.0.113.0/24 ```
Step 6: Check Outbound (Egress) Rules
```bash # Review egress rules aws ec2 describe-security-groups --group-ids sg-12345 \ --query 'SecurityGroups[*].IpPermissionsEgress[*].[IpProtocol,FromPort,ToPort,IpRanges[*].CidrIp]'
# Default allows all outbound, but may have been restricted # Add outbound rule if needed aws ec2 authorize-security-group-egress \ --group-id sg-12345 \ --protocol tcp \ --port 443 \ --cidr 0.0.0.0/0
# Allow all outbound (restore default) aws ec2 authorize-security-group-egress \ --group-id sg-12345 \ --ip-permissions 'IpProtocol=-1,FromPort=-1,ToPort=-1,IpRanges=[{CidrIp=0.0.0.0/0}]' ```
Step 7: Check Security Group Association
```bash # Verify security group is attached to instance aws ec2 describe-instances --instance-ids i-abc123 \ --query 'Reservations[*].Instances[*].SecurityGroups[*].GroupId'
# Attach security group if missing aws ec2 modify-instance-attribute \ --instance-id i-abc123 \ --groups sg-12345 sg-default
# Replace all security groups on instance aws ec2 modify-instance-attribute \ --instance-id i-abc123 \ --groups sg-12345 sg-67890 ```
Step 8: Check Network ACL Rules
NACLs process before security groups and can block traffic:
```bash # Get subnet's NACL SUBNET_ID=$(aws ec2 describe-instances --instance-ids i-abc123 \ --query 'Reservations[*].Instances[*].SubnetId' --output text)
NACL_ID=$(aws ec2 describe-network-acls \ --filters Name=association.subnet-id,Values=$SUBNET_ID \ --query 'NetworkAcls[*].NetworkAclId' --output text)
# Check NACL rules aws ec2 describe-network-acls --network-acl-ids $NACL_ID \ --query 'NetworkAcls[*].Entries[*].[RuleNumber,Egress,RuleAction,PortRange,CidrBlock]' ```
NACL rules are processed by rule number (lowest first). Ensure: - Inbound ALLOW for required port exists - Outbound ALLOW for ephemeral ports (1024-65535) exists
Step 9: Debug with VPC Flow Logs
```bash # Enable flow logs if not already aws ec2 create-flow-logs \ --resource-type VPC \ --resource-id vpc-12345 \ --traffic-type ALL \ --log-group-name /aws/vpc/flow-logs
# Query flow logs for rejected traffic aws logs filter-log-events \ --log-group-name /aws/vpc/flow-logs \ --filter-pattern "REJECT" \ --start-time $(date -d '10 minutes ago' +%s)000
# Example rejected traffic: # 2 123456789010 eni-abc123 10.0.1.50 203.0.113.100 8080 51532 6 1 100 REJECT OK ```
Step 10: Verify Protocol and Port Range
```bash # Check exact rule configuration aws ec2 describe-security-groups --group-ids sg-12345 \ --query 'SecurityGroups[*].IpPermissions[*].[IpProtocol,FromPort,ToPort]'
# Common protocols: # - tcp: 6 # - udp: 17 # - icmp: 1 # - all: -1
# Add rule for port range aws ec2 authorize-security-group-ingress \ --group-id sg-12345 \ --protocol tcp \ --port 8000-9000 \ --cidr 10.0.0.0/16
# Add ICMP rule (ping) aws ec2 authorize-security-group-ingress \ --group-id sg-12345 \ --protocol icmp \ --port -1 \ --cidr 10.0.0.0/16 ```
Step 11: Check Security Group References
```bash # Rules can reference other security groups instead of CIDR aws ec2 describe-security-groups --group-ids sg-12345 \ --query 'SecurityGroups[*].IpPermissions[*].UserIdGroupPairs[*].[GroupId,UserId]'
# Add rule referencing another security group aws ec2 authorize-security-group-ingress \ --group-id sg-12345 \ --protocol tcp \ --port 3306 \ --source-group sg-67890 \ --group-owner 123456789012
# This allows traffic from any instance with sg-67890 attached ```
Verification
```bash # Test connectivity after fix curl -v http://INSTANCE_IP:8080
# SSH connection ssh -v ec2-user@INSTANCE_PUBLIC_IP
# For ALB target health aws elbv2 describe-target-health --target-group-arn TG_ARN \ --query 'TargetHealthDescriptions[*].TargetHealth.State'
# Should return "healthy" ```
Related Issues
- [Fix AWS EC2 Instance Not Responding](/articles/fix-aws-ec2-instance-not-responding)
- [Fix AWS ELB Health Check Failing](/articles/fix-aws-elb-health-check-failing)
- [Fix AWS VPC Peering Not Working](/articles/fix-aws-vpc-peering-connection-not-working)
Related Articles
- [AWS troubleshooting: Fix IAM Permission Denied - Complete Tro](fix-iam-permission-denied)
- [AWS cloud troubleshooting: AWS ACM Certificate Pending Validation Because the](aws-acm-certificate-pending-validation-wrong-route53-zone)
- [AWS cloud troubleshooting: AWS ALB Returns 502 Because the Target Closed the ](aws-alb-502-target-closed-connection-keepalive-timeout-mismatch)
- [AWS cloud troubleshooting: Fix AWS ALB CreateListener TargetGroupNotFound Err](aws-alb-createlistener-targetgroupnotfound)
- [AWS cloud troubleshooting: Fix Aws Alb Lambda 502 Bad Gateway Issue in AWS](aws-alb-lambda-502-bad-gateway)
<script type="application/ld+json"> { "@context": "https://schema.org", "@type": "TechArticle", "headline": "Fix AWS EC2 Security Group Blocking Traffic", "description": "Troubleshoot EC2 security group traffic blocking. Fix ingress/egress rules, port configurations, and source IP restrictions.", "url": "https://www.fixwikihub.com/fix-aws-ec2-security-group-blocking", "publisher": { "@type": "Organization", "name": "FixWikiHub", "url": "https://www.fixwikihub.com" }, "author": { "@type": "Person", "name": "FixWikiHub Editorial Team" }, "datePublished": "2026-04-01T13:55:26.182Z", "dateModified": "2026-04-01T13:55:26.182Z" } </script>