A complete development environment for building Wireshark protocol dissectors and GUI plugins in Lua, with automated snapshot testing using TShark.
- π Protocol Dissector Development: Create custom protocol dissectors with full IDE support
- π‘ Type Hints: Full Wireshark Lua API type definitions for IntelliSense
- π§ͺ Snapshot Testing: Automated testing using TShark output comparison
- π Live Development: Watch mode that auto-runs tests as you code
- π¦ Automated Releases: GitHub Actions workflow for version management
-
Click "Use this template" on GitHub or fork this repository
-
Clone your new repository:
git clone https://github.com/your-username/your-plugin-name.git cd your-plugin-name
Install Node.js dependencies for the test infrastructure:
npm installPrerequisites:
- Node.js (v14 or higher)
- Wireshark/TShark installed and in PATH (or at
C:\Program Files\Wireshark\on Windows)
For IDE support with autocomplete and type checking:
- Install the Lua Lanugage Server (sumneko.lua) extension in VS Code
- The project includes Wireshark Lua API type definitions in
wireshark-lua-api/ - Start coding with full IntelliSense support!
Create a new file in the project root named after your protocol (e.g., xyz.lua if you are writing a dissector fot a protocol called "XYZ").
See myproto.lua for a complete example, as well as official Wireshark documentation at:
Important Naming Convention:
- Dissector filename:
myprotocol.lua(lowercase, no spaces) - Protocol name in Proto():
"myprotocol"(must match filename without.lua) - Test files prefix:
myprotocol-*.pcap(use the dissector filename as prefix)
Capture a set of sample packets for the protocol you are covering, and save them to test/samples, ideally 1 packet per file. This can be done from Wireshark using File / Export Specified Packets... / Selected.
Note: the filenames should follow the pattern of <protocol>-<scenario>.pcap. For example,
protocol myproto has an Acknowledge command, that is captured in a file named myproto-ack.pcap.
Use watch mode to see live dissector output while you develop:
npm run watch-sample myprotocol-packetname.pcapThis will:
- Run TShark with your dissector on the pcap file
- Display the parsed output
- Auto-reload whenever you save changes to any
.luafile
Tips for watch mode:
- Keep captures small (1-5 packets) for faster iteration
- Use descriptive filenames:
myprotocol-handshake.pcap,myprotocol-error-response.pcap - The script auto-detects the dissector from the filename prefix
When your dissector output looks correct, generate the expected output file:
npm run update-expected myprotocol-handshake.pcapThis creates tests/samples/myprotocol-test.expected containing the TShark output.
You can use globs:
npm run update-expected myprotocol-*.pcap # All myprotocol captures
npm run update-expected *.pcap # All capturesRun the full test suite to verify all snapshots match:
npm testThe test runner automatically:
- Finds all
.pcapfiles intests/samples/ - Matches them to
.expectedfiles - Extracts the protocol name from the filename (e.g.,
myprotocol-test.pcapβmyprotocol.lua) - Compares actual TShark output against expected output
Launch Wireshark with your dissectors pre-loaded:
npm run wiresharkThis automatically loads all .lua files from the project root.
Opening a specific capture:
npm run wireshark -- -r tests/samples/myprotocol-test.pcapLive capture:
npm run wireshark
# Then: Capture β Options β select interface and startWhat gets loaded:
- All
.luadissector files in the project root - Your dissectors are active immediately - no manual plugin installation needed
Wireshark Lua plugins aren't limited to protocol dissectors. You can also create GUI extensions, listeners, etc.
The template includes a GUI plugin example in mywindow.lua.
See Lua Support in Wireshark for full documentation.
| Component | Example | Rule |
|---|---|---|
| Dissector file | myprotocol.lua |
Lowercase, in project root |
| Protocol name | Proto("myprotocol", ...) |
Must match filename (without .lua) |
| Capture files | myprotocol-handshake.pcap |
Prefix must match dissector filename |
| Expected files | myprotocol-handshake.expected |
Auto-generated, same name as .pcap |
| Test detection | myprotocol-*.pcap β myprotocol.lua |
Automatically maps by prefix |
Why this matters:
- The test framework splits filenames on
-to find the dissector myprotocol-test.pcapβ looks formyprotocol.luafoobar-error.pcapβ looks forfoobar.lua
You can delete all examples included with this template by running
npm run delete-examplesThis will delete mywindow.lua, myproto.lua and tests/samples/myproto*.* files.
The included GitHub Actions workflow automatically creates releases when you push version tags.
-
Update your version (optional - workflow does this automatically):
-- In your dissector file local release = "1.2.3"
-
Create and push a git tag:
git tag v1.2.3 git push origin v1.2.3
-
Workflow automatically:
- Updates
local release = "1.2.3"in all.luafiles - Creates a GitHub release with tag
v1.2.3 - Attaches all
.luafiles as release assets - Generates release notes from commits
- Updates
Note: The workflow only runs for repositories created from this template, not the template itself (checked via repository name).
This template includes a complete real-world example - myproto.lua.
Test samples: See tests/samples/myproto-*.pcap for examples of test coverage.
This template was created as a byproduct of my mitka/wireshark-scte project that has a bit more complex dissector than the one included with the template.
βββ .github/
β βββ workflows/
β βββ release.yml # Automated release workflow
βββ tests/
β βββ samples/ # Packet captures and expected outputs
β β βββ myproto-test.pcap
β β βββ myproto-test.expected
β βββ helpers/ # Test infrastructure
β β βββ runTShark.js # TShark wrapper
β β βββ compare.js # Snapshot comparison
β βββ test_samples.spec.js # Main test runner
β βββ update_expected.js # Generates .expected files
β βββ watch_sample.js # Watch mode script
β βββ run_wireshark.js # Wireshark launcher
βββ wireshark-lua-api/ # Type definitions for IDE (not loaded at runtime)
βββ .luarc.json # Lua Language Server configuration
βββ myprotocol.lua # Your dissector(s) / plugins
βββ package.json # npm module manifest / scripts
| Command | Description |
|---|---|
npm test |
Run all snapshot tests |
npm run watch-sample <name> |
Watch mode for single capture |
npm run update-expected <glob> |
Generate/update .expected files |
npm run wireshark |
Launch Wireshark with all .lua files loaded |
npm run wireshark -- -r file.pcap |
Launch Wireshark with a specific capture |
npm run clean-myproto |
Delete example files (myproto.lua, mywindow.lua, samples) |
Official Documentation:
- Lua API Reference - Complete API documentation
- Lua Modules - GUI, Proto, Field modules
- Start small: Begin with a simple dissector for 1-2 fields
- Use watch mode: Iterate quickly with
npm run watch-sample - Keep captures minimal: 1-5 packets per test case
- Test edge cases: Create separate captures for errors, malformed packets, etc.
- Descriptive filenames:
protocol-scenario.pcap(e.g.,http-redirect.pcap) - One scenario per file: Don't mix multiple test cases
- Commit both files: Always commit
.pcapand.expectedtogether - Review diffs: Check
git diffon.expectedfiles when making changes
- Avoid repeated lookups: Cache field extractions
- Limit tree depth: Don't create unnecessary subtrees
- Use local variables: Minimize global access
- Profile with large captures: Test with realistic traffic volumes
Tests failing after editing dissector?
- Delete the corresponding
.expectedfile - Run
npm run update-expected <name>.pcapto regenerate expected output
Dissector not loading in Wireshark?
- Check for Lua syntax errors in the dissector file
tsharkand Wireshark will report Lua syntax / runtime errors as well- Ensure protocol name matches filename
TShark not found?
- Install Wireshark ant tshark and add to PATH. On a Mac, there is an additional
installation package in the
.dpkgfor this.
Test runner can't find .lua file?
- Ensure
.pcapfilename prefix matches.luafilename exactly
MIT License - see LICENSE file for details
Contributions welcome! Please open an issue or submit a pull request.
