Show HN: Whosthere: A LAN discovery tool with a modern TUI, written in Go
Posted by rvermeulen98 1 day ago
Comments
Comment by rvermeulen98 1 day ago
It works by combining several discovery methods:
- mDNS and SSDP scanning
- ARP cache reading (after triggering ARP resolution via TCP/UDP sweeps)
- OUI lookups to identify device manufacturers
It also includes:
- A fast, keyboard-driven TUI (powered by tview)
- An optional built-in port scanner
- Daemon mode with a simple HTTP API to fetch devices
- Configurable theming and behavior via a YAML config file
Why I built it:
Mainly to learn, I've been programming in Go for about a year now and wanted to combine learning Go with learning more about networking in one single project. I've always been a big fan of TUI applications like lazygit, k9s, and dive. And then the idea came to build a TUI application that shows devices on your LAN. I am by no means a networking expert, but it was fun to figure out how ARP works, and discovery protocols such as mDNS and SSDP.
Example usage:
---
# install via HomeBrew brew tap ramonvermeulen/whosthere brew install whosthere
# or with go install go install github.com/ramonvermeulen/whosthere@latest
# run as TUI whosthere
# run as daemon whosthere daemon --port 8080
---
I'd love to hear your feedback, if you have ideas for additional features or improvements that is highly appreciated! Current platform support is Linux and MacOS.
Comment by genericacct 21 hours ago
Comment by nickcw 22 hours ago
It would be great it it could show the reverse lookup of the IPs as on my LAN everything has a name and if it hasn't then it is probably an interloper!
Comment by N3802E 21 hours ago
Some feedback of what I found on my network, as compared to some other scanners I've used.
I've never seen anything that can beat Advanced IP Scanner at finding hostnames. I've never even found a way to get arp or nmap to get close to Advanced IP Scanner; I've tried dozens of suggested commands of each, all with no luck. Here's the results of my scans:
Alive hosts: 309
Unkown: 201
With hostnames: 80
https://www.advanced-ip-scanner.com/
####################################
I also tried a program called Angry IP Scanner:
Hosts scanned: 510
Hosts alive: 315
With hostnames: 75
####################################
whosthere
Devices: 318
With hostnames: 54
Comment by alphax314 20 hours ago
Comment by mmh0000 18 hours ago
Those who cannot remember nmap are condemned to remake it poorly
Rootless nmap scan of a /24 in under 10 seconds: nmap -T5 -sn -PR --script broadcast-dns-service-discovery,broadcast-upnp-info 10.0.0.0/24
…SNIP…
Nmap done: 256 IP addresses (30 hosts up) scanned in 9.99 seconds
https://nmap.org/book/toc.htmlComment by zbentley 17 hours ago
What makes you think it’s not learning from/remembering nmap?
Comment by mmh0000 16 hours ago
Comment by sally_glance 15 hours ago
Comment by andrewxdiamond 14 hours ago
Comment by rvermeulen98 13 hours ago
I am very grateful for all the feedback and suggestions, and I will take my time to evaluate every comment. In the coming weeks I will try to implement most of the feedback and do releases to improve the tool further, thanks everyone!
Comment by gerdesj 11 hours ago
Comment by yu3zhou4 7 hours ago
Congrats for the execution, it looks more complete and feature rich and Go is a better choice for sure
Comment by 84634E1A607A 23 hours ago
Comment by rvermeulen98 23 hours ago
1. It only scans the subnet of the configured network interface.
2. The scan is limited to a maximum size of a /16 subnet.
3. It runs just once every 5 minutes (this interval should be made configurable, currently still hardcoded).
If a subnet larger than /16 is configured, whosthere will log a warning and only scan the first /16 portion of that subnet. As of now the network interface itself is configured via the YAML file. I agree it would be a good idea to add command-line flags for more of these settings to make them easier to adjust.
Comment by pjmlp 2 hours ago
Comment by mrcaramelpants 22 hours ago
Comment by adzm 19 hours ago
Comment by pinkmuffinere 9 hours ago
Comment by dalton_zk 1 hour ago
Comment by zahlman 20 hours ago
Comment by cpuguy83 19 hours ago
Comment by pstuart 20 hours ago
This project appears to be using github.com/rivo/tview which is is really solid.
Comment by jen20 20 hours ago
Comment by fulafel 8 hours ago
Comment by awesome_dude 15 hours ago
Much like cobra (or was it viper) did for CLI switches
This is cool if that's what you like, but if you have your own thinking on layout/architecture then you're in for a world of pain.
I use rivo/tview in my projects, and like it, but it's not without its "quirks"
Comment by pstuart 20 hours ago
Comment by gerdesj 11 hours ago
You cannot see network traffic.
You'd be amazed at how many people think they can diagnose a network fault without using tools like this. Everyone is an expert until they prove themselves to be a bit of a twit!
At layer 1 you have electrical issues to deal with and that will need some hardware. Obviously you need to pick your network model too. Here you'll go in with a couple of PCs/laptops and APIPA and/or a Fluke or a cheap network tester effort off of Amazon. Use what you have available.
After that you will need nmap and wireshark. LLDP and CDP are very handy too.
If you have to deal with a large network, I can highly recommend Netdisco.
Comment by jasonjmcghee 20 hours ago
Comment by apitman 20 hours ago
Comment by adi_kurian 15 hours ago
Comment by vzaliva 20 hours ago
Comment by zahlman 20 hours ago
Generally speaking, the Debian package management system is really not a place I would look for prompt updates when new versions of software are released.
Comment by mzajc 19 hours ago
Comment by foresto 19 hours ago
Comment by yobert 17 hours ago
Comment by sneak 19 hours ago
I certainly don’t want programs I “go install” to change underneath me without notice or review. That’s basically handing ownership of your computer to a remote developer.
Comment by esseph 8 hours ago
System / application package updates??
Comment by GeoffKnauth 21 hours ago
Comment by cedws 20 hours ago
Comment by sneak 19 hours ago
I’m sure this has nothing to do with Apple’s subscription-based (and government ID requiring) developer program membership which is the only way to get such signatures.
Comment by kapitanjakc 22 hours ago
Comment by petcat 23 hours ago
Comment by Daviey 23 hours ago
$ go install github.com/ramonvermeulen/whosthere@latest
# golang.design/x/clipboard
clipboard_linux.c:14:10: fatal error: X11/Xlib.h: No such file or directory
14 | #include <X11/Xlib.h>
| ^~~~~~~~~~~~
compilation terminated.Comment by rvermeulen98 2 hours ago
Comment by fellerts 23 hours ago
Comment by rvermeulen98 22 hours ago
I hesitated a bit bringing in this feature. On one hand, I really like to have clipboard support, on the other hand, I don't like that it requires you to change from static to dynamic linking (and have the x11 dependency).
Maybe I could write an install.sh script for installation that detects the OS and fetches the correct version/tarball from the Github release.
Comment by Daviey 22 hours ago
How about this PR? https://github.com/ramonvermeulen/whosthere/pull/29
It switches to using github.com/dece2183/go-clipboard, which supports Mac, Windows, Linux (X11 + Wayland) and Android.
Comment by rvermeulen98 21 hours ago
On the other hand, I also don't want whosthere to be depended on a fork that isn't maintained anymore. I will think about this trade-off, but I am also interested how others look at this problem.
Comment by ok123456 21 hours ago
Comment by petcat 22 hours ago
Comment by Daviey 22 hours ago
Comment by sigmonsays 20 hours ago
There should be a build tag to disable clipboard, that'd be the easiest way around this.
Comment by Daviey 18 hours ago
Comment by Evidlo 21 hours ago
Comment by rvermeulen98 20 hours ago
Comment by Havoc 21 hours ago
Specifically it needs to pull additional detail out of proxmox servers and opnsense plus deduce where things are physically based on latency.
Thats a whole lot easier if it doesn’t need to work universally & you can hardcode some assumptions
Comment by jarek83 15 hours ago
Comment by fulafel 8 hours ago
Comment by SturgeonsLaw 8 hours ago
Comment by fulafel 8 hours ago
But yeah, bigcorp managed networks still often make do with v4 routing only. Besides mobile, homes and SOHO are more likely to have current internet access.
Comment by eqvinox 11 hours ago
ping ff02::1%eth0Comment by girishso 22 hours ago
Comment by vivzkestrel 12 hours ago
Comment by Anonbrit 1 day ago
Comment by rvermeulen98 22 hours ago
Comment by 47282847 18 hours ago
Nice tool!
Comment by est 21 hours ago
Comment by pimlottc 15 hours ago
Comment by coolius 23 hours ago
Comment by rvermeulen98 22 hours ago
When reading some blog posts, I found often a solution where it sends out an UDP dial to for example 8.8.8.8:53 because you can then get the network interface back from the connection it's local address. As fallback I implemented to pick the first non-loopback interface that is up.
Would be open to suggestions to do this in a better way!
Comment by fellerts 22 hours ago
router, _ := routing.New()
iface, _, _, _ := router.Route(net.ParseIP("8.8.8.8"))
fmt.Println(iface.Name)
this prints my Ethernet interface as expected. It doesn't make any requests, it just figures out where to route a packet. I guess it interfaces with the OS routing table.Comment by rvermeulen98 22 hours ago
Comment by contingencies 19 hours ago
# IPv4 default route only
uname
Darwin$ route -n get 0.0.0.0 | grep interface | cut -d ':' -f2
Linux$ route -nv |grep ^0.0.0.0 | awk '{print $NF}'Comment by ryancnelson 19 hours ago
Comment by rvermeulen98 14 hours ago
Comment by spacecadet 1 hour ago
Comment by sneak 19 hours ago
Great work.
Comment by hk1337 21 hours ago
Couldn't run it on macOS Tahoe. I believe this requires me lowering the security to allow it, which is something I would rather not doing.
Comment by rawgreaze 21 hours ago
Comment by rvermeulen98 21 hours ago
Comment by wtetzner 7 hours ago
Comment by phubbard 20 hours ago
xattr -c `which whosthere`