DEV Community

John  Ajera
John Ajera

Posted on

Access Internal URLs (e.g. Grafana) via AWS SSM Port Forwarding

Access Internal URLs (e.g. Grafana) via AWS SSM Port Forwarding

You have a service behind an ALB at a private or hard-to-reach URL (e.g. app.internal.example.com). You also have an EC2 instance with SSM (Session Manager) enabled that can reach that URL. This guide shows how to port-forward through that instance so you can open the app in your browser—and why you might see 404 until you fix the Host header.


1. Overview

What this guide does:

  • Uses AWS SSM port forwarding to reach an internal ALB host (e.g. Grafana) from your laptop
  • Explains why opening http://localhost:8080 can return 404 (wrong Host header)
  • Shows how to fix the Host header with a hosts entry and the correct URL so the ALB routes correctly

No VPN required: Only an EC2 bastion with SSM and the AWS CLI Session Manager plugin.


2. Prerequisites

Before starting, ensure you have:

  • An EC2 instance with the SSM agent and the right IAM role (e.g. AmazonSSMManagedInstanceCore)
  • The instance must be able to reach the target host (same VPC or routing as the ALB)
  • AWS CLI and Session Manager plugin installed, with credentials configured for the instance’s account and region

3. Start the Port Forward

Forward a local port through the instance to the internal host and port (here: HTTP 80; use 443 for HTTPS):

aws ssm start-session \
  --target i-0abcd1234efgh5678 \
  --document-name AWS-StartPortForwardingSessionToRemoteHost \
  --parameters '{"host":["app.internal.example.com"],"portNumber":["80"],"localPortNumber":["8080"]}' \
  --region ap-southeast-2
Enter fullscreen mode Exit fullscreen mode

Replace:

  • i-0abcd1234efgh5678 with your instance ID
  • app.internal.example.com with your internal hostname
  • 80 / 8080 with the remote and local ports (e.g. 443 and 8443 for HTTPS)

Leave this terminal running. Traffic to localhost:8080 on your machine is now forwarded to app.internal.example.com:80 via the instance.


4. Why You Get 404 When You Open http://localhost:8080

If you open http://localhost:8080 in your browser, the request looks like:

  • URL: http://localhost:8080/
  • Host header: localhost:8080

Your ALB has a listener rule that routes traffic only when the Host header is app.internal.example.com. So:

  • Host: localhost → no matching rule → ALB returns 404
  • Host: app.internal.example.com → rule matches → request reaches the app (e.g. Grafana 302 to login)

The port forward is working; the 404 is from the ALB because of the wrong Host header.


5. Fix the Host Header So the ALB Routes Correctly

Make your browser send Host: app.internal.example.com by resolving that hostname to your machine and opening that URL on the forwarded port.

Add a hosts entry (run once; needs sudo)

echo "127.0.0.1 app.internal.example.com" | sudo tee -a /etc/hosts
Enter fullscreen mode Exit fullscreen mode

Open in your browser

http://app.internal.example.com:8080
Enter fullscreen mode Exit fullscreen mode

The browser will send Host: app.internal.example.com, the ALB will match the rule, and you should see the app (e.g. Grafana login).

HTTPS: Use port 443 on both sides and open https://app.internal.example.com:8443. You may need to accept the certificate for that hostname on localhost.


6. Quick Reference

You want to… Do this
Forward HTTP (80) portNumber: 80, localPortNumber: 8080, then open http://app.internal.example.com:8080
Forward HTTPS (443) portNumber: 443, localPortNumber: 8443, then open https://app.internal.example.com:8443
Avoid 404 Add 127.0.0.1 app.internal.example.com to hosts and use that hostname (and port) in the browser
Use a different instance Change --target to your instance ID

7. Summary

  1. Start SSM port forwarding from a local port to internal-host:port via your bastion.
  2. Add a hosts entry so the internal hostname points to 127.0.0.1.
  3. Open http(s)://internal-host:local-port in the browser so the Host header matches the ALB rule and you avoid 404.

This gives you browser access to internal ALB-backed URLs without a VPN, using only SSM and a single EC2 instance.


8. Troubleshooting

Issue: SSM session starts but browser gets connection refused on localhost

Solution: Ensure the instance can reach the internal host and port (e.g. from the instance: curl -v http://app.internal.example.com). Check security groups and VPC routing.

Issue: 404 even after adding hosts entry

Solution: Confirm you are opening http://app.internal.example.com:8080 (with the internal hostname), not http://localhost:8080. Clear browser cache if needed.

Issue: Certificate warning for HTTPS

Solution: The ALB certificate is for app.internal.example.com. After the hosts entry, the browser talks to localhost but uses that hostname; accept the certificate for app.internal.example.com once.


9. References

Top comments (0)