When working with AWS Elastic Load Balancers (ELB), there's often a need to maintain health checks while restricting public access. The core issue arises because ELBs don't have their own security groups - they rely on the instances' security groups to control traffic flow.
Here's how to properly configure your security groups to achieve this:
# Security Group for EC2 instances (allow ELB health checks) aws ec2 authorize-security-group-ingress \ --group-id sg-0abcdef1234567890 \ --protocol tcp \ --port 80 \ --source-group sg-elb-healthchecks
1. Create a security group specifically for ELB health checks:
aws ec2 create-security-group \ --group-name elb-healthchecks \ --description "Allow health checks from ELB" \ --vpc-id vpc-12345678
2. Configure your instance security group to only allow traffic from this ELB security group on port 80:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": "*", "Action": "ec2:AuthorizeSecurityGroupIngress", "Resource": "arn:aws:ec2:region:account-id:security-group/sg-0abcdef1234567890", "Condition": { "ArnEquals": { "ec2:SourceInstanceARN": "arn:aws:elasticloadbalancing:region:account-id:loadbalancer/app/your-elb-name/50dc6c495c0c9188" } } } ] }
To limit ELB access to just your IP while maintaining health checks:
# Update security group to allow your IP aws ec2 authorize-security-group-ingress \ --group-id sg-elb-healthchecks \ --protocol tcp \ --port 80 \ --cidr YOUR.IP.ADDRESS.HERE/32
For stricter control, combine security groups with network ACLs:
# Network ACL rule to block public access to port 80 aws ec2 create-network-acl-entry \ --network-acl-id acl-12345678 \ --ingress \ --rule-number 100 \ --protocol tcp \ --port-range From=80,To=80 \ --cidr-block 0.0.0.0/0 \ --rule-action deny
Remember that security groups are stateful while NACLs are stateless. If you're using both, ensure your outbound rules properly accommodate the ELB health check responses.
When working with AWS Elastic Load Balancers (ELB), administrators often need to restrict public access to port 80 while maintaining internal ELB health checks. This creates a security versus availability dilemma that requires careful security group configuration.
To allow ELB health checks while blocking public access, implement these security group rules:
# Inbound rules for instances behind ELB
Type: HTTP
Protocol: TCP
Port Range: 80
Source: [ELB Security Group ID] # Not public IP range
# Alternative for Classic Load Balancers
Type: HTTP
Protocol: TCP
Port Range: 80
Source: [ELB's security group]
While ELBs don't support security groups directly, you can implement IP restriction through these methods:
# Option 1: Web Application Firewall (WAF)
aws wafv2 create-web-acl \
--name MyIPRestriction \
--scope REGIONAL \
--default-action Block \
--visibility-config SampledRequestsEnabled=true \
--rules file://waf-rules.json
# Sample waf-rules.json
{
"Name": "AllowMyIP",
"Priority": 0,
"Action": {
"Allow": {}
},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true
},
"Statement": {
"IPSetReferenceStatement": {
"ARN": "arn:aws:wafv2:us-east-1:123456789012:regional/ipset/MyIPSet"
}
}
}
For additional layer of security:
# Network ACL inbound rules
Rule #: 100
Type: HTTP (80)
Protocol: TCP
Action: ALLOW
Source: [Your Public IP]/32
Rule #: *
Type: HTTP (80)
Action: DENY
Source: 0.0.0.0/0
Common pitfalls to avoid:
- Ensure health check path is accessible internally
- Verify security group references use group IDs not IP ranges
- Check that NACLs don't override security group rules
- Confirm timeout settings match application response times
For temporary maintenance windows:
aws ec2 authorize-security-group-ingress \
--group-id sg-123456 \
--protocol tcp \
--port 80 \
--cidr [YourIP]/32 \
--output text