Linux

Setting Up Port Forwarding on Linux: A Comprehensive Guide

This guide will help you set up port forwarding on Linux to provide access to local services from an external network. We'll cover methods using iptables and firewalld.

Updated at February 17, 2026
10-15 minutes
Medium
FixPedia Team
Применимо к:Ubuntu 20.04+CentOS 7+Debian 10+Fedora 35+

Introduction / Why This Is Needed

Port forwarding allows you to make a local service running on an internal IP address and port accessible from an external network via the public IP and port of your Linux server. This is essential when you want to, for example, provide access to a web server on port 8080, a database, or an SSH daemon located behind NAT, without changing the configuration of the services themselves.

After completing this guide, you will be able to configure forwarding of incoming traffic from port 80 to the internal server 192.168.1.100:8080, or from port 2222 to the internal SSH server 192.168.1.100:22—depending on your needs.

Requirements / Preparation

Before you begin, ensure that:

  • You have access to a Linux system (Ubuntu, CentOS, Debian, Fedora, etc.) with sudo or root privileges.
  • The system has iptables installed and running (for classic distributions) or firewalld (for CentOS/RHEL/Fedora). You can check with:
    sudo systemctl status iptables   # for iptables
    sudo systemctl status firewalld  # for firewalld
    
  • You know the internal IP address and port of the service you want to forward. You can find this with:
    ip addr show
    
    or
    hostname -I
    
  • You have a public IP address (or domain name) that will receive the incoming traffic. If the server is on a local network, this is your router's IP, and port forwarding must be configured on the router to point to your Linux server.

Step 1: Enabling IP Forwarding in the Kernel

By default, IP forwarding is disabled in most Linux distributions. This means the kernel will not forward packets between network interfaces. Enable it temporarily:

sudo sysctl -w net.ipv4.ip_forward=1

To enable it permanently (so the setting persists after reboot), edit the file /etc/sysctl.conf or create a new one in /etc/sysctl.d/:

echo "net.ipv4.ip_forward = 1" | sudo tee /etc/sysctl.d/99-ipforward.conf
sudo sysctl -p /etc/sysctl.d/99-ipforward.conf

⚠️ Important: If you are using IPv6, also enable forwarding for it by adding net.ipv6.conf.all.forwarding=1 to the same file.

Step 2: Configuring Port Forwarding with iptables

This method is suitable for distributions where iptables is used by default (e.g., Ubuntu before 20.04, Debian, CentOS 6/7 without firewalld).

Assume you want to forward incoming connections on port 80 (HTTP) to an internal server with IP 192.168.1.100 on port 8080.

  1. Add a DNAT rule (destination NAT) to the nat table's PREROUTING chain. This rule will apply to incoming packets destined for port 80:
    sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 192.168.1.100:8080
    
    • -t nat — specifies the NAT table.
    • -A PREROUTING — appends the rule to the end of the PREROUTING chain (processes packets before routing).
    • -p tcp — protocol TCP (replace with udp for UDP).
    • --dport 80 — target port on the external interface.
    • -j DNAT — target is to change the destination address.
    • --to-destination 192.168.1.100:8080 — new address and port.
  2. Allow packet forwarding in the FORWARD chain. This is needed so the kernel doesn't block forwarding packets to the internal server:
    sudo iptables -A FORWARD -p tcp -d 192.168.1.100 --dport 8080 -j ACCEPT
    

    If the internal server needs to access the internet through this same gateway, add a MASQUERADE rule for outgoing traffic:
    sudo iptables -t nat -A POSTROUTING -p tcp -d 192.168.1.100 --dport 8080 -j MASQUERADE
    

    However, for simple incoming port forwarding, this is often not required if the internal server has a proper route back to the client.

Step 3: Configuring Port Forwarding with firewalld

For distributions with firewalld (CentOS 7+, RHEL 7+, Fedora), use the simpler syntax with zones.

  1. Identify the active zone (e.g., public):
    sudo firewall-cmd --get-default-zone
    

    Usually this is public.
  2. Add a port forwarding rule to that zone. To forward port 80 to 192.168.1.100:8080:
    sudo firewall-cmd --zone=public --add-forward-port=port=80:proto=tcp:toaddr=192.168.1.100:toport=8080
    
    • --add-forward-port — adds a port forwarding rule.
    • port=80 — external port.
    • proto=tcp — protocol (can be udp).
    • toaddr=192.168.1.100 — internal IP.
    • toport=8080 — internal port.
  3. Make the rule permanent (so it survives reboots):
    sudo firewall-cmd --zone=public --add-forward-port=port=80:proto=tcp:toaddr=192.168.1.100:toport=8080 --permanent
    

    💡 Tip: If your internal server needs internet access through this gateway, enable masquerading:

    sudo firewall-cmd --zone=public --add-masquerade --permanent
    

Step 4: Saving Rules

iptables and firewalld handle rule persistence differently.

For iptables

On most distributions, iptables rules are not saved automatically after reboot. Use:

  • Ubuntu/Debian with the iptables-persistent package:
    sudo netfilter-persistent save
    

    Or manually:
    sudo iptables-save > /etc/iptables/rules.v4
    
  • CentOS 6/7 (if not using firewalld):
    sudo service iptables save
    

    or
    sudo /etc/init.d/iptables save
    

For firewalld

Rules added with the --permanent flag are saved in configuration files (/etc/firewalld/). After adding rules, reload firewalld to ensure they are applied:

sudo firewall-cmd --reload

Step 5: Verifying Functionality

  1. View active rules:
    • For iptables:
      sudo iptables -t nat -L -n -v
      
      You should see the rule in the PREROUTING and FORWARD chains.
    • For firewalld:
      sudo firewall-cmd --list-all
      
      Look for forward-ports in the output.
  2. Check that the port is open on the external interface. Note: after DNAT, port 80 on the public interface is not listened to by a daemon but is forwarded. Therefore, ss -tuln | grep :80 might show nothing. It's better to test from outside.
  3. Test from outside:
    • From another computer on the network or from the internet, run:
      curl http://PUBLIC_IP:80
      
      or
      telnet PUBLIC_IP 80
      
    • You should receive a response from the internal server (e.g., a webpage from port 8080).

    If the service uses HTTPS, replace port 80 with 443 and the protocol with https.

Common Issues

Rules don't work after reboot

  • iptables: You didn't save the rules. Run sudo netfilter-persistent save or the equivalent command for your distribution.
  • firewalld: You added the rule without --permanent. Fix it: sudo firewall-cmd --zone=public --add-forward-port=... --permanent and reload.

"Permission denied" or "Operation not permitted" error

  • Ensure you are running the commands with sudo or as root. Port forwarding requires administrator privileges.

Port already in use

  • Another service (e.g., Apache/Nginx web server) is already running on the external port (e.g., 80). Stop it or choose a different port.
  • Check: sudo ss -tuln | grep :80

Incorrect internal IP

  • Ensure the IP 192.168.1.100 is correct and the service on it is running. Check: ping 192.168.1.100 and curl http://192.168.1.100:8080 from the Linux server itself.

firewalld and iptables conflict

  • On systems with firewalld (CentOS 7+), do not use iptables directly—firewalld manages rules via iptables. Instead, configure everything through firewall-cmd. If you accidentally added an iptables rule, it may be overwritten by firewalld.

SELinux blocking (for CentOS/RHEL/Fedora)

  • SELinux may forbid port forwarding by default. Temporarily disable it for testing:
    sudo setenforce 0
    
    If this helps, configure SELinux policies correctly. For firewalld, issues are rare, but for iptables you might need:
    sudo semanage port -a -t http_port_t -p tcp 80
    

Internal service not responding

  • Check that the service (e.g., web server) is listening on 0.0.0.0:8080 or on the internal IP, not just on 127.0.0.1. Use sudo ss -tuln | grep 8080.
  • Ensure the internal server (if separate) has a route back to the client via your gateway. Sometimes a static route or NAT on the gateway is required.

Forwarding UDP ports

  • For UDP, use the same commands but replace tcp with udp in iptables or proto=udp in firewalld. Example for firewalld:
    sudo firewall-cmd --zone=public --add-forward-port=port=53:proto=udp:toaddr=192.168.1.100:toport=53 --permanent
    

F.A.Q.

What is port forwarding and what is it used for?
Which is better: iptables or firewalld?
How to check if port forwarding is working?
Are root privileges required to set up port forwarding?

Hints

Enable IP forwarding in the Linux kernel
Add a port forwarding rule
Save rules for persistent application
Test port forwarding

Did this article help you solve the problem?

FixPedia

Free encyclopedia for fixing errors. Step-by-step guides for Windows, Linux, macOS and more.

© 2026 FixPedia. All materials are available for free.

Made with for the community