Open-source project
netsampler/goflow2 avatar
netsampler/goflow2

GoFlow2: collecting NetFlow, IPFIX and sFlow in Go

High performance sFlow/IPFIX/NetFlow Collector

822 stars185 forksGoBSD-3-Clause

At a glance

What is it?
GoFlow2 is a Go collector that decodes NetFlow v5, IPFIX/NetFlow v9 and sFlow v5 samples and hands them onward as JSON or protobuf. It is deliberately the first stage of a pipeline, not a monitoring product.
Who is it for?
GoFlow2 fits teams that already run Kafka or a log pipeline and want one consistent record shape across mixed flow exporters, and it fits anyone who needs raw samples to aggregate themselves. It does not fit a team expecting a turnkey dashboard, and it is the wrong choice when every device already speaks one protocol you can read directly.
Can I use it commercially?
Yes. BSD-3-Clause 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 4 days ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A collector that stops at the entrance of the pipeline

GoFlow2 exists for a narrow reason: it gathers network samples from several flow protocols, puts them into a common format, and stops there. The documentation is explicit that the software is the entry point of a pipeline, and that storage, transport, enrichment, graphing and alerting are not provided. That boundary is the design, not a gap left for later.

The listed use cases point the same way. You want it if you receive a decent amount of network samples and need horizontal scalability, if you have protocol diversity and need a consistent format, or if you require raw samples and build aggregation and custom enrichment. In other words, the intended users are platform engineers who already own the storage and the alerting side and want a decoding and normalisation layer they can scale out and shard.

The repository is written in Go and carries the BSD-3-Clause licence. Its module path is github.com/netsampler/goflow2/v3, and the go.mod file targets go 1.26.0 with toolchain go1.26.9. The project grew out of a fork of the earlier Cloudflare goflow code, and it now lives under the netsampler organization so it can be maintained separately.

The decoder, producer, format and transport chain

The architecture is a chain of replaceable pieces, and each piece does one job.

A decoder converts the payload of a flow packet into a structure. It exists so that load balancing and optimizations are possible, which is the reason the decoding libraries themselves were changed only minimally in the fork. A producer then converts those samples into another format; out of the box the repository ships a protobuf producer based on pb/flow.pb and a raw producer. In the protobuf path, the records inside a single flow packet are extracted into their own protobuf message, and custom mapping lets you add fields without rebuilding the proto.

The format directory holds utilities that call specific functions to marshal a message as JSON or as text. The transport layer provides the ways of processing the message: sending it via Kafka, writing it to a file, or printing to stdout. GoFlow2 itself is a wrapper that chains these functions together, so the pieces can be swapped without touching the whole application.

Application wiring sits under pkg/goflow2, covering config, logging, builder, collector, httpserver and app. The intent is reuse across binaries, and cmd holds more than one: cmd/goflow2 and cmd/enricher are both named in the documentation. Prometheus metrics are exposed for monitoring, so the collector reports on itself while it feeds something else.

sFlow ships headers while NetFlow waits for its templates

The three protocols carry different information, and the difference shows up in how quickly you get usable output.

sFlow is stateless. It sends the full header of a packet together with router information, including interfaces and destination AS. NetFlow and IPFIX instead rely on templates that describe which fields are present, for example a source IPv6 address, so a collector cannot interpret a record until the matching template has arrived.

The sampling rate in NetFlow and IPFIX arrives through Option Data Sets. Because those templates are not known in advance, the documentation notes it can take a few minutes for packets to be decoded until all templates have been received, both Option Template and Data Template. Sampling rates are cached in the FlowStore, with optional TTL and JSON persistence controls available through the sampling.* flags. If you cache rates without persistence, a restart can put you back in the waiting window.

Both protocol families bundle multiple samples in a single packet, a Data Set in NetFlow and IPFIX, a Flow Sample in sFlow. The practical payoff of a common abstract format such as protobuf is that you can sum across protocols, per ASN or per port, rather than being stuck with per (ASN, router) and (port, router) breakdowns that differ per exporter.

Building and driving the reflow binary

Reflow is the experimental binary in this repository, built for collecting, converting and aggregating traffic. It is the quickest way to see samples in a uniform shape without standing up the full collector.

Build a portable binary and collect IPFIX as JSON:

bash
CGO_ENABLED=0 go build -o reflow ./cmd/reflow
./reflow -input udp::4739:flow -output json:stdout

The flow input detects IPFIX, NetFlow v5/v9 and sFlow v5. Repeat the -input flag to listen on several sockets. With no flags at all, reflow listens on UDP ports 2055 and 6343 and writes JSON to stdout.

You can then feed it a sample by hand, which is the fastest way to confirm the output shape before any router is involved:

bash
printf '%s\n' '{"src_addr":"192.0.2.1","dst_addr":"198.51.100.2","proto":17,"src_port":12345,"dst_port":53,"bytes":128,"packets":1}' |
  ./reflow -input stream:-:json -output ipfix:udp:127.0.0.1:4739

JSON streams hold one object per line, and the - marker reads standard input. The JSON input accepts both reflow JSON output and plain field objects. Use -output json:stdout to inspect events, or -output protobuf:file:flows.pb to save protobuf. To see every supported input, output and aggregation setting, run reflow with -list-options. To change the pipeline itself, add -genconf > reflow.yaml to a command, edit the generated YAML, then run the binary against that file:

bash
./reflow -config reflow.yaml

An interface options example is included at cmd/reflow/reflow-json-interface-options-to-ipfix.yaml, and it shows custom aggregation fields together with IPFIX options export.

Turning a packet capture into IPFIX with the aggregation flag

The aggregation path is where reflow stops being a converter and becomes useful for load testing. It takes packets from a capture, groups them by addresses, ports, protocol and source ID, and emits IPFIX flows:

bash
./reflow -input stream:traffic.pcap:pcap -agg \
  -output ipfix:udp:127.0.0.1:4739

With -agg enabled, packet and byte counts are summed, idle flows are flushed after 10 seconds, and snapshots are emitted every 60 seconds. End of file or Ctrl-C flushes the remaining flows, so a short capture still produces a complete set of records rather than a truncated tail.

Input formats are broader than a single file type. PCAPNG input is also supported. Live capture uses pcap_live:<interface>:bytes, which requires a libpcap and cgo build, or ebpf:<interface>:bytes on Linux. That distinction matters when you plan to run the binary on the router-facing host: the portable static build that CGO_ENABLED=0 produces covers file and UDP inputs, but live capture needs either the cgo toolchain or the Linux eBPF path.

The same binary covers the conversion side of the pipeline too, since output targets include ipfix, json and protobuf, which makes it usable as a shim between an exporter and an existing IPFIX consumer.

Running the plain collector on ports 6343 and 2055

For production intake, the documentation points you at the release binaries for your operating system, whose names carry a version suffix, and the collector runs with no arguments:

bash
$ ./goflow2

That launches an sFlow collector on port :6343 and a NetFlow v9/IPFIX collector on port :2055. Samples arrive as JSON printed to standard output, in a record shape that carries the protocol type, timing, sequence number, sampling rate, sampler address, byte and packet counts, addresses, ethertype, transport protocol and ports.

json
{
    "type": "SFLOW_5",
    "time_received_ns": 1681583295157626000,
    "sequence_num": 2999,
    "sampling_rate": 100,
    "sampler_address": "192.168.0.1",
    "time_flow_start_ns": 1681583295157626000,
    "time_flow_end_ns": 1681583295157626000,
    "bytes": 1500,
    "packets": 1,
    "src_addr": "fd01::1",
    "dst_addr": "fd01::2",
    "etype": "IPv6",
    "proto": "TCP",
    "src_port": 443,
    "dst_port": 50001
}

For anything that ingests log files, the documentation suggests sending the output into a file, whether that is Loki with Promtail, Splunk, Fluentd or Google Cloud Logs:

bash
$ ./goflow2 -transport.file /var/logs/goflow

For Kafka, the transport layer handles delivery and partitioning, with sarama listed among the dependencies. If you are building from source instead of using a release, the Dockerfile compiles cmd/goflow2/main.go in a golang:1.26.9-alpine builder stage and copies the result into an alpine image running as the unprivileged flow user.

The parts of the job GoFlow2 refuses to do

The clearest limitation is also the project's premise. There is no storage, no graphing, no alerting and no enrichment in the box. If you were hoping for a collector that writes to a time series database and draws dashboards, this is the wrong tool, and the documentation says so rather than implying otherwise.

Protocol coverage is also bounded. Collection covers NetFlow v5, IPFIX and NetFlow v9 with sampling rate from the Option Data Set, and sFlow v5. NetFlow v1, v7 and v8 are described as being evaluated, so a legacy estate that still emits them is not served yet.

Two operational quirks deserve a place in any evaluation. The first is the template delay described earlier, which makes an empty dashboard in the first minutes a normal state rather than a fault. The second is that the sampling rate lives in a cached FlowStore, so a restart without JSON persistence resets that state and reintroduces the wait. The documentation on agents is the place to look for what exporters should send, and the protocol mapping page covers how each protocol is represented internally.

The practical alternative is not another collector but a different architecture: keep collection inside the network tooling you already run and store the flows where your existing systems live. GoFlow2 earns its place when you need protocol diversity normalised into one format, and loses to simpler setups when everything already speaks one protocol that your current stack reads.

Library reuse, release cadence and the licence

GoFlow2 is not only a binary. The documentation lists what you can replace when you build your own collector: a different transport such as RabbitMQ instead of Kafka, another output format such as Cap'n Proto or Avro instead of protobuf, decoders for samples outside IP networks such as MPLS, and a different metrics system such as OpenTelemetry. The dependencies in go.mod reflect the practical side of that, with sarama for Kafka, gopacket for packet handling, go-reuseport for socket reuse, geoip2-golang and maxminddb-golang for IP lookups, prometheus client libraries and protobuf.

Two release lines are visible in the recent tags. v2.2.7 was published on 2026-09-30 and v1.3.8 on the same day, one day after v2.2.6 from 2025-12-27, so the v1 line is still receiving patches alongside v2. The repository is not archived, and the last push was on 2026-10-19, so the code base is moving rather than frozen.

The licence is BSD-3-Clause, and the Makefile repeats that identifier in its metadata. Read the LICENSE file in the repository before deciding how to distribute a modified build. For anyone evaluating cost, the practical upgrade burden is the Go toolchain and the interfaces between decoder, producer and transport rather than the licence itself.

Editorial conclusion

GoFlow2 fits teams that already run Kafka or a log pipeline and want one consistent record shape across mixed flow exporters, and it fits anyone who needs raw samples to aggregate themselves. It does not fit a team expecting a turnkey dashboard, and it is the wrong choice when every device already speaks one protocol you can read directly. Before adopting it, check the first question that matters operationally: whether your exporters send NetFlow v9 or IPFIX, because template discovery means the first decoded packets can take minutes to appear, and confirm that your sampling rates arrive through Option Data Sets so the FlowStore can correct counters.

Frequently asked questions

Which flow protocols does GoFlow2 collect?

GoFlow2 collects NetFlow v5, IPFIX and NetFlow v9 with the sampling rate provided by the Option Data Set, and sFlow v5. NetFlow v1, v7 and v8 are listed as being evaluated, so they are not covered yet.

Does GoFlow2 store the flow data it collects?

No. The documentation describes GoFlow2 as the entry point of a pipeline, with storage, transport, enrichment, graphing and alerting left to other components. Out of the box it prints samples as JSON, writes them to a file, or sends them to Kafka.

How do I aggregate packets into IPFIX flows with GoFlow2?

Use the reflow binary with the -agg flag and a pcap input, for example ./reflow -input stream:traffic.pcap:pcap -agg -output ipfix:udp:127.0.0.1:4739. Aggregation sums packet and byte counts, flushes idle flows after 10 seconds and emits snapshots every 60 seconds.

Which ports does the goflow2 collector listen on by default?

Running ./goflow2 with no arguments starts an sFlow collector on port :6343 and a NetFlow v9/IPFIX collector on port :2055. The experimental reflow binary uses the same default pair of ports, 2055 and 6343, when no flags are given.

Official sources

  1. Issues
  2. License: BSD-3-Clause
  3. netsampler/goflow2 on GitHub
  4. README
  5. Releases
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/netsampler-goflow2.svg)](https://hysenlabs.com/projects/netsampler-goflow2)

Was this useful?