
Photo by Scott Rodgerson on Unsplash
In the age of cloud‑native services and distributed micro‑services, a solid grasp of Linux networking is no longer a niche skill—it’s an operational necessity. Whether you’re a system administrator keeping a data centre humming, a DevOps engineer automating deployments, or a developer debugging a flaky service, the same set of low‑level tools can help you see what’s really happening on the wire.
This article walks through the most useful Linux networking commands—ss, nc, and iptables—and shows how they fit into routing, DNS resolution, and real‑world troubleshooting. By the end, you’ll have a practical playbook for diagnosing connection issues in minutes, not hours.
1. Why Master These Tools Now?
- Infrastructure is increasingly software‑defined. Modern workloads run on virtual machines or containers that rely on Linux networking stacks for performance and isolation.
- Security concerns are growing. Understanding how packets flow through
iptablesor how a firewall filters traffic lets you harden your environment against attacks. - Speed matters. When a service is down, the first few minutes can cost time, money, or reputation. Knowing how to slice a packet stream or probe a port instantly saves those precious minutes.
2. The Core Command Set
| Tool | Purpose | Typical Use Case |
|---|---|---|
ss |
Socket statistics (TCP/UDP) | Inspect listening ports, identify which process owns a socket, detect stale connections |
nc (netcat) |
Read/write data across network connections | Test connectivity, act as a simple TCP/UDP server or client, transfer files |
iptables |
Linux kernel firewall and packet filtering | Define inbound/outbound rules, NAT, port forwarding |
2.1 ss: The Modern Replacement for netstat
# Show all listening sockets with process info
ss -tulnp
# Filter by protocol
ss -tnlp # TCP only
ss -unlp # UDP only
Why use ss?
* Faster than netstat.
* Gives you the owning PID/command (-p).
* Supports filters directly in the command line, reducing post‑processing.
2.2 nc: The Swiss Army Knife of Networking
# Simple TCP client: connect to port 80 and send an HTTP request
echo -e "GET / HTTP/1.0\r\nHost: example.com\r\n\r\n" | nc example.com 80
# Listening server on port 12345 (TCP)
nc -l -p 12345
# UDP echo test
echo "test" | nc -u -w1 localhost 9999
Practical tricks
| Scenario | nc command |
|---|---|
| Verify a remote host is reachable on a specific port | nc -zv example.com 443 |
| Quick port scan (not a full scanner) | for p in {20..25}; do nc -zv localhost $p; done |
2.3 iptables: The Gatekeeper
# List all rules with line numbers
iptables -L --line-numbers
# Allow SSH from a specific subnet
iptables -A INPUT -p tcp --dport 22 -s 192.168.1.0/24 -j ACCEPT
# Drop all other incoming traffic (default deny)
iptables -P INPUT DROP
Best practices
- Keep rules ordered: the first matching rule is applied.
- Use
-Ito insert at a specific position if you need precedence. - Persist changes with
iptables-save/iptables-restoreor through distribution‑specific tools (netfilter-persistent,firewalld, etc.).
3. Routing Basics on Linux
Routing determines how packets leave your machine. The key commands are:
# Show the routing table
ip route show
# Add a static route
sudo ip route add 10.0.0.0/24 via 192.168.1.1 dev eth0
# Delete a route
sudo ip route del 10.0.0.0/24
Important concepts
| Term | Meaning |
|---|---|
| Default gateway | The next hop for all traffic that doesn’t match a more specific route (default via <IP>). |
| Policy routing | Multiple tables and rules to direct traffic based on source IP, interface, or other criteria. |
| NAT (Network Address Translation) | Typically handled by iptables with the -t nat table; essential for outbound internet access from private subnets. |
4. DNS – The Name Resolver
Linux resolves domain names using the /etc/resolv.conf file and local caching services (systemd-resolved, dnsmasq, etc.).
# Query a specific name server
dig @8.8.8.8 example.com A
# Follow the chain of CNAMEs
dig +trace example.com
# Check which resolver is active
systemd-resolve --status
Common pitfalls
- Missing or misordered nameservers in
/etc/resolv.confcan cause silent failures. - Cached stale records:
sudo systemd-resolve --flush-caches. - DNS over HTTPS (DoH) setups may require configuration of a local proxy (
cURL,Firefox, etc.).
5. Putting It All Together – A Troubleshooting Playbook
Let’s walk through a realistic scenario: A web application on VM A cannot reach the database service on VM B, but ping works.
Step 1: Verify Connectivity with nc
# From VM A try to connect to DB port (e.g., 5432)
nc -zv db.example.com 5432
If it times out or reports “Connection refused,” we know the packet is not reaching the target port.
Step 2: Inspect Listening Sockets on VM B
# On VM B check that PostgreSQL is listening on all interfaces
ss -tnlp | grep 5432
Ensure the process is bound to 0.0.0.0 (all IPv4) or the specific internal IP.
Step 3: Check Firewall Rules
# On VM B list inbound rules for port 5432
sudo iptables -L INPUT --line-numbers | grep 5432
Look for a rule that drops or rejects traffic from VM A’s subnet. Add an allow rule if necessary.
Step 4: Validate Routing
# On both VMs, confirm the route to each other’s subnet
ip route show | grep <remote_subnet>
If a route is missing, add it with ip route add or adjust the default gateway.
Step 5: Confirm DNS Resolution (if using hostnames)
dig db.example.com +short
Make sure both VMs resolve to the same IP address. A discrepancy can explain why ping works but TCP fails.
Step 6: Look at Packet Flow with tcpdump (optional)
# Capture packets on VM A’s interface destined for DB port
sudo tcpdump -i eth0 dst host db.example.com and port 5432
You’ll see SYN packets, ACKs, or ICMP unreachable messages. This is the ultimate proof of what’s happening.
6. Advanced Tips & Common Gotchas
| Tip | Explanation |
|---|---|
Use ss -e for extended info |
Shows timers and congestion control data useful in performance tuning. |
Leverage iptables state modules |
E.g., -m state --state ESTABLISHED,RELATED -j ACCEPT to allow return traffic without explicit rules. |
Persist iptables across reboots |
Many distributions ship a helper (netfilter-persistent, firewalld) that loads /etc/iptables/rules.v4. |
Avoid -p tcp --dport 22 with wildcard IPs |
It can expose SSH to the entire internet if misconfigured. Use subnet restrictions or fail2ban. |
| Check for IPv6 interference | Some services default to IPv6; ensure firewalls and routing tables handle both families (ip -6 route). |
7. Conclusion
Linux networking tools like ss, nc, and iptables are the backbone of any reliable, secure infrastructure. By mastering these commands, you can quickly pinpoint why a service isn’t reachable, adjust firewall policies on the fly, or confirm that routing is behaving as expected—all without needing a GUI or external utilities.
Next time your application hiccups, start with a simple nc -zv test, look up the listening sockets with ss, and audit your firewall. You’ll often find the answer in just a few minutes of command‑line detective work. Happy troubleshooting!
Frequently Asked Questions (FAQ)
What is the advantage of using ss over older tools like netstat?
ss reads socket information directly from the kernel, making it faster and more accurate. It also provides process ownership (-p) and built‑in filtering, reducing the need for additional parsing.
How can I quickly test if a remote host is listening on a specific port?
Use Netcat in zero‑output mode:
nc -zv <host> <port>
The -z flag tells nc to scan without sending data, while -v gives verbose success or failure messages.
What is the simplest way to allow SSH access from a specific subnet using iptables?
Add an ACCEPT rule for the desired source network:
iptables -A INPUT -p tcp --dport 22 -s 192.168.1.0/24 -j ACCEPT
Place it before any DROP or REJECT rules so that traffic from that subnet is permitted.
How do I add a static route to reach a network behind a specific gateway?
sudo ip route add <network>/<mask> via <gateway-ip> dev <interface>
For example:
sudo ip route add 10.0.0.0/24 via 192.168.1.1 dev eth0
This directs packets for 10.0.0.0/24 through the specified gateway on eth0.


