Overview
This is the third installment in my Networking Basics series. In this post, I'll delve into Network Address Translation (NAT) and port forwarding—essential concepts for running game servers from behind a home router's single public IP address.
Background
The lab setup involves one public IP address provided by the ISP but multiple machines needing to be accessible over the internet. NAT is used to translate private 192.168.1.x addresses into the single public address, ensuring that outbound traffic works seamlessly while inbound traffic poses a challenge. This post will cover how we handle both outbound and inbound traffic.
How It Works
Outbound Traffic: Just Works
Outbound traffic is straightforward; any packet originating from an internal machine gets its source IP address replaced with the router's public IP, allowing it to traverse the internet. The router keeps track of these mappings so that responses can be correctly routed back to the original sender.
Inbound Traffic: The Problem and Solutions
Inbound traffic requires more attention because unsolicited packets arriving at the public IP have no information about which internal machine should receive them. There are two main solutions:
Port Forwarding: This involves explicitly configuring the router to direct incoming traffic on specific ports to particular internal machines. For example, Minecraft might use port 25565 and Valheim uses port 2456. The AMP host (Advanced Machine Protection) handles these mappings internally.
In BreadLab, AMP handles the inside half of this automatically: each game instance gets its own port assignment when it's created, and AMP exposes them as per-instance application endpoints. Our servers page reads those endpoints through the API, which is how it always shows the current `host:port` for players. The router's forwarding table is still maintained by hand — one forward per game port, pointing at the AMP host.Tunnels: For web traffic, we don't forward any ports at all. Instead, a tunneling service like
cloudflaredestablishes an outbound connection to Cloudflare. Traffic then flows through this secure tunnel without requiring open inbound ports for the websites.The short version of the tunnel setup: install the `cloudflared` daemon, authenticate it against your Cloudflare account, and give it a config file mapping hostnames to internal services. It then holds an outbound connection to Cloudflare's edge, and web traffic arrives down that tunnel with zero inbound port forwards. A later post in this series covers it properly — including the memorable failure mode of accidentally running two of them at once.
Concepts
- Ports: Ranges from 0 to 65535, with well-known ports like HTTP (80), HTTPS (443), and SSH (22).
- Ephemeral Ports: These are dynamically assigned by the operating system for temporary connections.
- Service Conflicts: Two services cannot listen on the same host:port combination simultaneously.
- TCP vs UDP: Game traffic often uses UDP because it's more tolerant of packet loss compared to TCP, which requires retransmissions.
Lab Lesson
Keep a spreadsheet documenting forwarded ports. Never forward a port to an unhardened service; the internet will scan your exposed services within minutes.
Results
The setup is functional but requires careful management. The spreadsheet ensures that we don't accidentally expose any services without proper security measures in place.
Lessons Learned
- Documentation: Maintain detailed records of forwarded ports.
- Security: Harden all services before exposing them to the internet.
- Flexibility: Use tunnels for web traffic where port forwarding is not feasible.
By understanding and implementing NAT and port forwarding, we can successfully run game servers from behind a home router's single public IP address.