Skip to content

Beginner · Linux for DevOps · topic 9 of 53 · 30 min

Linux networking for DevOps

Explanation

Most production problems sound like "the app cannot connect". A handful of commands answer them: ip addr and ip route show your addresses and routes, ping and curl test reachability, ss -tulpn shows which ports are listening, dig checks DNS, and ufw or firewalld control the firewall. ssh, scp, an ssh config file and port forwarding let you reach servers safely.

Why networking matters

Apps talk to databases, caches, other services and the internet. When something breaks, the question is often "where does the connection stop?" You do not need to be a network engineer, but you must be able to check each step: does this machine have an address, can it reach the other machine, does the name resolve, is anything listening on the port, and is a firewall in the way?

Your addresses and routes

bash
ip addr            # addresses on each interface (ip a for short)
ip route           # routing table; "default via" is the gateway
hostname -I        # just the IP addresses
The modern ip command replaces the older ifconfig and route.

Is the other side reachable?

bash
ping -c 4 10.0.1.20                 # 4 ICMP echo requests
curl -I https://example.com          # only the response headers: status code, server
curl -v http://localhost:3000/healthz   # verbose: DNS, connect, request, response
wget https://example.com/file.tar.gz # download a file
ping tests basic reachability; curl tests the actual HTTP service.
Tip: A failed ping does not prove a server is down: many cloud firewalls block ICMP (the protocol ping uses). For a web app, curl to the real port is the better test.

What is listening? ss -tulpn

A port is a number from 0 to 65535 that identifies a service on a machine: 22 for SSH, 80 for HTTP, 443 for HTTPS, 5432 for PostgreSQL, 3306 for MySQL, 6379 for Redis. A program "listens" on a port and waits for connections.

bash
sudo ss -tulpn
# Netid State  Recv-Q Send-Q Local Address:Port  Peer Address:Port Process
# tcp   LISTEN 0      511          0.0.0.0:80         0.0.0.0:*     users:(("nginx",pid=812,fd=6))
# tcp   LISTEN 0      4096       127.0.0.1:5432       0.0.0.0:*     users:(("postgres",pid=640,fd=5))
t = TCP, u = UDP, l = listening, p = show the process, n = numbers instead of names. sudo shows processes of other users.

Read the local address carefully. 0.0.0.0:80 means "all IPv4 addresses", so other machines can connect. 127.0.0.1:5432 means "only this machine" (localhost). A classic problem: the database listens on 127.0.0.1, so the app on another server gets "connection refused". netstat -tulpn shows the same on older systems, but ss is the modern tool.

Names: DNS and /etc/hosts

bash
dig api.example.com +short     # the IP address(es) for a name
dig api.example.com MX         # mail records
nslookup api.example.com       # older tool, same idea
cat /etc/hosts                 # local name overrides
dig asks DNS servers directly; /etc/hosts can override names on this machine.

On most Linux systems, the file /etc/nsswitch.conf says the order: usually /etc/hosts first ("files"), then DNS. That is why an old line in /etc/hosts can make one server see a different IP than everyone else, a confusing bug. Note that dig ignores /etc/hosts, while curl and your app use it.

Firewalls

bash
# Ubuntu: ufw
sudo ufw allow 22/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbose

# RHEL / Rocky / Alma: firewalld
sudo firewall-cmd --add-service=https --permanent
sudo firewall-cmd --reload
sudo firewall-cmd --list-all
Allow SSH BEFORE enabling a firewall on a remote server, or you lock yourself out.

In the cloud there is usually a second firewall outside the machine, such as an AWS security group or an Azure network security group. A port must be open in both.

SSH, scp, config and port forwarding

bash
ssh deploy@203.0.113.10                 # log in
ssh -p 2222 deploy@203.0.113.10         # SSH on a non-standard port (lower-case p)
scp app.tar.gz deploy@203.0.113.10:/tmp/    # copy a file to the server
scp -P 2222 -r config/ deploy@203.0.113.10:/opt/app/   # scp uses capital P for the port
ssh -L 5433:localhost:5432 deploy@bastion   # local port 5433 -> port 5432 on bastion
With -L, connecting to localhost:5433 on your laptop reaches PostgreSQL on the remote side through the encrypted SSH connection.
output
# ~/.ssh/config
Host web1
    HostName 203.0.113.10
    User deploy
    Port 22
    IdentityFile ~/.ssh/id_ed25519
With this file, "ssh web1" and "scp file web1:/tmp/" just work.

Connection refused versus timeout

ErrorWhat it meansCheck
Connection refusedThe machine answered, but nothing is listening on that port (or a firewall actively rejected it)Is the app running? ss -tulpn: is it on the right port and address, 0.0.0.0 not 127.0.0.1?
TimeoutNo answer at all: packets were silently dropped or never arrivedFirewall or security group, wrong IP, routing, server down
Could not resolve hostDNS failed before any connectiondig the name, check /etc/hosts and /etc/resolv.conf

A troubleshooting order

  1. Does the name resolve? dig the host name.
  2. Is the address reachable? ping, or better, curl the real port (nc -zv host port tests any TCP port).
  3. Is the service listening on the right port and address? ss -tulpn on the server.
  4. Is a firewall or security group in the way? Check ufw or firewalld and the cloud rules.
  5. Does the app itself answer correctly? curl -v and the app’s logs.
Careful: Common mistakes: (1) Testing from the wrong place: curl localhost:8080 on the server works, but users cannot reach it because the app listens only on 127.0.0.1 or the security group is closed. Test from the client side too. (2) Enabling ufw over SSH before allowing port 22. (3) Two programs trying to use the same port: the second one fails with "address already in use". ss -tulpn shows who holds it.

Need help?

Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.

Try:

Watch the lesson

Linux networking for DevOps · 1/8

Address? Route? DNS? Listening? Firewall?

Most production problems sound like the app cannot connect. You find where the connection stops, step by step.

Prefer a video by a teacher? Find free videos on “linux networking commands for devops ss curl dig troubleshooting” on YouTube ↗

In real life: Why can the app not reach the database?

After moving a ticketing app to a new VM, the logs say "connection refused" to 10.0.2.15:5432. The engineer runs ss -tulpn on the database server and sees postgres listening on 127.0.0.1:5432 only. She changes listen_addresses in the PostgreSQL config to include the private IP, restarts it, allows 5432 from the app subnet in firewalld and the cloud security group, and the error is gone. Before the change, the refusal (not a timeout) told her the machine was reachable and the problem was the listener.

Practice (0/3 done)

Task 1 · Question

curl to a server on port 8080 fails immediately with "connection refused". What is the most likely cause?

Task 2 · Code · Python

Write parse_ss(text) for output like "ss -tulpn". Skip the header line and blank lines. For each other line return a tuple (protocol, port, process): protocol is the first column, port is the int after the LAST ":" of the 5th column (so "[::]:80" gives 80), and process is the name inside users:(("NAME",...), or "-" if the line has no users part. Then write who_uses(text, port, protocol="tcp") that returns the process name using that port and protocol, or None if it is free.

Task 3 · Code · Javascript

Write diagnose(error) that turns a connection error message into the first thing to check. If the message contains "refused" (any case), return "check the app is running and listening on that port"; if it contains "timed out" or "timeout", return "check firewalls, security groups and the IP address"; if it contains "resolve", return "check DNS and /etc/hosts"; otherwise return "read the full error and logs".

Quick quiz

Question 1

1.ss -tulpn shows postgres on 127.0.0.1:5432. An app on another server cannot connect. Why?

Question 2

2.Which command shows only the HTTP response headers of a URL?

Question 3

3.Which flag sets the port for scp?

Question 4

4.You are about to run "sudo ufw enable" on a remote server over SSH. What must you do first?

Question 5

5.What does "ssh -L 5433:localhost:5432 deploy@bastion" do?

Read more (free)

Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.

ss -tulpn shows postgres on 127.0.0.1:5432. An app on another server cannot connect. Why?

Answer: PostgreSQL only listens on localhost, so other machines cannot reach it

127.0.0.1 is only reachable from the same machine. It must listen on the private IP or 0.0.0.0.

Which command shows only the HTTP response headers of a URL?

Answer: curl -I https://example.com

curl -I sends a HEAD request and prints the status line and headers.

Which flag sets the port for scp?

Answer: -P

scp uses capital -P for the port; ssh uses lower-case -p.

You are about to run "sudo ufw enable" on a remote server over SSH. What must you do first?

Answer: Run sudo ufw allow 22/tcp (or allow OpenSSH)

If SSH is not allowed before the firewall turns on, your session can be cut and you are locked out.

What does "ssh -L 5433:localhost:5432 deploy@bastion" do?

Answer: Makes localhost:5433 on your laptop reach port 5432 on the bastion side through SSH

-L forwards a local port through the SSH connection to a host and port as seen from the server.

In ss -tlnp, what does -l mean?Related

Answer: Listening sockets only

-l shows listening sockets.

From Network basics: IP addresses, routes, DNS and the ip command

The port is open in firewalld but clients still cannot connect, and ss shows 127.0.0.1:9000. What is wrong?Related

Answer: The app listens only on loopback

Change the app to listen on 0.0.0.0 or the server IP.

From firewalld: zones, services and ports

A PC can ping 8.8.8.8 but not www.irctc.co.in. What is the most likely problem?Related

Answer: DNS

Reaching an IP address proves routing works. Failing on a name points to name resolution (DNS).

From Troubleshooting tools and common faults

Which port does HTTPS use by default?Related

Answer: 443

HTTP uses port 80 and HTTPS uses port 443 when no port is written in the URL.

From Clients, servers, IP addresses and URLs

Pass the quiz (60% or more) or mark this topic as done when you are ready.

Your progress is saved on this device only.

Next steps

  1. This is the last topic of “Linux for DevOps”. The module exam comes next.
  2. Module 2 exam: Linux for DevOps · 13 questions · 25 min, without help. 5 topics of this module still to finish first.
  3. Then the next module, Git in depth. 53 topics left in the course before the final exam.

← Previous: Bash scripting, text tools and cron