Every network scanner worth using runs into the same wall: to send an
ICMP echo request - a ping - you traditionally need a raw socket, and a
raw socket needs privileges. CAP_NET_RAW on Linux, an administrator
token on Windows, root on macOS. So the tool either asks for elevation
on every launch, or it quietly drops ICMP and probes TCP ports instead.
Dropping ICMP sounds harmless until you think about what it costs. A host with no open ports and a working network stack answers a ping and nothing else. TCP-only discovery reports it as absent. On a home or office LAN that is a lot of hosts - appliances, printers in a sleep state, anything hardened - and the scanner gives you a shorter list with no indication that it was ever incomplete.
Mildly Irritated IP Scanner exists because that is a false choice, and it has been false for years.
Three operating systems, three unprivileged ICMP interfaces
Raw sockets are not the only way to send an echo request. Each platform grew a narrower interface that does exactly this one thing, and each one is available without elevation:
- Linux - ping sockets:
SOCK_DGRAMwithIPPROTO_ICMP - macOS - datagram ICMP
- Windows -
IcmpSendEcho2, from the IP Helper API
They have nothing in common at the source level, which is presumably why
so few tools use all three. But the capability is the same: send an echo
request, get a reply, without asking the user for anything. So that is
what the scanner uses, on all three platforms, with no sudo, no
setcap, and no UAC prompt.
When ICMP genuinely is not available, it falls back to TCP connect probes - and says so in the results. That second half matters as much as the first. A scanner that silently degrades hands you a list that looks authoritative and isn't.
"Up" and "down" are not enough states
The more useful thing that falls out of probing both ways is that a host can be unreachable in several distinguishable ways, and the difference is the diagnostic part:
- Alive - answered ICMP.
- Alive (TCP) - ignored ping, but accepted a connection. Something is filtering ICMP, and the host is plainly there.
- Filtered - an ICMP error came back. Something is actively blocking it. A firewall that replies "administratively prohibited" has told you it exists.
- Dead - nothing at all.
Most scanners collapse all four into one bit and throw away the only part that would have told you why. "Filtered" and "dead" look identical in a list of up/down, and they mean completely different things about the network you are standing in.
Most devices have no DNS name, and will tell you theirs anyway
The Hostname column in a typical scan is mostly empty, because reverse DNS only knows about hosts someone bothered to give a PTR record. Printers, phones, speakers and smart plugs generally have none.
They will, however, answer if you ask them in a protocol they actually speak. An mDNS query and a NetBIOS node status request are the same mechanisms that make a Sonos speaker or a Windows box announce itself on a LAN. Measured across a real /24: DNS alone named 35% of hosts; adding mDNS and NetBIOS took it to 69%.
The doubling is not the interesting part. The interesting part is which hosts moved - almost exactly the ones you could not have identified from an IP address, which is the reason you were reading the column.
A PTR record is input from a machine you do not control
One detail worth calling out, because it took a moment to notice. Scan results export to CSV, and the Hostname column comes from a PTR record. That record is set by the administrator of the host being scanned - so it is attacker-controlled text arriving in a file you are about to open in a spreadsheet.
A cell beginning with =, +, - or @ is a formula. So those cells
get an apostrophe prefix on export. It is a small thing that only
matters once.
What it deliberately does not do
IPv4 only. The smallest normally-allocated IPv6 subnet is a /64 - eighteen quintillion addresses. "Sweep this range" is not an operation that terminates. IPv6 host discovery is a genuinely different problem and belongs in its own feature, rather than behind a parser that would cheerfully accept a target it can never finish.
Connect scans, not SYN scans. A half-open SYN scan is faster and
quieter. It also needs CAP_NET_RAW, which is the entire thing we were
avoiding. Given the choice between "quieter" and "no privileges", this
picks no privileges every time.
Both of those are in the README under a heading that says "Scope, honestly stated", which is roughly the house style.
GPL-3.0-or-later, Qt 6, with builds for Linux, Windows and macOS on the releases page. There is a CLI too, so it works over SSH and in a cron job.