09/05/2025 | Press release | Distributed by Public on 09/04/2025 22:31
Accidental route leaks and hijacks have been business-as-usual ever since Yakov Rekhter and Kirk Lougheed sketched out the Border Gateway Protocol (BGP) on two napkins 35 years ago. It has taken all this time to realize that a very simple tweak, though very limited in its nature, could have prevented the vast majority of those incidents. That tweak is now defined in RFC 9234, which, as I said, is something we wish had existed back then.
But it's never too late. The RFC was published three years ago, and the first implementations are now appearing. Quagga/FRR have already implemented it, and there's a patch available for BIRD. The first commercial implementation has also arrived - HPE Juniper Networking supports RFC 9234 as of Junos OS Release 25.2R1. More vendors are likely to follow!
In its essence, RFC 9234 is simple. It's directly derived from the model of relationships between two adjacent Autonomous Systems (ASes) in BGP, which in its nature can be either provider-customer, often being offered to the customer by their provider under a commercial agreement or peering, which is often settlement-free. And every network engineer who ever touched BGP knows that with respect to each BGP neighbor, your network can play one of the following roles:
Or, in a nutshell:
In its original specification, BGP did not account for the roles an AS might have with respect to its neighbors. The standard left every AS free to define routing policies however they wished. In theory, any AS can be configured to provide transit to anyone else. Yet, even early experiments back in 1991 showed that once NSFNET was decommissioned in 1995, leaving BGP to operate solely on AS-PATH length would lead to an unmanageable situation. The need for routing controls gave rise to the concept of roles, as well as the well-known Tier 1/2/3 architecture of the global network - a structure that has shaped interconnection ever since, with some recent refinements, as excellently observed by Nina Hjorth Bargisen in her article on the RouteViews site
Still, nothing changes with respect to the roles of Customer, Peer, and Provider and the way we implement those. Traditionally, we needed complex routing policies on our BGP-speaking routers to implement those, such as Cisco route-map / route-policy, Juniper/Nokia policy-statement, and so on. In those policies, we had to ensure that:
This is shown in Figure 2. AS B, together with its customers E and F, forms the 'AS B Customer Cone'. Similarly, AS C with D and E forms another cone. As shown, AS E is a customer of both C and B, so it belongs to both cones. Hence, customer cones may overlap with each other, and that's normal.
At the edges, the 'leaf' networks (D, E, F, and I) advertise only the IP prefixes originating in their ASes to their upstream providers (C, B, and H). In turn, C, B, and H advertise their entire customer cones to their own upstreams (A and G). Meanwhile, A and G, as well as B and H, maintain peering relationships with one another, exchanging only the routes from their respective cones.
Typically, implementing routing policies like this involves creating BGP import / export policies towards a BGP neighbor, where we implement the policies stated above. For instance, if we model the network shown in Figure 1 with one router for each network, the configuration of the router AS200 would look like Figure 3.
In the Internet Routing Registries (IRRs) such as the RIPE Database or RADB, these relationships are documented using RPSL in the following way:
The traditional way
As operators have been doing for decades, the more or less classical way of implementation of the above-defined rules is performed as follows:
For instance, in Junos, this would be implemented using standard BGP import/export policies. For simplicity, we'll show only the export policies that implement the rules above, and only an excerpt of them. The import policies are symmetrical:
Although we've been doing this for years, mistakes still happen. Automation helps reduce errors, but urgent, manual changes to router configurations - often made under pressure during critical outages - can easily introduce problems. What if the wrong community is applied? What if the export policy isn't referenced in the BGP neighbor configuration?
The example above is very simple. Now imagine a network with 2,000 BGP neighbors, each with its own pair of import/export policies, and each policy containing hundreds of terms. It's easy for one term to be overlooked. Most of the time, this leads to unwanted route leaks.
For instance, suppose we forget to apply the policy in the BGP neighbor configuration between AS100 and AS200, instead of advertising only the routes of AS200 and AS250:
We would have:
In other words, we are leaking AS1, AS2, and AS3 routes to AS100. Not good - and certainly not how it's meant to work. If AS100 had a higher local preference for routes learned from a Peer than from a Provider, it would prefer to reach AS1, AS2, and AS3 via AS200 instead of using its direct links (see Figure 1). In this simple example, the mistake is easy to spot and correct, but what if the scenario were much more complex?
RFC 9234 - the safety pin
RFC 9234 offers a neat solution, the so-called Only-To-Customer (OTC) BGP Capability and Attribute. HPE Juniper Networking has recently implemented this, providing a simple way to prevent issues like the one described.
As mentioned earlier, RFC 9234 is straightforward - it defines the of your AS with respect to each of your neighbors. While your policies and neighbor classes may vary, it's important to emphasize that RFC 9234 roles are defined from the perspective of your own AS relative to the rest of the Internet. As shown in Figure 3 above:
How do we use this? The basic usage is simple. Just go to your BGP configuration and add the knob:
And that's it. You can configure this at the BGP global level (), group level (), or neighbor level (), as documented in the Junos Reference for the knob.
Important note: Committing the configuration above will reset all BGP sessions. Changing the role of a group or neighbor or deleting the OTC role will reset all BGP sessions for that group or neighbor. Keep this in mind when applying changes.
Once you commit the configuration, even though you forgot the BGP export policy on AS200 towards AS100, you will notice that AS200 now advertises the routes correctly:
So we fixed it, and no policy included! Yay!
However, even though this knob can simplify your routing policies, remember that it is not a Swiss-army knife for every scenario, nor a cure-all for poor routing architecture or design. It is certainly not intended to be used as the sole mitigation tool. Well-crafted routing policies, respecting the principles in RFC 8212 and MANRS, remain essential.
Think of this feature as a safety pin or 'circuit breaker', protecting you and your BGP neighbors in the same way that RCD breakers safeguard electrical installations and appliances in your home.
RFC 9234 Principle of Operation - in a Nutshell
Just like any other BGP extension, this one is also based on two mechanisms:
How is that latter attribute used? Suppose AS200 had another customer - AS500. If no export policies are used and the BGP roles are correctly set on the AS200 router for AS500 (provider), the routes received from AS100 should be propagated to AS500, but not to AS2 or AS100. Let's check the route 150.150.0.0/16 coming from AS100, and let's disable the direct BGP session between AS200 and AS250:
So, with AS_PATH: 100 250, is correctly advertised to AS500, while not being advertised to AS1, so this is fine.
Strict or loose?
As mentioned before, when a BGP session is established and roles are defined, they are exchanged in the messages using BGP OTC Capability. But what if one of the neighbors does not support this capability? As with any other BGP Capability, it will be ignored by the neighbor not supporting it. However, RFC 9234 Chapter 4.2, envisages a slightly different handling of this attribute:
How does strict mode work? Let's configure it on AS100 for the BGP session with AS200, and then remove the OTC role from the AS200 router, for example:
Now, let's commit this configuration on both sides and check the syslog:
Policy-based OTC role override
Sometimes, setting a fixed role per BGP group or neighbor may be insufficient. Twenty years ago, in the traditional ISP environment, especially within Tier 1 carrier networks with well-structured and (mostly) clean BGP policies, this limitation was rarely an issue. But in the mobile and enterprise segments, it can create restrictions. For example, what if a neighbor is defined as a Peer, yet you still need to leak a route received from them to other peers or even transit providers? In mobile core networks, this situation is not unusual, it is often the norm.
Junos has a nice solution for that, too! You can override a role for one or more prefixes, routes having certain attributes (AS-PATH, community, and so on) or whatever you can match in the Routing Policy Match Conditions ('from' statement) and assign it a specific OTC Role within the Routing Policy Actions ("then" statement). As of Junos 25.1R2, there is an action for that:
Let's see this one in action now. Let AS200 advertise the route to AS100, aside of the /16 route:
Let's check what AS100 receives:
So far, so good. Now, let's check what AS100 advertises to its providers, for example, AS1:
That's correct. Now, suppose AS100 needs to leak the prefix , which it received from its peer AS200, towards its upstream providers (AS1 and AS2). Since AS100 has assigned AS200 the Peer role, any routes received from AS200 are blocked from being propagated to other peers or providers, that is, to neighbors for which AS100's local role is Peer or Customer. Simply adding an exception in the EBGP export policy toward AS1 and AS2, without overriding the OTC Local Role, will not work. The routes will still be filtered:
Remember this very important rule: OTC Local Role setting has an absolute priority over anything explicitly set in the BGP import/export routing policies. No matter how specific that setting is, OTC Local Role overrides this and acts as a safety pin for any wrongly constructed routing policy.
But as mentioned above, we have a solution - override OTC Local Role for the individual prefix within the EBGP export policy towards AS1 and AS2:
After committing, we get this:
Now AS100 is nicely leaking the route to its upstream transit providers AS1 and AS2, even though it is received from its peer AS200. And that's precisely what we wanted to achieve.
Berislav Todorovic is a seasoned network architect, being active for more than 30 years in the industry. Currently working as a Professional Services Consultant at Juniper Networks, where he is actively involved in the design and implementation of large-scale IP/MPLS networks and complex service provider network migration projects.
Originally posted at LinkedIn.
The views expressed by the authors of this blog are their own and do not necessarily reflect the views of APNIC. Please note a Code of Conduct applies to this blog.