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; // Put the best route of every prefix in the kernel's routing table, so // that the machine forwards packets by them. Left out, the daemon only // speaks BGP and the machine's forwarding is not touched. Kernel kernel = 11; } // Installing routes in the kernel. Linux only; the daemon needs the // CAP_NET_ADMIN capability. // // The best route of a prefix is installed if its next hop is a neighbor: // an address in the network of one of the machine's interfaces. Routes // are marked as BGP's ("proto bgp"), and every route with that mark, the // table and the metric below is taken to be this daemon's: what it finds // at startup and no longer wants, it removes. When the daemon stops in // good order it removes its routes. message Kernel { // The routing table. Defaults to 254, the main table, which is the one // packets are forwarded by unless rules say otherwise. uint32 table = 1; // The metric of the routes. Defaults to 20. Of several routes for a // prefix the kernel uses the one with the lowest metric. uint32 metric = 2; // By default, where the kernel has nexthop objects (Linux 5.3 and // later), a gateway is put there once as such an object and routes name // it, which makes installing a full table about a third faster. `ip // route` then shows routes with "nhid". True has every route carry its // own gateway, as on older kernels. bool without_nexthop_objects = 3; // How long, after the daemon starts, routes of its own that an earlier // run left in the kernel are kept though no peer has announced them // (again). Defaults to 120. The daemon's table is empty until its peers // have sent theirs; removing the old routes at once would stop the // machine forwarding for as long as that takes. After this time, what // was not announced again is removed. uint32 stale_seconds = 4; } // 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. Not for a peer in our own AS. With it set: // // - Our OPEN says what we are to the peer, and a peer that says it is // something else than configured here is refused (RFC 9234). One side // having the other down as a customer and the other as a peer is how // leaks come about. // - Routes are marked "only to customer" as they come in from a provider, // a peer or a route server, and as they go out to a customer, a peer // or a route server client. A route with that mark that comes back up // from a customer, or across from a second peer, is a leak and is // refused. This cannot be turned off. // - Where rpki is configured, the AS paths of the peer's routes are // verified against the ASPAs: 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, none of this is done for the peer. Role role = 9; // Refuse the peer unless its OPEN says what it is. By default a peer // that says nothing (one that does not implement RFC 9234) is taken at // this configuration's word for it. Needs role. bool require_role = 10; } // 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; }