Skip to main content
iptables Port Forwarding for Linux - Virtarix Blog

iptables Port Forwarding for Linux

December 2, 2025 · Blog / Technical Guides

Port forwarding redirects network traffic from external ports to internal services. This allows applications running behind firewalls to receive incoming connections from external networks.

Important Note: Most modern Linux distributions now use nftables as the default firewall framework. While iptables remains fully supported and widely used in production environments, nftables offers improved syntax and performance. This guide focuses on iptables for legacy system administration and environments where nftables are not available.

iptables vs nftables quick comparison

Decision factor iptables interface nftables interface
System support Confirm the distribution backend and compatibility layer Confirm the distribution package, service, and active ruleset
Existing rules Common in older runbooks and tooling Can express rules in native nftables sets, maps, chains, and tables
Performance Benchmark only if rule-processing cost is material to the workload Benchmark the same traffic and ruleset
Migration Inventory generated rules, Docker/firewall tooling, persistence, and rollback Validate translated behavior and boot persistence before cutover
Selection Maintain when required by the supported platform or tooling Prefer when it is the supported native interface for the target platform

Quick start

Forward port 80 to internal server 192.168.1.10:8080:

“`bash title="Enable forwarding and route HTTP to an internal server" sysctl -w net.ipv4.ip_forward=1 iptables -t nat -A PREROUTING -p tcp –dport 80 -j DNAT –to-destination 192.168.1.10:8080 iptables -A FORWARD -p tcp -d 192.168.1.10 –dport 8080 -j ACCEPT iptables -t nat -A POSTROUTING -o ens33 -j MASQUERADE netfilter-persistent save


Replace `ens33` with your network interface name. See the full guide below.

## Prerequisites

Requirements:

- Root or sudo access to your Linux server
- Properly configured network interfaces (verify: `ip addr show`)
- Basic networking knowledge (IP addresses, ports, protocols)
- `iptables` installed (verify: `iptables --version`)

All iptables commands require root privileges to modify firewall rules.

## How iptables works

iptables configures Linux packet filtering through tables and chains. Each table serves a specific purpose, with chains processing packets sequentially.

Basic command syntax:

```bash title="Show the basic iptables command structure"
iptables -t [table] -A [chain] [match_criteria] -j [target]

The nat table handles Network Address Translation operations. For port forwarding, we use three chains in the nat table.

The PREROUTING chain processes incoming packets before routing decisions are made. When a packet arrives, PREROUTING rules execute first, allowing you to change the destination address before the kernel routes the packet.

The POSTROUTING chain handles packets after routing decisions, just before they leave the system. POSTROUTING ensures response packets can find their way back to the original sender.

The FORWARD chain in the filter table controls which packets can traverse your system. Every packet passing through your system must be explicitly allowed in the FORWARD chain, unless you set a permissive default policy.

The default FORWARD policy is typically DROP for security. Check your policy with:

“`bash title="Check the FORWARD chain policy" iptables -L FORWARD -v -n | grep policy


## Installing iptables

On Debian-based systems, install iptables with the following command:

```bash title="Install iptables on Debian-based systems"
apt update && apt install iptables

Verify the installation by viewing current rules:

“`bash title="List the current iptables rules" iptables -L -v -n


Check your network interface names as you will need them later:

```bash title="List the network interfaces"
ip link show

Modern systems typically use interface names like ens33, ens5, or eth0.

Enabling IP forwarding

Enable IP forwarding (disabled by default):

Check the current forwarding status:

“`bash title="Check the IPv4 forwarding status" sysctl net.ipv4.ip_forward


A value of `0` means disabled. A value of `1` means enabled.

Enable forwarding temporarily for immediate testing:

```bash title="Enable IPv4 forwarding temporarily"
sysctl -w net.ipv4.ip_forward=1

To make forwarding permanent across reboots, edit the sysctl configuration file:

“`bash title="Open the sysctl configuration" nano /etc/sysctl.conf


Add or modify this line:

```conf title="Enable persistent IPv4 forwarding"
net.ipv4.ip_forward = 1

Apply the changes immediately:

“`bash title="Apply the sysctl settings" sysctl -p


## Complete port forwarding configuration

Port forwarding requires three components working together: destination address translation, firewall forwarding rules, and source address masquerading. Configure each component in sequence.

Example: Forward external port `80` to internal server `192.168.1.2:8080`.

### Step 1: configure the PREROUTING rule

Redirect incoming traffic:

```bash title="Forward TCP port 80 to port 8080"
iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 192.168.1.2:8080

Step 2: add a FORWARD rule

Allow the redirected traffic through your firewall:

“`bash title="Allow forwarded TCP traffic to port 8080" iptables -A FORWARD -p tcp -d 192.168.1.2 –dport 8080 -j ACCEPT


### Step 3: configure MASQUERADE

Configure masquerading for proper return traffic handling.

Replace `ens33` with your actual outgoing interface name:

```bash title="Masquerade outgoing forwarded traffic"
iptables -t nat -A POSTROUTING -o ens33 -j MASQUERADE

Step 4: verify your configuration

“`bash title="Verify the NAT and FORWARD rules" iptables -t nat -L -v -n iptables -L FORWARD -v -n


The packet counters should increment when traffic passes through these rules.

## Common port forwarding scenarios

### HTTP and HTTPS traffic

Forward standard web traffic from external ports to an internal web server:

```bash title="Forward HTTP and HTTPS to an internal web server"
iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 192.168.1.10:80
iptables -t nat -A PREROUTING -p tcp --dport 443 -j DNAT --to-destination 192.168.1.10:443
iptables -A FORWARD -p tcp -d 192.168.1.10 --dport 80 -j ACCEPT
iptables -A FORWARD -p tcp -d 192.168.1.10 --dport 443 -j ACCEPT

SSH access to internal servers

Forward SSH connections to an internal server. Consider using non-standard ports to reduce automated attacks:

“`bash title="Forward external port 2222 to internal SSH" iptables -t nat -A PREROUTING -p tcp –dport 2222 -j DNAT –to-destination 192.168.1.5:22 iptables -A FORWARD -p tcp -d 192.168.1.5 –dport 22 -j ACCEPT


This configuration forwards external port 2222 to the internal SSH port 22.

**Warning:** Maintain alternative access (console access, secondary SSH port) to prevent lockout if forwarding rules malfunction.

## Saving rules permanently

iptables stores rules in memory. Without persistence, all rules disappear after a system reboot.

Install the iptables-persistent package:

```bash title="Install iptables-persistent"
apt install iptables-persistent

During installation, select yes to save current rules. This creates configuration files at /etc/iptables/rules.v4 for IPv4 and /etc/iptables/rules.v6 for IPv6.

After making changes to your rules, save them using one of these methods:

Method 1: manual save

“`bash title="Save the IPv4 and IPv6 iptables rules" iptables-save > /etc/iptables/rules.v4 ip6tables-save > /etc/iptables/rules.v6


### Method 2: using netfilter-persistent (recommended)

```bash title="Save rules with netfilter-persistent"
netfilter-persistent save

Both methods achieve the same result. Method 2 is cleaner and handles both IPv4 and IPv6 simultaneously.

Create a backup before making changes:

“`bash title="Back up the persistent IPv4 firewall rules" cp /etc/iptables/rules.v4 /etc/iptables/rules.v4.backup


## Troubleshooting port forwarding

### Verify rules are active

List all NAT rules with packet counters:

```bash title="List NAT rules with packet counters"
iptables -t nat -L -v -n

Zero packet counts indicate traffic is not matching your rules. Verify IP addresses, ports, and interface names.

Check IP forwarding status

Confirm forwarding is enabled:

“`bash title="Confirm IPv4 forwarding is enabled" sysctl net.ipv4.ip_forward


If this returns 0, forwarding is disabled. Enable it using the commands in the IP forwarding section.

### Enable logging for debugging

Add a LOG rule to track traffic:

```bash title="Log incoming TCP traffic for port 80"
iptables -t nat -I PREROUTING -p tcp --dport 80 -j LOG --log-prefix "FORWARD-80: " --log-level 4

View the logs:

“`bash title="Follow the system log" tail -f /var/log/syslog


Remove logging rules after troubleshooting to prevent log flooding.

### Test with tcpdump

Monitor traffic on your network interface:

```bash title="Capture port 80 traffic on ens33"
tcpdump -i ens33 port 80

This shows whether packets are actually reaching your server.

Verify destination service

On the internal server, confirm the service is running:

“`bash title="Check whether port 8080 is listening" netstat -tuln | grep 8080


## Security considerations

**Warning:** Port forwarding exposes internal services to the internet. Forward only necessary ports because each represents a security risk.

Limit access by source IP address when possible:

```bash title="Restrict port forwarding to one source subnet"
iptables -t nat -A PREROUTING -s 203.0.113.0/24 -p tcp --dport 80 -j DNAT --to-destination 192.168.1.2:8080

This restricts forwarding to traffic from the specified subnet.

Docker conflicts

Docker manages iptables rules automatically and may override custom configurations. Review Docker's rules before manual port forwarding:

“`bash title="Find Docker-managed NAT rules" iptables -t nat -L -n -v | grep DOCKER


### Cloud environment considerations

When running on cloud platforms like AWS, Azure, or Google Cloud, configure both your iptables rules and cloud security groups. Cloud-level firewalls operate independently of iptables. A common mistake is configuring iptables correctly while forgetting to open ports in the cloud security group.

### Rate limiting

Implement rate limiting to prevent abuse:

```bash title="Rate-limit accepted forwarded TCP packets"
iptables -A FORWARD -p tcp -d 192.168.1.2 --dport 8080 -m limit --limit 25/minute --limit-burst 100 -j ACCEPT

This rule allows 25 connections per minute with a burst of 100.

Monitor forwarded traffic

Enable logging for forwarded connections:

“`bash title="Log forwarded TCP traffic to port 8080" iptables -A FORWARD -p tcp -d 192.168.1.2 –dport 8080 -j LOG –log-prefix "FWD-MONITOR: "


Review these logs regularly for unusual patterns. Set up automated alerts using tools like fail2ban.

### Testing and maintenance

Test all changes on non-production systems first. When working on production systems remotely, maintain a secondary access method. Schedule regular audits to remove forwards for inactive services. Document each rule's purpose for easier maintenance.

### Principle of least privilege

Grant only the minimum access necessary. If a service only needs access from specific IP ranges, do not configure it for worldwide access.

## Quick reference

Copy these commands and replace bracketed values with your actual configuration.

### Check current rules

```bash title="Check the current NAT and FORWARD rules"
iptables -t nat -L -v -n
iptables -L FORWARD -v -n

Enable IP forwarding

“`bash title="Enable IPv4 forwarding" sysctl -w net.ipv4.ip_forward=1


### Basic port forward

```bash title="Configure a basic TCP port forward"
iptables -t nat -A PREROUTING -p tcp --dport [external_port] -j DNAT --to-destination [internal_ip]:[internal_port]
iptables -A FORWARD -p tcp -d [internal_ip] --dport [internal_port] -j ACCEPT
iptables -t nat -A POSTROUTING -o [interface] -j MASQUERADE

Save rules

“`bash title="Save the current firewall rules" iptables-save > /etc/iptables/rules.v4 netfilter-persistent save


### Delete a specific rule

```bash title="Delete a numbered PREROUTING rule"
iptables -t nat -D PREROUTING [rule_number]

Flush all rules (use with caution)

Safety check: Confirm the target and keep a recent backup or snapshot. Preview the affected resources where possible, and document a tested recovery or rollback path before running this command.

“`bash title="Flush all filter and NAT rules" iptables -F iptables -t nat -F


## Conclusion

Port forwarding with iptables provides precise control over network traffic routing, enabling you to expose internal services securely while maintaining proper access controls. While nftables has become the modern standard, iptables remains a reliable solution for legacy systems and backward compatibility. Always prioritize security by exposing only necessary services, implementing rate limiting, monitoring logs regularly, and conducting periodic audits of your forwarding rules. With proper planning and careful implementation, port forwarding becomes a powerful tool for managing your network infrastructure.

Ready to manage port forwarding on Virtarix VPS?

Start with a VPS that gives you root access, firewall control, IPv4 + IPv6, NVMe storage, snapshots, and backups for safer network changes.

VPS S

For small sites, dev servers and Docker

$ 5 .50 /month
  • 3 cores
  • 6 GB
  • 50 GB NVMe
  • Unlimited
Get It Now
BEST SELLER

VPS M

For growing apps, websites and staging

$ 11 .40 /month
  • 6 cores
  • 16 GB
  • 100 GB NVMe
  • Unlimited
Get It Now
Peter French
About the Author Peter Frenchis the Managing Director at Virtarix, with over 17 years in the tech industry. He has co-founded a cloud storage business, led strategy at a global cloud computing leader, and driven market growth in cybersecurity and data protection.