Pim van Pelt 055cf9f830 Update docs and header comments for the IP_PKTINFO attribution model
The SO_BINDTODEVICE → IP_PKTINFO switch in the previous commit
was a semantic change: the module no longer touches outgoing
routing at all, and several places in the docs and the module's
top-of-file comment still described the old mechanism.

- README.md and debian/control now describe attribution as
  reading the ingress ifindex per connection from the kernel's
  IP_PKTINFO / IPV6_PKTINFO cmsg, and explicitly call out that
  the DSR / maglev return-path constraint is what makes the
  change necessary.
- docs/design.md FR-1.1 / FR-1.5 / FR-1.6 are rewritten to
  forbid SO_BINDTODEVICE and to describe the cmsg-based lookup.
  NFR-6.1 notes these are ordinary unprivileged socket options.
  The "Components" / "Composes With" sections and the
  "Alternatives Considered" entry are brought in line — and a
  new entry records SO_BINDTODEVICE as a rejected alternative
  with the exact failure mode seen on an IPng production box.
- docs/config-guide.md already carried the new description;
  unchanged here.
- src/ngx_http_ipng_stats_module.c's top-level block comment is
  rewritten to match; the section header above init_module goes
  from "rebind listen sockets with SO_BINDTODEVICE" to "enable
  IP_PKTINFO on listen sockets, resolve ifindexes".

Three SO_BINDTODEVICE mentions deliberately remain in the source
and one in the design doc's alternatives table — all of them
explain that the module *avoids* the option, which is itself
load-bearing documentation.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 15:16:10 +02:00
2026-04-18 15:00:46 +02:00

nginx-ipng-stats-plugin

Per-VIP, per-device traffic counters for nginx. Ships as a dynamic nginx module and a Debian package that loads into stock upstream nginx on Debian Trixie.

The module attributes every HTTP request to the interface it arrived on, reading the ingress ifindex per connection from the kernel's IP_PKTINFO / IPV6_PKTINFO cmsg. Listening sockets stay plain wildcards, so outgoing packets follow the normal routing table — which is what makes this safe for DSR / maglev deployments where the SYN arrives via a GRE tunnel and the SYN-ACK must leave via the default route. Counters — requests, status codes, bytes, latency histograms — are exposed as Prometheus text or JSON from a single HTTP scrape endpoint, filtered per-source. This is useful for any deployment where traffic arrives on distinct interfaces — GRE tunnels, VLANs, bonded links, or plain ethernet — and per-interface observability is needed.

Without any device=/ipng_source_tag= parameters, the module still counts and exposes per-VIP traffic under the configurable default source tag (direct), which makes it a useful plain observability module for any nginx host.

See docs/design.md for the full design, including the attribution model, data flow, and requirements.

Quick start

make install-deps      # install build and test dependencies (apt)
make build             # build the .so out-of-tree
make pkg-deb           # build a .deb package
make robot-test        # run end-to-end tests via containerlab

Installing

sudo dpkg -i build/*.deb

The package installs the .so into /usr/lib/nginx/modules, drops a load_module stanza into /etc/nginx/modules-enabled/, and runs nginx -t before completing.

Configuring

See docs/user-guide.md for an end-to-end walkthrough and docs/config-guide.md for the directive and listen parameter reference.

License

Apache-2.0. See LICENSE.

Description
No description provided
Readme Apache-2.0 920 KiB
Languages
C 72.7%
RobotFramework 14.9%
Makefile 7.4%
Shell 4%
C++ 0.6%
Other 0.4%