Point it at Suricata's eve.json and it tells you every device on your network, what each one
is, and what's wrong with it. One binary, one file, no agents, no scanning, no credentials.
Suricata already parses DHCP, ARP, TLS, Kerberos, SMB, SNMP, SSH, Modbus and twenty other
protocols. Almost every deployment uses the alert records and treats the rest as log volume.
That rest is a complete, continuously updated inventory of your network. Tarsier reads it.
Open-source Suricata dashboard and eve.json analyser for passive network discovery, network asset inventory and device fingerprinting — a free, self-hosted Suricata web UI and IDS visibility tool. Runs on OPNsense, pfSense, Docker, bare metal and cloud traffic mirrors.
The scanner and the watcher. Point
tarsier-scanat aneve.jsonfor a one-shot report, or leavetarsier-watchfollowing the live log to keep one current. Both are real and you can run them in two minutes.Between them: the device inventory with its evidence, findings with fixes, segmentation checking against a policy you declare, who signs in where, change detection that reaches out to you, and a rolling window that survives restarts.
Not yet built: a server, a web UI, and a remote agent. Those are described under Where this is going, in future tense, with no commands — because none of them exist yet and pretending otherwise would waste your afternoon.
Wanted: people to run it on a real network and tell us what it got wrong. Wrong identifications are worth more to us than right ones — see Contributing.
Illustration of the report, not a screenshot. Left: every device, what it is, and how confident we are — the ring around each icon fills to its confidence. Right: what's actually wrong, each with a fix and, where one exists, a command to copy. Top: the time range — it opens on the last 24 hours, and you can pick 3, 7, 14 or 30 days, or drag the chart for any window.
The whole report is one self-contained HTML file. No server, no internet, no dependencies — it opens from a USB stick on a machine that has never been online, which is often exactly where this work happens.
What this touches: one log file, read-only. Tarsier runs as an unprivileged user, is never in the traffic path, never transmits, and never modifies Suricata or its configuration. Stop it and nothing on your network notices. Removing it is deleting one binary and one directory.
What you need:
| Suricata | any version — 6.0 and up are tested in CI. ARP events need 8.0+, JA4 needs 7.0.7+. Older builds work, they just tell you less. |
| Event types | more than alert. See Configure Suricata — tarsier-scan reports what's missing, so you don't have to guess. |
| Access | read permission on the log directory, usually /var/log/suricata/. |
| Disk | none for the scanner. It reads and exits. |
| Not needed | root, a database, Docker, internet access, an agent on anything. |
If SELinux or AppArmor is enforcing, the reading process needs access to the Suricata log directory.
On a stock RHEL-family box, running as a user in the suricata group is enough.
Prebuilt binaries, no toolchain:
base=https://github.com/kapoordeepanshu/tarsier/releases/latest/download
for tool in tarsier-scan tarsier-watch tarsier-diff; do
curl -fLO "$base/${tool}-linux-amd64"
done
curl -fLO "$base/SHA256SUMS.txt"
sha256sum --ignore-missing -c SHA256SUMS.txt
for tool in tarsier-scan tarsier-watch tarsier-diff; do
sudo install -m 0755 "${tool}-linux-amd64" "/usr/local/bin/${tool}"
doneThree tools, and you can stop after the first if all you want is a report:
tarsier-scan reads a log and exits, tarsier-watch follows one and keeps a report current, and
tarsier-diff compares two snapshots.
Builds are published for linux/amd64, linux/arm64, linux/armv7, freebsd/amd64
(OPNsense and pfSense, where most of the world's dormant Suricata installs live), macOS on both
architectures, and Windows.
Air-gapped? Copy the one binary across. It has no dependencies and never calls out.
Building from source instead
Needs Go 1.22+. Nothing else — no dependencies, no database, no Docker.
git clone https://github.com/kapoordeepanshu/tarsier.git
cd tarsier
go build ./cmd/tarsier-scan ./cmd/tarsier-watch ./cmd/tarsier-diffEvery tool is published for every target, so building is for contributors rather than operators.
A week of realistic sample traffic ships with the repo, so you can see the output before touching anything of your own:
tarsier-scan -html survey.html testdata/demo-week.jsonwrote survey.html — 18 devices, 15 findings
Open survey.html in any browser. It opens on the last 24 hours, because that's the window
anyone actually checks — click All for the whole week: 18 devices and 15 things wrong with them,
each with a fix.
On Windows, run it from PowerShell as
.\tarsier-scan.exe— the leading.\is required, because Windows does not look in the current folder by default. Double-clicking will not work: it is a command-line tool and needs a file to read, so it would open and close instantly.
tarsier-scan /var/log/suricata/eve.json # print to the terminal
tarsier-scan -v eve.json # show the evidence for every identification
tarsier-scan -last 24h /var/log/suricata/ # every rotated log, last day
tarsier-scan -since 2026-07-28 -until 2026-07-30 'eve.json.*'
tarsier-scan -html survey.html /var/log/suricata/ # shareable report
tarsier-scan -json monday.json /var/log/suricata/ # machine-readable inventory
tarsier-scan -netbox ips.csv /var/log/suricata/ # NetBox ipam.ip_addresses importRotation is handled for you. Point it at the directory and it finds every rotated log itself,
reading .gz files directly. You never pick files by hand. Read order doesn't matter either —
where a device reports something that changes over time, like a firmware version, the newest
observation wins regardless of which file was parsed first.
Flags: -v, -min-confidence 0.5, -html, -json, -netbox, -last, -since, -until,
-zones. Run tarsier-scan -h for the full list.
No server and no database — two snapshots and a diff:
tarsier-scan -json monday.json /var/log/suricata/
tarsier-scan -json friday.json /var/log/suricata/
tarsier-diff monday.json friday.jsonIt reports devices that appeared, devices that went quiet, and devices that changed — a new listening port, a new user, a new VLAN, a firmware version that moved. Findings are matched on kind rather than wording, so rewording a message doesn't present the whole network as newly broken.
Exit status is 0 when nothing changed and 1 when something did, so it runs from cron and stays silent until it has something to say:
# Weekday mornings: snapshot, compare with yesterday, mail only on a change.
30 7 * * 1-5 tarsier-scan -json /var/lib/tarsier/today.json /var/log/suricata/ \
&& tarsier-diff /var/lib/tarsier/yesterday.json /var/lib/tarsier/today.json \
|| mail -s "network changed" you@example.comtarsier-scan reads a file and exits, which means somebody has to remember to run it.
tarsier-watch doesn't: it follows the live log and rewrites the report as events arrive.
tarsier-watch -html /var/www/survey.html /var/log/suricata/eve.json14:02:11 replayed 4 rotated logs — 1,284,902 events
14:02:11 following /var/log/suricata/eve.json — writing /var/www/survey.html every 1m0s
14:02:11 214 devices · 11 findings · 1,284,902 events
Rotation is handled, both kinds. logrotate's default renames the file and creates a new one; a lot of setups instead copy it and truncate it in place. Those need different handling, and assuming only the first is how a log reader silently loses a chunk of every rotation. The file we hold is drained to EOF before we let go of it, so the bytes written just before a rename are not lost. A partial last line is held until the writer finishes it, so the parser never sees half a record.
It holds a rolling window, thirty days by default (-retain). A device silent for longer than
that is forgotten — otherwise "what is on my network" quietly becomes "what has ever been on my
network", and those are different questions. Raw traffic is never copied or kept: eve.json stays a
short-lived buffer that Suricata and logrotate manage, and what survives here is the conclusions,
which are small.
It cannot affect Suricata. We open the log read-only, never write to the log directory, and never apply backpressure — if we fall behind we fall behind and say so. On Windows the handle is opened so that rotation still works, because a reader that blocks logrotate has broken the thing it was only supposed to watch.
Restarting keeps the window. Pass -state /var/lib/tarsier/state.json and the inventory is
restored on start, with following resuming at the exact byte it stopped at — so a restart neither
forgets the network nor counts the same events twice. Without it, the picture is rebuilt by replaying
the rotated logs still on disk, which works but caps your window at whatever logrotate kept.
The state file is conclusions, never traffic: one record per device plus a byte per device-hour. A
month is tens of megabytes, where a month of eve.json is hundreds of gigabytes. That difference is
why this needs no database.
# /etc/systemd/system/tarsier.service
[Unit]
Description=Tarsier network inventory
After=suricata.service
[Service]
ExecStart=/usr/local/bin/tarsier-watch -html /var/www/survey.html -state /var/lib/tarsier/state.json /var/log/suricata/eve.json
User=tarsier
Restart=on-failure
ProtectSystem=strict
ReadOnlyPaths=/var/log/suricata
ReadWritePaths=/var/www
StateDirectory=tarsier
NoNewPrivileges=yes
[Install]
WantedBy=multi-user.targettarsier-watch -h for the full set of flags. It writes through a temporary file and renames into
place, so a browser reloading the report never catches it half-written.
Write the report into a directory something already serves, and everyone has a URL:
tarsier-watch -html /var/www/html/survey.html /var/log/suricata/eve.jsonWhen the report is being served it notices that it has been rewritten and picks the new data up on its own. If you are in the middle of something — a filter typed, a time range held, a device expanded — it offers you a New data · reload button instead of yanking the page out from under you. Opened from a USB stick there is nothing to poll, so it does nothing at all and the file stays the single offline artefact it claims to be.
That is the whole "dashboard": a static file and any web server. No database, no login, no service of ours listening on a port. There is no web UI — this is a generated page, not an application, and you cannot configure anything through it.
The watcher already knows what changed. -on-change runs a command when something does — hourly by
default, and silent when nothing did:
tarsier-watch -html /var/www/survey.html \
-on-change 'mail -s "network changed" you@example.com' \
/var/log/suricata/eve.json14:58:02 changed: 1 new, 1 changed
3 Aug 2026 14:02 → 3 Aug 2026 14:58
17 devices → 18 devices
1 NEW
+ 10.0.20.9 plc-line-2
10.0.20.9 00:1d:9c:aa:31:07 Rockwell Automation ports 502
The report arrives on the command's stdin, and the counts arrive in its environment —
TARSIER_NEW, TARSIER_CHANGED, TARSIER_GONE, TARSIER_NEW_FINDINGS, TARSIER_TOTAL,
TARSIER_SOURCE — so a script can decide whether to wake somebody without parsing anything:
-on-change 'if [ "$TARSIER_NEW_FINDINGS" -gt 0 ]; then page-oncall; else cat >> /var/log/tarsier-changes.txt; fi'-changes FILE appends one JSON object per report, which is the shape anything that tails a file
already expects. Every list is present even when empty, so jq '.appeared | length' works on a quiet
night instead of erroring on null.
Nothing here speaks SMTP, Slack or webhooks on your behalf. Holding credentials for a network we are only meant to be watching is not a trade worth making, and your site already has a way to send a message. Silence when nothing changed is the point: a notification that arrives every hour regardless teaches people to filter it, and then the one that mattered gets filtered too.
One honest limit. A device is only reported as no longer seen once retention forgets it, which at the default is thirty days. Devices go quiet for a night constantly, and reporting that hourly would be noise wearing the costume of signal.
Every framework asks for network segmentation and almost nobody verifies it, because verifying it has meant either trusting the firewall config or running a scan you are not allowed to run. Describe the network you meant to build, and Tarsier reports where the traffic disagrees:
zone office 10.0.1.0/24 10.0.2.0/24
zone cameras 10.0.7.0/24
zone card 10.0.5.0/24
zone ot 10.0.20.0/24
allow office -> servers
tarsier-scan -zones zones.conf /var/log/suricata/HIGH 10.0.1.21 Traffic crossed from office to cameras, which your policy does not allow
...this device is talking across that line anyway — first seen going to
10.0.7.31:554. Either the firewall rule is not doing what it looks like it
does, or there is a path around it.
→ Fix: check the firewall rule between office and cameras. If the crossing
is intended, add 'allow office -> cameras' so it stops being reported.
Deny-by-default between declared zones; traffic inside a zone is always fine; an address you never declared raises nothing at all — we don't know where you meant it to live, and guessing would bury the real findings under noise. A typo in a zone name refuses to load rather than silently never matching, because a policy that fails open reports a clean network for the one question you most wanted answered.
Zones are CIDR only. VLAN tags look tempting, but a sensor watching a routed link sees one tag for the whole frame and cannot tell the two endpoints apart — a policy that appeared to check VLANs while silently checking nothing would be worse than not offering it.
A commented starting point is at docs/zones.example.conf. Works with
tarsier-watch -zones too, so a crossing that starts today reaches you through the same change
report as everything else.
The inventory answers "what is on this network". The identity graph answers "who", which is the question that follows about four seconds later — and it needs no new collection, because Kerberos and SMB have been naming users on the wire the whole time.
The report carries a Who signs in where panel, and -json carries the same thing:
"identities": [
{ "user": "jsmith", "devices": ["10.0.1.20", "10.0.1.55"] },
{ "user": "apatel", "devices": ["10.0.1.60"] }
]It recomputes with the time filter, so it always describes the window on screen.
No finding comes out of this, on purpose. The tempting one is "this account signed in from nine machines", and it would be wrong constantly: service accounts, shared kiosks, roaming profiles and admin tooling all look exactly like a stolen credential from out here. A number that fires on ordinary Tuesdays gets ignored, and then it is worth less than nothing. What you want is to look, recognise your own network, and notice the one line that surprises you.
Most installs log alerts only. Tarsier needs the metadata. One file, one restart, fully reversible —
in suricata.yaml:
app-layer:
protocols:
tls:
ja3-fingerprints: yes # TLS fingerprinting for device identification
outputs:
- eve-log:
enabled: yes
types:
- alert
- flow # which device serves which port
- dns # friendly device names
- http # operating systems, browsers, embedded devices
- tls: {extended: yes} # certificates, fingerprints, shadow IT
- dhcp: {extended: yes} # names, MACs, vendor — the single best signal
- arp # every device on the segment, Suricata 8.0+
- smb # Windows hostnames and usernames
- krb5 # usernames and AD realm
- ssh
- snmp
- anomalytarsier-scan reports which of these are missing every time you run it, so you never have to guess
what you forgot.
No Suricata at all? The sensor image contains it, pre-configured for exactly this:
cd deploy/sensor && docker compose up -dIt auto-detects the capture interface, enables promiscuous mode, disables NIC offloading (which
corrupts protocol parsing), validates the config with suricata -T before starting, and drops every
Linux capability except the two it needs. Hardware: a spare VM, an old desktop, or a €150 Intel N100
mini-PC for a 1 Gbps network.
The image installs Suricata from OISF's own stable repository rather than the distribution's, so you get a current release — 8.0.6 at the time of writing. Distribution packages lag badly: Debian bookworm ships 6.0, which has no ARP events and no JA4. Once built, the image is pinned and nothing upgrades itself behind your back. If you run your own Suricata, we never touch it.
Worth knowing before you deploy, not after.
It sees: every device that speaks, including the ones you can't install software on — printers, cameras, badge readers, PLCs, the contractor's laptop. Names, hardware addresses, vendors, operating systems, usernames, certificates, served ports, and what talks to the outside world.
It cannot see three things, and no passive tool can:
TLS 1.3 hides certificates. In TLS 1.2 the server's certificate crossed the wire in clear text. TLS 1.3 encrypts it. Verified against real Suricata 8 output: of seven TLS 1.3 connections, zero exposed a certificate. So certificate findings — expiring, expired, self-signed — only fire on TLS 1.2 and below. In practice that's still where they matter most: internal NAS boxes, printers, cameras and management interfaces are exactly the things running older TLS and exactly the certificates nobody tracks. But we won't see your TLS 1.3 web server's certificate, and any tool claiming otherwise without a proxy is misleading you.
Only what crosses the sensor. Two devices talking to each other on the same switch, in traffic that never reaches your mirror port, are invisible for flow purposes. Broadcast protocols — DHCP, ARP, mDNS, NBNS — reach the mirror regardless, so those devices are still discovered and identified; it's their conversations you'd miss. Placement matters, which is why we push the uplink between the access switch and the router.
Encrypted payloads stay encrypted. We read metadata — SNI, JA4, certificates where visible, DNS, flow. Never content. That's a deliberate limit, not a gap we intend to close.
Nobody knows what's on their network. Ask any IT manager how many devices they have and the answer will be wrong — usually by two or three times. The forgotten Windows 7 machine running a lathe. The camera with a default password. The contractor's laptop from four months ago that never left. You cannot protect, patch or decommission what you don't know exists, which is why every security framework on earth opens with "maintain an asset inventory" — CIS Control 1, NIS2, PCI-DSS, Essential Eight.
Three reasons it stays unsolved:
Scanning is banned where it matters most. You do not run Nmap against a hospital or a factory floor — active scans crash medical devices and PLCs. In OT, healthcare and utilities, passive discovery is the only lawful option.
Agents don't reach the things you're worried about. You can install software on a managed laptop. You cannot install it on a printer, a camera, a badge reader or a PLC — and those are exactly the devices nobody has inventoried.
The tools that do solve it cost a fortune. Armis, Axonius, runZero and Forescout all work, and all make you deploy their collectors and pay per asset. That's fine for an enterprise and impossible for a 60-person company.
Meanwhile the answer is already on your disk. Suricata writes it every second. Where it's kept at all, it's kept as searchable logs — retained, billed per gigabyte, and never turned into an inventory. Nobody joins the DHCP vendor class to the SNMP description to the served ports and says "that's a Zebra label printer on firmware 6.4."
| What everyone else does | What Tarsier does | |
|---|---|---|
| Discovery | Scan the network, or install agents | Listens to traffic that's already flowing. Nothing is scanned, probed or connected to. |
| Coverage | Managed devices only | Every device that speaks — printers, cameras, PLCs, the unmanaged laptop |
| Where the data comes from | A collector you buy and deploy | The Suricata you already run, or a €150 mini-PC |
| What it reads | Suricata's alert events |
Everything else — DHCP, ARP, TLS, Kerberos, SMB, SNMP, flow |
| Risk of deploying it | Inline device, agents, change windows | Zero. Never in the traffic path. If it dies, nothing notices. |
| When it's wrong | A label you can't question | Every identification shows its confidence and the evidence behind it |
The Suricata front-ends — EveBox,
SELKS, Security Onion
— are built on the alert stream. They're genuinely good. If you want an alert inbox, use EveBox.
If you want a full SOC distribution, use Security Onion. Use Tarsier if your question is "what is
on this network and what's wrong with it?"
We are not an IDS UI, a SIEM, a firewall, or an OT security platform.
By listening to what they already say. Every device announces more than people realise:
| What it says | Where | What it reveals |
|---|---|---|
| DHCP request | dhcp |
hostname, MAC, vendor class, OS |
| ARP | arp |
every device on the segment, including static IPs |
| Kerberos / SMB login | krb5, smb |
usernames, AD realm, Windows hostname |
| TLS handshake | tls |
certificates, expiry, JA3/JA4 client fingerprint |
| HTTP header | http |
operating system, browser, embedded device |
SNMP sysDescr |
snmp |
exact model and firmware |
| SSH banner | ssh |
distribution and version |
| Ports it answers on | flow |
its role — printer, database, PLC, domain controller |
| EtherNet/IP, Modbus, DNP3 | enip, modbus, dnp3 |
vendor, model, firmware, serial, station address |
Individually weak; combined, conclusive. Signals accumulate as noisy-OR, so two independent 0.5 signals give 0.75 — nothing ever reaches certainty from accumulation alone, because passive identification is inference, not proof. Every device shows its confidence and the exact evidence behind it, so you can check the working.
That last part isn't decoration. An identification you can't audit is one you won't trust, and the first thing a competent operator does with a tool like this is try to catch it out.
On JA4. Tarsier decodes the first ten characters of every JA4 fingerprint it sees, because they are a documented structure rather than a hash: TLS version offered, whether the client sent a server name, and the negotiated protocol. That works on every TLS client on the network with no database at all, and it's how a device that speaks nothing but encrypted traffic still gets identified. A client still offering TLS 1.0 becomes a finding in its own right — distinct from a server that accepts it, because the offer happens before anything is negotiated.
On OT. An EtherNet/IP List Identity response volunteers vendor, product name, firmware revision and serial number in one unauthenticated reply. That's four of the five fields IEC 62443-3-2 asks for, from a network where scanning is forbidden. Nothing on the IT side of a network is anywhere near this forthcoming.
Identifying "this is a Hikvision camera on firmware 5.x" needs a mapping from observable signals to device identity. The commercial platforms have one. It's proprietary, and it's most of what they're worth.
We're building the open one, and giving it away under CC0.
Everything lives as plain text under
internal/identify/data/, not Go source. That's deliberate: the person
who knows exactly how a Zebra label printer announces itself on DHCP is very often not a Go
programmer, and requiring a code change to record that fact is a guaranteed way never to hear from
them. Editing a .tsv and opening a pull request is the whole contribution process.
| File | What it holds | Size |
|---|---|---|
oui.tsv |
MAC prefix → vendor, from the public IEEE MA-L/MA-M/MA-S registries | 52,843 |
oui_override.tsv |
Curated prefixes IEEE cannot express — QEMU, VirtualBox, Docker | hand-maintained |
fingerprints.tsv |
DHCP vendor class, User-Agent, SSH and service banners, hostnames | hand-maintained |
ports.tsv |
Listening port → role, including the ICS protocols | hand-maintained |
ja4.tsv |
JA4 TLS fingerprint → device | empty, by design — see below |
Regenerate the IEEE table with go run ./tools/genoui -fetch.
Provenance rule, and it is not optional. Entries must come from your own observations, vendor documentation, or other public-domain sources. Do not copy rows out of Fingerbank: their data is ODbL, which is share-alike, and anything derived from it must also be ODbL — which would silently destroy the CC0 licence this database carries.
ja4.tsv is empty because a fingerprint cannot be derived from a specification; each row has to come
from someone observing a device they can positively identify. A wrong row there is worse than a
missing one. Only JA4 itself is used — it is BSD-3-Clause. The JA4+ family (JA4S, JA4H, JA4X,
JA4SSH) is under the FoxIO License 1.1 and is deliberately not implemented.
No dates. A roadmap with dates on it is a promise, and missing one costs more trust than making it ever bought. Nothing below exists yet — there are no commands here because there is nothing to run.
A remote agent and a server, so one place can hold the history of several sensors. This is last on purpose and may never be needed: everything above works on the sensor itself, and adding a server turns a five-minute deployment into a change-control project. It gets built when someone running this on a real network says they need it, not before.
A real web interface, if the served report stops being enough. Today's report is a generated page and deliberately not an application — see A shared dashboard.
Deliberately not doing yet — multi-tenancy, SSO, compliance packs. They matter to some people, but not before the basics are proven on real networks.
Tarsier holds a complete map of your network, and we treat a compromise of it as catastrophic for you. The scanner is self-hosted, reads one file, and talks to nothing. There is no cloud service, no account, no phone-home and no telemetry. The HTML report is a single offline file.
For what's coming: per-sensor mTLS with single-use enrolment tokens, no default credentials, audit logging, signed releases with SBOM, and a published disclosure policy before v1.0. Any future LLM feature will be opt-in, bring-your-own-key, local-model capable, and will redact internal IPs and hostnames before sending anything.
Reporting a vulnerability: see SECURITY.md.
Will this fill my disk?
The scanner writes nothing but the report you asked for. It reads and exits.
If you use the Tarsier sensor, eve.json is a buffer, not an archive: Suricata rotates it
hourly and a guard loop enforces a hard ceiling — default 2 GB, set with TARSIER_MAX_LOG_MB. When
it's hit, the oldest rotated files are deleted, never the file being written. Deleting the oldest
data is the correct failure mode: recent events matter more, and the alternative is a full disk that
stops capture entirely.
If you run your own Suricata, your logrotate config stays yours. We never rotate, truncate or delete your logs.
Suricata releases often. Will an upgrade break this?
Frequent releases, but rarely breaking ones — Suricata ships a major roughly annually and the rest are bugfixes that don't touch the EVE schema. So you're facing about one compatibility event a year.
Five things handle it:
- Nothing parses strictly. Records are read by path, not unmarshalled into fixed structs. A new field in a future release is a no-op, not an error.
- The original line is always kept. When a field turns out to matter later, it's backfilled across history rather than lost.
- Fields that moved are looked up under every known spelling.
- Feature detection, not version checks. Distributions backport, so the presence of a field is the only trustworthy signal.
- CI runs real Suricata 6.0 / 7.0 / 8.0 /
mastercontainers against a fixed pcap on every commit. The nightlymasterrun means a breaking upstream change turns the build red weeks before it reaches anyone.
How does a Docker container see my whole network?
Three things, all in the shipped compose file:
network_mode: host — the container uses the host's real interfaces rather than Docker's private
bridge. Without this it would only ever see Docker's own traffic.
cap_add: NET_ADMIN, NET_RAW — permission to put the interface into promiscuous mode and read
raw packets. Every other Linux capability is dropped: a box holding a map of your network should
hold no privilege it doesn't use.
A mirror (SPAN) port on your switch — the part that isn't Docker. Normally a switch only sends a machine traffic addressed to it. You configure the switch to copy traffic from other ports to the port your sensor sits on. That's a five-minute change in the switch's web UI, and it can't break anything.
No mirror port available? Run the sensor as a VM with the virtual switch in promiscuous mode — no hardware needed at all.
Do devices connect to it? Does anything get installed on them?
No, and no. Nothing on your network knows Tarsier exists.
Nothing is installed on any laptop, server, printer or PLC. No credentials, no agents, no scanning. You tell your switch to send a copy of traffic to one spare port, and the sensor listens on it.
your devices ──► [ switch ] ──copy──► [ sensor ] listens only
│
▼
the internet
The sensor cannot transmit onto the monitored network. If it crashes, nothing notices — there's no failure domain, no maintenance window and no change-control battle. It's also why this is usable in hospitals and factories, where active scanning is banned because it crashes medical devices and PLCs.
Is this a firewall? Does it block anything?
No. Tarsier never sits in the traffic path and blocks nothing. If you have no firewall, you still need one.
What it gives you is the thing you almost certainly don't have: knowing what's on your network and being told when something changes. It can also generate blocklists for the router you already own — detect here, block there — without ever becoming a device that can break your network.
Will it slow my network down?
It cannot. It isn't in the path — it receives a copy of traffic and can't transmit. Even a completely saturated sensor has no effect on the network it's watching.
If the sensor can't keep up it drops packets and tells you so, from Suricata's own counters. A partially-blind sensor is more dangerous than an offline one, so that's surfaced rather than hidden.
Does my data leave my network?
No. Tarsier is self-hosted. There is no cloud service, no account, no phone-home and no telemetry you didn't switch on. The HTML report is a single offline file.
We're looking for people to run this on a real network and say what's wrong with it — anyone running Suricata, anyone who manages networks for other people, anyone who has ever tried to answer "what's actually on this network?"
Most useful right now:
- Devices we identify wrongly. Those are worth more to us than the ones we get right, and there is an issue template for exactly this.
eve.jsonsamples withflow,dns,tls,dhcpenabled, tagged with your Suricata version.- Device fingerprints from your network — one
.tsvline, public domain, helps everyone. - What you tried to build around Suricata yourself, and what it cost you.
See CONTRIBUTING.md.
Tarsier is free. All of it.
Not a trial, not a limited tier, not free-until-we-change-our-minds. Unlimited devices, unlimited sensors, every feature, no account required. Self-hosted, so your network data never leaves your building.
It's free because it's built on Suricata, which is free, and because the thing it needs most is for people to use it and contribute device fingerprints back.
If you want something we haven't built — a custom integration, a report shaped for your regulator, help deploying it across a large or unusual estate — that's paid work, quoted per engagement. Ask.
| Component | Licence |
|---|---|
| Scanner and server | AGPL-3.0 — free to self-host and modify |
| Agent and sensor image | Apache-2.0 — install it anywhere, embed it in anything |
| Device fingerprint database | CC0 — public domain, no strings, use it in your own tools |
Built on Suricata by the OISF. Tarsier is an independent project — not affiliated with, sponsored by, or endorsed by OISF — and simply reads the output Suricata already produces. Suricata is a registered trademark of the Open Information Security Foundation. The sensor image installs Suricata (GPL-2.0) from OISF's repository at build time; the two run as separate programs and no Suricata code is included in this repository. Device vendor and product names are used only to identify equipment observed on a network.
