iptables Connection Refused & Packet Loss: Complete Troubleshooting Guide
Fix iptables connection refused and packet loss errors with step-by-step diagnostics, rule auditing, conntrack tuning, and safe rule insertion commands.
- Root cause 1: An explicit REJECT or DROP rule in the INPUT, OUTPUT, or FORWARD chain is blocking traffic before a permissive ACCEPT rule can match — iptables processes rules top-down and stops at the first match.
- Root cause 2: The nf_conntrack table is full (kernel log shows 'nf_conntrack: table full, dropping packet'), causing the kernel to silently drop new connection attempts and triggering packet loss.
- Root cause 3: A NAT or MASQUERADE rule is missing or misconfigured in the nat table, breaking return traffic for forwarded connections and appearing as one-sided connection refused errors.
- Quick fix summary: Run `iptables -L INPUT -n -v --line-numbers` to identify the blocking rule, insert an ACCEPT rule above it with `iptables -I INPUT <line> -p tcp --dport <port> -j ACCEPT`, and for conntrack exhaustion increase `net.netfilter.nf_conntrack_max` via sysctl.
| Method | When to Use | Time to Apply | Risk |
|---|---|---|---|
| Insert ACCEPT rule above DROP/REJECT | Single port or IP is blocked by an explicit rule | < 1 min | Low — surgical, non-destructive |
| Flush entire chain (iptables -F) | Ruleset is corrupted or unknown; need clean slate | < 1 min | High — removes ALL firewall protection |
| Increase nf_conntrack_max via sysctl | Kernel logs show 'table full, dropping packet' | 1–2 min | Low — no service restart needed |
| Replace REJECT with ACCEPT for target port | Service is intentionally REJECT-ed and needs to be opened | < 1 min | Low — targeted rule deletion + insertion |
| Reload from saved ruleset (iptables-restore) | Rules have been manually corrupted in a live session | 1–3 min | Medium — depends on saved ruleset quality |
| Enable connection tracking helpers (nf_conntrack_ftp etc.) | Stateful protocols (FTP, SIP) drop packets after handshake | 2–5 min | Low — module-level, reversible |
Understanding iptables Connection Refused and Packet Loss
When a client receives Connection refused or experiences packet loss through a Linux host running iptables, the firewall is almost always the first suspect — but the diagnosis requires distinguishing between three fundamentally different failure modes:
- REJECT — the kernel actively sends back a TCP RST or ICMP port-unreachable, resulting in an immediate
Connection refused. - DROP — the kernel silently discards the packet; the client waits until its TCP timeout expires, producing
Connection timed outrather than an instant refusal. - Conntrack table exhaustion — new connections are dropped because the kernel's connection tracking table is full, causing intermittent packet loss that appears as flaky connectivity.
Understanding which failure mode you face determines which fix to apply.
Step 1: Reproduce the Exact Error
Capture the client-side error message before touching any rules. Common forms include:
curl: (7) Failed to connect to 10.0.1.50 port 8080: Connection refused
ssh: connect to host 10.0.1.50 port 22: Connection refused
telnet 10.0.1.50 5432: Connection refused
ERRNO: ECONNREFUSED (111)
An instant Connection refused (ECONNREFUSED) means a REJECT rule is active. A hang followed by Connection timed out (ETIMEDOUT) points to a DROP rule or packet loss. Knowing this narrows your search significantly.
Step 2: Audit the Active Ruleset
Dump all chains with verbose output and line numbers so you can reference exact positions:
# List INPUT chain with packet/byte counters and line numbers
iptables -L INPUT -n -v --line-numbers
# List all tables (filter, nat, mangle, raw)
iptables -L -n -v --line-numbers
iptables -t nat -L -n -v --line-numbers
iptables -t mangle -L -n -v --line-numbers
Look for any rule matching your source IP, destination port, or protocol that has a target of REJECT or DROP. The line number column is critical — you will need it to insert a fix rule above the blocking entry.
Example output indicating a blocked port:
Chain INPUT (policy DROP)
num pkts bytes target prot opt in out source destination
1 0 0 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
2 45 2700 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22
3 0 0 REJECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:8080 reject-with icmp-port-unreachable
Here line 3 explicitly REJECTs port 8080.
Step 3: Check the Conntrack Table for Exhaustion
If your audit shows no obvious blocking rule but you still see packet loss, check for conntrack exhaustion:
# Check current conntrack table usage vs. maximum
cat /proc/sys/net/netfilter/nf_conntrack_count
cat /proc/sys/net/netfilter/nf_conntrack_max
# Look for kernel drop messages
dmesg | grep -i 'nf_conntrack'
journalctl -k | grep 'nf_conntrack: table full'
If nf_conntrack_count is at or near nf_conntrack_max, that is your packet loss source. The kernel will log:
nf_conntrack: table full, dropping packet
Step 4: Use tcpdump to Verify Packets Are Arriving
Before modifying rules, confirm that packets actually reach the interface:
# Listen on all interfaces for TCP SYN packets to port 8080
tcpdump -i any 'tcp port 8080 and tcp[tcpflags] & tcp-syn != 0' -n
# Also check if RST is sent back (REJECT behavior)
tcpdump -i any 'tcp port 8080' -n
If you see SYN packets arriving but no SYN-ACK in response, iptables is dropping or rejecting them. If you see SYN + RST, a REJECT rule is active.
Step 5: Enable Logging for Precise Rule Identification
Insert a temporary LOG rule immediately before the suspected blocking rule to confirm which rule fires:
# Insert LOG rule at line 3 (before the REJECT at old line 3, now pushed to 4)
iptables -I INPUT 3 -p tcp --dport 8080 -j LOG --log-prefix "IPTABLES-DEBUG-8080: " --log-level 4
# Then test the connection from the client, and watch logs
tail -f /var/log/kern.log | grep IPTABLES-DEBUG
# or
journalctl -f -k | grep IPTABLES-DEBUG
You will see lines like:
Feb 23 14:32:11 myhost kernel: IPTABLES-DEBUG-8080: IN=eth0 OUT= SRC=192.168.1.100 DST=10.0.1.50 PROTO=TCP DPT=8080
This confirms packets are hitting the blocking rule. Remove the LOG rule after diagnosis:
iptables -D INPUT 3
Step 6: Apply the Fix
Fix A — Insert ACCEPT rule above the blocking rule:
# If the REJECT is at line 3, insert ACCEPT at line 3 (pushing REJECT to line 4)
iptables -I INPUT 3 -p tcp --dport 8080 -j ACCEPT
# Verify the fix
iptables -L INPUT -n -v --line-numbers
Fix B — Delete the blocking rule entirely:
# Delete by line number
iptables -D INPUT 3
# Or delete by rule specification (safer, avoids line-number drift)
iptables -D INPUT -p tcp --dport 8080 -j REJECT
Fix C — Fix conntrack exhaustion:
# Temporarily increase the limit (immediate effect, lost on reboot)
sysctl -w net.netfilter.nf_conntrack_max=524288
# Make permanent
echo 'net.netfilter.nf_conntrack_max = 524288' >> /etc/sysctl.d/99-conntrack.conf
sysctl -p /etc/sysctl.d/99-conntrack.conf
# Also tune the hashsize for performance
echo 131072 > /sys/module/nf_conntrack/parameters/hashsize
Step 7: Persist the Rules Across Reboots
iptables rules are ephemeral by default. After confirming the fix works, save the ruleset:
# Debian/Ubuntu
iptables-save > /etc/iptables/rules.v4
# Ensure iptables-persistent is installed to reload on boot:
apt-get install iptables-persistent
# RHEL/CentOS/Fedora
service iptables save
# or with firewalld as the manager:
firewall-cmd --permanent --add-port=8080/tcp
firewall-cmd --reload
Step 8: Validate End-to-End
# From the client, test connectivity
curl -v telnet://10.0.1.50:8080
# Check packet counters on the new ACCEPT rule to confirm traffic is matching
watch -n1 'iptables -L INPUT -n -v --line-numbers'
The pkts and bytes counters on your new ACCEPT rule should increment with each successful connection attempt.
Advanced: Debugging NAT / Forwarding Issues
If the server is acting as a router or NAT gateway and forwarded traffic is refused:
# Verify IP forwarding is enabled
cat /proc/sys/net/ipv4/ip_forward
# Should be 1; enable with:
sysctl -w net.ipv4.ip_forward=1
# Check FORWARD chain
iptables -L FORWARD -n -v --line-numbers
# Check NAT table for MASQUERADE or DNAT rules
iptables -t nat -L -n -v
A missing MASQUERADE rule on the outbound interface means return traffic has no valid source address and is dropped by the destination.
Frequently Asked Questions
#!/usr/bin/env bash
# iptables-diagnose.sh — connection refused / packet loss diagnostic script
# Usage: sudo bash iptables-diagnose.sh <target-port>
PORT="${1:-80}"
echo "=== 1. Chain policies ==="
iptables -L -n | grep -E 'Chain (INPUT|OUTPUT|FORWARD)'
echo "\n=== 2. INPUT chain rules (verbose, line numbers) ==="
iptables -L INPUT -n -v --line-numbers
echo "\n=== 3. OUTPUT chain rules ==="
iptables -L OUTPUT -n -v --line-numbers
echo "\n=== 4. NAT table ==="
iptables -t nat -L -n -v
echo "\n=== 5. Rules matching port ${PORT} ==="
iptables -L -n -v --line-numbers | grep "dpt:${PORT}\|spt:${PORT}"
echo "\n=== 6. Conntrack table usage ==="
echo -n "Current entries: "; cat /proc/sys/net/netfilter/nf_conntrack_count
echo -n "Maximum entries: "; cat /proc/sys/net/netfilter/nf_conntrack_max
echo "\n=== 7. Conntrack exhaustion in dmesg ==="
dmesg | grep -i 'nf_conntrack' | tail -20
echo "\n=== 8. Is the service actually listening? ==="
ss -tlnp | grep ":${PORT}"
echo "\n=== 9. IP forwarding status ==="
cat /proc/sys/net/ipv4/ip_forward
echo "\n=== 10. Active packet drops/rejects on INPUT (non-zero counters) ==="
iptables -L INPUT -n -v --line-numbers | awk '$1 != "0" && /DROP|REJECT/'
echo "\n--- Suggested fixes ---"
echo "Insert ACCEPT before blocking rule (replace LINE_NUM and PORT):"
echo " iptables -I INPUT LINE_NUM -p tcp --dport ${PORT} -j ACCEPT"
echo ""
echo "Fix conntrack exhaustion:"
echo " sysctl -w net.netfilter.nf_conntrack_max=524288"
echo " echo 'net.netfilter.nf_conntrack_max = 524288' >> /etc/sysctl.d/99-conntrack.conf"
echo ""
echo "Fix default DROP policy:"
echo " iptables -P INPUT ACCEPT"
echo ""
echo "Save rules (Debian/Ubuntu):"
echo " iptables-save > /etc/iptables/rules.v4"Error Medic Editorial
The Error Medic Editorial team consists of senior DevOps engineers, SREs, and Linux systems administrators with decades of combined experience troubleshooting network, kernel, and infrastructure issues in production environments. Articles are technically reviewed and tested against real systems before publication.
Sources
- https://netfilter.org/documentation/HOWTO/packet-filtering-HOWTO.html
- https://www.kernel.org/doc/html/latest/networking/nf_conntrack-sysctl.html
- https://wiki.archlinux.org/title/iptables
- https://www.frozentux.net/iptables-tutorial/iptables-tutorial.html
- https://serverfault.com/questions/157375/reject-vs-drop-when-using-iptables
- https://stackoverflow.com/questions/tagged/iptables