Skip to content

Latest commit

 

History

History
268 lines (199 loc) · 15.9 KB

bgp-role.md

File metadata and controls

268 lines (199 loc) · 15.9 KB

BGP Role (RFC 9234)

BGP Role enables route leak prevention by declaring the relationship between peers. When configured, ze adds the Only To Customer (OTC) path attribute to enforce proper route propagation based on the business relationship.

Configuration

bgp {
    peer upstream {
        remote { ip 10.0.0.1; as 65001; }
        local { ip 10.0.0.2; as 65000; }
        router-id 10.0.0.2

        role {
            import customer
            strict true
        }

        family { ipv4/unicast; }
    }
}

Config Reference

Path Type Default Description
role / import enum -- Declares local role and enables RFC 9234 ingress rules: provider, customer, rs, rs-client, peer
role / export list -- Destination roles that may receive routes: default, unknown, or explicit role names. See Export set
role / strict bool false Reject peers that don't advertise the Role capability

Role can be set at the group level and overridden per peer.

Role Values

Role Code Description
provider 0 Sells transit to customers
rs 1 Route server at an IXP
rs-client 2 Client of a route server
customer 3 Buys transit from providers
peer 4 Settlement-free peering

Valid Peer Pairs

The local and remote roles must form a valid pair:

Local Remote
provider customer
customer provider
rs rs-client
rs-client rs
peer peer

Mismatched roles cause a Role Mismatch NOTIFICATION (error 2, subcode 11).

OTC Filtering

The OTC (Only To Customer) attribute (type 35) prevents route leaks:

What role the procedures use

The Section 5 procedures act on what the PEER is to ze, not on what ze is to the peer. Ze resolves that value in one place, for the source peer on ingress and for the destination peer on egress.

Source When it is used
The Role capability in the peer's OPEN Whenever the peer sent one
The complement of the local import role When the peer sent no Role capability

RFC 9234 Section 4.2 settles the second row: "The locally configured BGP Role is used for the procedures described in Section 5." Section 8 names the non-compliant remote as the case the local AS must still stamp for. The complement is the pair table read the other way: customer means the peer IS a Provider, provider means the peer IS a Customer, rs-client means the peer IS an RS, rs means the peer IS an RS-Client, and peer means the peer IS a Peer.

These RFC procedures require a locally configured import role on the session. A destination that advertises a Role but has no local role config does not acquire RFC stamping, suppression or role-pair validation from that advertisement alone. Ze still observes its advertised role for the source's operator-selected export set.

The complement feeds the RFC MUST gates only. The export set below still reads the capability, because unknown there is an operator-selected target and not a missing answer.

On Receipt

Condition Action
OTC is malformed Treat-as-withdraw (RFC 7606)
OTC present, peer is Customer or RS-Client Route leak, mark ineligible
OTC present, peer is Peer, OTC value is not the peer's AS Route leak, mark ineligible
OTC absent, peer is Provider, Peer, or RS Add OTC with the peer's AS

On Send

Four checks run in order. The first one that fires decides.

# Check Action
1 The route carries OTC and the destination is a Provider, Peer, or RS Suppress (RFC 9234 Section 5, no source config needed)
2 The destination is a Provider, Peer, or RS, and ze's role toward the SOURCE is customer, peer, rs-client, or rs (the source is not a Customer) Suppress. This is the Gao-Rexford check of RFC 9234 Section 3.1: only a route learned from a Customer, or locally originated, goes upward or sideways
3 The source states export and the destination's capability role is outside that set Suppress. Operator policy, not an RFC gate
4 The destination is a Customer, Peer, or RS-Client, the UPDATE advertises a route, and OTC is absent Add OTC with ze's local AS for this session

Check 2 reads the ingress metadata when the route came through the ingress filter, and falls back to the source peer's own import role when it did not. A stored-route replay carries no ingress metadata, and a missing value used to select the permissive branch.

Check 4 does not depend on the source. A route from an iBGP peer, a route reflector client, a locally originated route, or an API-injected route reaches a Customer with OTC, because the RFC conditions that rule on the destination only.

Scope

Both tables act on a route, so OTC processing is bounded twice:

Bound Effect
Address family Only AFI 1 (IPv4) and AFI 2 (IPv6) with SAFI 1 (unicast). The family comes from MP_REACH_NLRI, or from MP_UNREACH_NLRI when the UPDATE only withdraws, so a VPN, EVPN, flowspec or multicast withdrawal is excluded exactly as its announcement is, per RFC 9234 Section 5's "MUST NOT be applied to other address families by default"
Reachable NLRI OTC is added only to an UPDATE that advertises a route. A withdraw-only UPDATE, an MP_UNREACH-only UPDATE and an End-of-RIB marker are forwarded untouched. Adding an attribute to them would produce a message RFC 4271 Section 4.3 says must not carry path attributes, which RFC 7606 Section 5.2 lets a conforming peer escalate to a session reset

Suppression is not bounded by the second rule: a route that already carries OTC is withheld from a Provider, Peer, or RS whether or not this particular UPDATE advertises it.

Export Set

role { export [ ... ] } names the destination roles that can receive routes from this peer. It is operator policy on top of the RFC gates, and it applies only when the SOURCE peer states it.

Token Meaning
default The RFC 9234 Section 5 defaults for the local role. See the table below
unknown Also send to a peer whose role ze does not know
An explicit role name provider, customer, peer, rs, rs-client
Local import default expands to
provider customer, rs-client
customer provider, rs, peer
rs rs-client
rs-client rs, provider
peer customer, rs-client

An unrecognized token is logged as a warning and kept as written, so it matches no destination.

unknown matches two states of a destination: a peer whose OPEN declared no role, and a peer whose OPEN was never recorded. The two suppress identically and are counted apart, so the drop reason tells an operator which one to look at. An unrecorded role points at validate-open, not at the export policy.

Groups and Dynamic Groups

A role stated on a group reaches every member. A configured peer already carries its group's role, merged at parse time. A member of a dynamic group has no entry in the configuration document, so ze resolves its role through its group.

Resolution is by address first and by group second, so a member that states its own role keeps it. Three decisions take that route: the Section 5 OTC gates, the Section 4.2 OPEN pair check with its strict mode, and the Role capability ze advertises to the member.

A learned role survives a configuration reload while the configuration still names the peer, or names the group a dynamic member belongs to. An established session sends no second OPEN, so a dropped learned role could not be written back.

Ze observes OPENs from configured roleless destinations and members of configured dynamic groups even when no source role is active. Their advertised roles serve export-set matching only. Each new OPEN replaces the prior observation, including recording an OPEN with no Role as unknown. Config commits prune removed peers and groups; the registered OPEN observer receives removal events independently of filter membership. Events free a peer's observation in generation order, so an old queued removal cannot delete a newer OPEN. Activating a source's export policy therefore uses the destination's current role without reconnecting it. OPENs for unconfigured roleless identities, including runtime-created peers outside this census, are not recorded.

Config That Cannot Be Reached

The runtime resolves role config by peer ADDRESS. A peer with no connection > remote > ip, and a name that is not an address, is logged as a warning and its role config is dropped. The group placeholder dynamic on a peer is refused the same way. Both used to be stored under a key nothing could look up, so the role was inert and silent.

Every drop is counted, and the first one of each reason raises a warning that names the peer. Later drops are counted only, with per-route detail at debug level.

Metric Reason labels
ze_role_route_rejects_total leak, malformed-otc
ze_role_route_suppressions_total otc-present, source-role, export-set, role-unrecorded

The label set is bounded at six series per metric. Peer identity is in the log line, never in a label.

role-unrecorded and export-set both mean the destination was outside the export set. They are counted apart because they call for opposite actions: export-set points at the policy, and role-unrecorded points at validate-open.

Strict Mode

When strict true is set, ze requires the peer to advertise the Role capability in its OPEN message. If the peer does not, ze sends a Role Mismatch NOTIFICATION and rejects the session.

When strict mode is off (default), ze proceeds even if the peer does not advertise Role. OTC filtering is applied based on the locally configured role.

The OTC Procedures a Role Inserts

A peer whose config sets role import carries bgp-role:otc-ingress at the head of its import list, with nothing for you to write. While any peer or dynamic group declares a role, every peer's export list carries bgp-role:otc-egress. Egress must reach destinations with no role too: the source's export set still controls whether they receive its routes. The plugin declares this through the generic any-peer insertion scope.

The members run the RFC 9234 Section 5 procedures described above, the same way whether bgp-role runs inside Ze or as its own process. On import a leaked route is withdrawn, as is an UPDATE whose OTC is malformed, and a route that must carry OTC gets it; on export a route that must not reach the peer is not sent, and one that must carry OTC gets the local AS.

Both members are required. RFC 9234 Section 5 says "The operator MUST NOT have the ability to modify the procedures defined in this section." So a chain that names either member, plain or inactive:, is refused at load with that sentence, naming the peer, the list and the member. A peer with no role import has no ingress member, but its required egress member remains while any source declares a role. With no roles anywhere, neither member is inserted.

The Upstream Check a Role Inserts

A declared role puts one more member in the peer's filter list, with nothing for you to write: bgp-role:upstream-asn. It rejects a route whose AS path carries the ASN of one of your transit providers, at any position, an AS_SET member included. RFC 7454 Section 9 recommends it twice: a customer's routes "must not be accepted" when their paths hold "upstream transit providers", and "Network administrators SHOULD NOT advertise prefixes with upstream AS numbers in the AS path to their peering AS".

Your role import The session is to The check runs on
provider a customer import
peer a peer import and export
rs an RS-client import
rs-client a route server export
customer a provider nowhere: every route a provider sends carries its own ASN

The providers are derived from the config you already wrote: the remote ASN of every peer whose role import is customer (RFC 9234 Section 3.1: "the local AS is a transit customer of the remote AS"). A provider this router does not peer with, one reached through another router of your network, goes in a policy asn-set, named by role transit-asns on any peer or group. The check compares the union of the two, and never the session's own remote ASN.

Provider discovery uses the same role inheritance as the session: a peer declaring its own role import overrides its group; a peer with only transit-asns or the default strict false still inherits the group's role. Transit sets named on the peer and group both contribute to the union.

policy {
    asn-set far-transit {
        asn [ 64700 64701 ];
    }
}
bgp {
    group customers {
        role {
            import provider;
            transit-asns far-transit;
        }
    }
}

With no provider peer and no transit-asns, the set is empty and the member rejects nothing: a network with no transit provider has no upstream ASN that can leak. Adding or removing a provider peer, or editing the asn-set, takes effect on the next route with no session reset. The member is not required, because RFC 7454 is a Best Current Practice: name it as inactive:bgp-role:upstream-asn in a chain to run that session without it.

Without Role

A peer with no role has no OTC ingress procedure and no inserted upstream check: no relationship is declared for that session. Its export list still runs the OTC egress procedure while any peer declares a role, so a source's export set cannot be bypassed by omitting the destination's role. With no roles anywhere, no OTC members are inserted.

ze says so rather than passing in silence. The role plugin writes ONE warning naming how many peers and dynamic groups declare no role and the first few by name, each time it installs a config (at start and at every reload) and when ze config validate checks one. ze doctor reports every one of them under doctor-bgp-peer-no-role. All three read the same set, so they always name the same peers.

A dynamic group is named with the peers. Its members' AS arrives in the OPEN (RFC 4271 Section 4.2), so ze cannot know a listen range is eBGP, and an IXP route-server range that declares no role is exactly what the report is for. An iBGP peer is left out: a role describes an eBGP relationship, so a route reflector's sessions owe none.