Networking from the CLI
No desktop, no browser, no settings window. Just a shell and the tools that read the network, resolve names, and talk to services.
Builds on
What you will learn
- -Read a host's interfaces, addresses, and routes with ip and the legacy ifconfig
- -Test reachability with ping and turn names into addresses with dig
- -Talk to a live service using curl, wget, and netcat
- -List every socket a host exposes with ss
The previous lesson, "text-processing", turned pages of tool output into a single answer with grep, cut, and awk. Every one of those tools assumes something already produced the text. On a Linux with no desktop, no browser, and no settings window, the commands in this lesson are what produce it. They report where the host sits, test what it can reach, turn names into addresses, and hold a conversation with a live service, all as plain text a pipe can chew on.
A note before any of them run. Probing a host, reading a service banner, or pulling a file onto a machine is fair game on hardware owned by the person doing it, or on a with written to test it. Aimed anywhere else, the same commands are a crime. Everything below assumes a lab or an authorized target.
Where the host sits: ip and ifconfig
Every machine reaches the network through a network interface: a single
connection point, usually one per network card or radio, each carrying its own
address. A typical Linux host has at least two. One is real hardware, an
Ethernet or a Wi-Fi radio. The other is the interface, a
software-only interface named lo that a host uses to talk to itself at the
address 127.0.0.1, without a single bit ever touching the wire.
The ip command reports all of it. ip addr lists every interface and the
addresses bound to it.
$ip addrTwo interfaces. lo carries the loopback address every host has. eth0 holds
10.10.14.5, the address this host presents to the of its network, and the
/24 marks how far the local network stretches, from 10.10.14.0 to
10.10.14.255. That one line tells a tester which network the host landed on and
roughly how many neighbors might sit on it. The addresses here come from one
specific machine and will differ on any other.
ip route prints where go once they leave the host.
$ip routeThe default line names the gateway, the that every packet without a
closer destination gets handed to. Networking Foundations covered why that line
is the exit door from the local network. Here it is a fact the reads in one
command.
The older ifconfig shows much of the same interface information and still turns
up in scripts and on older systems, but most current Linux distributions ship
ip and leave ifconfig out of the base install. A shell that answers
ifconfig: command not found is not broken. ip addr is the replacement.
ip addr on a host lists two addresses: 127.0.0.1 on lo and 10.10.14.5 on eth0. Another machine on the same network wants to reach this host. Which address does it use?
Reaching a host, and naming it: ping and dig
ping answers one question: is a host reachable right now. It sends a small
echo request, a -message packet that asks a host to answer back, and it
times the reply.
$ping -c 4 10.10.14.1A reply means the host is up and a path exists in both directions. Silence proves nothing. Plenty of hosts and drop ICMP on purpose, so a machine can be running every service it owns and still never answer a ping. "No reply" means "no reply", nothing stronger. That distinction saves hours of chasing a host that was alive the whole time.
ping needs an address, and most targets are named, not numbered. Turning a name
like example.com into an address is name resolution, and is the system that
performs it, as Networking Foundations set out. dig runs a single lookup and
prints the answer.
$dig +short example.comWithout +short, dig prints a full ANSWER SECTION that names the record
type, A for an address, and the time-to-live, the number of seconds a
resolver may cache the answer before it has to ask again. dig also reports which
answered, which matters on an internal network, where a private DNS server
often knows hostnames no public resolver has ever heard of.
A host answers no pings at all, yet a web server on it is serving pages normally. How is that possible?
Talking to a service: curl, wget, and netcat
Reaching an address is not the same as getting a service to answer, a split Networking Foundations flagged as one of the three things that trip people up. Three tools close that gap.
curl sends a request to a service and prints the response. Against a web
server, curl -I asks for the alone, the metadata a server sends ahead
of the page body.
$curl -I http://10.10.14.23That Server line is a gift to anyone mapping a target: it names the
software and, here, the operating system underneath it. curl -s fetches the
body instead and stays quiet about progress, which is exactly what makes it pipe
cleanly into grep or awk.
wget does the neighboring job. It downloads a file to disk instead of printing
it. A command like wget http://10.10.14.5:8000/script.sh pulls a file from a
server, commonly one the tester is running, onto the current host. curl prints,
wget saves. That is the whole difference worth carrying early.
netcat, run as nc, is the blunt instrument. It opens a raw connection and
moves bytes in both directions with no idea what is on the far end.
Pointed at a port, it reads whatever the service announces on connect: its
banner, a line of text many services send that names the software and version.
$nc -nv 10.10.14.23 22One connection, and the service handed over its exact build. That string is
enough to look up known weaknesses in that specific version. The same tool, run
with -l, waits for an incoming connection instead of making one, which is how
it catches a connection a target sends back. The side belongs to a
later lesson.
What the host exposes: ss
curl and nc reach outward. ss looks inward. It lists the on the local
host. A socket is one end of a network connection, an address and a port bound
together, either an active connection or a port sitting open and waiting. ss
replaced the older netstat on modern systems and reads the same kernel tables
faster.
$ss -tulpnThe Local Address column is the whole story. 0.0.0.0:22 means the
listens on every interface, so anything that can route to the host is free to try
a connection. 127.0.0.1:3306 means the MySQL database listens only on the
loopback address, reachable from the host itself and nowhere else. Lesson 2,
"processes-and-services", named the process behind each open port. ss ties that
process to the exact address and port it holds open.
A database bound to 127.0.0.1 rejects the whole network, which is why its
owners so often leave it with a weak or none: they assumed no outsider
could to it. A tester who already holds a shell on the host is not an
outsider. From that shell the loopback address is local, the database answers,
and a service someone believed was private becomes the next step. Binding to
localhost is a real control, but only against machines that are not already on
the host.
ss -tulpn shows a service listening on 127.0.0.1:5432. A tester with a shell on that same host tries to connect to it. What happens?
On any Linux or macOS host, run ip addr (on macOS, ifconfig). Find the
interface that is not lo, and write down its address and the / number after
it. That is the host's place on its own network.
Now run ss -tulpn (on macOS, netstat -an -p tcp, which drops the process
column). Read the local address on each listening line and sort the services into
two piles: the ones on 0.0.0.0 or ::, reachable from the network, and the
ones on 127.0.0.1, reachable only from this host.
Last, pick one address that answered and probe it. Run curl -I http://<address>
if it speaks , or nc -nv <address> <port> to read whatever banner it
offers. Whatever comes back is the raw material the last lesson taught how to cut
down to a single finding.
Every command here prints text, and printing text was the point. The next lesson, "bash-recon-script", stops running these one at a time and wires them together: a variable to hold an address, a loop to walk a list of ports, a conditional to act on what came back, so one command runs the whole sweep and the text tools from lesson 3 trim the result down to what matters.