Origin validation says who may originate a prefix and nothing about the
rest of the path: it does not catch a route leak, nor a hijack that keeps
the right origin at the end of a made-up path. ASPAs, in which a network
lists its providers, do.
bgp-rpki:
- aspa: the ASPAs and the upstream and downstream verification procedures
of draft-ietf-sidrops-aspa-verification-24, tested against the draft's
wording as written.
- rtr: protocol version 2 (draft-ietf-sidrops-8210bis-23) with the ASPA
PDU and the new error codes.
- client: asks for version 2 and falls back to whatever older version the
cache speaks; keeps ASPAs with the VRPs, applied whole or not at all;
publishes which customers' ASPAs changed; tells the cache why it is
being left (Error Report); does not ask one version's serial of another.
Server:
- A peer has a role (provider, customer, peer, route server, route server
client), which decides how its paths are verified. Without one they are
not.
- A route whose path is invalid is refused ("ASPA invalid") and held, like
one with an invalid origin; accept_aspa_invalid exempts a peer.
- When ASPAs change, routes in the table whose path has a changed customer
on it are verified again, and held routes are released when they pass
both checks.
- The revalidator finds a route's peer by index instead of searching a
list for every route.
The status page and API show each peer's role, each route's path validity,
the number of ASPAs and the RTR version in use; bgp_rpki_aspas is on
/metricz.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
255 lines
9.7 KiB
Protocol Buffer
255 lines
9.7 KiB
Protocol Buffer
syntax = "proto3";
|
|
|
|
package bgp.server;
|
|
|
|
// Top level BGP Server configuration.
|
|
message BgpConfig {
|
|
// The router ID, written as a dotted-quad IPv4 address (e.g. "192.0.2.1").
|
|
// Required even on IPv6-only routers per RFC 4271.
|
|
string router_id = 1;
|
|
|
|
// The local 4-byte AS number (RFC 6793).
|
|
uint32 local_asn = 2;
|
|
|
|
// Endpoints to accept incoming BGP connections on.
|
|
// Defaults to 0.0.0.0:179 and [::]:179 when empty.
|
|
repeated TcpEndpoint listen_endpoints = 3;
|
|
|
|
// Peers configured on this server.
|
|
repeated Peer peers = 4;
|
|
|
|
// Routes this router originates and announces to every peer.
|
|
repeated OriginatedRoute originate = 5;
|
|
|
|
// Where to serve the HTTP API, status page and metrics. The port is
|
|
// required. Unset disables the HTTP server.
|
|
TcpEndpoint http_endpoint = 6;
|
|
|
|
// Initial delay between attempts to connect to a configured peer, in
|
|
// seconds. Doubles after each failure up to two minutes. Defaults to 5.
|
|
uint32 connect_retry_seconds = 7;
|
|
|
|
// Connection collisions (RFC 4271 §6.8) against a session that is already
|
|
// Established are, by default, resolved by closing the new connection.
|
|
// When true they are resolved like any other collision: the connection
|
|
// initiated by the higher BGP Identifier survives, and a second connection
|
|
// opened by the same side replaces the first. This lets a peer that
|
|
// restarted take over from a session we have not yet noticed is dead,
|
|
// instead of being refused until the hold timer expires.
|
|
bool collision_detect_established_state = 8;
|
|
|
|
// Connections are accepted only from the addresses of configured peers;
|
|
// from anywhere else they are closed before a byte is read. When true,
|
|
// any host that can reach a listening endpoint may open a session, as
|
|
// any AS it cares to name, and have its routes taken. That is for
|
|
// testing on a closed network and nothing else.
|
|
bool accept_unconfigured_peers = 9;
|
|
|
|
// Route origin validation (RFC 6811) and AS path verification with the
|
|
// RPKI. Left out, routes are not validated.
|
|
Rpki rpki = 10;
|
|
}
|
|
|
|
// Where to get the validated ROA payloads that say which AS may originate
|
|
// which prefixes. With this set, a route whose origin is not authorised
|
|
// for its prefix ("invalid") is refused, from every peer that is not in
|
|
// our own AS and does not have accept_rpki_invalid set. Routes that
|
|
// nothing is known about are taken as before.
|
|
//
|
|
// A validator that speaks version 2 of the protocol also gives the ASPAs,
|
|
// in which networks say who their providers are. With those, a route
|
|
// whose AS path cannot have come about by networks passing routes on as
|
|
// they should (a route leak, or a made-up path) is refused, from every
|
|
// peer that has a role set and does not have accept_aspa_invalid set.
|
|
message Rpki {
|
|
// The RPKI-to-Router servers (RFC 8210, draft-ietf-sidrops-8210bis) of
|
|
// one or more validators, such as Routinator, rpki-client with StayRTR,
|
|
// or FORT, in order of preference. The port is required. One is used at
|
|
// a time, over plain TCP: keep it on a network you trust.
|
|
repeated TcpEndpoint caches = 1;
|
|
|
|
// How often to ask the cache for changes unprompted, how long to wait
|
|
// before trying again after a failure, and how long the data may be used
|
|
// without a cache confirming it, after which nothing is invalid any
|
|
// more. Each defaults to what the cache says, or to 3600, 600 and 7200.
|
|
uint32 refresh_seconds = 2;
|
|
uint32 retry_seconds = 3;
|
|
uint32 expire_seconds = 4;
|
|
}
|
|
|
|
// A route originated by this router. It is announced with an AS_PATH of the
|
|
// local AS and, on each session, that session's local address as next hop.
|
|
message OriginatedRoute {
|
|
// The prefix in CIDR notation, e.g. "192.0.2.0/24" or "2001:db8::/32".
|
|
string prefix = 1;
|
|
|
|
// ORIGIN attribute: "IGP" (the default), "EGP" or "INCOMPLETE".
|
|
string origin = 2;
|
|
|
|
// Extra copies of the local AS to prepend to the AS_PATH. At most 16.
|
|
uint32 as_path_prepend = 3;
|
|
|
|
// MULTI_EXIT_DISC. Left out of the announcement when unset.
|
|
optional uint32 med = 4;
|
|
|
|
// Standard communities (RFC 1997): "ASN:VALUE", or a well-known name such
|
|
// as "NO_EXPORT".
|
|
repeated string communities = 5;
|
|
|
|
// Large communities (RFC 8092): "GLOBAL:LOCAL1:LOCAL2".
|
|
repeated string large_communities = 6;
|
|
}
|
|
|
|
// An IP address and port pair.
|
|
message TcpEndpoint {
|
|
// IP address (V4 or V6).
|
|
string address = 1;
|
|
// TCP port. Defaults to 179 for BGP when unset.
|
|
uint32 port = 2;
|
|
}
|
|
|
|
// Configuration of a BGP peer.
|
|
message Peer {
|
|
// Human-readable name for logging and diagnostics.
|
|
string name = 1;
|
|
|
|
// Address and port to connect to for this peer.
|
|
TcpEndpoint endpoint = 2;
|
|
|
|
// The peer's 4-byte AS number (RFC 6793).
|
|
uint32 remote_asn = 3;
|
|
|
|
// Hold time to advertise in the OPEN message, in seconds (RFC 4271 §4.2).
|
|
// Must be 0 or >= 3. Defaults to 90 when unset.
|
|
uint32 hold_time_seconds = 4;
|
|
|
|
// Source IP address for connections we open to this peer. It is also the
|
|
// next hop of the routes we send it. Required when the peer identifies us
|
|
// by address and the host has several, e.g. when both speakers run on the
|
|
// same machine. Must be the same address family as the endpoint. Unset
|
|
// lets the operating system choose.
|
|
string local_address = 5;
|
|
|
|
// The address families to exchange with this peer. Each is offered to the
|
|
// peer in our OPEN, and is in use on the session only if the peer offers
|
|
// it too (RFC 4760). Defaults to all of them when empty. A session with
|
|
// no family in common is refused.
|
|
repeated AddressFamily address_families = 6;
|
|
|
|
// ADD-PATH (RFC 7911): whether to take several routes for one prefix
|
|
// from this peer, to send it several, or both. It is in use, for each
|
|
// direction and address family, only if the peer agrees. Defaults to
|
|
// off: one route for each prefix, as in plain BGP.
|
|
AddPath add_path = 7;
|
|
|
|
// Which of the peer's routes are taken. Left out, the general checks
|
|
// apply and there is no limit and no list.
|
|
ImportPolicy import = 8;
|
|
|
|
// What the peer is to us. It decides how the AS paths of its routes are
|
|
// verified against the ASPAs, where rpki is configured: a route from a
|
|
// customer, a peer or a route server must have come up through
|
|
// providers all the way; one from a provider may have come up and then
|
|
// down. Left out, the paths of the peer's routes are not verified.
|
|
Role role = 9;
|
|
}
|
|
|
|
// What a peer is to us.
|
|
enum Role {
|
|
ROLE_UNSPECIFIED = 0;
|
|
// We buy transit from the peer.
|
|
PROVIDER = 1;
|
|
// The peer buys transit from us.
|
|
CUSTOMER = 2;
|
|
// The peer and we exchange our own and our customers' routes.
|
|
PEER = 3;
|
|
// The peer is an Internet exchange's route server.
|
|
ROUTE_SERVER = 4;
|
|
// We are a route server and the peer is one of our clients.
|
|
ROUTE_SERVER_CLIENT = 5;
|
|
}
|
|
|
|
// What is taken from a peer. Every route is judged before it goes into
|
|
// the routing table. One that is refused is dropped, and so is the route
|
|
// it would have replaced.
|
|
//
|
|
// A route whose AS path holds our own AS number is always refused.
|
|
message ImportPolicy {
|
|
// The most routes the peer may have at a time. One more ends the session
|
|
// with Cease / Maximum Number of Prefixes Reached, and the peer is kept
|
|
// down for hold_down_seconds. Set it somewhat above what the peer is
|
|
// expected to send. Zero is no limit.
|
|
uint32 max_prefixes = 1;
|
|
|
|
// How long the peer is kept down after going over max_prefixes. Neither
|
|
// side's connections are taken meanwhile. Defaults to 600.
|
|
uint32 hold_down_seconds = 2;
|
|
|
|
// By default, prefixes that are not routed on the Internet are refused
|
|
// (private, loopback, link-local, documentation, multicast and reserved
|
|
// space), and so are routes with a reserved, private or documentation AS
|
|
// number anywhere in their path. True takes them.
|
|
bool accept_bogons = 3;
|
|
|
|
// By default a default route (0.0.0.0/0 or ::/0) is refused. True takes
|
|
// one, as from an upstream that is asked to send it.
|
|
bool accept_default_route = 4;
|
|
|
|
// The longest prefixes taken. Default to 24 and 48, the longest that are
|
|
// routed between networks.
|
|
uint32 max_ipv4_prefix_length = 5;
|
|
uint32 max_ipv6_prefix_length = 6;
|
|
|
|
// By default the AS path of a route has to begin with the peer's own AS
|
|
// number. True takes any, as is needed for an Internet exchange's route
|
|
// server, which does not put its AS on the path.
|
|
bool accept_any_first_as = 7;
|
|
|
|
// The longest AS path taken, counted in AS numbers. Defaults to 64.
|
|
uint32 max_as_path_length = 8;
|
|
|
|
// The prefixes the peer may announce. Empty allows any. This is the
|
|
// list generated for a peer from the routing registries (with bgpq4,
|
|
// say).
|
|
repeated PrefixRange prefixes = 9;
|
|
|
|
// The AS numbers the peer's routes may originate from: the last AS of
|
|
// the path. Empty allows any.
|
|
repeated uint32 origin_asns = 10;
|
|
|
|
// By default, where route origin validation is configured (rpki), a
|
|
// route that is invalid is refused. True takes it all the same.
|
|
bool accept_rpki_invalid = 11;
|
|
|
|
// By default, where the validator gives ASPAs and the peer has a role,
|
|
// a route whose AS path they find invalid is refused. True takes it all
|
|
// the same.
|
|
bool accept_aspa_invalid = 12;
|
|
}
|
|
|
|
// A prefix, and optionally the more specific prefixes inside it.
|
|
message PrefixRange {
|
|
// In CIDR notation, e.g. "193.0.0.0/21".
|
|
string prefix = 1;
|
|
// The longest prefix inside it that is also allowed. Left out, only the
|
|
// prefix itself is.
|
|
uint32 max_length = 2;
|
|
}
|
|
|
|
// The directions ADD-PATH can be offered for.
|
|
enum AddPath {
|
|
ADD_PATH_OFF = 0;
|
|
// Accept several routes for a prefix from the peer.
|
|
ADD_PATH_RECEIVE = 1;
|
|
// Send the peer several routes for a prefix.
|
|
ADD_PATH_SEND = 2;
|
|
ADD_PATH_BOTH = 3;
|
|
}
|
|
|
|
// An address family routes can be exchanged for.
|
|
enum AddressFamily {
|
|
ADDRESS_FAMILY_UNSPECIFIED = 0;
|
|
IPV4_UNICAST = 1;
|
|
IPV6_UNICAST = 2;
|
|
}
|