How to Fix AWS EC2 403 Forbidden and Permission Denied Errors
Resolve AWS EC2 403 Forbidden, 502 Bad Gateway, and connection refused errors by fixing IAM roles, security groups, and WAF rules. Step-by-step guide.
- IAM instance profile lacks necessary permissions for the requested AWS service or resource.
- AWS WAF (Web Application Firewall) is blocking the incoming request due to rate limiting or bad IP reputation.
- Security Groups or Network ACLs are misconfigured, leading to connection refused or timeout errors.
- Quick Fix: Verify the EC2 instance's attached IAM role policies using the AWS CLI and check WAF web ACL traffic logs.
| Method | When to Use | Time | Risk |
|---|---|---|---|
| Update IAM Role Policies | When EC2 logs show 'AccessDenied' for AWS API calls | 5 mins | Low |
| Adjust WAF Rules | When CloudFront/ALB returns 403 for external web traffic | 10 mins | Medium |
| Modify Security Groups | When encountering 'Connection Refused' or 'Timeout' | 5 mins | High (if overly permissive) |
| Nginx/Apache Config Check | When the web server itself throws a 403 on specific paths | 15 mins | Low |
Understanding AWS EC2 403 Forbidden Errors
An AWS EC2 403 Forbidden error indicates that the server understands the request but refuses to authorize it. Unlike a 401 Unauthorized error (which implies missing or invalid authentication), a 403 means the identity is known, but the permissions are insufficient. In an AWS ecosystem, this error can originate from several layers: the EC2 instance's IAM role, an Application Load Balancer (ALB), AWS WAF, or the web server software (Nginx, Apache) running on the instance.
When troubleshooting, you might also encounter related errors like 502 Bad Gateway (often an ALB failing to communicate with the EC2 target), Connection Refused (Security Group or service down), or Timeout / Throttling (AWS API rate limits).
Step 1: Diagnose the Origin of the 403
Before applying fixes, you must determine which component is returning the 403.
- Check the Web Server Logs: Connect to your EC2 instance and inspect the access/error logs for Nginx (
/var/log/nginx/error.log) or Apache (/var/log/apache2/error.log). If the 403 originates here, it's likely a file permission issue or web server misconfiguration. - Inspect AWS WAF Logs: If your EC2 instance sits behind an ALB or CloudFront distribution integrated with AWS WAF, WAF might be blocking the request. Check the WAF sampled requests or Athena queries for AWS WAF logs. Look for the
terminatingRuleId. - Review CloudTrail for IAM Issues: If your application on the EC2 instance is getting a 403 (or
AccessDenied) when trying to access other AWS services (like S3 or DynamoDB), the instance's IAM role is the culprit. Search AWS CloudTrail forAccessDeniedevents associated with the instance's role session.
Step 2: Fix IAM Instance Profile Permissions
If your EC2 instance cannot access an S3 bucket or invoke an API, you need to update its IAM role.
- Navigate to the EC2 Console > Instances.
- Select your instance and check the Security tab for the attached IAM role.
- Click the role to open the IAM console.
- Review the attached policies. Ensure the role has explicit
Allowpermissions for the required actions and resources. - Example: If the app needs S3 read access, ensure
s3:GetObjectis allowed for the specific bucket ARN.
Step 3: Resolve AWS WAF Blocking
If AWS WAF is returning the 403:
- Identify the triggered rule in the WAF console.
- If it's a false positive from an AWS Managed Rule (e.g., SQLi or XSS rules blocking legitimate payloads), you can set the specific rule to Count mode or add an exception.
- If you are hitting rate limits (
aws ec2 rate limitorthrottling), adjust the threshold of your rate-based rule if the traffic is legitimate.
Step 4: Fix Web Server File Permissions
If Nginx or Apache is throwing the 403:
- Ensure the web server user (usually
www-dataornginx) has read access to the web directory. - Run
sudo chown -R www-data:www-data /var/www/html(adjust path as needed). - Run
sudo find /var/www/html -type d -exec chmod 755 {} \; - Run
sudo find /var/www/html -type f -exec chmod 644 {} \;
Handling Related Errors: 502, Connection Refused, and Timeouts
- 502 Bad Gateway: The ALB cannot reach the EC2 instance. Verify the web service (e.g., Node.js, Nginx) is actually running on the instance and listening on the port configured in the Target Group.
- Connection Refused: Check your EC2 Security Groups and Network ACLs. Ensure the inbound rules allow traffic on the required ports (80, 443, 22) from the expected source IPs.
- Timeout: Often caused by Security Groups dropping packets (no route) rather than actively refusing them. Also, verify the instance has a public IP or is correctly routed through a NAT Gateway if in a private subnet.
Frequently Asked Questions
# Diagnostic Commands for EC2 403 and Connection Issues
# 1. Check Nginx Error Logs for 403s
sudo tail -n 50 /var/log/nginx/error.log | grep "403"
# 2. Check Apache Error Logs
sudo tail -n 50 /var/log/apache2/error.log | grep "authz_core:error"
# 3. Test local connectivity (Fixing 502/Connection Refused)
# Ensure the service is listening on the expected port (e.g., 8080)
sudo netstat -tulpn | grep 8080
curl -I http://localhost:8080
# 4. Check attached IAM Role from instance metadata (IMDSv2)
TOKEN=`curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"`
curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/iam/info
# 5. Fix common web directory permissions (Debian/Ubuntu)
sudo chown -R www-data:www-data /var/www/html
sudo find /var/www/html -type d -exec chmod 755 {} \;
sudo find /var/www/html -type f -exec chmod 644 {} \;
# 6. Check disk space (if experiencing weird failures)
df -hError Medic Editorial
Error Medic Editorial is a team of certified AWS DevOps engineers and SREs dedicated to diagnosing and solving complex cloud infrastructure issues. With over a decade of experience managing enterprise EC2 workloads, we focus on actionable, secure, and highly available architectures.