⚠️ Finished learning project — archived. Built to explore Go's networking and concurrency primitives. Complete and not actively maintained.
A lightweight port scanner desktop app built with a Go backend and React frontend via Wails. Scans TCP ports, grabs service banners, detects live hosts on a network, and displays results in real time through a dark-themed UI.
Built as a learning project to explore Go's networking primitives, goroutine worker pools, and Wails as a desktop app framework.
Prebuilt binaries for Linux and Windows are available on the Releases page:
| Platform | File |
|---|---|
| Linux (x64) | GoMap-linux-amd64 |
| Windows (x64) | GoMap-windows-amd64.exe |
A latest pre-release is updated automatically on every push to main.
- Port Range Scan — scan any TCP port range with configurable timeout and worker count
- Common Ports Preset — one-click scan of ~80 well-known ports (SSH, HTTP, databases, DevOps tools, etc.)
- Network Discovery — scan a CIDR range (e.g.
192.168.1.0/24) to find live hosts via TCP probing - Banner Grabbing — reads service banners from open ports (SSH version, HTTP headers, etc.)
- Service Detection — maps port numbers to known service names (100+ entries)
- Real-time Results — ports appear as they are found, no waiting for the full scan to finish
- Filter — show all results, only open ports, or only filtered (firewalled) ports
- Progress Tracking — live progress bar, scanned/total counter, and ports/sec speed
- Cancel — gracefully stop any scan mid-way
| Layer | Technology |
|---|---|
| Backend | Go — net package, goroutine worker pools, context cancellation |
| Frontend | React + Tailwind CSS |
| Desktop | Wails v2 — wraps the app in a native webview window |
GoMap/
├── app.go # Core logic — StartScan, StartScanList, ScanNetwork, CancelScan
├── main.go # Wails app entry point
├── wails.json # Wails project config
├── go.mod
├── go.sum
└── frontend/
├── src/
│ ├── App.jsx # Main React UI — scan form, results table, event listeners
│ └── main.jsx
├── index.html
├── package.json
├── tailwind.config.js
└── vite.config.js
- Go 1.21+
- Node.js 18+
- Wails CLI —
go install github.com/wailsapp/wails/v2/cmd/wails@latest - On Linux:
webkit2gtk— e.g.sudo dnf install webkit2gtk4.1-develon Fedora
Verify your setup:
wails doctorwails devOpens the app in a live-reload window. Go changes restart the backend; React changes hot-reload instantly.
wails buildProduces a single native binary in build/bin/.
Modern Linux distributions (Fedora 40+, Ubuntu 24.04+, Debian 13+, etc.) have deprecated the webkit2gtk-4.0 package in favor of webkit2gtk-4.1. If you see a libwebkit Not Found error when trying to run the app, you need to:
-
Install the 4.1 development package for your distro. For example:
# Fedora sudo dnf install webkit2gtk4.1-devel # Ubuntu / Debian sudo apt install libwebkit2gtk-4.1-dev
-
Run the project with the
webkit2_41build tag:wails dev -tags webkit2_41
For production builds, use the same tag:
wails build -tags webkit2_41
- Port scanning uses
net.DialTimeoutover TCP. A full connection is attempted for each port — if it succeeds the port isOPEN, if it times out it'sFILTERED(likely firewalled), and if it's refused it'sCLOSED(silently skipped by default). - Worker pool — a configurable number of goroutines pull ports from a channel concurrently, making large scans significantly faster than sequential scanning.
- Cancellation — each scan runs under a
context.WithCancel. TheCancelScanmethod triggers the cancel function (protected by a mutex to avoid data races), and all workers exit cleanly via aselectcheck at the top of their loop. - Real-time UI — Go emits a
port_resultWails event the instant a port state is determined. The React frontend buffers incoming events and flushes them to state every 300ms to avoid excessive re-renders. - Banner grabbing — after confirming a port is open, a 500ms read deadline is set on the connection. Any bytes received are emitted as a separate
port_bannerevent and injected into the matching table row. - Network discovery —
ScanNetworkparses a CIDR withnet.ParseCIDR, iterates all host addresses, and probes each one on ports22, 80, 443, 8080, 3389, 8443. The first successful connection marks the host as live.
A deliberate exercise in Go's concurrency and networking model:
- Goroutine worker pools — a bounded set of goroutines pulling ports from a channel concurrently, turning a slow sequential scan into a fast parallel one.
- Context-based cancellation — every scan runs under
context.WithCancel; cancelling unwinds all workers cleanly via aselectcheck, with a mutex guarding the cancel function against data races. - Low-level TCP networking —
net.DialTimeoutfor port probing, connection read deadlines for banner grabbing, andnet.ParseCIDRfor host enumeration. - Concurrency-safe result streaming — emitting results the instant they're found and buffering them on the frontend to avoid excessive re-renders.
This project is licensed under the MIT License.
