stenographer - Stenographer packet capture daemon
stenographer [-config FILE] [-syslog] [-v INT]
Stenographer is a full-packet-capture utility for buffering
packets to disk for intrusion detection and incident response purposes. It
provides a high-performance implementation of NIC-to-disk packet writing,
handles deleting those files as disk fills up, and provides methods for
reading back specific sets of packets quickly and easily.
This is the main executable for Stenographer. It is recommended to
interact with it via the provided init scripts.
- -config
FILE
- File location to read configuration from (default
"/etc/stenographer/config")
- -syslog
- If true, log to syslog. Otherwise, log to stderr (default true)
- -v int
- log many verbose logs (default -1)
A single system group `stenographer`, and a system user
`stenographer` are used to run Stenographer.
The `stenographer` group is used to control access to
locally stored packet data. Users are added to this group to allow them to
query stenographer (via the `stenoread` command).
The `stenographer` user is used to run the
`stenographer` and `stenotype` binaries. We use the
`stenographer` user to protect the system from `stenographer`
and `stenotype`... this user has no special privileges except the ability to
read/write packet data and run the (setcap'd) stenotype binary. So if either
is compromised, the system as a whole won't be.
The `/etc/stenographer/config` file tells Stenographer what
packets to read, where to write them, how to serve them, etc. It also tells
the clients where the Stenographer server is running and how to query
it.
Here's an example config (note: it's JSON):
{
"Threads": [
{ "PacketsDirectory": "/disk1/stenopkt", "IndexDirectory": "/disk3/stenoidx/disk1"}
, { "PacketsDirectory": "/disk2/stenopkt", "IndexDirectory": "/disk3/stenoidx/disk2", "DiskFreePercentage": 25}
]
, "StenotypePath": "/usr/local/bin/stenotype"
, "Interface": "em1"
, "Port": 1234
, "Flags": []
, "CertPath": "/etc/stenographer/certs"
}
Let's look at each part of this in detail:
- * `StenotypePath`:
- Where `stenographer` can find the `stenotype` binary, which it runs
as a subprocess
- * `Interface`:
- Network interface to read packets from
- * `Port`:
- Port `stenographer` will bind to in order to serve `stenoread`
requests.
- * `CertPath`:
- Where `stenographer` will write certificates for client
verification, and where the clients will read certificates when issuing
queries.
The `Threads` section is one of the most important. It tells
`stenotype`, the packet capturing subprocess, a number of things: how many
threads to read packets with, where to store those packets, and how to clean
them up.
For each packet reading thread you'd like to run (IE: for each
core you'd like to use), you must specify:
- * `PacketsDirectory`:
- Where to write packet files. We recommend mounting a separate disk for
each thread... we've found that at least for spinning disks, a single core
can easily fill a disk's entire write throughput with room to spare.
- * `IndexDirectory`:
- Where to write index files. We've had good luck with using a single
separate disk to write all index files, writing each thread's index to a
separate subdirectory. This directory gets FAR fewer writes, and they're
FAR smaller. We've found that even with up to 8 threads, the all 8 index
directories take up less than 20% of the space of a single thread's
packets.
- * `DiskFreePercentage`:
- The amount of space to keep free in the packets directory.
`stenographer` will delete files in this thread's packets directory
when free disk space decreases below this percentage. Note that we don't
currently do any automated cleanup of the index directory. When a packet
file is cleaned up, its index file is cleaned up, and because index files
take so little space, we haven't ever needed to clean them up directly.
Note that `DiskFreePercentage` is optional, it defaults to 10%.
- * `MaxDirectoryFiles`:
- The maximum number of packet/index files to create before cleaning old
ones up. Defaults to 30K files, to avoid issues with ext3's 32K
file-per-directory maximums. For ext4 you should be able to go higher
without issue. Note that since we create at least one file every minute,
this defaults to a maximum limit of 8 1/3 days before we drop old
packets.
The `Flags` section allows you to specify flags to pass to the
`stenotype` binary. Here are some flags which may prove particularly
useful:
- * `-v`:
- Add verbosity to logging. Logs by default are written to syslog, and are
relatively quiet. Adding one `-v` will have stenotype write
per-thread capture statistics every minute or 100MB of packets, whichever
comes first. Adding more `-v` flags will provide you with reams of
debugging information.
- * `--blocks=NUM`:
- The number of 1MB packet blocks used by AF_PACKET to store packets in
memory, *per thread*. This flag basically allows you to control how much
RAM the `stenotype` binary uses: `blocks * threads * 1MB`. More blocks
will allow a thread to handle traffic spikes: if you have 2048 blocks (the
default), then a thread can hold 2GB of traffic in memory while waiting
for it to hit disk. If you have slow links and you want to decrease memory
usage, you can probably decrease this a LOT. :)
- * `--fanout_type=NUM`:
- This sets the AF_PACKET fanout type to the passed-in value. See AF_PACKET
documentation for details on options here. The default should probably be
fine.
- * `--filter=HEX`:
- Allows users to specify a BPF filter for packet capture, only packets
which match this filter will be written by `stenotype`. This is NOT a
human-readable BPF filter, it's a hex-encoded compiled filter. Use the
supplied `compile_bpf.sh` script to generate this encoding from a
human-readable filter.
- * `--seccomp=none|trace|kill`:
- We use seccomp to sandbox stenotype, but we've found that this can be
fragile as we switch between different machine configurations. Some VMs
appear to freeze while trying to set up seccomp sandboxes: for those
environments, you can pass `--seccomp=none` in (note that this will
turn off some sandboxing). If you're trying to debug a `stenotype` failure
you think is caused by overzealous sandboxing, you can pass in
`--seccomp=trace`, then run stenotype with `strace` to figure out
why things are misbehaving.
- * `--preallocate_file_mb=NUM`:
- Certain file systems handle writes faster if the file has already been
allocated to its eventual size. If you set this flag to `4096`, then
stenotype will preallocate each new packet file to this size while opening
it. The file will be truncated to its actual size when closed. This should
not be necessary unless you're really trying to eak out some extra speed
on a file system that supports extents.
If you are using xfs on 4.1+ kernel, setting
"--preallocate_file_mb" becomes crucial to performance.
This is in that when appending to the end of file (i.e. EOF updates), kernel
will serialize all operations. Please refer to upstream commit (b9d5984 xfs:
DIO write completion size updates race).