guide · 7 min read
Opening a port on your router
A generic guide, whatever the router. Including the CGNAT test to run FIRST, and what an open port actually costs you.
Your services run at home. From the sofa, everything works. From a train, nothing — and that is normal: your router lets nobody in.
Opening a port tells it "when someone knocks here, send them to that machine". This guide covers how to do it on any router, what to know first, and why this site recommends a different method.
First: check it is even possible
Much of consumer fibre, and all mobile broadband, gives you a public address shared between several subscribers. That is CGNAT. In that case no port forward will ever work, whatever you tick: the address people knock on is not yours.
The test takes two minutes. Get the public address you appear to have:
curl -4 ifconfig.me
Then open your router's interface and find the WAN address of its internet
interface. If the two match, the rest of this guide can work. If they differ —
the router shows something in 100.64.x.x to 100.127.x.x, or in
10.x.x.x — you are behind CGNAT.
Two ways out: ask your ISP for a public IPv4 address (free with some, paid or impossible with others), or use a tunnel, which needs no public address at all. Setting up Cloudflare Tunnel covers the second, and it is the method we recommend anyway.
What you need
- Your server's local IP address, the
192.168.x.xor10.x.x.xone.ip -br aon the server, or your router's list of connected devices. - The port number your service listens on. It is the first number in the
portsline of yourdocker-compose.yml: in"8096:8096", that is - Admin access to your router.
Step 1 — Pin the server's address first
This is the step everyone skips, and the one that makes the forward stop working three weeks later with no explanation.
Your router hands out addresses over DHCP, with leases that expire. The day your
server reboots after a power cut, it may get 192.168.1.57 instead of
192.168.1.42. Your rule still points at .42 — where a television now
lives.
In your router's interface, look for static lease, DHCP reservation, address reservation or static DHCP. Tie the address you want to the server's MAC address, which the same page usually shows you.
Step 2 — Find the screen, whatever it is called
Every router has this; almost none call it the same thing. Look for, in order:
- Port forwarding — most consumer routers
- NAT/PAT — some ISP boxes and professional gear
- Virtual Server — TP-Link, D-Link, much Asian hardware
- Applications & Gaming → Single Port Forwarding — Linksys
- Firewall → Port forwards — OPNsense, pfSense, OpenWrt
- Advanced → NAT rules — various ISP boxes
The interface is almost always at 192.168.1.1 or 192.168.0.1. When in
doubt, ip route | grep default on any machine on the network gives the
router's address.
Step 3 — Create the rule
The fields change names, never meaning:
| What it asks for | What it means | Example |
|---|---|---|
| Name / Description | For you only | jellyfin |
| Protocol | TCP in 95% of cases | TCP |
| External / WAN / start port | What the outside knocks on | 8096 |
| Internal IP / LAN / Destination | Your server | 192.168.1.42 |
| Internal / destination port | What the service listens on | 8096 |
External and internal ports may differ, and often should. Exposing Jellyfin on external port 41096 rather than 8096 does not make it safe, but it does take it out of the laziest scans, which only try well-known ports.
What not to do, whatever a forum says: enable the DMZ. It forwards every port to one machine — you are no longer opening a door, you are removing the wall. One rule per service, always.
Step 4 — Open the server's firewall too
A forward brings traffic to the machine; the machine's firewall can still refuse
it. If you followed the Ubuntu guide, ufw is on:
sudo ufw allow 8096/tcp
sudo ufw status
This is the second most common cause of "I made the rule and it does not work".
Step 5 — Test from outside
Testing from your own network proves nothing. Many routers cannot send a request that started inside back inside — that is NAT hairpinning, or its absence. You will get either a failure while everything works, or a success that means nothing.
Test from a network that is not yours:
- Turn off your phone's Wi-Fi and open
http://YOUR-PUBLIC-IP:8096over mobile data. - Or use an online port checker, giving it your public address and the number.
If nothing answers, go back in this order: CGNAT (step 0), the server's IP that
may have changed (step 1), the server's firewall (step 4), and the service that
may only be listening on 127.0.0.1. From the server, sudo ss -tulpn | grep 8096 should show 0.0.0.0:8096 and not 127.0.0.1:8096.
Step 6 — The public address changes
With most consumer ISPs it moves — on router reboot, or occasionally without warning. Memorising a number that changes leads nowhere.
The answer is dynamic DNS: a domain name that follows your address. A small client runs at home and tells the service whenever it changes. Many routers have one built in (look for DynDNS or Dynamic DNS), and DuckDNS or No-IP have free tiers.
If you already have a domain at Cloudflare, the same mechanism exists there — and at that point, you may as well read the next section.
What you have actually just done
This needs saying plainly, because most guides do not say it.
You have made a service reachable by the entire planet. Within the hour, bots will knock on it: they sweep the whole IPv4 space continuously, and they do not need to know you exist to find you.
What becomes true from now on:
- Every flaw in that service is your problem. An un-updated Jellyfin exposed to the internet is a machine that eventually belongs to someone else — and from there, your whole home network is within reach.
- Over HTTP, everything travels in the clear. Passwords included. An open port without a certificate means a readable password at every hotel, every station, every network in between.
- Your public IP points at your home, to within a few streets. It now appears in the logs of everyone scanning it.
The minimum, if you open anyway: never port 22 for SSH to the outside, never a service without authentication, and a reverse proxy with HTTPS in front of anything that asks for a password.
The alternative, and why this site prefers it
An outbound tunnel reverses the direction: a small program runs at home and goes out to an external service, which becomes the public entry point. Nothing comes in. No open port, your public address appears nowhere, and the HTTPS certificate comes with it.
Two ways, both free for personal use:
- Cloudflare Tunnel, if you want your services public — a domain is enough.
- Tailscale or WireGuard, if you only want to reach them yourself from your own devices. Nothing is public, and it is by far the safest option.
Opening a port is still the right answer in a few cases: a game server, a protocol an HTTP tunnel cannot carry, or simply not wanting to depend on anyone. In every other case, the box you just ticked costs you more than it gives you.
Video
SpaceRex explains what forwarding a port actually exposes before showing how to do it — the same order of priorities this guide takes.
Nothing is sent to YouTube until you press play. This site sets no cookies of its own.Watch on YouTube