Port Forwarding Configuration

Configure port forwarding to expose internal services to the internet


Port Forwarding Configuration

"If builders built buildings the way programmers wrote port forwarding rules, then the first port scanner that came along would destroy civilization." - Bloch's Extension of Murphy's Law

Port forwarding allows external devices on the internet to access services running on your internal network through your Pimeleon router. This guide covers how to safely configure port forwarding rules.

Quick Start

Forward external port 8080 to internal server port 80:

ssh pi@your-router-ip
sudo nft add rule ip nat prerouting iifname "eth0" tcp dport 8080 dnat to 192.168.76.100:80
sudo nft add rule ip filter forward ip daddr 192.168.76.100 tcp dport 80 ct state new,established,related accept

Understanding Port Forwarding

Port forwarding redirects incoming connections from your router's WAN interface to a specific device and port on your internal network.

How It Works

graph LR
    A[Internet] -->|Port 8080| B[Router WAN]
    B -->|NAT| C[Internal Device]
    C -->|Port 80| D[Web Server]

Key Concepts:

  • External Port - Port on your router's public IP that accepts connections
  • Internal IP - IP address of the device on your LAN
  • Internal Port - Port on the internal device running the service
  • Protocol - TCP, UDP, or both

Before You Begin

Prerequisites

  1. Static Internal IP - Assign a static IP or DHCP reservation to your target device
  2. Know Your Service - Understand which ports your service requires
  3. Security Awareness - Exposing services increases attack surface
  4. Firewall Rules - Understand that port forwarding bypasses NAT protection

Security Considerations

Important Security Notes:

  • Port forwarding exposes services to the entire internet
  • Only forward ports for services you actively use
  • Use non-standard ports when possible
  • Keep forwarded services updated and patched
  • Consider using VPN instead of port forwarding
  • Monitor logs for unauthorized access attempts
  • Use strong authentication on exposed services

Configuration Methods

Pimeleon router uses nftables for port forwarding. Rules can be configured via command line or by editing configuration files.

Method 1: nftables Command Line

Add port forwarding rules directly:

# SSH to your router
ssh pi@your-router-ip

# Add DNAT rule (destination NAT)
sudo nft add rule ip nat prerouting iifname "eth0" tcp dport EXTERNAL_PORT dnat to INTERNAL_IP:INTERNAL_PORT

# Add FORWARD rule
sudo nft add rule ip filter forward ip daddr INTERNAL_IP tcp dport INTERNAL_PORT ct state new,established,related accept

# Rules are automatically persistent in /etc/nftables.conf

Method 2: Configuration File

Edit the nftables rules file directly:

# Edit rules file
sudo nano /etc/nftables.conf

# Add rules to appropriate chains (see examples below)

# Reload rules
sudo nft -f /etc/nftables.conf

Common Port Forwarding Examples

Web Server (HTTP/HTTPS)

Forward standard web traffic to an internal web server:

# HTTP (port 80)
sudo nft add rule ip nat prerouting iifname "eth0" tcp dport 80 dnat to 192.168.76.100:80
sudo nft add rule ip filter forward ip daddr 192.168.76.100 tcp dport 80 accept

# HTTPS (port 443)
sudo nft add rule ip nat prerouting iifname "eth0" tcp dport 443 dnat to 192.168.76.100:443
sudo nft add rule ip filter forward ip daddr 192.168.76.100 tcp dport 443 accept

SSH Server

Forward SSH to internal server on non-standard external port:

# Forward external port 2222 to internal SSH port 22
sudo nft add rule ip nat prerouting iifname "eth0" tcp dport 2222 dnat to 192.168.76.50:22
sudo nft add rule ip filter forward ip daddr 192.168.76.50 tcp dport 22 accept

Security Tip: Using a non-standard external port (2222) reduces automated attack attempts.

Game Server

Forward game server ports (example: Minecraft):

# Minecraft server (TCP and UDP port 25565)
sudo nft add rule ip nat prerouting iifname "eth0" tcp dport 25565 dnat to 192.168.76.150:25565
sudo nft add rule ip nat prerouting iifname "eth0" udp dport 25565 dnat to 192.168.76.150:25565
sudo nft add rule ip filter forward ip daddr 192.168.76.150 tcp dport 25565 accept
sudo nft add rule ip filter forward ip daddr 192.168.76.150 udp dport 25565 accept

Remote Desktop

Forward RDP for Windows Remote Desktop:

# RDP (port 3389) to non-standard external port
sudo nft add rule ip nat prerouting iifname "eth0" tcp dport 33890 dnat to 192.168.76.200:3389
sudo nft add rule ip filter forward ip daddr 192.168.76.200 tcp dport 3389 accept

VNC Server

Forward VNC for remote desktop access:

# VNC (port 5900)
sudo nft add rule ip nat prerouting iifname "eth0" tcp dport 5900 dnat to 192.168.76.75:5900
sudo nft add rule ip filter forward ip daddr 192.168.76.75 tcp dport 5900 accept

Home Automation

Forward Home Assistant or similar services:

# Home Assistant (port 8123)
sudo nft add rule ip nat prerouting iifname "eth0" tcp dport 8123 dnat to 192.168.76.180:8123
sudo nft add rule ip filter forward ip daddr 192.168.76.180 tcp dport 8123 accept

Port Range Forwarding

Forward a range of consecutive ports:

# Forward ports 6000-6010 to internal device
sudo nft add rule ip nat prerouting iifname "eth0" tcp dport 6000-6010 dnat to 192.168.76.100:6000-6010
sudo nft add rule ip filter forward ip daddr 192.168.76.100 tcp dport 6000-6010 accept

Managing Port Forwarding Rules

List Current Rules

View all port forwarding rules:

# List all rules with handles
sudo nft -a list ruleset

# List only NAT rules
sudo nft list table ip nat

# List only FORWARD rules
sudo nft list chain ip filter forward

Understanding Output:

  • handle - Unique rule identifier for deletion
  • counter - Packet and byte counters
  • dnat to - Destination NAT target
  • accept - Allow packet through
  • tcp dport - TCP destination port
  • ip daddr - IP destination address

Delete Port Forwarding Rule

Remove a specific rule by handle:

# First, list rules with handles
sudo nft -a list table ip nat

# Delete rule by handle (example: handle 5)
sudo nft delete rule ip nat prerouting handle 5

# Also delete corresponding FORWARD rule
sudo nft -a list chain ip filter forward
sudo nft delete rule ip filter forward handle 10

Delete Rule by Specification

Remove rule by recreating the exact rule:

# Delete specific NAT rule
sudo nft delete rule ip nat prerouting iifname "eth0" tcp dport 8080 dnat to 192.168.76.100:80

# Delete corresponding FORWARD rule
sudo nft delete rule ip filter forward ip daddr 192.168.76.100 tcp dport 80 accept

Disable All Port Forwarding

Temporarily disable without deleting:

# Flush PREROUTING chain (removes all port forwarding)
sudo nft flush chain ip nat prerouting

# Restore from backup when needed
sudo nft -f /etc/nftables.conf

Setting Up Static IPs

For reliable port forwarding, assign static IPs to target devices.

DHCP Reservation

Create a DHCP reservation to always assign the same IP:

# Edit DHCP configuration
sudo nano /etc/dhcp/dhcpd.conf

# Add reservation (example)
host webserver {
    hardware ethernet aa:bb:cc:dd:ee:ff;
    fixed-address 192.168.76.100;
}

# Restart DHCP server
sudo systemctl restart isc-dhcp-server

Find Device MAC Address

# View ARP table
arp -n

# Or check DHCP leases
cat /var/lib/dhcp/dhcpd.leases

Testing Port Forwarding

Test from Internal Network

Test local connectivity first:

# Test connection to internal device
nc -zv 192.168.76.100 80

# Or use curl
curl http://192.168.76.100:80

Test from External Network

Test from outside your network:

# From another network or use online tools
nc -zv YOUR_PUBLIC_IP EXTERNAL_PORT

# Or use curl
curl http://YOUR_PUBLIC_IP:EXTERNAL_PORT

Find Your Public IP

# On router
curl -4 ifconfig.me

# Or
curl https://api.ipify.org

Online Testing Tools

Use these websites to test port accessibility:

Troubleshooting

Port Forwarding Not Working

Step 1: Verify Rules Are Active

# Check NAT rules
sudo nft list table ip nat

# Check FORWARD rules
sudo nft list chain ip filter forward

Step 2: Test Internal Connectivity

# Ping internal device
ping 192.168.76.100

# Test port on internal device
nc -zv 192.168.76.100 80

Step 3: Check Service is Running

# On the target device, verify service is listening
sudo netstat -tulpn | grep :80
# Or
sudo ss -tlnp | grep :80

Step 4: Verify Firewall on Target Device

# On target device, check if firewall is blocking
sudo ufw status
# Or
sudo nft list chain ip filter input

Step 5: Check WAN Interface

# Verify WAN interface name
ip link show

# Ensure eth0 is up
ip link show eth0

Connection Times Out

If connections timeout:

  1. Check target service is running
  2. Verify internal device firewall allows connections
  3. Confirm correct internal IP and port
  4. Test from within LAN first
  5. Check ISP doesn't block the port

ISP Port Blocking

Some ISPs block common ports:

  • Port 25 (SMTP) - Often blocked
  • Port 80 (HTTP) - Sometimes blocked on residential plans
  • Port 443 (HTTPS) - Rarely blocked
  • Port 22 (SSH) - Usually allowed

Solution: Use alternative ports (e.g., 8080 instead of 80, 2222 instead of 22)

Wrong Service Responds

If you reach the wrong device or service:

  1. Check for duplicate rules:
    sudo nft -a list table ip nat
    
  2. Verify internal IP is correct:
    arp -n
    cat /var/lib/dhcp/dhcpd.leases
    
  3. Remove duplicate or incorrect rules

Best Practices

Security Best Practices

  1. Minimize Exposure
    • Only forward ports you actively need
    • Close ports when no longer needed
    • Use VPN for admin access instead of port forwarding
  2. Use Non-Standard Ports
    • External port 2222 → Internal SSH port 22
    • Reduces automated scanning and attacks
  3. Strong Authentication
    • Use strong passwords or key-based authentication
    • Enable two-factor authentication where possible
    • Disable default accounts
  4. Keep Services Updated
    • Regularly update exposed services
    • Monitor security advisories
    • Apply patches promptly
  5. Monitor Access
    • Review logs regularly
    • Set up alerts for failed authentication
    • Use fail2ban to block brute force attempts

Operational Best Practices

  1. Document Your Rules
    • Keep a list of all port forwards
    • Note purpose and owner of each rule
    • Include expiration dates for temporary rules
  2. Use DHCP Reservations
    • Assign static IPs via DHCP
    • Prevents IP conflicts
    • Easier to manage than device static IPs
  3. Test Before Deployment
    • Test internally first
    • Verify from external network
    • Document testing results
  4. Backup Configuration
    # Backup nftables rules
    sudo nft list ruleset > ~/nftables-backup-$(date +%Y%m%d).nft
    
  5. Regular Audits
    • Review port forwards quarterly
    • Remove unused rules
    • Update documentation

Common Ports Reference

ServicePortProtocolNotes
HTTP80TCPWeb servers (unencrypted)
HTTPS443TCPWeb servers (encrypted)
SSH22TCPSecure shell access
FTP21, 20TCPFile transfer (insecure)
SFTP22TCPSecure file transfer
SMTP25TCPEmail (often blocked by ISP)
RDP3389TCPWindows Remote Desktop
VNC5900+TCPRemote desktop access
Minecraft25565TCP/UDPMinecraft server
Plex32400TCPPlex media server
Emby8096TCPEmby media server
Home Assistant8123TCPHome automation

Advanced Configuration

Port Forwarding with Source IP Restriction

Only allow port forwarding from specific source IP:

# Only allow access from specific IP
sudo nft add rule ip nat prerouting iifname "eth0" ip saddr 203.0.113.50 tcp dport 8080 dnat to 192.168.76.100:80
sudo nft add rule ip filter forward ip saddr 203.0.113.50 ip daddr 192.168.76.100 tcp dport 80 accept

Hairpin NAT (Loopback NAT)

Access forwarded services from internal network using public IP:

# Add hairpin NAT rule
sudo nft add rule ip nat postrouting ip saddr 192.168.76.0/24 ip daddr 192.168.76.100 tcp dport 80 masquerade

Multiple Internal Destinations

Load balance between multiple internal servers:

# Round-robin between two servers using numgen
sudo nft add rule ip nat prerouting iifname "eth0" tcp dport 80 numgen inc mod 2 0 dnat to 192.168.76.100:80
sudo nft add rule ip nat prerouting iifname "eth0" tcp dport 80 numgen inc mod 2 1 dnat to 192.168.76.101:80

Backing Up and Restoring Rules

Create Backup

# Backup current rules
sudo nft list ruleset > ~/nftables-rules-backup.nft

# Backup with timestamp
sudo nft list ruleset > ~/nftables-backup-$(date +%Y%m%d-%H%M%S).nft

Restore Backup

# Restore from backup
sudo nft -f ~/nftables-rules-backup.nft

# Rules in /etc/nftables.conf are automatically loaded on boot

Support

For questions or issues:

Further Reading