Skip to content

Session Accounting

github-actions[bot] edited this page Aug 3, 2026 · 1 revision

Session Accounting — who transferred what, where

session-report answers the questions occtl can't: when did each client connect and disconnect, how much data did the session move, and — the part unique to this image — how much of it went through the user's gateway versus each attached bypass pool.

docker exec <container> session-report              # everything
docker exec <container> session-report -u alice     # one user
docker exec <container> session-report --json       # machine-readable, same data

Options: -u NAME (one user) · -j/--json · --no-geo (skip client-IP geolocation, faster offline) · --no-rate (skip the 1-second throughput sampling of active sessions).

================================================================
ocserv-server SESSION REPORT : 2026-08-03T01:20:11+03:00
Collecting since             : 2026-08-02 09:23:41 (container start, 15h57m ago)
================================================================

### Active sessions (2)

alice  (online, connected 2026-08-03 00:59:34, up 20m37s)
    assigned 10.20.0.37  client 198.51.100.7 (Amsterdam, NL - AS64496 ExampleNet)  dev vpns3  gateway nl
    total (forwarded)        up 321.7K     down 636.1K   [now: up 12.4K/s down 1.1M/s]
    pool ru -> direct        up 21.7K      down 96.1K
    via gateway nl           up 300.0K     down 540.0K
...

### Completed sessions (newest first)

bob  (connected 2026-08-02 09:24:02, disconnected 2026-08-03 00:58:47, duration 15h34m)
    assigned 10.20.0.52  client 203.0.113.80 (Berlin, DE - AS64511 ExampleCom)  dev vpns1  gateway us
    total (ocserv)           up 89.1M      down 1.1G
    total (forwarded)        up 88.9M      down 1.1G
    pool ru -> direct        up 12.1M      down 220.4M
    via gateway us           up 76.8M      down 0.9G
...

### Per-user totals (active + completed)
user                 sessions  up          down
bob                  2         98.2M       1.2G
    via gateway us           up 76.8M      down 0.9G
    direct                   up 12.1M      down 220.4M
    blocked (rejected)       up 45.1K      down 0B
...

### Reconnect loops
[flap] alice: 4 sessions shorter than 2m in the last hour - client may be reconnect-looping

How it works

The gateway-mode connect/disconnect hook already runs for every session. It now additionally:

  • on connect — records the connect time, the client's real IP and the tun device, and installs per-session nftables counters: one up/down pair for the session total and one pair per attached bypass pool (matching the pool's address sets, both families);
  • on disconnect — snapshots the counters together with ocserv's own session totals into a history file, then removes everything it installed.

session-report reads the live counters for active sessions and the history file for completed ones. There is nothing to configure and no measurable overhead — accounting is active whenever gateway mode with a per-user map (VPN_USER_GATEWAY[_FILE]) is, i.e. whenever the hook runs. Without gateway mode there is no path split to report; use occtl show users / network-diagnostic for live state.

Reading the numbers

  • up is client → world, down is world → client.
  • [now: up …/s down …/s] on active sessions is live throughput, sampled over one second at report time (--no-rate skips the sampling and the 1s wait).
  • Client geolocation ((Amsterdam, NL - …) after the client IP) is looked up over the network at report time and silently omitted when unreachable; --no-geo skips the attempt.
  • Reconnect loops: a user with 3 or more completed sessions shorter than 2 minutes within the last hour gets flagged — the classic signature of a router stuck in a reconnect loop.
  • Per-user totals are broken down by where the bytes went, aggregated across all of the user's sessions: one line per gateway used, one direct line (direct-target pools plus unmapped sessions), and one blocked (rejected) line (attempts into block-target pools — upload only, since rejected traffic never returns).
  • total (forwarded) counts traffic actually forwarded between the tunnel and the WAN — the numbers the per-path split is computed from (via gateway = total − all pools).
  • total (ocserv) (completed sessions) is ocserv's own count of tunnel bytes. It also includes traffic that terminates in the container — tunneled DNS, for example — so it is normally slightly higher than the forwarded total.
  • A pool's share counts traffic to/from that pool's addresses as attached at connect time; if you change a user's pools with vpngw-reload mid-session, routing follows immediately but the new pool's counters start with the next session.
  • Traffic that the kill switch rejects (fail-closed drops) is counted as "up" — the client did send it — but never produces "down" bytes.

Data lifetime

By default everything lives on tmpfs (/run/ocserv-vpngw/): history covers the current container lifetime. Sessions cannot outlive the container anyway, and an ocserv-only restart inside a running container keeps the collected history. Collecting since in the header tells you the horizon.

For accounting that survives container recreations, point the history at the config volume:

environment:
  - SESSION_HISTORY_FILE=/etc/ocserv/session-history
Variable Default Description
SESSION_HISTORY_FILE (unset — tmpfs) Where completed sessions are appended. Put it on a volume to keep history across container recreations. The file grows one line per session; rotate or truncate it yourself when needed.

The format is stable and machine-parseable, one line per completed session:

connect-epoch disconnect-epoch user ip4 ip6 client-ip gateway device up down ocserv-in ocserv-out pool=up:down,...

(- marks an unknown field; --json serves the same data already parsed.)


Next: Gateway Mode · Destination Bypass · Troubleshooting

Clone this wiki locally