When you create a VPC endpoint for S3, it's important to note that the routing happens at the AWS infrastructure level, not at the EC2 instance level. This explains why you don't see specific S3 routes in your EC2 instance's routing table.
Here are several ways to verify your VPC endpoint is functioning correctly:
1. DNS Resolution Test
Check if S3 requests resolve to the VPC endpoint's private IP:
nslookup s3.us-east-1.amazonaws.com
If working properly, this should return private IP addresses from the 169.254.169.0/24 range or similar.
2. Network Traffic Analysis
Use tcpdump to monitor traffic:
sudo tcpdump -i eth0 -n host s3.us-east-1.amazonaws.com
Look for traffic to private IP addresses rather than public S3 endpoints.
3. S3 API Test with Detailed Logging
This Python script shows detailed connection information:
import boto3
import requests
from botocore.client import Config
s3 = boto3.client('s3', config=Config(
connect_timeout=5,
retries={'max_attempts': 0}
))
try:
response = s3.list_buckets()
print("Connection successful via VPC endpoint")
except Exception as e:
print(f"Connection failed: {str(e)}")
4. VPC Flow Logs Analysis
Enable VPC Flow Logs and check for traffic to S3 endpoints:
filter(
($.interfaceEndpointId = "vpce-1234567890abcdef")
and
($.dstAddr like "52.216.*")
)
Using curl with Verbose Output
curl -v https://s3.us-east-1.amazonaws.com/mybucket/
Check the resolved IP address in the verbose output.
AWS CLI with Debug Mode
AWS_DEBUG=1 aws s3 ls
This shows detailed connection information including endpoints used.
- Ensure your route tables are properly associated with the VPC endpoint
- Verify security groups and NACLs allow outbound traffic to the S3 prefix list
- Check DNS resolution in your VPC (DHCP option sets)
When you create a VPC endpoint for S3, AWS automatically modifies the route tables associated with your VPC subnets. However, these routes won't appear in your EC2 instance's local routing table because:
- VPC endpoints use AWS's private network backbone (not visible in instance route tables)
- The routing happens at the VPC level before reaching your instance
Method 1: DNS Resolution Test
# Check S3 endpoint resolution (should return private IP)
dig +short s3.amazonaws.com
# Should return something like:
# 10.0.0.1
# (your VPC endpoint IP)
Method 2: Network Tracing
# Trace route to S3 (should show private hops)
traceroute s3.amazonaws.com
# Alternative with curl timing
curl -w "DNS: %{time_namelookup} Connect: %{time_connect} TTFB: %{time_starttransfer}\n" -o /dev/null -s https://s3.amazonaws.com
Create a test script to verify endpoint functionality:
import boto3
from botocore.client import Config
# Force path-style to test endpoint
s3 = boto3.client('s3', config=Config(s3={'addressing_style': 'path'}))
try:
response = s3.list_buckets()
print("Successfully accessed S3 via VPC endpoint")
except Exception as e:
print(f"Access failed: {e}")
Create flow logs and check for S3 traffic:
# Sample Athena query for flow logs
SELECT
interface_id,
srcaddr,
dstaddr,
action
FROM vpc_flow_logs
WHERE dstaddr LIKE '52.218.%' # Common S3 IP ranges
AND date BETWEEN '2023-01-01' AND '2023-01-02'
- Verify endpoint policy allows necessary S3 actions
- Check security group rules allow HTTPS (443) to the endpoint
- Confirm no conflicting IAM policies restricting access
- Validate DNS resolution within the VPC