When setting up web services, you often need to redirect incoming traffic from standard ports to your application's listening port. With nftables (the successor to iptables), this requires careful NAT configuration to handle both the incoming request and response mapping.
Your existing filter table rules look correct for allowing traffic, but the NAT portion needs adjustment. Here's why your current setup might not work:
# Problematic rules in current config
add rule nat prerouting redirect # This is too broad
add rule nat prerouting tcp dport 80 redirect to 3000 # Missing target IP
Here's the complete working configuration for port 80 to 3000 redirection:
# Clear existing rules (optional)
nft flush ruleset
# Filter table (unchanged from your config)
add table inet filter
add chain inet filter input { type filter hook input priority 0; policy accept; }
add chain inet filter forward { type filter hook forward priority 0; policy accept; }
add chain inet filter output { type filter hook output priority 0; policy accept; }
add rule inet filter input ct state related,established counter accept
add rule inet filter input ip protocol icmp counter accept
add rule inet filter input iifname "lo" counter accept
add rule inet filter input ct state new tcp dport 80 counter accept
add rule inet filter input ct state new tcp dport 4489 counter accept
add rule inet filter input ct state new tcp dport 8080 counter accept
# NAT table with correct redirect
add table ip nat
add chain ip nat prerouting { type nat hook prerouting priority -100; }
add chain ip nat postrouting { type nat hook postrouting priority 100; }
# Specific redirect rule
add rule ip nat prerouting iif eth0 tcp dport 80 dnat to 127.0.0.1:3000
# Masquerade for response routing (alternative to your snat rule)
add rule ip nat postrouting oif eth0 masquerade
After applying these rules, verify with:
nft list ruleset
ss -tulnp | grep 3000 # Check if service is listening
curl -I http://192.168.0.1 # Test from another machine
tcpdump -i eth0 port 80 # Monitor incoming traffic
If you're still having issues, consider these variations:
# Option 1: Using redirect (simpler but less explicit)
add rule ip nat prerouting tcp dport 80 redirect to :3000
# Option 2: With specific interface and address
add rule ip nat prerouting iif eth0 ip daddr 192.168.0.1 tcp dport 80 dnat to 127.0.0.1:3000
- Using "inet" table instead of "ip" for NAT (nftables limitation)
- Forgetting to enable IP forwarding (sysctl net.ipv4.ip_forward=1)
- Having conflicting iptables rules (check with iptables -L)
- Local firewall blocking 127.0.0.1:3000 connections
When working with web applications, it's common to need port redirection from standard HTTP port 80 to your application's port (3000 in this case). Here's how to properly configure nftables for this:
# Flush existing rules
nft flush ruleset
# Define tables and chains
nft add table inet filter
nft add chain inet filter input { type filter hook input priority 0; policy accept; }
nft add chain inet filter forward { type filter hook forward priority 0; policy accept; }
nft add chain inet filter output { type filter hook output priority 0; policy accept; }
# Filter rules
nft add rule inet filter input ct state related,established accept
nft add rule inet filter input iifname "lo" accept
nft add rule inet filter input tcp dport { 22, 80, 3000 } ct state new accept
nft add rule inet filter input counter reject with icmp type host-prohibited
# NAT configuration
nft add table nat
nft add chain nat prerouting { type nat hook prerouting priority -100; }
nft add chain nat postrouting { type nat hook postrouting priority 100; }
# Port 80 redirection rule
nft add rule nat prerouting iif eth0 tcp dport 80 dnat to 127.0.0.1:3000
# Masquerade for response packets
nft add rule nat postrouting oif eth0 masquerade
Here are some issues you might encounter and how to solve them:
# Problem 1: Redirect not working for local traffic
# Solution: Add specific rule for loopback
nft add rule nat prerouting iif != "lo" tcp dport 80 dnat to 127.0.0.1:3000
# Problem 2: Response packets not being properly NATed
# Solution: Ensure masquerade is properly configured
nft add rule nat postrouting ip saddr 127.0.0.1 tcp sport 3000 masquerade
After applying the rules, verify them with:
# List all rules
nft list ruleset
# Check active connections
ss -tulnp | grep 3000
# Test from another machine
curl -v http://192.168.0.1
For high-traffic scenarios, consider these optimizations:
# Use named sets for better performance
nft add set inet filter allowed_ports { type inet_service; flags constant; elements = { 22, 80, 3000 } }
nft add rule inet filter input tcp dport @allowed_ports ct state new accept