13.4 Build a network scanner
Lesson 13.2's scanner read a package list. This one goes out on the network and interrogates machines, which is the kind of scan lesson 13.1 called network surface, and it is what most people mean when they say "we ran a vulnerability scan."
The tool is OpenVAS, now packaged as the Greenbone Community Edition. It is free, it is genuinely what smaller organisations run in production, and it is the heaviest thing you will install in this course.
Read this before you start, because it is about your machine
I am going to be straight with you about cost, because finding out halfway through is worse.
This scanner is large. It runs as several containers, and it downloads a vulnerability feed containing hundreds of thousands of tests. That feed sync is the slow part: expect it to take between thirty minutes and several hours on a first run, depending on your connection. It is not stuck. There is no way to make it fast, and every person who has deployed this tool has sat through it.
UBNT01 already has your monitoring stack on it from Module 12. Both want memory at the same time, and a 6 GB server running Wazuh's manager, indexer and dashboard does not have room to spare.
Check what you actually have before deciding:
# On UBNT01. The "available" column is the honest number: it counts
# memory currently used for cache, which the kernel will release.
free -h
# And disk, because the feed needs room. Look at the line for /.
df -h /
Then pick your path:
| Your situation | What to do |
|---|---|
| Available memory above about 4 GB, and 20 GB of free disk | Run both. Continue below. |
| Tight on memory | Stop the monitoring stack while you scan, then start it again. Instructions below. Nothing is lost; Wazuh picks up where it left off. |
| Genuinely cannot fit it | Skip to lesson 13.7. You have already done the most transferable work in this module, and 13.8 needs no scanner either. |
Treat 4 GB and 20 GB as a starting estimate rather than a specification. The vulnerability feed grows every week, so the disk this needs six months from now is larger than the disk it needs today, and nobody's published figure stays accurate.
So watch it rather than trusting a number:
# In a second session while the feed syncs. Available memory
# and free disk, refreshed every 5 seconds. Ctrl+C to stop.
watch -n 5 'free -h | head -2; df -h /'
If available memory drops toward zero and the machine starts swapping, stop and use the run-one-at-a-time path above. Swapping is the failure you are watching for, and it is obvious: everything gets slow at once.
Write the figures you actually see into your journal. That number is about your machine, which makes it worth more than any number in a course.
Running one at a time, if you need to:
# Stop the monitoring stack. Substitute your own directory name
# from lesson 12.2 if you called it something else.
cd ~/docker/wazuh && docker compose stop
# ...do your scanning work...
# And bring it back when you're done.
cd ~/docker/wazuh && docker compose start
How you know the stop worked:
# Expect no wazuh containers in the list.
docker ps --format '{{.Names}}'
# And the memory back. Compare against what free -h said before.
free -h
Install it
Greenbone publish this as a set of containers with a compose file, which is exactly the shape you learned in lesson 6.5.
Get the current instructions from the source, rather than from me. This is software that changes its packaging between releases, and a compose file copied into a course goes stale in a way that wastes your evening:
Go to greenbone.github.io/docs and
find the Community Containers installation guide. It is the page that
walks through docker compose and gives you a docker-compose.yml to
download.
What you are looking for, so you land on the right page:
- The page title includes "Community Containers". Greenbone also publish instructions for building from source and for their commercial appliances; both are the wrong page for you today.
- It gives you a
curlorwgetcommand that downloads a compose file. - The wrong turn to avoid: the Greenbone Enterprise TRIAL is a downloadable virtual appliance, prominently offered, and it is a different product with a licence and an expiry. You want the community containers.
Put the stack where your other stacks live, per lesson 6.5's convention:
mkdir -p ~/docker/greenbone
cd ~/docker/greenbone
Then follow their download-and-start steps in that directory. It will be a
docker compose pull followed by a docker compose up -d, the same two
verbs from lesson 6.5.
Greenbone's commercial equivalents are Tenable, Qualys and Rapid7, and the comparison is closer than you would expect. They run the same kinds of checks, hit the same authenticated-versus-unauthenticated distinction you will meet in lesson 13.6, and produce the same flood of findings.
What you pay for is the feed and the reporting. Commercial vulnerability data is updated faster and covers more products, and the platforms are built to answer management's question rather than yours: coverage over time, by business unit, against a policy.
What does not change is the hard part. Scanning is easy and finding vulnerabilities is easy. Deciding what to fix first, getting somebody else to fix it, and documenting what you have decided not to fix is the whole job, and it is identical whichever scanner produced the list. Lesson 13.8 is about that and it is the lesson that matters.
How you know it worked
Three checks, in order, because they fail differently.
1. The containers are running.
cd ~/docker/greenbone
docker compose ps
Expect several services with state running or Up. A container in
Restarting is a container crashing in a loop; docker compose logs <service-name> tells you why.
2. The feed is synchronising, or has finished. This is the one that takes hours, and the one people assume has hung.
# Follow the feed sync. Ctrl+C stops watching; it does NOT stop
# the sync, which continues in the container.
docker compose logs -f
You are looking for steady progress messages rather than repeated errors. It is normal for this to look boring for a very long time. This is what tmux was for, from lesson 6.2: start it, detach, come back later.
3. The web interface answers. From your own computer, browse to
https://10.10.10.20:9392.
- Expect a certificate warning. This is a self-signed certificate, the situation lesson 7.1 explained. You know exactly what this warning means now and why clicking through it on a machine you built is a different act from clicking through it on the internet.
- The default credentials are in Greenbone's instructions, and their setup step has you set a password. Set a real one, and put it in your password manager rather than your journal.
If the page does not load at all, work the ladder from lesson 4.4 rather
than guessing: can you ping 10.10.10.20, is the container running
(docker compose ps), is the port published (docker compose ps shows the
mapping), and is ufw from lesson 6.3 blocking it?
# ufw allows SSH and web from lesson 6.3, but not this port.
sudo ufw allow 9392/tcp
sudo ufw status
That last one catches most people, and it is your own firewall doing its job correctly.
You have just installed a tool whose entire purpose is finding weaknesses in machines, with a web interface and a password. It belongs on your lab network and nowhere else.
Never forward a port to it from your router, and never put it on the internet "just to check from work". A scanner reachable from outside is a gift: it tells an attacker exactly what is wrong with everything you own, in a tidy report, with your own credentials protecting it.
What you take from this
A working network scanner, on your own server, that took real resources and real waiting. That waiting is not a flaw in the lesson; it is what this class of tool costs, and knowing that is part of knowing the job.
Next lesson you point it at something.