I created a VPC Interface Endpoint for the Systems Manager (SSM) service so my private EC2 instances could reach the SSM API without going through the internet. I followed the console steps, added the endpoint to my VPC, assigned a security group, but when I tried to run SSM operations from an instance, the connection timed out. The endpoint was there, but traffic wasn’t using it. In this post, I’ll walk through exactly what causes this and how to fix it.
The Problem
You created a VPC Interface Endpoint for an AWS service (SSM, ECR, S3, Secrets Manager, etc.), but traffic still routes over the internet or connections time out. The endpoint appears “available” in the console, but when you try to use the service from a private instance, it fails. Or the private endpoint DNS name doesn’t resolve.
Here’s what you might see when testing connectivity:
$ aws ssm describe-instances --region us-east-1
An error occurred (InvalidParameterException): Retrieving instance information failed
$ nslookup ssm.us-east-1.amazonaws.com
Non-existent host/domain
$ curl -v https://ssm.us-east-1.amazonaws.com/
Timeout waiting for DNS response
| Issue | Description |
|---|---|
| Endpoint DNS Name Doesn’t Resolve | nslookup returns NXDOMAIN or times out |
| Connection Times Out | Requests to endpoint hang with no response |
| Traffic Still Goes Over Internet | CloudTrail shows public endpoint IP being used instead of private |
| Endpoint is Available but Unused | Endpoint shows “available” in console but gets no traffic |
Why Does This Happen?
-
VPC doesn’t have DNS hostname and DNS support enabled: Interface Endpoints rely on DNS to resolve service names to private IPs. If
enableDnsHostnamesandenableDnsSupportare not both true on the VPC, the private endpoint DNS name won’t resolve. Instead, DNS queries return the public service endpoint. -
Using the regional endpoint URL instead of private DNS name: If you hardcode
https://ssm.us-east-1.amazonaws.comin your code, it resolves to the public endpoint IP regardless of whether an Interface Endpoint exists. You must rely on DNS resolution or use the private DNS name (usually the same as the regional name when DNS is enabled). -
Security group on the endpoint doesn’t allow inbound traffic: Interface Endpoints have their own security group. This SG must allow inbound traffic from the EC2 instance’s security group on port 443 (HTTPS). If the endpoint SG denies the source, connections time out.
-
Endpoint is in a different subnet or AZ than the instance: For best performance and to avoid cross-AZ charges, deploy endpoints in the same subnets where your instances are. If the endpoint is only in AZ-A and your instance is in AZ-B, you can still connect but experience latency.
-
Route table still has routes sending S3 traffic to the internet: For Gateway Endpoints (S3, DynamoDB), routes are added automatically. But if you’re using Interface Endpoints and the route table has an old route sending traffic through NAT, traffic might still go to the public endpoint.
The Fix
First, enable DNS support and hostname resolution on the VPC:
aws ec2 modify-vpc-attribute \
--vpc-id vpc-0a1b2c3d4e5f6g7h8 \
--enable-dns-hostnames
aws ec2 modify-vpc-attribute \
--vpc-id vpc-0a1b2c3d4e5f6g7h8 \
--enable-dns-support
Verify the settings:
aws ec2 describe-vpc-attribute \
--vpc-id vpc-0a1b2c3d4e5f6g7h8 \
--attribute enableDnsHostnames \
--query 'EnableDnsHostnames.Value'
aws ec2 describe-vpc-attribute \
--vpc-id vpc-0a1b2c3d4e5f6g7h8 \
--attribute enableDnsSupport \
--query 'EnableDnsSupport.Value'
Check if the endpoint exists and its status:
aws ec2 describe-vpc-endpoints \
--filters "Name=service-name,Values=com.amazonaws.us-east-1.ssm" \
--query 'VpcEndpoints[*].[VpcEndpointId,State,ServiceName]' \
--output table
If the endpoint doesn’t exist, create one:
aws ec2 create-vpc-endpoint \
--vpc-id vpc-0a1b2c3d4e5f6g7h8 \
--service-name com.amazonaws.us-east-1.ssm \
--vpc-endpoint-type Interface \
--subnet-ids subnet-0a1b2c3d4e5f6g7h8 subnet-0x1y2z3a4b5c6d7e8 \
--security-group-ids sg-0a1b2c3d4e5f6g7h8 \
--private-dns-enabled
Fix Security Group on the Endpoint
Get the endpoint’s security group:
aws ec2 describe-vpc-endpoints \
--vpc-endpoint-ids vpce-0a1b2c3d4e5f6g7h8 \
--query 'VpcEndpoints[0].Groups[*].GroupId' \
--output text
Add an inbound rule to allow traffic from your EC2 instance’s security group:
aws ec2 authorize-security-group-ingress \
--group-id sg-0endpoint1234567890 \
--protocol tcp \
--port 443 \
--source-group sg-0instance1234567890
Or allow from the VPC CIDR:
aws ec2 authorize-security-group-ingress \
--group-id sg-0endpoint1234567890 \
--protocol tcp \
--port 443 \
--cidr 10.0.0.0/16
Test DNS Resolution
From the EC2 instance, test DNS resolution of the private endpoint:
nslookup ssm.us-east-1.amazonaws.com
If it returns a private IP (10.x.x.x), DNS is working. If it returns a public IP (not 10.x.x.x), then DNS is still resolving to the public endpoint.
Also verify private DNS is enabled on the endpoint:
aws ec2 describe-vpc-endpoints \
--vpc-endpoint-ids vpce-0a1b2c3d4e5f6g7h8 \
--query 'VpcEndpoints[0].PrivateDnsEnabled'
If false, enable it:
aws ec2 modify-vpc-endpoint \
--vpc-endpoint-id vpce-0a1b2c3d4e5f6g7h8 \
--private-dns-enabled
Verify Endpoint is in the Right Subnets
Check which subnets the endpoint is deployed in:
aws ec2 describe-vpc-endpoints \
--vpc-endpoint-ids vpce-0a1b2c3d4e5f6g7h8 \
--query 'VpcEndpoints[0].SubnetIds'
Add more subnets if needed for coverage and to avoid cross-AZ costs:
aws ec2 modify-vpc-endpoint \
--vpc-endpoint-id vpce-0a1b2c3d4e5f6g7h8 \
--add-subnet-ids subnet-0new1234567890
How to Run This
- Enable DNS hostname and DNS support on the VPC (critical step).
- Create the Interface Endpoint with private DNS enabled.
- Deploy endpoints in all subnets where instances need them.
- Update the endpoint security group to allow inbound from EC2 instances on port 443.
- Test DNS resolution from an instance:
nslookup service.region.amazonaws.com. - Verify the returned IP is private (10.x.x.x), not public.
Is This Safe?
Yes, Interface Endpoints are safe and recommended for security. Enabling DNS and adding security group rules doesn’t affect existing connectivity.
Key Takeaway
PrivateLink (Interface Endpoints) requires DNS to work properly. Always enable DNS hostnames and support on the VPC first. Then verify the endpoint’s security group allows traffic from your instances. Use the private DNS name for connectivity—it automatically routes through the endpoint when DNS is enabled.
Have questions or ran into a different networking issue? Connect with me on LinkedIn or X.