Capture, inspect, and save network packets in pure Ruby.
Features · Installation · Quick start · Website · User Guide · Ruby API · Documentation · Development
Redhound combines tcpdump-style capture filters, protocol dissection, and pcap/pcapng files in a command-line tool and Ruby library. It runs on Linux and macOS using Ruby's standard libraries.
Note
Version 2 is a release candidate. Install it with --pre and see
release validation for the remaining GA acceptance checks.
| Capability | What you can do |
|---|---|
| Live capture | Capture on Linux and macOS with kernel timestamps, direction selection, capture filters, and drop statistics. |
| Capture files | Read and write pcap/pcapng, stream through stdin/stdout, and rotate files by size or time. |
| Protocol dissection | Inspect Ethernet, VLAN, IPv4/IPv6, TCP/UDP, DNS, DHCP, NTP, HTTP/1.x, TLS hellos, GRE, and VXLAN. |
| Packet output | Choose a one-line summary, tree, hex dump, JSON/NDJSON, or selected fields. |
| Stateful analysis | Reassemble IP/TCP data, follow TCP streams, and summarize conversations, endpoints, and traffic intervals. |
| Ruby library | Read captures, dissect bytes, access typed fields, and register custom dissectors. |
Install the v2 release candidate from RubyGems:
gem install redhound --pre
redhound --versionOr add it to your Gemfile:
gem 'redhound', '~> 2.0.0.rc2'Ruby 3.3 or newer is required. The CLI enables YJIT when available. Live capture requires root or capture permissions. File analysis runs as your regular user.
List the available capture interfaces:
redhound -DChoose an interface from that list and save 100 packets. This example uses
en0 on macOS; on Linux, use your device name or any for all interfaces.
Capture files are private; give your account ownership after capturing as root.
sudo redhound -i en0 -c 100 -w trace.pcapng
sudo chown "$(id -un)" trace.pcapngInspect the saved capture as a protocol tree:
redhound -r trace.pcapng -T treeThe default output is one line per packet. A TCP handshake looks like this:
07:13:20.000000 pcap IP 192.0.2.1.40000 > 192.0.2.2.9999: TCP [S], seq 4294967280, ack 0, win 64240, length 0
07:13:20.010000 pcap IP 192.0.2.2.9999 > 192.0.2.1.40000: TCP [.S], seq 5000, ack 4294967281, win 64240, length 0
07:13:20.020000 pcap IP 192.0.2.1.40000 > 192.0.2.2.9999: TCP [.], seq 4294967281, ack 5001, win 64240, length 0
| Task | Command |
|---|---|
| Show packet details | redhound -r trace.pcapng -V |
| Filter DNS traffic | redhound -r trace.pcapng 'udp port 53' |
| Export newline-delimited JSON | redhound -r trace.pcapng -T ndjson |
| Select packet fields | redhound -r trace.pcapng -T fields -e ip.src -e tcp.dstport |
| Summarize TCP conversations | redhound -r trace.pcapng --stats conv,tcp |
| Report one-second traffic intervals | redhound -r trace.pcapng --stats io,1 |
| Follow the first TCP stream | redhound -r trace.pcapng --follow tcp,ascii,0 |
Place options before the filter expression, and quote filters containing shell
operators. Addresses are numeric by default; -N enables name resolution.
-w alone saves packets without dissection or display. Add -T summary to
print packets while saving them.
Run redhound --help for all options, or see the
usage guide and tcpdump option mapping.
Use the same packet model from Ruby:
require 'redhound'
Redhound.open('trace.pcapng', filter: 'udp port 53') do |reader|
reader.each do |packet|
puts packet.summary
p packet['ip.src']
p packet.to_h
end
endDissect a frame already held in memory:
packet = Redhound.dissect(frame_bytes, linktype: :ethernet)
p packet['ip.src']
p packet.to_hSee the API and plugin guide for live capture, writers, filters, packet metadata, and custom Ruby dissectors.
| Platform | Live capture backend | Interface examples |
|---|---|---|
| Linux | TPACKET_V3 ring or AF_PACKET socket | eth0, lo, any |
| macOS | BPF devices | en0, lo0 |
On Linux, Ruby 4.0 uses the socket backend. Use Ruby 3.3/3.4 for ring capture. The platform guide covers automatic backend selection, VLAN metadata, and supported capture-filter syntax.
Visit the website and follow the User Guide for installation, your first capture, and common analysis tasks.
| Guide | Covers |
|---|---|
| User Guide | Getting started, common workflows, and troubleshooting |
| Usage | CLI options, tcpdump mapping, capture files, rotation, and privileges |
| Protocols | Supported protocols and fields |
| Capture filters | Filter syntax, examples, and cBPF inspection |
| Ruby API | Packets, readers, writers, analysis, and plugins |
| Migration | Moving from the 1.x API and CLI |
| Release validation | Completed checks and remaining GA acceptance gates |
| Benchmarks | Measured results and reproducible performance checks |
| Changelog | User-facing changes by release |
git clone https://github.com/ydah/redhound.git
cd redhound
bundle install
bundle exec rbs collection install --frozen
bundle exec rakeThe Rake task runs RSpec, generates RBS signatures, and checks types with Steep. Differential tests use tcpdump and tshark as development tools.
The website lives in docs/. The Pages workflow builds it with GitHub's Jekyll
action, checks internal links, and publishes main to GitHub Pages. Pull requests
build and check the site without publishing it.
Additional checks and fixture maintenance
bundle exec yard stats --list-undoc
FUZZ_ITERATIONS=1000000 bundle exec rspec spec/fuzz
sudo -E env "PATH=$PATH" REDHOUND_LIVE=1 bundle exec rspec --tag liveRegenerate protocol fixtures with:
ruby -Ilib spec/fixtures/generators/applications.rb
ruby -Ilib spec/fixtures/generators/network.rbUpdate output snapshots with UPDATE_GOLDEN=1 bundle exec rspec spec/golden,
then review the changes. See benchmark results for performance
checks.
Bug reports and pull requests are welcome. Contributors must follow the code of conduct.
Redhound is released under the MIT License.