UnderHost
Knowledgebase Docs

NAT and Port Forwarding: Route to Internal Services

Configure NAT and port forwarding on VPS. Route external traffic to internal services, access multiple apps on single VPS, expose internal networks.

On this page

NAT (Network Address Translation) rewrites network packets, allowing traffic from one IP/port to reach another IP/port. Port forwarding is NAT's most common use: expose internal services to the internet on a single public IP.

What is NAT?

Basic example:

  • Internet user visits yourserver.com:8080
  • NAT intercepts traffic on port 8080
  • Rewrites packet to internal IP:9000
  • Internal app (running on port 9000) responds
  • NAT rewrites response back to public IP:8080
  • User receives response transparently

Port Forwarding Basics

Three components:

  • Public IP: What internet sees (your VPS IP)
  • Public port: Port users connect to (80, 443, 8080, etc.)
  • Internal service: Private IP:port (localhost:3000, 192.168.1.10:9000)

Common forwarding scenarios:

Internet:80 → localhost:8080 (local web app)
Internet:443 → localhost:443 (local HTTPS)
Internet:3306 → 10.0.0.5:3306 (remote database)
Internet:22 → localhost:2222 (SSH on non-standard port)

Real-World Use Cases

Use CaseExample
Multiple web apps on one VPSPort 80→8000, 443→8001, etc.
Game serverInternet:7777 → localhost:7777
Database access from officeInternet:3306 → internal-db:3306
SSH on custom portInternet:2222 → localhost:22
Expose internal networkInternet → internal LAN service

Configure with iptables

Simple port forward (temporary):

# Forward port 8080 to localhost:3000
sudo iptables -t nat -A PREROUTING -p tcp --dport 8080 -j REDIRECT --to-port 3000

# Forward to different IP (requires ip_forward enabled)
sudo sysctl -w net.ipv4.ip_forward=1
sudo iptables -t nat -A PREROUTING -p tcp --dport 3306 -j DNAT --to-destination 10.0.0.5:3306
sudo iptables -A FORWARD -p tcp -d 10.0.0.5 --dport 3306 -j ACCEPT

View current rules:

sudo iptables -t nat -L -n -v

Make Rules Persistent

Rules disappear on reboot. Save permanently:

# Save current rules
sudo iptables-save > /etc/iptables/rules.v4

# Load on boot (Debian/Ubuntu)
sudo apt install iptables-persistent
# Choose 'Yes' when prompted to save IPv4 rules

Or edit /etc/iptables/rules.v4 directly:

# Add this to nat table
-A PREROUTING -p tcp --dport 8080 -j REDIRECT --to-port 3000

Verify Configuration

# Test port forwarding from another machine
telnet yourserver.com 8080

# Check if port is listening
sudo netstat -tulpn | grep 8080

# Test with curl
curl http://yourserver.com:8080

Advanced Scenarios

Load balance across multiple backends:

# Round-robin between two servers
iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 10.0.0.1:8000
iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 10.0.0.2:8000

Forward SSH to different port (security):

# Hide SSH on standard port 22, expose on 2222
iptables -t nat -A PREROUTING -p tcp --dport 2222 -j REDIRECT --to-port 22

# Now: ssh -p 2222 user@server.com

Troubleshooting

ProblemSolution
Port forwarding not workingCheck: iptables rules exist, ip_forward enabled, service listening
Rules disappear on rebootSave with iptables-persistent or edit rules.v4
Connection refusedVerify internal service is actually listening on target port
Slow connectionNAT overhead is minimal; check network itself
Forward carefully—exposed services = risk

Port forwarding exposes internal services to the internet. Only forward what you need. Prefer reverse proxies (Nginx) or VPNs for sensitive services.

Related: VPS networking | Firewall setup | Reverse proxy setup

Was this article helpful?

Need a Cloud VPS?

Launch an UnderHost Cloud VPS when you need root access, dedicated resources, custom software, or more control than shared hosting.

Related articles

Back to Cloud VPS