Skip to content

RTFM · Healthchecks

lb.saphira.gre: does the tunnel carry traffic back?

A GRE tunnel can pass a handshake and still swallow packets. This check sends a real encapsulated packet into the tunnel and requires the peer to send an encapsulated packet back; the two-party contract that proves the data path, not just the control plane.

Saphira Linux dragon mascot

What it proves

The GRE data path end to end: a GRE-encapsulated inner IP packet is sent to the peer, and health requires any GRE-encapsulated reply from the peer. Nothing less is honest: proving the outer endpoint answers tells you nothing about whether encapsulated payloads traverse.

RFC 2784/2890 define the GRE header, key and sequence format only; the keepalive loop itself is the common tunnel-keepalive practice, not a standard. It is therefore a two-party contract: both ends must be configured for it, and the check refuses to invent defaults (missing configuration is exit 2).

How it works

The probe engine opens a raw socket on IP protocol 47, builds a GRE header (optionally with the configured key) around an inner IP/UDP packet addressed from LB_SAPHIRA_GRE_INNER_SRC to LB_SAPHIRA_GRE_INNER_DST, and waits for any encapsulated reply from the peer within the timeout. IPv4 in v1. Requires CAP_NET_RAW; the check runs as root, which ldirectord already does.

Configuration

Knobs
VariableDefaultMeaning
LB_SAPHIRA_GRE_INNER_SRC(required)The checker's address as the peer routes it back
LB_SAPHIRA_GRE_INNER_DST(required)The peer-side inner destination address
LB_SAPHIRA_GRE_INNER_PORT33434Inner UDP port pair for the payload
LB_SAPHIRA_GRE_KEY-GRE key when the tunnel uses keyed GRE
LB_SAPHIRA_TIMEOUT3Loop deadline

Wiring it up

ldirectord
# ldirectord.cf - tunnel-member pool
virtual = 203.0.113.10:47
    protocol = fwm
    scheduler = rr
    real = 192.168.20.120 gate 1
    checktype = external
    checkcommand = "/var/lib/lb/saphira/lb.saphira.gre"
The two-party contract
# /etc/saphira/lb-healthchecks.d/gre.conf
LB_SAPHIRA_GRE_INNER_SRC=10.99.0.1
LB_SAPHIRA_GRE_INNER_DST=10.99.0.5
LB_SAPHIRA_GRE_INNER_PORT=33434

Run it by hand

Manual run
LB_SAPHIRA_GRE_INNER_SRC=10.99.0.1 LB_SAPHIRA_GRE_INNER_DST=10.99.0.5 \
  /var/lib/lb/saphira/lb.saphira.gre gre-pool 0 192.168.20.120 0
echo $?
# 0 = an encapsulated reply came back from the peer
# 1 = silence: the data path is broken
# 2 = inner endpoints not configured

Failure modes

  • Timeout with the outer endpoint pingable; the classic split: control plane alive, data path dead (MTU blackhole, missing inner route, key mismatch)
  • exit 2: the contract is not configured: fix the conf file before trusting any verdict

Did we miss something?

If this page left something unanswered, found an error, or there is another subject you would like documented, tell us. Saphira’s documentation grows from real problems people need to solve.

Send feedback or request a new section →

Prefer not to do it yourself?

Everything needed to do the work yourself is documented here and remains free; we charge for human time, not for withholding knowledge. Sometimes the missing resource is simply time. The same people who build Saphira can provide paid professional help with implementation, migration, troubleshooting and administration.

Ask about professional support →