<?xml version="1.0" encoding="UTF-8"?>
  <?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?>

<!DOCTYPE rfc  [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">

]>

<?rfc comments="yes"?>

<rfc ipr="trust200902" docName="draft-cassen-vrrp-auth-hmac-01" category="std" consensus="true" submissionType="IETF" tocInclude="true" sortRefs="true" symRefs="true">
  <front>
    <title abbrev="VRRP HMAC Authentication">An HMAC Authentication Extension for the Virtual Router Redundancy Protocol (VRRP)</title>

    <author initials="A." surname="Cassen" fullname="Alexandre Cassen">
      <organization abbrev="Free">Free / keepalived.org</organization>
      <address>
        <email>acassen@corp.free.fr</email>
      </address>
    </author>
    <author initials="Q." surname="Armitage" fullname="Quentin Armitage">
      <organization>keepalived.org</organization>
      <address>
        <email>quentin@armitage.org.uk</email>
      </address>
    </author>

    <date year="2026" month="July" day="27"/>

    <area>Routing</area>
    <workgroup>Routing Area Working Group</workgroup>
    <keyword>VRRP</keyword> <keyword>authentication</keyword> <keyword>HMAC</keyword> <keyword>replay</keyword> <keyword>unicast</keyword>

    <abstract>


<t>VRRP relies on a hop limit of 255 to prove that an advertisement came from
the local link. That guard cannot apply when advertisements travel as
multi-hop unicast across a routed or overlay network, as is common in cloud
deployments, leaving the protocol open to off-segment injection and
replay. The legacy VRRPv2 authentication types do not close this gap and were
removed from later VRRP specifications. This document defines an
authentication extension that appends an HMAC-SHA256 trailer and a time-based
sequence number to VRRPv3 advertisements, authenticating the sender as a
holder of the group key, protecting message integrity and bounding replay,
for both IP address families. The extension is the
primary defense where the hop-limit check cannot apply, and defense in depth
for multicast and single-hop unicast, where that check remains in force.</t>



    </abstract>



  </front>

  <middle>


<section anchor="introduction"><name>Introduction</name>

<t>The Virtual Router Redundancy Protocol <xref target="RFC9568"/> lets a group of routers
share a virtual IP address so that a backup takes over when the active router
fails. VRRP was designed as a first-hop protocol that runs on a single link,
and its only built-in protection against a forged advertisement is the hop
limit. An active router sends every advertisement with an IPv4 TTL or an IPv6
Hop Limit of 255, and a receiver drops any advertisement that does not arrive
with that value. Because a router cannot raise a hop limit, an advertisement
that arrives with 255 cannot have crossed a router, which proves it
originated on the local link. This is the Generalized TTL Security Mechanism
(GTSM) <xref target="RFC5082"/>, and VRRPv3 leans on it entirely.</t>

<t>Unicast operation by itself does not lose that guard. A unicast VRRP
specification that keeps the group on a shared link
<xref target="I-D.abinabraham-vrrp-unicast"/> sends with a hop limit of 255 and rejects
anything lower, so GTSM holds exactly as it does for multicast, and that
specification explicitly excludes multi-hop operation. The gap opens in the
deployments that go further. Implementations commonly run VRRP
in cloud and virtualized networks where multicast is unavailable and the peers
sit behind routers, so advertisements travel as unicast to a configured list
of peers. They cross hops, arrive with a hop limit well below 255, and the
receiver has to relax the check to accept them. The moment it does, the
only guard VRRP had is gone. Anyone who can place a packet at the
receiver with a spoofed source address can inject a forged advertisement
that raises priority to demote the legitimate active router or sets
priority 0 to force an immediate failover. Captured advertisements replay
just as easily.</t>

<figure title="Off-segment injection against multi-hop unicast VRRP" anchor="fig-threat"><artwork><![CDATA[
   Routed path: no multicast, TTL decremented en route

     ACTIVE  --- advert (VRID 51, prio 200) --->  BACKUP
   198.51.100.10                              192.0.2.10
       ^
       |  spoofed advert: src = 192.0.2.10 (a peer), prio 255
   ATTACKER
   203.0.113.9
]]></artwork></figure>

<t>The same attack and defense apply over IPv6, where a deployment would use
addresses such as 2001:db8::10 in place of those above.</t>

<t>The authentication types of earlier VRRP versions were removed as
ineffective <xref target="RFC3768"/> and never carried into VRRPv3. In practice, unicast
VRRP runs unauthenticated.</t>

<t>This document defines an authentication extension that closes the gap. It
appends to each advertisement a trailer carrying an HMAC-SHA256 and a
time-based sequence number. The HMAC authenticates the sender as a holder of
the group key and protects integrity, the sequence number bounds replay, and
both work the same way for unicast and multicast. For multi-hop unicast, where the hop-limit check cannot
apply, the extension is the primary defense. For multicast and single-hop
unicast it adds defense in depth against a compromised host on the local
link.</t>

</section>
<section anchor="requirements-language"><name>Requirements Language</name>

<t>The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD",
"SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this
document are to be interpreted as described in BCP 14 <xref target="RFC2119"/> <xref target="RFC8174"/>
when, and only when, they appear in all capitals, as shown here.</t>

</section>
<section anchor="definitions"><name>Definitions</name>

<dl indent="9" newline="false" spacing="normal">
  <dt>Trailer</dt>
  <dd>
    <t>The authentication trailer this document appends to an advertisement.</t>
  </dd>
  <dt>HMAC</dt>
  <dd>
    <t>The truncated HMAC-SHA256 carried in the trailer.</t>
  </dd>
  <dt>Group key</dt>
  <dd>
    <t>A symmetric key shared by every node of the virtual router group. A group
holds one or more of them under distinct Key IDs (<xref target="keys"/>) and a sender
signs with one.</t>
  </dd>
  <dt>Single-hop</dt>
  <dd>
    <t>Sender and receiver share a link. No router forwards the advertisement,
so the hop limit arrives intact and GTSM holds.</t>
  </dd>
  <dt>Multi-hop</dt>
  <dd>
    <t>The advertisement crosses one or more routers, each of which decrements
the hop limit, so GTSM cannot apply.</t>
  </dd>
</dl>

</section>
<section anchor="applicability"><name>Applicability</name>

<t>The extension applies to VRRPv3 <xref target="RFC9568"/> advertisements, for both address
families. A group either uses it on every node or on none, since a node
that does not understand the trailer sees a longer packet and rejects it
(<xref target="migration"/>). It authenticates advertisements
only. It does not protect any other VRRP traffic and provides no
confidentiality, which VRRP does not need because an advertisement carries
routing intent rather than secret data.</t>

<t>Three deployment models differ in what the hop limit still proves, and the
extension plays a different role in each.</t>

<dl newline="true" spacing="normal">
  <dt>multicast</dt>
  <dd>
    <t>The hop-limit check of <xref target="RFC9568"/> is mandatory and GTSM holds. The
extension adds group-key-holder authentication, integrity and replay
protection on top of it.</t>
  </dd>
  <dt>single-hop unicast</dt>
  <dd>
    <t>The group stays on a shared link and the hop-limit check of
<xref target="I-D.abinabraham-vrrp-unicast"/> is equally mandatory. The extension plays
the same defense-in-depth role.</t>
  </dd>
  <dt>multi-hop unicast</dt>
  <dd>
    <t>The advertisement crosses routers, the hop-limit check cannot succeed and
is relaxed. The extension is the primary defense.</t>
  </dd>
</dl>

<t>In multicast and single-hop unicast operation a receiver MUST keep enforcing
the hop-limit check, since this extension complements GTSM and never
replaces it.</t>

<t>Multi-hop operation itself is out of scope for this document. Hop-limit
policy, source address selection, peer validation and routing behaviour for a
routed VRRP deployment belong to a dedicated specification, and
<xref target="I-D.abinabraham-vrrp-unicast"/> notes that multi-hop operation needs a
security model of its own. This extension supplies the authentication and
anti-replay component of that model. A
multi-hop deployment or a future multi-hop specification SHOULD require it in
enforce mode (<xref target="migration"/>) or an equivalent authenticated channel, since
GTSM cannot apply there.</t>

</section>
<section anchor="advertisement-trailer-format"><name>Advertisement Trailer Format</name>

<section anchor="placement-and-detection"><name>Placement and Detection</name>

<t>A sender appends the trailer after the last virtual IP address, as the final
octets of the IP payload. The IPv4 Total Length or the IPv6 Payload
Length grows by the trailer size. Integrity of both the message and the
trailer comes from the HMAC, not from the VRRP checksum, which anyone can
recompute. On IPv4 the checksum covers the VRRP message without the trailer
<xref target="RFC9568"/>, while on IPv6 the
mandatory transport checksum covers the whole IP payload, trailer and HMAC
included. The coverage difference cannot
affect authentication, because the checksum field is read as zero when the
HMAC is computed and verified (<xref target="hmac"/>).</t>

<t>VRRP has no spare header bit to flag the extension, so a receiver detects the
trailer by length. The trailer starts at the expected VRRP message length,
which follows from the address count in the VRRP header, and its total length
is a fixed property of its Ext Type (<xref target="iana"/>), 28 octets for the scheme of
this document. The IP payload length is taken from the IP header, the IPv4
Total Length minus the header length or the IPv6 Payload Length, so
link-layer padding never reaches the test. The receive rules of
<xref target="receiving"/> accept an exact scheme length, in the migration modes the bare
message length, and drop everything else.</t>

</section>
<section anchor="trailer-fields"><name>Trailer Fields</name>

<figure title="Authentication trailer, Ext Type 1 (28 octets)" anchor="fig-trailer"><artwork><![CDATA[
 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|    Ext Type   |     Key ID    |            Reserved           |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                            Seconds                            |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|          Subseconds           |            Counter            |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                                                               |
|                 HMAC (128 bits, truncated)                    |
|                                                               |
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
]]></artwork></figure>

<dl indent="10" newline="false" spacing="normal">
  <dt>Ext Type</dt>
  <dd>
    <t>The authentication scheme. This document defines value 1, HMAC-SHA256
truncated to 128 bits. A sender uses one configured scheme. A receiver drops
an advertisement carrying an Ext Type it does not support or is configured
not to accept.</t>
  </dd>
  <dt>Key ID</dt>
  <dd>
    <t>Selects the key that verifies the HMAC (<xref target="keys"/>). Values run from 1 to 255,
and 0 is invalid.</t>
  </dd>
  <dt>Reserved</dt>
  <dd>
    <t>MUST be zero on send and MUST be checked as zero on receipt.</t>
  </dd>
  <dt>Seconds</dt>
  <dd>
    <t>The integer-seconds part of the sequence number, in network byte order
(<xref target="seqnum"/>).</t>
  </dd>
  <dt>Subseconds</dt>
  <dd>
    <t>The fractional-seconds part of the sequence number, a 16-bit binary fraction
giving a timestamp resolution of 2^-16 s, in network byte order
(<xref target="seqnum"/>).</t>
  </dd>
  <dt>Counter</dt>
  <dd>
    <t>A 16-bit tie-breaker for advertisements that share one timestamp, in network
byte order (<xref target="seqnum"/>).</t>
  </dd>
  <dt>HMAC</dt>
  <dd>
    <t>The truncated HMAC computed over the inputs in <xref target="hmac"/>.</t>
  </dd>
</dl>

</section>
<section anchor="pseudo"><name>Pseudo-Header</name>

<t>The HMAC binds a 20-octet pseudo-header that never travels on the wire. Family,
Version, VRID and Zero each occupy one octet, followed by a 16-octet Address.
Both sender and receiver reconstruct it from fields they already hold:</t>

<dl indent="9" newline="false" spacing="normal">
  <dt>Family</dt>
  <dd>
    <t>4 for IPv4, 6 for IPv6.</t>
  </dd>
  <dt>Version</dt>
  <dd>
    <t>The VRRP version of the advertisement.</t>
  </dd>
  <dt>VRID</dt>
  <dd>
    <t>The virtual router identifier.</t>
  </dd>
  <dt>Zero</dt>
  <dd>
    <t>A padding octet set to zero. It rounds the fields before the Address to 4
octets and keeps the pseudo-header at its fixed 20 octets.</t>
  </dd>
  <dt>Address</dt>
  <dd>
    <t>The sender IP source address. For IPv4 it occupies the first 4 octets and the
rest is zero. For IPv6 it fills all 16.</t>
  </dd>
</dl>

<t>Binding the family, version and VRID stops a captured trailer from being
spliced onto a different instance that happens to share a key. Binding the
source address ties the advertisement to its claimed sender. The receiver
builds the pseudo-header from the source address of the packet it received, so
a spoofed source still has to carry an HMAC computed over that same address,
which an attacker without the key cannot produce. By the same token, the
address the receiver observes must match the one the sender signed, so the
extension does not operate across a source NAT between peers.</t>

</section>
<section anchor="hmac"><name>HMAC Computation</name>

<t>The HMAC is HMAC-SHA256 <xref target="RFC2104"/> <xref target="RFC6234"/> over the concatenation of the
pseudo-header, the VRRP message with its Checksum field read as zero and the
trailer with its HMAC field read as zero, truncated to the high-order 128
bits:</t>

<figure><artwork><![CDATA[
   HMAC = HMAC-SHA256(K, pseudo || vrrp || prefix || Z) [0..15]
]]></artwork></figure>

<t>where K is the key identified by Key ID, pseudo is the 20-octet pseudo-header
(<xref target="pseudo"/>), vrrp is the VRRP message from the start of the VRRP header
through the octet before the trailer, that is through the last address
(the IP header is not included), with the 16-bit
VRRP Checksum field taken as zero, prefix is the first 12 octets of the trailer,
that is Ext Type through Counter, and Z is 16 zero octets standing in for the
HMAC field. The sender writes the 16-octet result into the HMAC field.</t>

<t>Both the VRRP Checksum field and the HMAC field are read as zero for HMAC
computation and verification, whatever value they carry in the packet. The
substitution is logical, it does not modify the packet that the checksum is
computed or verified over. Excluding the checksum removes a circular
dependency on IPv6, where the transport checksum covers the trailer and
therefore the HMAC, and makes the HMAC input identical across address
families and independent of where a stack computes the checksum. The IP header
is excluded so that a change to the hop limit or the header checksum in
transit does not break the HMAC.</t>

</section>
</section>
<section anchor="sending-advertisements"><name>Sending Advertisements</name>

<t>To send an advertisement, a sender proceeds in this order:</t>

<t><list style="numbers">
  <t>Build the VRRP message as usual and append the trailer.</t>
  <t>Set Ext Type to its scheme, Key ID to its active key (<xref target="keys"/>), Reserved
to zero, and fill the sequence number as in <xref target="seqnum"/>.</t>
  <t>Compute the HMAC of <xref target="hmac"/> and write the result into the HMAC field.</t>
  <t>Compute and insert the VRRP checksum over the completed packet, on IPv4
over the VRRP message only and on IPv6 over
the whole IP payload, typically by the sending stack.</t>
</list></t>

<t>The VRRP checksum comes last because on IPv6 it covers the trailer and
therefore the HMAC just written. On IPv4 the checksum does not cover the
trailer, and since the HMAC input reads the checksum field as zero either
way, a stack that fills the IPv4 checksum before signing produces the same
packet. A sender MUST allocate one Sequence Number and compute one HMAC per
logical advertisement. In unicast mode every peer copy carries those same
authentication fields, only the destination address and, on IPv6, the
resulting checksum differ between copies <xref target="I-D.abinabraham-vrrp-unicast"/>.</t>

</section>
<section anchor="receiving"><name>Receiving Advertisements</name>

<t>A receiver processes the trailer before any advertisement field reaches the
VRRP state machine, so that a forged or stale packet never influences the
election. Given an advertisement of expected VRRP message length L and an
IP payload length P taken from the IP header:</t>

<t><list style="numbers">
  <t>If P equals L, the advertisement carries no trailer. In receive-only and
permissive modes (<xref target="migration"/>) the receiver accepts it and skips the
remaining steps. In enforce mode the receiver drops it.</t>
  <t>Otherwise the trailer starts at offset L. If Ext Type identifies a scheme
the receiver does not accept, or P does not equal L plus the trailer
length that scheme defines, drop the advertisement as malformed. A payload
shorter than L never reaches this step, the length checks of <xref target="RFC9568"/>
already discard it.</t>
  <t>If Reserved is non-zero, drop the advertisement as malformed.</t>
  <t>In time mode (<xref target="modes"/>), compute the difference between the local clock
and the Seconds field as in <xref target="seqnum"/>. If its magnitude exceeds the
freshness window, drop the advertisement as stale. This test runs on an
unauthenticated timestamp, so it only rejects and never grants trust.</t>
  <t>Look up the key identified by Key ID. If no such key exists, drop the
advertisement.</t>
  <t>Recompute the HMAC of <xref target="hmac"/> over the advertisement as received and
compare it to the HMAC field in constant time. On any mismatch, drop the
advertisement. The VRRP checksum itself is validated under the normal
rules of the address family, which on IPv6 the receiving stack
typically does before delivery.</t>
  <t>Resolve the per-sender replay state (<xref target="replay"/>) and require the sequence
to be newer than the stored high-water mark, compared as in <xref target="seqnum"/>. If
it is not, drop the advertisement as a replay. Otherwise raise the
high-water mark to this sequence and accept the advertisement.</t>
</list></t>

<t>The replay high-water mark advances only after the HMAC verifies in step 6, so
forged or replayed data never moves it.</t>

</section>
<section anchor="replay"><name>Anti-Replay</name>

<section anchor="seqnum"><name>Sequence Number</name>

<t>The sequence number is an unsigned 64-bit value made of the 32-bit Seconds, the
16-bit Subseconds and the 16-bit Counter, most significant first. Seconds is the
sender UTC time in seconds since the Unix epoch (1970-01-01T00:00:00Z), the same
absolute reference on every node, which NTP distributes as UTC. Subseconds adds a
binary fraction of a second, so the high 48 bits form a high-resolution timestamp
and the Counter only separates advertisements that share one timestamp. A handful
of Counter values suffice, because the 10 ms minimum advertisement interval caps a
sender near a hundred advertisements per second, and the immediate advertisement a
higher-priority router sends on seeing a lower-priority one (Section 6.4.3 of
<xref target="RFC9568"/>) adds only a few.</t>

<t>A sender keeps the last sequence it used. On each transmission it loads its clock
into Seconds and Subseconds with Counter zero, then sends that value if it exceeds
the stored one, otherwise the stored value plus one. The increment raises Counter
and carries into the timestamp on overflow, so the sequence advances even when the
clock has not. The sequence does not move backward across a backward clock
step, including a leap second, and needs no persistent storage as long as the
clock advances across a restart. One exception recovers a corrected forward
step in time mode, where the sender resets the sequence to the clock once
the stored timestamp lies more than the freshness window (<xref target="modes"/>) ahead
of it, since receivers already reject such advertisements as stale. Monotonic
mode grows strictly, with no exception.</t>

<t>All three fields are unsigned and wrap, so all comparisons are modular rather than
absolute. A receiver orders two sequences under serial number arithmetic
<xref target="RFC1982"/> and forms the time-mode difference from the Seconds field as a signed
32-bit value modulo 2^32. A legitimate clock difference is far smaller than the
2^32-second wrap period, so the wrap is a non-event and the extension needs no
epoch other than the Unix one.</t>

</section>
<section anchor="modes"><name>Freshness Modes</name>

<t>The receiver enforces freshness in one of two modes.</t>

<dl newline="true" spacing="normal">
  <dt>time mode</dt>
  <dd>
    <t>The receiver keeps the freshness window from step 4 of <xref target="receiving"/> and
also the per-sender high-water mark, so a valid but old capture is rejected
both by absolute time and by the sequence. Time mode is the default and the
security baseline of this document, and
requires the group to keep its clocks in sync, for instance with NTP. The
freshness window defaults to three times the configured advertisement
interval with a floor of 5 seconds, and is configurable from 1 to 300
seconds. The receiver expires a high-water mark whose timestamp lies outside
the window. This loses nothing, the window already rejects anything the mark
would order, and it lets a sender that reset after a clock step recover.</t>
  </dd>
  <dt>monotonic mode</dt>
  <dd>
    <t>The receiver drops the freshness window and relies on the high-water mark
alone, which removes the dependency on synchronized clocks at the cost of
bounding freshness only against the last packet seen from each sender. The
sequence is still clock-derived, so monotonic mode drops only the need for
clocks to agree between nodes, not the need for a sender's clock to advance
across a restart (<xref target="seqnum"/>). A sender that cannot guarantee that advance
SHOULD
persist its last sequence or use time mode, otherwise a restart can leave
its advertisements rejected until the sequence climbs back above the stored
high-water mark. A receiver MAY instead expire the high-water mark of a
sender that has been silent for a configured time, so a restarted sender is
treated as new, at the cost of a replay window as long as that time.
Monotonic mode gives no inter-session replay protection once receiver state
is lost and is unsuitable where that protection is required, unless sender
and receiver persist their state.</t>
  </dd>
</dl>

</section>
<section anchor="per-sender-state"><name>Per-Sender State</name>

<t>Replay state is per sender, because each active router signs an independent
sequence. For unicast, the receiver anchors the state on the configured peer
whose address matches the packet source, and it drops a packet whose source
is not a configured peer. For multicast there is no configured peer list, so
the receiver keeps a small table of recent senders keyed by source address and
evicts the least recently used entry when the table is full. The table is
touched only after the HMAC verifies, so an attacker who floods forged source
addresses cannot churn it. A handful of slots suffice, because several
legitimate senders for one VRID appear only during a transient election.</t>

</section>
</section>
<section anchor="keys"><name>Key Management and Rotation</name>

<t>A key is 32 to 64 octets of secret material with an identifier from 1 to 255.
The 32-octet floor gives a 256-bit key, which keeps a 128-bit security margin
against Grover's quantum search algorithm <xref target="GROVER"/>, and 64 octets matches the
HMAC-SHA256 block, so a longer key would only be pre-hashed. Every node in a
group MUST hold the same keys under the same identifiers. Key material MUST
be cryptographically random or derived by a key derivation function
<xref target="RFC4086"/>, a human-chosen passphrase of the minimum length does not carry
the intended entropy. A key MUST NOT be reused by other protocols or
unrelated groups.</t>

<t>A sender signs with one active key. A receiver verifies against whichever key
the Key ID identifies, so a group can hold several keys at once. That overlap makes
rotation safe without downtime. The operator installs the new key under a new
identifier on every node, then moves the active key to the new identifier one
node at a time, and once no node signs with the old identifier, removes that
key everywhere. Signing and verifying keys never have to change in the same
instant, matching the send and accept lifetimes of <xref target="RFC8177"/>.</t>

<t>A key SHOULD be stored outside the VRRP configuration where the platform allows
it, for instance as an encrypted system credential that the service manager
unseals at start and exposes only to the running process. Keeping the secret
off disk at rest and out of the configuration file limits its exposure.</t>

</section>
<section anchor="migration"><name>Deployment and Migration</name>

<t>A node runs the extension in one of three modes, which differ only in whether
the node sends a trailer and whether it tolerates the absence of one. A
trailer that is present is always verified, and an advertisement whose
trailer fails verification is always dropped, in every mode.</t>

<dl newline="true" spacing="normal">
  <dt>receive-only</dt>
  <dd>
    <t>The node holds the keys and verifies a present trailer, accepts an
advertisement without a trailer, and sends without a trailer.</t>
  </dd>
  <dt>permissive</dt>
  <dd>
    <t>The node signs every advertisement it sends and still accepts one without a
trailer.</t>
  </dd>
  <dt>enforce</dt>
  <dd>
    <t>The node signs every advertisement it sends and drops one without a valid
trailer. This is the default, and a deployment that requires every
advertisement to be authenticated MUST use it.</t>
  </dd>
</dl>

<t>Because a receiver detects the trailer by length, a node that does not
implement the extension, or that does not hold the keys yet, can drop the
longer advertisements. A node therefore MUST NOT send a trailer before every
peer can accept one, which is the state receive-only establishes. Migration
takes three sweeps, and each sweep is hitless with no timing constraint
between nodes. First the operator configures the keys with receive-only on
every node, which changes nothing on the wire while every node becomes able
to verify. Then the operator switches every node to permissive, and signing
starts against peers that already accept trailers. Once trailers verify in
both directions everywhere, the operator switches every node to enforce,
after which untrailered advertisements are dropped.</t>

</section>
<section anchor="security-considerations"><name>Security Considerations</name>

<section anchor="threat-model"><name>Threat Model</name>

<t>The extension targets an adversary who can place a packet at a receiver with a
spoofed source address but does not hold the group key. For unicast this
includes any party that can reach the receiver across the routed or overlay
network, such as another tenant in a shared fabric or a compromised host in a
different subnet. For multicast it includes a host on the local link. The
adversary may inject forged advertisements and replay captured ones, aiming to
seize the virtual address by advertising a high priority, to force a failover
with priority 0, or to flap the group.</t>

</section>
<section anchor="what-the-extension-provides"><name>What the Extension Provides</name>

<t>A valid HMAC proves that the sender holds the group key and that the VRRP
message and the bound fields arrived intact. The pseudo-header (<xref target="pseudo"/>)
stops a captured trailer from being spliced onto another instance or accepted
from another source. The sequence number and, in time mode, the freshness
window reject replays. Against the
off-segment unicast attacker the extension restores the protection that the
hop-limit check gave on a shared link, and it does so whether or not that
check still applies.</t>

</section>
<section anchor="group-key"><name>Group Key</name>

<t>The scheme uses one symmetric key per group, so every member can impersonate
every other member. It defends the group perimeter, not one member against
another, which matches the VRRP trust model where all routers in a group are
mutually trusting. A compromised node exposes the key for the whole group, and
the response is to rotate the key out as in <xref target="keys"/>.</t>

</section>
<section anchor="migration-exposure"><name>Migration Exposure</name>

<t>The receive-only and permissive modes accept advertisements that carry no
trailer, so while any node runs one of them, an attacker who can place a
packet at that node injects an unsigned advertisement exactly as before the
extension. The protections of this document only hold once every node in the
group enforces. Migration modes exist to sequence a rollout, not to operate
in, so an operator SHOULD bound the time a group spends outside enforce mode.</t>

</section>
<section anchor="denial-of-service"><name>Denial of Service</name>

<t>A receiver computes at most one HMAC per packet that passes the cheap length
check and, in time mode, the freshness window, so replayed captures are shed
before the digest. Monotonic mode keeps no window, so there every well-formed
packet under a known key reaches the digest. A flood that clears these checks
still forces one HMAC per packet, so an operator SHOULD keep the usual rate
limiting and network-layer filtering in place.</t>

</section>
<section anchor="clock-dependence"><name>Clock Dependence</name>

<t>Time mode drops advertisements when the sender and receiver clocks differ by
more than the freshness window, so a group that uses it depends on time
synchronization for availability. Where that is not assured, monotonic mode
(<xref target="modes"/>) removes the dependency on clock agreement between nodes. An
operator SHOULD secure the time synchronization itself, since stepping a
sender or receiver clock becomes an availability attack.</t>

</section>
<section anchor="state-loss-and-replay"><name>State Loss and Replay</name>

<t>Replay state is volatile. After a receiver restart, time mode accepts a valid
capture once if it still lies inside the freshness window, so the replay
protection of this document is bounded by the window rather than absolute.
Monotonic mode accepts a valid capture of any age once after state loss.
After a sender recovers from a forward clock step (<xref target="seqnum"/>), the
advertisements signed during the incident stay replayable until their
timestamps leave the window.</t>

</section>
<section anchor="cryptographic-strength"><name>Cryptographic Strength</name>

<t>HMAC-SHA256 truncated to 128 bits gives 128-bit forgery resistance, which is
appropriate for a per-packet HMAC on a control protocol. The 256-bit minimum
key preserves a 128-bit margin under Grover's quantum search algorithm
<xref target="GROVER"/>. The receiver compares the HMAC in constant time so that the
comparison leaks no timing information about the expected HMAC.</t>

</section>
<section anchor="relationship-to-other-mechanisms"><name>Relationship to Other Mechanisms</name>

<t>Compared with IPsec and the IP Authentication Header <xref target="RFC4302"/>, the
extension avoids IKE and security-association state, works identically for
multicast and unicast, and rotates keys without downtime, at the cost of
being specific to VRRP and using a single group key. For a routed pair,
pairwise IPsec with IKEv2 additionally authenticates individual peers and
automates rekeying, properties this extension trades for deployment
simplicity.</t>

</section>
</section>
<section anchor="iana"><name>IANA Considerations</name>

<t>This document requests a new registry, "VRRP Authentication Extension Types",
for the 8-bit Ext Type field of <xref target="fig-trailer"/>. The initial contents are:</t>

<texttable>
      <ttcol align='right'>Value</ttcol>
      <ttcol align='left'>Description</ttcol>
      <ttcol align='left'>Trailer Length</ttcol>
      <ttcol align='left'>Reference</ttcol>
      <c>0</c>
      <c>Reserved</c>
      <c>&#160;</c>
      <c>This document</c>
      <c>1</c>
      <c>HMAC-SHA256, truncated to 128 bits</c>
      <c>28 octets</c>
      <c>This document</c>
      <c>2-255</c>
      <c>Unassigned</c>
      <c>&#160;</c>
      <c>&#160;</c>
</texttable>

<t>New assignments are made under the Specification Required policy of
<xref target="RFC8126"/> and MUST define the total trailer length, which receivers use
for detection (<xref target="receiving"/>). An Ext Type identifies one complete construction,
algorithm, truncation and trailer length. Constructions that differ in any
of these need distinct values, so the length always follows from the type.
The Key ID field of the trailer is a local
selector and is not managed by IANA.</t>

</section>


  </middle>

  <back>


    <references title='Normative References'>



<reference anchor='RFC1982'>
  <front>
    <title>Serial Number Arithmetic</title>
    <author fullname='R. Elz' initials='R.' surname='Elz'/>
    <author fullname='R. Bush' initials='R.' surname='Bush'/>
    <date month='August' year='1996'/>
    <abstract>
      <t>The DNS has long relied upon serial number arithmetic, a concept which has never really been defined, certainly not in an IETF document, though which has been widely understood. This memo supplies the missing definition. It is intended to update RFC1034 and RFC1035. [STANDARDS-TRACK]</t>
    </abstract>
  </front>
  <seriesInfo name='RFC' value='1982'/>
  <seriesInfo name='DOI' value='10.17487/RFC1982'/>
</reference>

<reference anchor='RFC2104'>
  <front>
    <title>HMAC: Keyed-Hashing for Message Authentication</title>
    <author fullname='H. Krawczyk' initials='H.' surname='Krawczyk'/>
    <author fullname='M. Bellare' initials='M.' surname='Bellare'/>
    <author fullname='R. Canetti' initials='R.' surname='Canetti'/>
    <date month='February' year='1997'/>
    <abstract>
      <t>This document describes HMAC, a mechanism for message authentication using cryptographic hash functions. HMAC can be used with any iterative cryptographic hash function, e.g., MD5, SHA-1, in combination with a secret shared key. The cryptographic strength of HMAC depends on the properties of the underlying hash function. This memo provides information for the Internet community. This memo does not specify an Internet standard of any kind</t>
    </abstract>
  </front>
  <seriesInfo name='RFC' value='2104'/>
  <seriesInfo name='DOI' value='10.17487/RFC2104'/>
</reference>

<reference anchor='RFC6234'>
  <front>
    <title>US Secure Hash Algorithms (SHA and SHA-based HMAC and HKDF)</title>
    <author fullname='D. Eastlake 3rd' initials='D.' surname='Eastlake 3rd'/>
    <author fullname='T. Hansen' initials='T.' surname='Hansen'/>
    <date month='May' year='2011'/>
    <abstract>
      <t>Federal Information Processing Standard, FIPS</t>
    </abstract>
  </front>
  <seriesInfo name='RFC' value='6234'/>
  <seriesInfo name='DOI' value='10.17487/RFC6234'/>
</reference>

<reference anchor='RFC9568'>
  <front>
    <title>Virtual Router Redundancy Protocol (VRRP) Version 3 for IPv4 and IPv6</title>
    <author fullname='A. Lindem' initials='A.' surname='Lindem'/>
    <author fullname='A. Dogra' initials='A.' surname='Dogra'/>
    <date month='April' year='2024'/>
    <abstract>
      <t>This document defines version 3 of the Virtual Router Redundancy Protocol (VRRP) for IPv4 and IPv6. It obsoletes RFC 5798, which previously specified VRRP (version 3). RFC 5798 obsoleted RFC 3768, which specified VRRP (version 2) for IPv4. VRRP specifies an election protocol that dynamically assigns responsibility for a Virtual Router to one of the VRRP Routers on a LAN. The VRRP Router controlling the IPv4 or IPv6 address(es) associated with a Virtual Router is called the Active Router, and it forwards packets routed to these IPv4 or IPv6 addresses. Active Routers are configured with virtual IPv4 or IPv6 addresses, and Backup Routers infer the address family of the virtual addresses being advertised based on the IP protocol version. Within a VRRP Router, the Virtual Routers in each of the IPv4 and IPv6 address families are independent of one another and always treated as separate Virtual Router instances. The election process provides dynamic failover in the forwarding responsibility should the Active Router become unavailable. For IPv4, the advantage gained from using VRRP is a higher-availability default path without requiring configuration of dynamic routing or router discovery protocols on every end-host. For IPv6, the advantage gained from using VRRP for IPv6 is a quicker switchover to Backup Routers than can be obtained with standard IPv6 Neighbor Discovery mechanisms.</t>
    </abstract>
  </front>
  <seriesInfo name='RFC' value='9568'/>
  <seriesInfo name='DOI' value='10.17487/RFC9568'/>
</reference>

<reference anchor='RFC2119'>
  <front>
    <title>Key words for use in RFCs to Indicate Requirement Levels</title>
    <author fullname='S. Bradner' initials='S.' surname='Bradner'/>
    <date month='March' year='1997'/>
    <abstract>
      <t>In many standards track documents several words are used to signify the requirements in the specification. These words are often capitalized. This document defines these words as they should be interpreted in IETF documents. This document specifies an Internet Best Current Practices for the Internet Community, and requests discussion and suggestions for improvements.</t>
    </abstract>
  </front>
  <seriesInfo name='BCP' value='14'/>
  <seriesInfo name='RFC' value='2119'/>
  <seriesInfo name='DOI' value='10.17487/RFC2119'/>
</reference>

<reference anchor='RFC8174'>
  <front>
    <title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</title>
    <author fullname='B. Leiba' initials='B.' surname='Leiba'/>
    <date month='May' year='2017'/>
    <abstract>
      <t>RFC 2119 specifies common key words that may be used in protocol specifications. This document aims to reduce the ambiguity by clarifying that only UPPERCASE usage of the key words have the defined special meanings.</t>
    </abstract>
  </front>
  <seriesInfo name='BCP' value='14'/>
  <seriesInfo name='RFC' value='8174'/>
  <seriesInfo name='DOI' value='10.17487/RFC8174'/>
</reference>

<reference anchor='RFC8126'>
  <front>
    <title>Guidelines for Writing an IANA Considerations Section in RFCs</title>
    <author fullname='M. Cotton' initials='M.' surname='Cotton'/>
    <author fullname='B. Leiba' initials='B.' surname='Leiba'/>
    <author fullname='T. Narten' initials='T.' surname='Narten'/>
    <date month='June' year='2017'/>
    <abstract>
      <t>Many protocols make use of points of extensibility that use constants to identify various protocol parameters. To ensure that the values in these fields do not have conflicting uses and to promote interoperability, their allocations are often coordinated by a central record keeper. For IETF protocols, that role is filled by the Internet Assigned Numbers Authority (IANA).</t>
      <t>To make assignments in a given registry prudently, guidance describing the conditions under which new values should be assigned, as well as when and how modifications to existing values can be made, is needed. This document defines a framework for the documentation of these guidelines by specification authors, in order to assure that the provided guidance for the IANA Considerations is clear and addresses the various issues that are likely in the operation of a registry.</t>
      <t>This is the third edition of this document; it obsoletes RFC 5226.</t>
    </abstract>
  </front>
  <seriesInfo name='BCP' value='26'/>
  <seriesInfo name='RFC' value='8126'/>
  <seriesInfo name='DOI' value='10.17487/RFC8126'/>
</reference>




    </references>

    <references title='Informative References'>



<reference anchor='RFC3768'>
  <front>
    <title>Virtual Router Redundancy Protocol (VRRP)</title>
    <author fullname='R. Hinden' initials='R.' role='editor' surname='Hinden'/>
    <date month='April' year='2004'/>
    <abstract>
      <t>This memo defines the Virtual Router Redundancy Protocol (VRRP). VRRP specifies an election protocol that dynamically assigns responsibility for a virtual router to one of the VRRP routers on a LAN. The VRRP router controlling the IP address(es) associated with a virtual router is called the Master, and forwards packets sent to these IP addresses. The election process provides dynamic fail over in the forwarding responsibility should the Master become unavailable. This allows any of the virtual router IP addresses on the LAN to be used as the default first hop router by end-hosts. The advantage gained from using VRRP is a higher availability default path without requiring configuration of dynamic routing or router discovery protocols on every end-host. [STANDARDS-TRACK]</t>
    </abstract>
  </front>
  <seriesInfo name='RFC' value='3768'/>
  <seriesInfo name='DOI' value='10.17487/RFC3768'/>
</reference>

<reference anchor='RFC4086'>
  <front>
    <title>Randomness Requirements for Security</title>
    <author fullname='D. Eastlake 3rd' initials='D.' surname='Eastlake 3rd'/>
    <author fullname='J. Schiller' initials='J.' surname='Schiller'/>
    <author fullname='S. Crocker' initials='S.' surname='Crocker'/>
    <date month='June' year='2005'/>
    <abstract>
      <t>Security systems are built on strong cryptographic algorithms that foil pattern analysis attempts. However, the security of these systems is dependent on generating secret quantities for passwords, cryptographic keys, and similar quantities. The use of pseudo-random processes to generate secret quantities can result in pseudo-security. A sophisticated attacker may find it easier to reproduce the environment that produced the secret quantities and to search the resulting small set of possibilities than to locate the quantities in the whole of the potential number space.</t>
      <t>Choosing random quantities to foil a resourceful and motivated adversary is surprisingly difficult. This document points out many pitfalls in using poor entropy sources or traditional pseudo-random number generation techniques for generating such quantities. It recommends the use of truly random hardware techniques and shows that the existing hardware on many systems can be used for this purpose. It provides suggestions to ameliorate the problem when a hardware solution is not available, and it gives examples of how large such quantities need to be for some applications. This document specifies an Internet Best Current Practices for the Internet Community, and requests discussion and suggestions for improvements.</t>
    </abstract>
  </front>
  <seriesInfo name='BCP' value='106'/>
  <seriesInfo name='RFC' value='4086'/>
  <seriesInfo name='DOI' value='10.17487/RFC4086'/>
</reference>

<reference anchor='RFC5082'>
  <front>
    <title>The Generalized TTL Security Mechanism (GTSM)</title>
    <author fullname='V. Gill' initials='V.' surname='Gill'/>
    <author fullname='J. Heasley' initials='J.' surname='Heasley'/>
    <author fullname='D. Meyer' initials='D.' surname='Meyer'/>
    <author fullname='P. Savola' initials='P.' role='editor' surname='Savola'/>
    <author fullname='C. Pignataro' initials='C.' surname='Pignataro'/>
    <date month='October' year='2007'/>
    <abstract>
      <t>The use of a packet's Time to Live (TTL) (IPv4) or Hop Limit (IPv6) to verify whether the packet was originated by an adjacent node on a connected link has been used in many recent protocols. This document generalizes this technique. This document obsoletes Experimental RFC 3682. [STANDARDS-TRACK]</t>
    </abstract>
  </front>
  <seriesInfo name='RFC' value='5082'/>
  <seriesInfo name='DOI' value='10.17487/RFC5082'/>
</reference>

<reference anchor='RFC4302'>
  <front>
    <title>IP Authentication Header</title>
    <author fullname='S. Kent' initials='S.' surname='Kent'/>
    <date month='December' year='2005'/>
    <abstract>
      <t>This document describes an updated version of the IP Authentication Header (AH), which is designed to provide authentication services in IPv4 and IPv6. This document obsoletes RFC 2402 (November 1998). [STANDARDS-TRACK]</t>
    </abstract>
  </front>
  <seriesInfo name='RFC' value='4302'/>
  <seriesInfo name='DOI' value='10.17487/RFC4302'/>
</reference>

<reference anchor='RFC8177'>
  <front>
    <title>YANG Data Model for Key Chains</title>
    <author fullname='A. Lindem' initials='A.' role='editor' surname='Lindem'/>
    <author fullname='Y. Qu' initials='Y.' surname='Qu'/>
    <author fullname='D. Yeung' initials='D.' surname='Yeung'/>
    <author fullname='I. Chen' initials='I.' surname='Chen'/>
    <author fullname='J. Zhang' initials='J.' surname='Zhang'/>
    <date month='June' year='2017'/>
    <abstract>
      <t>This document describes the key chain YANG data model. Key chains are commonly used for routing protocol authentication and other applications requiring symmetric keys. A key chain is a list containing one or more elements containing a Key ID, key string, send/accept lifetimes, and the associated authentication or encryption algorithm. By properly overlapping the send and accept lifetimes of multiple key chain elements, key strings and algorithms may be gracefully updated. By representing them in a YANG data model, key distribution can be automated.</t>
    </abstract>
  </front>
  <seriesInfo name='RFC' value='8177'/>
  <seriesInfo name='DOI' value='10.17487/RFC8177'/>
</reference>


<reference anchor='I-D.abinabraham-vrrp-unicast'>
   <front>
      <title>Unicast Support for the Virtual Router Redundancy Protocol (VRRP)</title>
      <author fullname='Aditya Dogra' initials='A.' surname='Dogra'>
         <organization>Cisco Systems</organization>
      </author>
      <author fullname='Abin Mathew Abraham' initials='A. M.' surname='Abraham'>
         <organization>Cisco Systems</organization>
      </author>
      <author fullname='Seshan Krishnamurthy' initials='S.' surname='Krishnamurthy'>
         <organization>Independent</organization>
      </author>
      <date day='28' month='May' year='2026'/>
      <abstract>
	 <t>   The Virtual Router Redundancy Protocol (VRRP) Version 3 as specified
   in RFC 9568 assumes multicast operation on a shared LAN.  Some
   deployments require the VRRP first-hop redundancy function but cannot
   use multicast delivery for VRRP advertisements.  This document
   updates RFC 9568 by defining an optional configured unicast mode for
   VRRP Version 3 in which advertisements are sent to configured peer
   addresses rather than to the VRRP multicast group.  The VRRP packet
   format, state machine, protocol number, virtual IP semantics, and
   Virtual Router MAC behavior remain unchanged from RFC 9568.

	 </t>
      </abstract>
   </front>
   <seriesInfo name='Internet-Draft' value='draft-abinabraham-vrrp-unicast-01'/>
   
</reference>


<reference anchor="GROVER" target="https://doi.org/10.1145/237814.237866">
  <front>
    <title>A Fast Quantum Mechanical Algorithm for Database Search</title>
    <author initials="L. K." surname="Grover" fullname="Lov K. Grover">
      <organization></organization>
    </author>
    <date year="1996"/>
  </front>
<refcontent>Proceedings of the 28th Annual ACM Symposium on Theory of Computing (STOC '96)</refcontent></reference>


    </references>


<section anchor="vectors"><name>Test Vectors</name>

<t>Both vectors use VRRPv3, VRID 51, priority 200, a one-second advertisement
interval and a single virtual address, signed with Ext Type 1 under Key ID 1
and this 32-octet key:</t>

<figure><artwork><![CDATA[
  00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
  10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f
]]></artwork></figure>

<t>The trailer carries Seconds 0x68000000, Subseconds 0x8000 and Counter 0. The
dumps show the payload as transmitted, so the Checksum field at octets 6 and
7 and the HMAC in the last 16 octets carry their final values, and both are
read as zero in the HMAC input.</t>

<section anchor="ipv4"><name>IPv4</name>

<t>The sender 198.51.100.10 advertises the virtual address 192.0.2.100. The
pseudo-header of <xref target="hmac"/> is:</t>

<figure><artwork><![CDATA[
  04 03 33 00 c6 33 64 0a 00 00 00 00 00 00 00 00
  00 00 00 00
]]></artwork></figure>

<t>The full HMAC-SHA256 before truncation is:</t>

<figure><artwork><![CDATA[
  1b84bc4e8e43892dc6d98448f8ee2265
  f674824d1bfd1c6e62aa1b5f4312fe4a
]]></artwork></figure>

<t>The IP payload as transmitted, VRRP message then trailer, is:</t>

<figure><artwork><![CDATA[
  31 33 c8 01 00 64 44 02 c0 00 02 64 01 01 00 00
  68 00 00 00 80 00 00 00 1b 84 bc 4e 8e 43 89 2d
  c6 d9 84 48 f8 ee 22 65
]]></artwork></figure>

<t>The checksum 0x4402 covers the message only <xref target="RFC9568"/>, without a
pseudo-header, and is therefore identical in every unicast peer copy.</t>

</section>
<section anchor="ipv6"><name>IPv6</name>

<t>The sender fe80::10 addresses the peer fe80::20 and advertises the virtual
address fe80::100, link-local as <xref target="RFC9568"/> requires. The pseudo-header of
<xref target="hmac"/> is:</t>

<figure><artwork><![CDATA[
  06 03 33 00 fe 80 00 00 00 00 00 00 00 00 00 00
  00 00 00 10
]]></artwork></figure>

<t>The full HMAC-SHA256 before truncation is:</t>

<figure><artwork><![CDATA[
  c8c56146ebfd66ee10ec4d8186461b78
  016459dfdb722df2300edca011646494
]]></artwork></figure>

<t>The IP payload as transmitted is:</t>

<figure><artwork><![CDATA[
  31 33 c8 01 00 64 a2 e9 fe 80 00 00 00 00 00 00
  00 00 00 00 00 00 01 00 01 01 00 00 68 00 00 00
  80 00 00 00 c8 c5 61 46 eb fd 66 ee 10 ec 4d 81
  86 46 1b 78
]]></artwork></figure>

<t>The transport checksum 0xa2e9 covers the whole payload, trailer and HMAC
included, which is why it is computed last and read as zero in the HMAC
input.</t>

</section>
</section>
<section anchor="acknowledgements"><name>Acknowledgements</name>

<t>This extension grew out of the keepalived project. Its design matured over
several iterations there, shaped by reports from operators who run keepalived
at scale and by seeing how widely VRRP now runs as unicast in cloud and
virtualized networks. The authors thank the keepalived users and contributors
whose feedback, testing, and field experience guided the work.</t>

<t>The authors thank Aditya Dogra for his thorough review, which uncovered real
defects and sharpened both the mechanism and this document.</t>

</section>

  </back>
</rfc>

