Dalton: running pcaps against Snort and Suricata to test detection rules
Suricata, Snort and Zeek IDS rule and pcap testing system
At a glance
- What is it?
- Dalton is a Python system for replaying packet captures against an IDS sensor to check rulesets, ad hoc signatures and engine configuration changes, with a controller and agent split, a Redis job queue and a browser interface. It also bundles a Flowsynth web UI for generating the test pcaps in the first place.
- Who is it for?
- Adopt Dalton if you maintain IDS rules and want to see whether a signature or a ruleset change actually fires on traffic you already have samples of, since it turns rule review into a repeatable job rather than a manual run. Do not adopt it to monitor live traffic, because it is a testing harness that replays captures rather than a sensor.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 10 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What Dalton is for: rule development, not detection in production
Dalton is described as a system that allows a user to quickly and easily run network packet captures against an intrusion detection system sensor of his choice, such as Snort or Suricata, using defined rulesets and/or bespoke rules.
The interesting thing is the list of use cases, because it shows this is a development and testing tool rather than a sensor.
Testing Rulesets and Ruleset Coverage means running user-provided pcaps through an IDS engine loaded with a particular ruleset. Troubleshooting and Developing Signatures means testing user-provided pcaps against user-provided ad hoc IDS rules to see the alerts and to test for rule syntax errors. Testing Variable Changes means modifying the ruleset variables the engine uses for a submitted job, to determine the impact a variable change has on a specific detection. Testing Configuration Changes means including customised engine configuration files with a job, to see the impact of an engine configuration change on a specific detection. And Testing specific IDS engine behavior covers applying all of the above to particular sensors, because the architecture is designed to accommodate sundry sensor engines and engine versions.
That last point is the design constraint that shapes everything else. Rulesets are not portable between engines. A Suricata rule and a Snort rule differ in syntax and in what fields exist, and a rule that works on one version may not parse on another. A tool that wants to test rulesets across engines and versions has to keep the engine specific configuration alongside the rule content, and that means the job carries more than a pcap.
The sixth use case is the one that is arguably the most useful and the least obvious: crafting custom packet captures. As part of the web interface, Dalton has a module that provides a wizard-like web interface for Flowsynth, which allows for quick and easy network flow definition and pcap creation for popular protocols and traffic patterns.
So the loop it closes is the one that matters in signature development. You need a pcap that exercises the rule you just wrote. Generating one by hand with a packet capture tool is slow, and finding one on the internet that matches your case is luck. Flowsynth defines network flows declaratively and compiles them to pcaps, and Dalton feeds the result straight into the sensor.
The primary language is Python, the licence is Apache-2.0, the default branch is master, and the recent releases are v4.0.0 from 2026-02-27, v3.6.0 from 2026-02-17 and v3.5.0 from 2025-09-18. The last push was on 2026-10-13.
Controller and agents, and how a job moves between them
The Design section describes an architecture that splits into two halves.
Dalton consists of a controller (dalton.py) and agents (dalton-agent.py). The controller provides a web interface as well as an HTTP API for agent communication and programmatic job results retrieval. From a web interface, a user submits a job to be run on a particular agent or agent platform.
What a job contains is where the design pays off.
A Dalton job consists of one or more pcaps, a pre-defined ruleset and/or custom rules, agent engine configuration options, for example configuration to apply to Suricata when running a job, and a manifest file specifying other options for the job, for example return rule performance logs.
So the job is a self-contained bundle. It carries the traffic, the rules, the engine configuration and a manifest that says what to return. That is what makes the variable-change and configuration-change use cases possible: because the configuration is part of the job rather than part of the sensor, two jobs differing only in a configuration variable are directly comparable.
The agent side runs on the IDS sensor and provides an interface between the controller and the IDS engine. Dalton agents grab pending jobs from the Dalton controller, run them locally, and report the results back, and those results are then displayed in the web GUI. Jobs are submitted to specific sensor engines and versions, with 4.0.0 given as the example version.
The pull model matters for deployment. Agents fetch pending jobs rather than the controller pushing to them, so a sensor only needs to be able to reach the controller, and the controller does not need inbound connectivity to every sensor. That is the difference between a lab where everything is on one host and a spread of sensors across a network.
On the controller side, Redis is used to manage the job queue, store the results, and maintain a list of active Dalton agents. The agent list being in Redis is what lets the web interface show which sensors are currently reachable, and it means an agent that drops off the list stops being offered jobs.
The controller and the webapp are written in Python and use Flask and Jinja2, and the pyproject.toml pins the versions: Jinja2 3.1.6, Flask 3.1.3, redis 5.2.0 and Werkzeug 3.1.6, with ruamel.yaml under 0.18.0 and idstools 0.6.5.
Those pins are strict, which for a security tool is the right default. The dependency set also includes flowsynth at 1.4.1 or newer, which is the pcap generator the web UI drives.
Running it: Docker Compose and a start script
The quickest way up is the Docker route, and the README gives two equivalent commands.
./start-dalton.shOr, doing the same thing directly.
docker compose build && docker compose up -dThen you navigate to http://<docker-host>/dalton/.
The requirements are Docker, Docker Compose V2, and an internet connection to build. The README notes that Compose Version 2 should be used, and the compose file confirms it by relying on the v2 syntax with the top-level services key.
The compose file shows the three-part topology. The controller service builds from Dockerfile-dalton, depends on redis, and mounts three host directories into the container: ./app, ./rulesets and ./engine-configs. That last mount is the interesting one, because it means the rulesets and the engine configuration files are live on the host and editable without rebuilding the image. The nginx service builds from Dockerfile-nginx and is the only one publishing ports, the external HTTP listen port and an optional SSL listener that is commented out by default.
The port configuration is deliberately split, and the comments are emphatic about where to change it. The nginx service publishes ${DALTON_EXTERNAL_PORT}:80, and the comment says to set DALTON_EXTERNAL_PORT in the .env file and not here, with a default value of 80. The SSL listener follows the same pattern with DALTON_EXTERNAL_PORT_SSL defaulting to 443. The HTTP listen port for the controller itself is changed by editing the same DALTON_EXTERNAL_PORT value in the .env file in the root of the repository.
Application configuration is split the same way. Configuration options for the Dalton Controller are found in dalton.conf, and configuration options for Dalton Agents are found in dalton-agent/dalton-agent.conf, with the inline comments in those files giving more detail.
The agent containers are added to the same compose file, and the comment in the compose file explains how: to add a new, different or another agent for a particular Suricata or Snort version, copy one of the existing specifications and change the version number as necessary.
That is a very cheap way to add engine coverage, and it tells you something about the architecture's assumption: that a sensor is a container built from a version-specific specification, so supporting a new engine version is a matter of adding another container rather than extending the agent's configuration.
The Flowsynth, Zeek and CyberChef modules
Dalton embeds a surprising amount of adjacent tooling, and the README's contents list is the best map of it.
The Flowsynth WebUI section covers a controller module that provides a user interface to assist with rapid Flowsynth language prototyping and development of network flow definitions that are then compiled into network pcaps by the Flowsynth script. In the README's own words, it is basically a GUI to facilitate input and output to Flowsynth, and there is the option to easily send Flowsynth WebUI generated pcaps to Dalton for testing.
That last capability is the join. A user can define a flow in the web UI, compile it to a pcap, and submit it to a sensor in the same session, which removes the step of downloading a file and uploading it by hand.
The Zeek and CyberChef entries are separate integrations. Zeek is the network security monitor that can run alongside the IDS sensors, and CyberChef is the data manipulation toolkit for working with the packet and payload data that comes out of a capture. Neither is described in detail in the README, but their presence in the contents list alongside the Dalton core sections tells you the project is aiming at a complete workflow for someone doing rule development rather than a narrow rule runner.
The other sections of the README describe the operational surface in more detail. Suricata Socket Control Mode covers running Suricata in its unix socket control mode so that rules can be reloaded and results read without restarting the engine. Job Settings and Config Files cover the per-job configuration. Job Results and Job Queue cover what comes back and how work is scheduled. Sensors covers adding sensors. Adding Rulesets and Adding Sensor Configs cover the two configuration trees, and the repository has matching top-level directories named rulesets/ and engine-configs/.
The Dalton API section lists a Job API and a Controller API, so the same operations the web interface exposes are available programmatically.
There is also a Teapot Jobs section, which is a piece of naming humour for a deliberately trivial job type, presumably for testing the pipeline end to end without needing a real capture or a real ruleset.
Where Dalton is the wrong tool
There are three limits, and the first is the most important thing to understand before evaluating it.
The first is that Dalton is not a sensor and cannot be mistaken for one. It replays captures you already have against an engine you already run, and the result is a set of alerts that tells you whether a rule fired. It does not see live traffic, it does not generate alerts for traffic you did not capture, and it does not belong in a detection pipeline. Using it as though it were a sensor would be a category error.
The second is the operational surface. Even the simplest deployment is three containers plus one container per agent, with Redis holding the job queue and the results, and nginx in front for the web interface and the optional TLS listener. That is a reasonable amount of machinery for a lab, and it is a meaningful amount for a team whose only need is to check one rule against one pcap. At that scale, running Suricata directly on the capture and reading its alert log answers the question with less to operate.
There is a related point about where the pcaps come from. Dalton does not capture traffic itself, so the hard part of the work, getting representative and appropriately sensitive traffic, is still yours. The Flowsynth module helps by letting you define flows declaratively, which is valuable when you need a specific pattern such as a particular exploit sequence or a protocol handshake that behaves in a specific way. It does not produce realistic traffic for free, and a synthetic capture that exercises a rule is not the same as one that reveals a false positive against real background traffic.
The third is the maturity of the packaging. The project is on version 4.x with a changelog in reStructuredText, the pyproject.toml classifies it as Development Status :: 5 - Production/Stable and as Private :: Do Not Upload, which is an odd pairing and suggests an internal tool published for completeness rather than a public package. The dependency versions are pinned exactly, including Werkzeug and itsdangerous at exact releases, which is careful but also means you are carrying an exact-version Python environment and will need to revisit those pins on every upgrade.
The build tooling is also split across two version bump configurations. The Makefile has a bumpversion target using the root pyproject.toml and a separate bumpagent target using dalton-agent/.bumpversion.toml, so the controller and the agent have independent version streams. That is correct for a distributed system where a sensor might lag, and it also means there is no single version number to quote when you ask what is running.
The honest alternative for a rule author is to run the engine yourself against the capture. That is one command and one log file, and it is the fastest path for verifying that a rule fires. What Dalton adds is the parts you would otherwise build yourself: a job queue so that many rule and capture combinations can be run reproducibly, a way to vary engine configuration and ruleset variables per job, a way to target specific engine versions, a web interface so that people other than the rule author can submit and read results, and the Flowsynth UI for generating the traffic.
For a security team maintaining a ruleset across several engine versions, that combination is the value. For an individual analyst testing a single signature, the direct approach is faster, and Dalton is the heavier answer to a question that may not be yours yet.
Editorial conclusion
Adopt Dalton if you maintain IDS rules and want to see whether a signature or a ruleset change actually fires on traffic you already have samples of, since it turns rule review into a repeatable job rather than a manual run. Do not adopt it to monitor live traffic, because it is a testing harness that replays captures rather than a sensor. Before you deploy, read the sensors and rulesets sections, since the sensor set is defined in the compose file, and note the last push was on 2026-10-13 with v4.0.0 from 2026-02-27.
Frequently asked questions
What is Dalton and what does it do?
It is a system that lets you run network packet captures against an intrusion detection sensor of your choice, such as Snort or Suricata, using defined rulesets and/or bespoke rules. It covers testing ruleset coverage, developing and troubleshooting signatures, and evaluating the effect of ruleset variable or engine configuration changes on a specific detection.
What is the architecture of the Dalton controller and agents?
Dalton consists of a controller, dalton.py, and agents, dalton-agent.py. The controller provides a web interface and an HTTP API, and agents run on the IDS sensors, grab pending jobs from the controller, run them locally and report results back. Redis on the controller manages the job queue, stores the results and maintains the list of active agents.
How do I install and run Dalton?
With Docker and Docker Compose V2, run ./start-dalton.sh from the root of the repository, or run docker compose build && docker compose up -d, then navigate to http://<docker-host>/dalton/. An internet connection is needed to build the images, and the external listen port is set with DALTON_EXTERNAL_PORT in the .env file.
What does a Dalton job contain?
One or more pcaps, a pre-defined ruleset and/or custom rules, agent engine configuration options such as configuration to apply to Suricata when running a job, and a manifest file specifying other options for the job, for example return rule performance logs.
Can Dalton generate its own test traffic?
Yes. The controller includes a Flowsynth WebUI module that provides a wizard-like interface for rapid Flowsynth language prototyping and development of network flow definitions that are then compiled into network pcaps, and the option to easily send the generated pcaps to Dalton for testing.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/secureworks-dalton)Was this useful?