> ## Documentation Index
> Fetch the complete documentation index at: https://help.freakhosting.com/llms.txt
> Use this file to discover all available pages before exploring further.

# How to Set Up Port Forwarding with iptables on Linux

> Port forwarding with iptables on Linux: enable ip_forward, add a DNAT rule, allow it in FORWARD, add MASQUERADE and save the rules (UFW and firewalld too).

To set up port forwarding with iptables, enable IP forwarding (`net.ipv4.ip_forward=1`), add a DNAT rule such as `sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 8080 -j DNAT --to-destination 10.0.0.2:80`, allow the traffic in the `FORWARD` chain, and add a `MASQUERADE` rule so replies come back through your server. Save the rules so they survive a reboot. With UFW, put the rules in `/etc/ufw/before.rules`; on AlmaLinux/Rocky, use `firewall-cmd --add-forward-port`.

| Difficulty | Time | Works on | Needs |
| - | - | - | - |
| Advanced | 20 minutes | Ubuntu 22.04/24.04, Debian 12/13 (iptables); AlmaLinux/Rocky 9/10 (firewalld) | sudo access, a reachable target host, console access as a fallback |

## Before you start

* **Port forwarding** sends connections that arrive on one port of your server to another port or another machine. **NAT** (network address translation) rewrites the addresses in those packets. **DNAT** changes the destination; **MASQUERADE** changes the source to your server's address.
* Typical uses: reach a service on a machine behind a private network or VPN (for example [WireGuard](https://help.freakhosting.com/portals/other/how-to-set-up-a-wireguard-vpn-server.md)), move a service to another port, or give a private network internet access.
* The examples use `eth0` as the public interface, `wg0` as the private one and `10.0.0.2` as the target. Find your interface names with `ip -br addr`.
* Open the [VNC console](https://help.freakhosting.com/portals/vps-panel/how-to-enable-and-use-vnc-console-access.md) first. A wrong rule can cut your SSH connection.
* Commands use `sudo`; as root, leave it out.

> [!WARNING]
>
> Never run `iptables -F` or change the `INPUT` policy over SSH without a console open. Port forwarding rules only touch the `nat` table and the `FORWARD` chain, so your SSH access stays as it is if you follow the steps below.

## How to enable IP forwarding

Linux doesn't pass packets between interfaces until forwarding is on (the [kernel default](https://docs.kernel.org/networking/ip-sysctl.html) is `0`).

```bash theme={null}
echo "net.ipv4.ip_forward=1" | sudo tee /etc/sysctl.d/99-ip-forward.conf
sudo sysctl --system
sysctl net.ipv4.ip_forward
```

The last command should print `net.ipv4.ip_forward = 1`.

## How to forward a port to another machine

> [tab] Ubuntu / Debian with UFW
>
> If UFW is your firewall (`sudo ufw status` shows `Status: active`), add the rules through UFW, as in the [ufw-framework manual](https://manpages.ubuntu.com/manpages/noble/man8/ufw-framework.8.html). UFW drops forwarded traffic by default (`DEFAULT_FORWARD_POLICY="DROP"`).
>
> **1. Enable forwarding for UFW**
>
> ```bash theme={null}
> sudo nano /etc/ufw/sysctl.conf
> ```
>
> Remove the `#` in front of `net/ipv4/ip_forward=1`. UFW applies this file when it starts, so set forwarding here as well as in the section above.
>
> **2. Add the NAT rules**
>
> ```bash theme={null}
> sudo nano /etc/ufw/before.rules
> ```
>
> Add this at the end of the file, after the last `COMMIT` of the `*filter` section:
>
> ```ini theme={null}
> *nat
> :PREROUTING ACCEPT [0:0]
> :POSTROUTING ACCEPT [0:0]
> -A PREROUTING -i eth0 -p tcp --dport 8080 -j DNAT --to-destination 10.0.0.2:80
> -A POSTROUTING -o wg0 -p tcp -d 10.0.0.2 --dport 80 -j MASQUERADE
> COMMIT
> ```
>
> **3. Allow the forwarded traffic**
>
> ```bash theme={null}
> sudo ufw route allow in on eth0 out on wg0 to 10.0.0.2 port 80 proto tcp
> ```
>
> **4. Reload UFW**
>
> ```bash theme={null}
> sudo ufw reload
> ```
>
> The rules are stored in UFW's files and survive reboots.

> [tab] Ubuntu / Debian without UFW
>
> **1. Add the DNAT rule**
>
> Send TCP port 8080 on the public interface to port 80 on `10.0.0.2`:
>
> ```bash theme={null}
> sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 8080 -j DNAT --to-destination 10.0.0.2:80
> ```
>
> **2. Allow the forwarded traffic**
>
> ```bash theme={null}
> sudo iptables -A FORWARD -i eth0 -o wg0 -p tcp -d 10.0.0.2 --dport 80 -m conntrack --ctstate NEW,ESTABLISHED,RELATED -j ACCEPT
> sudo iptables -A FORWARD -i wg0 -o eth0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
> ```
>
> **3. Make replies return through this server**
>
> ```bash theme={null}
> sudo iptables -t nat -A POSTROUTING -o wg0 -p tcp -d 10.0.0.2 --dport 80 -j MASQUERADE
> ```
>
> Without this, the target answers the visitor directly and the connection fails. The trade-off: the target sees your server's private IP instead of the visitor's IP. If the target's default route already goes through this server (common on a VPN), you can leave this rule out and keep the real visitor IP.
>
> **4. Save the rules**
>
> ```bash theme={null}
> sudo apt install iptables-persistent
> sudo netfilter-persistent save
> ```
>
> The rules are written to `/etc/iptables/rules.v4` and loaded at boot.
>
> > [!WARNING]
> >
> > On Ubuntu, installing `iptables-persistent` **removes UFW** (the packages conflict). Only use this method if you don't use UFW.

> [tab] AlmaLinux / Rocky (firewalld)
>
> firewalld is the default firewall here, so use it instead of raw iptables rules.
>
> **1. Add the forward rule**
>
> ```bash theme={null}
> sudo firewall-cmd --permanent --zone=public --add-forward-port=port=8080:proto=tcp:toport=80:toaddr=10.0.0.2
> ```
>
> firewalld turns on IP forwarding itself when you set `toaddr`.
>
> **2. Enable masquerading**
>
> ```bash theme={null}
> sudo firewall-cmd --permanent --zone=public --add-masquerade
> ```
>
> **3. Reload and check**
>
> ```bash theme={null}
> sudo firewall-cmd --reload
> sudo firewall-cmd --zone=public --list-all
> ```
>
> The output lists the rule under `forward-ports` and shows `masquerade: yes`.

## How to redirect one port to another on the same server

To accept connections on port 2222 and send them to a service on port 22 of the same server:

```bash theme={null}
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 2222 -j REDIRECT --to-ports 22
```

No forwarding or masquerading is needed for this.

## How to give a private network internet access (NAT)

If machines on `10.0.0.0/24` (for example VPN clients) should reach the internet through your server:

```bash theme={null}
sudo iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o eth0 -j MASQUERADE
sudo iptables -A FORWARD -s 10.0.0.0/24 -o eth0 -j ACCEPT
sudo iptables -A FORWARD -d 10.0.0.0/24 -i eth0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
```

IP forwarding must be on, as above. Save with `sudo netfilter-persistent save`, or with UFW use the masquerade example in the [ufw-framework manual](https://manpages.ubuntu.com/manpages/noble/man8/ufw-framework.8.html).

## How to check it worked

```bash theme={null}
sudo iptables -t nat -L -n -v --line-numbers
sudo iptables -L FORWARD -n -v --line-numbers
```

The packet counters (`pkts`) on your rules go up when traffic matches. Then test from outside: `nc -zv 203.0.113.10 8080` (see [check if a port is open](https://help.freakhosting.com/portals/other/how-to-check-if-a-port-is-open-from-outside.md)).

To remove a rule, delete it by its number, for example `sudo iptables -t nat -D PREROUTING 1`, then save again.

## Frequently asked questions

### Why doesn't my port forward work?

Check, in order: `net.ipv4.ip_forward = 1`; the DNAT rule's counter increases; the `FORWARD` chain (or a `ufw route` rule) allows the traffic; the `MASQUERADE` rule exists or the target routes back through you; the target service listens on the right port.

### Does this work for UDP, such as game servers?

Yes. Use `-p udp` in the DNAT, FORWARD and MASQUERADE rules (or `proto=udp` in firewalld). Add a second set of rules if you need both TCP and UDP.

### Are these iptables or nftables rules?

On current Ubuntu, Debian, AlmaLinux and Rocky releases, the `iptables` command uses the nftables back end (`iptables -V` shows `nf_tables`). The syntax above still applies. See [nftables and iptables](https://help.freakhosting.com/portals/other/how-to-use-nftables-and-iptables.md).

### How do I forward IPv6?

IPv6 uses `ip6tables` and `net.ipv6.conf.all.forwarding=1`. firewalld's `--add-forward-port` is IPv4 only; IPv6 forwarding there needs a rich rule.

## Related guides

> [card] [VPS and dedicated server guides](https://help.freakhosting.com/portals/other/vps-and-dedicated-server-guides.md)
>
> Every guide in this section.

> [card] [nftables and iptables](https://help.freakhosting.com/portals/other/how-to-use-nftables-and-iptables.md)
>
> Firewall rules in depth.

> [card] [Set up a WireGuard VPN](https://help.freakhosting.com/portals/other/how-to-set-up-a-wireguard-vpn-server.md)
>
> A private network to forward into.

> [card] [Check if a port is open](https://help.freakhosting.com/portals/other/how-to-check-if-a-port-is-open-from-outside.md)
>
> Test the forward from outside.

> [card] [Set up firewalld](https://help.freakhosting.com/portals/other/how-to-set-up-a-firewall-with-firewalld.md)
>
> Zones and rules on AlmaLinux and Rocky.

> [card] [Locked out after a firewall change](https://help.freakhosting.com/portals/other/how-to-fix-locked-out-after-firewall-change.md)
>
> Recover access with the console.

***

> [!NOTE]
>
> **Checked against the [ufw-framework manual](https://manpages.ubuntu.com/manpages/noble/man8/ufw-framework.8.html), the [firewall-cmd manual](https://firewalld.org/documentation/man-pages/firewall-cmd.html) and the [Linux kernel IP sysctl documentation](https://docs.kernel.org/networking/ip-sysctl.html)** on 4 November 2026; the iptables rules were validated with `iptables-restore --test` (iptables 1.8.10, nf\_tables) the UFW route rule with `ufw --dry-run`, and the `iptables-persistent`/UFW conflict with `apt-get install -s` on Ubuntu 24.04 LTS, without applying any rules. Commands can differ on other distributions or releases.

> [!NOTE]
>
> ### Need Extra Help?
>
> If you encounter any issues, our support team is ready to assist:
>
> * **Live Chat:** Quick assistance via our website.
> * **Support Ticket:** [Open a Ticket](https://freakhosting.com/clientarea/submitticket.php)
> * **Discord:** [Join our Community](https://discord.gg/freakhosting)
> * **Email:** [support@freakhosting.com](mailto:support@freakhosting.com)

> [!TIP]
>
> ### Save on Your Hosting
>
> Ready to upgrade your hosting? Use code **KB20** at checkout for **20% off** your first order!

***

**Last Updated:** November 2026


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.