CGNAT troubleshooting

CGNAT port forwarding: get public ports without a public IP

Learn why router port forwarding fails behind CGNAT and how to expose SSH, Docker, APIs, game servers, and self-hosted apps with stable public ports.

Quick diagnosis checklist

  1. Confirm the service is listening locally.
  2. Confirm the service responds from the host itself.
  3. Check host firewall rules before changing router rules.
  4. Compare the host/router WAN address with the public IP seen by the internet.
  5. Test from a different network, not from the same LAN.
  6. If inbound traffic still times out, use a public forwarded endpoint instead of relying on upstream NAT.

Commands to run first

# What public IPv4 does the internet see?
curl -4 ifconfig.me

# What is listening locally?
ss -tulpen
sudo ss -tulpen

# Test a local web/API service
curl -v http://127.0.0.1:8080
curl -v http://127.0.0.1:8000/health

# Check common Linux firewalls
sudo ufw status verbose
sudo iptables -S
sudo nft list ruleset

What CGNAT changes

Carrier-grade NAT means your ISP or upstream provider shares one public IPv4 address across many customers. Your router may show a private or carrier-grade WAN address, while the internet sees a different public address. Normal port forwarding fails because unsolicited inbound packets stop at the provider NAT before they ever reach you.

Check whether you are behind CGNAT

# Public IPv4 seen by the internet
curl -4 ifconfig.me

# Local default route source address
ip route get 1.1.1.1

# CGNAT/private ranges to look for on router WAN or host path:
# 10.0.0.0/8
# 100.64.0.0/10
# 172.16.0.0/12
# 192.168.0.0/16

Common fixes that do not solve CGNAT

Working options compared

ISP public IP

Clean when available, but often expensive, unavailable on LTE/5G, or not provided for rented hosts.

DIY VPS reverse proxy

Flexible, but you operate firewall rules, tunnels, monitoring, TLS, abuse handling, and failover.

HTTP tunnel

Great for web apps, but not always a fit for SSH, raw TCP/UDP, game servers, or port ranges.

NeedPorts

Provides assigned public ports through an outbound tunnel without router or ISP changes.

Example: expose SSH and a web app

YOUR_SETUP_TOKEN is shown after signup/trial checkout and binds the client to your assigned endpoint.

curl -fsSL https://api.needports.com/install | sudo bash -s YOUR_SETUP_TOKEN --accept-tos
sudo needports setup --dry-run
sudo needports use ssh 30000
sudo needports expose custom --public-port 30001 --local-port 8080 --name "Web App" --confirm
sudo needports restart
ssh -p 30000 user@your-needports-endpoint
curl -v http://your-needports-endpoint:30001

FAQ

Can I port forward behind CGNAT?
Not with normal router forwarding alone. You need the ISP to provide a public IP, or you need an outbound tunnel/public endpoint service.
Does DDNS fix CGNAT?
No. DDNS only names an IP address; it does not create an inbound route through upstream CGNAT.
How do I know if I am behind CGNAT?
Compare the router WAN IP with curl -4 ifconfig.me. Addresses in 100.64.0.0/10 or private ranges are strong CGNAT signals.
Do I need router access for NeedPorts?
No. NeedPorts uses an outbound connection from your machine to a public tunnel endpoint.
Can I expose Docker, SSH, APIs, or game servers?
Yes, if the local service is listening and the NeedPorts plan/port supports the needed protocol.

Deep troubleshooting examples

Example 1: Router WAN IP does not match public IP

This is the classic CGNAT symptom. The router receives a private or carrier-grade address while the internet sees the ISP shared public IP.

# Public IP seen by internet
curl -4 ifconfig.me

# On Linux, show the selected local source address for outbound traffic
ip route get 1.1.1.1

# On your router, compare WAN/Internet IP with curl output.
# If router WAN is 100.64.x.x, 10.x.x.x, 172.16-31.x.x, or 192.168.x.x,
# normal router forwarding cannot create a public inbound route.

Example 2: DDNS updates correctly but the port is still closed

DDNS can point a name at the public IP, but it cannot make the upstream NAT forward unsolicited inbound packets to you.

dig your-ddns-name.example
curl -4 ifconfig.me
nc -vz your-ddns-name.example 30000

If DNS is correct and the port still times out, the problem is routing/firewalling, not naming.

Example 3: LTE/5G backup internet breaks inbound access

Many cellular plans use CGNAT. A service that is reachable on fiber may disappear when failover switches to LTE/5G.

# Run before and after failover
curl -4 ifconfig.me
nc -vz your-public-endpoint 30000

NeedPorts keeps the local machine making an outbound tunnel, so the public endpoint can remain stable across networks where normal inbound routing is impossible.

Public port options by use case

SSH and admin access

Use key-only SSH and map one assigned public port. Keep a fallback path.

Docker dashboards

Map only authenticated dashboards. Never expose the Docker daemon TCP socket.

Game servers

Check whether the game requires TCP, UDP, or both. Test externally with the right protocol.

APIs and webhooks

Use authentication, rate limits, and HTTPS/TLS for production APIs.

Ready for a stable public endpoint?

Start with a NeedPorts trial, map one service, and test the public port from another network before depending on it for production traffic.

Start a trialRead more guides