NetDTL — Reference Manual
Complete reference for the NetDTL v3.0 agentless network inventory and diagnostic web application.
Overview
NetDTL is a self-hosted web application for agentless network discovery and inventory management on Windows infrastructure. It runs on a PHP/MySQL/Nmap stack (XAMPP or LAMP) and provides real-time scanning via Server-Sent Events, machine profiling, network diagnostics, and patch panel management — all through a dark-themed web interface with no external JavaScript dependencies.
The application is structured as a set of PHP pages, each responsible for one functional area, sharing a common database layer (db.php), a CSS stylesheet (style.php), and layout partials (topbar.php, sidebar.php).
Requirements
| Component | Version | Notes |
|---|---|---|
| PHP | 8.x | Extensions required: pdo_mysql, mbstring |
| MySQL / MariaDB | any recent | Used via PDO |
| Nmap | any recent | Must be accessible from the PHP process; path set via NMAP_PATH |
| XAMPP or LAMP | — | Any standard PHP+MySQL server environment |
| PowerShell | 5.1 / 7+ | Required for WMI descriptions and local IP/service queries |
shell_exec. The PHP process account must have sufficient privileges, and Nmap must be in the system PATH or its full path set in db.php.Installation
Deploy the application files to the web server document root (e.g. htdocs/netdtl/ under XAMPP, or a dedicated virtual host).
1. Create the database
CREATE DATABASE netdtl CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'netdtl'@'localhost' IDENTIFIED BY 'yourpassword';
GRANT ALL PRIVILEGES ON netdtl.* TO 'netdtl'@'localhost';
FLUSH PRIVILEGES;
2. Configure db.php
Edit the constants at the top of db.php to match your environment. The database schema is created automatically on first run by initDB().
3. First run
Open the application in a browser. initDB() will create all required tables if they do not exist. Log in with the credentials defined in AUTH_USER / AUTH_PASS.
Configuration
All configuration lives in db.php as PHP constants. There is no separate config file.
| Constant | Description |
|---|---|
| DB_HOST | MySQL host, typically localhost |
| DB_NAME | Database name |
| DB_USER | Database user |
| DB_PASS | Database password |
| AUTH_USER | HTTP Basic Auth username |
| AUTH_PASS | HTTP Basic Auth password (plaintext in current version) |
| NMAP_PATH | Full path to the Nmap binary, e.g. C:/Program Files (x86)/Nmap/nmap.exe |
| DEFAULT_NETWORK | Pre-filled CIDR range shown on the discovery page |
| APP_VERSION | Version string displayed in the sidebar footer |
Database Schema
Tables are created automatically by initDB() in db.php using CREATE TABLE IF NOT EXISTS.
machines
Central inventory table. One row per IP address (unique key on ip).
| Column | Type | Description |
|---|---|---|
| id | INT AUTO_INCREMENT | Primary key |
| hostname | VARCHAR | Short hostname or IP if no name resolved |
| ip | VARCHAR(45) | IPv4 address — unique constraint |
| mac | VARCHAR(17) | MAC address in uppercase colon-separated format |
| vendor | VARCHAR | NIC manufacturer from Nmap OUI lookup |
| os | VARCHAR | OS string from Nmap detection or manual entry |
| switch_port | VARCHAR | Switch port label (e.g. port1.0.3), manually set |
| patch_port | VARCHAR | Patch panel port label (e.g. B31), manually set |
| open_ports | TEXT | Comma-separated list of open ports from last port scan |
| status | ENUM('up','down','unknown') | Current reachability status |
| last_ping_ms | INT | Average ping RTT in milliseconds from last ping |
| comment | TEXT | Free-form note; also populated by WMI / NetBIOS enrichment |
| first_seen | DATETIME | Set at INSERT, never updated |
| last_seen | DATETIME | Updated on every scan hit or ping |
scan_history
One row per completed discovery scan.
| Column | Type | Description |
|---|---|---|
| id | INT AUTO_INCREMENT | Primary key |
| scan_date | DATETIME | Timestamp of scan completion |
| network | VARCHAR | CIDR range that was scanned |
| hosts_up | INT | Number of hosts found up |
| hosts_down | INT | Stored as 0 in current version |
| duration_s | INT | Scan duration in seconds |
diag_history
Log of all diagnostic operations (ping, traceroute, DNS, port scan, OS detection).
| Column | Type | Description |
|---|---|---|
| id | INT AUTO_INCREMENT | Primary key |
| action | VARCHAR | Tool name: ping, nmap, traceroute, dns, ports, infos, services, nmap_os |
| target | VARCHAR | IP, hostname, or CIDR that was targeted |
| result | TEXT | First 20 lines of command output |
| success | TINYINT | Always 1 in current version |
| created | DATETIME | Timestamp of the operation |
patch_panel
Physical patch panel ports, typically populated by import (CSV or direct SQL).
| Column | Type | Description |
|---|---|---|
| id | INT AUTO_INCREMENT | Primary key |
| prise | VARCHAR | Wall outlet label (e.g. B31) — unique |
| type | VARCHAR | RJ45, RJ11, or other |
| entite | VARCHAR | Owning entity or department |
| local_name | VARCHAR | Room or location name |
| etage | VARCHAR | Floor |
| poste | VARCHAR | Workstation or desk reference |
| switch | VARCHAR | Switch name or identifier |
| port_switch | VARCHAR | Switch port (e.g. port1.0.3) |
| notes | TEXT | Free-form notes |
patch_machines
Many-to-many join between patch panel ports and machines (a port may serve multiple IPs).
| Column | Type | Description |
|---|---|---|
| id | INT AUTO_INCREMENT | Primary key |
| prise | VARCHAR | Foreign reference to patch_panel.prise |
| machine_ip | VARCHAR | IP address of the machine at this port |
| hostname | VARCHAR | Hostname at time of association |
Pages
Dashboard
Requires authentication via requireAuth(). Default landing page after login.
- Total machine count, counts by status (
up,down,unknown) - Last scan: date, network, host count (from
scan_history) - 8 most recently seen machines ordered by
last_seen DESC - 5 most recent
diag_historyentries
Read-only page. All actions (ping, add, delete) are on inventory.php and machine.php.
Inventory
| Parameter | Description |
|---|---|
| q | Free-text search across hostname, IP, OS, comment |
| status | Filter by status: up, down, or unknown |
| export=csv | Triggers CSV download of the full inventory (bypasses all filters) |
| Field | Action |
|---|---|
| add_machine | Inserts a new machine row. Required fields: hostname, ip (valid IP). Optional: os, comment, switch_port, patch_port. |
| delete_id | Deletes the machine with the given ID. Asks for confirmation via JavaScript before submission. |
| ping_id | Runs a ping against the machine's IP via runPing(), updates status, last_ping_ms, last_seen. |
| ping_all | Pings every machine in the inventory sequentially. Updates all status fields. |
Triggered by ?export=csv. Outputs all machines ordered by INET_ATON(ip) (numerical IP sort). Columns: Hostname, IP, MAC, Vendor, Switch port, Patch port, OS, Status, Open ports, Ping (ms), Last seen, Comment. BOM prepended for Excel UTF-8 compatibility.
$_SERVER['SERVER_ADDR'] and replaces its MAC field display with ce PC (italicised) to avoid confusion with Nmap's own MAC (which Nmap cannot read for the scanning machine itself).Machine detail
diag_history.| Parameter | Description |
|---|---|
| id | Machine ID (integer). Redirects to inventory.php if not found. |
| Field / value | Action |
|---|---|
| save | Updates os, switch_port, patch_port, comment for the machine. |
| diag=ping | Runs ping via runPing(). Updates status and last_ping_ms. |
| diag=ports | Runs nmap -p 21,22,23,25,80,110,143,443,445,3306,3389,5900,8080. Updates open_ports in DB. |
| diag=traceroute | Runs tracert (Windows). |
| diag=dns | Runs nslookup. |
| diag=nmap_os | Runs nmap -O --host-timeout 10s. Extracts and saves OS details line to machines.os. |
Each output line is classified and colour-coded: lines matching TTL, Reply, or open are green; timeout / unreachable / filtered are amber; error / failed are red. A hidden <pre id="raw-output"> element holds the plain text for clipboard copy.
nmap -O requires the PHP process to run as Administrator (Windows) or root (Linux).Network discovery
scan_stream.php. Discovered hosts are automatically upserted into the machines table.| Control | Description |
|---|---|
| Network input | CIDR range (e.g. 192.168.1.0/24). Pre-filled with DEFAULT_NETWORK. |
| Ports communs | If checked, runs an additional port scan on each discovered host (?ports=1). |
| Détection OS | Adds -O to the Nmap command (?os=1). Requires admin/root. |
| Identifier NetBIOS | Runs a second pass of nbstat queries after the main scan (?nbstat=1). |
| Descriptions WMI | Queries each up host via PowerShell WMI for OS description (?wmi=1). |
The page opens an EventSource connection to scan_stream.php with query parameters reflecting the selected options. Events are handled by handleEvent(data) in JavaScript.
| Event type | Description |
|---|---|
| line | Raw Nmap output line. Colour-classified and appended to the terminal block. |
| host_saved | A host has been upserted. Adds a row to the discovered hosts table in the UI. |
| mac | MAC address and vendor resolved for an IP. Updates the corresponding table row. |
| os | OS string detected. Updates the corresponding table row. |
| nbstat | NetBIOS name resolved. Updates the description column in the hosts table. |
| wmi | WMI description retrieved. Appended to the description column in the hosts table. |
| done | Scan complete. Updates stats (host count, duration), adds a row to the scan history table, completes the progress bar. |
| error | Fatal error from the server side. Closes the EventSource, displays the error message. |
The bottom of the page displays the 10 most recent scan_history entries. A new row is appended dynamically in JavaScript when the done event is received, without page reload.
Discovery SSE endpoint
discovery.php. Executes Nmap, parses its output line by line, upserts machines into the database, and optionally runs NetBIOS and WMI enrichment passes. Not intended to be accessed directly.| Parameter | Default | Description |
|---|---|---|
| network | DEFAULT_NETWORK | CIDR range to scan. Validated by isValidTarget() before use. |
| ports | 0 | If 1, runs a port scan on each discovered host after the ping sweep. |
| os | 0 | If 1, uses nmap -sS -O instead of nmap -sn. Requires elevated privileges. |
| nbstat | 0 | If 1, runs a NetBIOS pass after the main scan. |
| wmi | 0 | If 1, queries WMI descriptions via PowerShell after the main scan. |
- Phase 1 — Nmap sweep: Runs
nmap -sn -R -T4(or-sS -Oif OS detection enabled) viapopen(). Output is parsed line by line. On eachNmap scan report forline, the previous host (if any) is saved to the DB and ahost_savedevent is emitted. MAC addresses, vendors, and OS strings are extracted by regex and emitted as separate events. - Phase 2 — NetBIOS (optional): Iterates all
status='up'machines. For each, runsnmap -sU -p 137 --script nbstat. Extracts NetBIOS name, workgroup, and logged-in user. Updates hostname (if currently an IP) and comment in the DB. - Phase 3 — WMI (optional): Iterates all
status='up'machines. For each, runs a PowerShellGet-WmiObject Win32_OperatingSystemquery. Stores theDescriptionfield inmachines.commentif not already set.
The saveMachineStream() function uses INSERT ... ON DUPLICATE KEY UPDATE on the ip column. Existing values for MAC, vendor, and OS are preserved with COALESCE(VALUES(col), col) — a scan will not erase manually entered data with a null value.
Nmap output on Windows is typically CP850. Each line is converted to UTF-8 via mb_convert_encoding($raw, 'UTF-8', 'CP850') before being emitted as a JSON SSE payload.
set_time_limit(600) is called. Large networks or slow hosts may approach this limit. Output buffering is disabled (ob_end_flush()) to ensure events are streamed as they arrive.Patch panel
patch_panel table joined with associated machine IPs and hostnames from patch_machines. Supports filtering by switch, entity, and free-text search.| Parameter | Description |
|---|---|
| q | Free-text search across port label, room name, workstation, IP, hostname |
| switch | Filter by switch identifier |
| entite | Filter by entity / department |
The patch_panel table is not populated by NetDTL itself. It is intended to be filled by external import (CSV, SQL script, or the NetDTL Installer's patch panel engine). The application provides the read and filter interface only.
For each port, associated machines are retrieved from patch_machines via a GROUP_CONCAT join. Multiple IPs and hostnames per port are displayed as comma-separated lists.
Port types are colour-coded: RJ45 in blue, RJ11 in amber, unknown in grey. Entity badges are distinguished between local equipment (teal) and delegated (green) based on a case-insensitive match on the word locale in the entity name.
Shared Components
Security
NetDTL uses HTTP Basic Authentication implemented in requireAuth(). Credentials are stored in plain text in db.php. This is acceptable for a trusted local network deployment but should not be exposed to the public internet without additional protection (reverse proxy with TLS, IP filtering, etc.).
- All user-supplied values rendered in HTML are passed through
htmlspecialchars(). - All database queries use PDO prepared statements with bound parameters.
- Shell commands use
escapeshellarg()on all user-supplied targets, validated beforehand byisValidTarget(). - The CIDR range in
scan_stream.phpis validated byisValidTarget()before being passed to Nmap.
AUTH_PASS constant is stored in plaintext. Do not reuse a sensitive password. For production environments, consider replacing requireAuth() with session-based authentication or delegating authentication to the web server.Known Limitations
- Windows-centric commands. Ping uses
ping -n 4and traceroute usestracert. On Linux,runPing()switches toping -c 4, buttracert(menu.php) is not adapted — usetraceroutemanually on Linux. - MAC address not available for the scanning machine itself. Nmap cannot read its own MAC. The inventory page detects this case and replaces the MAC field with a ce PC label.
- OS detection requires elevated privileges.
nmap -Oandnmap -sSrequire the web server process to run as Administrator (Windows) or root (Linux). Without elevation, these options silently return no OS data. - WMI queries require network access and Windows target. The PowerShell WMI call in
scan_stream.phponly works against Windows machines that allow remote WMI, and only when the scanning server has appropriate credentials on the target. - NetBIOS identification requires UDP 137. The
nbstatNmap script uses UDP port 137. Firewalls or Windows Firewall rules blocking this port will prevent NetBIOS name resolution. - Patch panel data is not managed by the application. The
patch_panelandpatch_machinestables must be populated externally (e.g. via the NetDTL Installer's patch panel engine or direct SQL import). - Single-user authentication. There is only one set of credentials. There is no role management or per-user audit trail.
- Scan duration limit.
set_time_limit(600)limits scans to 10 minutes. Large or slow networks may exceed this. hosts_downis always 0. Thescan_history.hosts_downcolumn is inserted as 0; hosts that do not respond are simply not added to the inventory during a scan.
NetDTL Web site