Hi. I was working on a route server configuration for BIRD and while it's commonplace and often publicly documented [1, 2] that a route server checks that the origin AS number is in the as-set, then I didn't find a single route server documentation which states that the entire AS-path is checked. Same is true for software [3] used for building the route servers configuration. I mean that in principle, route servers running BIRD and checking that the origin AS is in as-set may call a similar function in their ingress filters: function origin_as_in_asset(int peer_as) -> bool { case peer_as { # FOO (as-set: AS-FOO) # Content of AS-FOO_as_numbers.conf file: # [65536,65537, # 65538,65539] 64501: return bgp_path.last ~ include "/etc/bird/AS-FOO_as_numbers.conf";; # BAR (as-set: AS-BAR) 64502: return bgp_path.last ~ include "/etc/bird/AS-BAR_as_numbers.conf";; else: return false; } }; A stricter approach checking the entire AS path would be something like this: function as_in_asset(int peer_as) -> bool { case peer_as { # FOO (as-set: AS-FOO) 64501: for int asn in bgp_path do { if asn !~ include "/etc/bird/AS-FOO_as_numbers.conf"; then { #printn "Invalid AS number: ", asn, "; "; return false; } } # BAR (as-set: AS-BAR) 64502: for int asn in bgp_path do { if asn !~ include "/etc/bird/AS-BAR_as_numbers.conf"; then { #printn "Invalid AS number: ", asn, "; "; return false; } } # Exception. For AS 64503 check only the origin AS number. 64503: return bgp_path.last ~ include "/etc/bird/AS-BAZ_as_numbers.conf";; else: return false; } return true; }; For example, the second approach would have rejected those two route leaks: martin@lab-svr:~$ # AS 21217 announces a prefix from its upstream AS 25091 to its other upstream AS 47176 which accepts the prefix martin@lab-svr:~$ # 91.206.52.252 is rs1 of SwissIX martin@lab-svr:~$ curl -s https://data.ris.ripe.net/rrc20/2026.01/updates.20260102.1440.gz | bgpdump -m -v - | awk -F '|' '$4 == "91.206.52.252" && $7 == "47176 21217 25091 3303 50350"' BGP4MP|1767364961|A|91.206.52.252|42476|193.104.238.0/24|47176 21217 25091 3303 50350|IGP|91.206.52.39|0|0||AG|50350 193.104.238.209| martin@lab-svr:~$ martin@lab-svr:~$ # AS 56635 announces a prefix from its upstream AS 12778 to its other upstream AS 3212 which accepts the prefix martin@lab-svr:~$ curl -s https://data.ris.ripe.net/rrc20/2026.01/updates.20260111.1950.gz | bgpdump -m -v - | awk -F '|' '$4 == "91.206.52.252" && $7 == "21215 3212 56635 12778 197944"' BGP4MP|1768161244|A|91.206.52.252|42476|91.230.90.0/24|21215 3212 56635 12778 197944|IGP|91.206.52.96|0|0||NAG|| martin@lab-svr:~$ Or those ones, which seem to be a typo in AS path prepending: martin@lab-svr:~$ curl -s https://data.ris.ripe.net/rrc20/2026.01/updates.20260110.2020.gz | bgpdump -m -v - | awk -F '|' '$4 == "91.206.52.252" && $7 == "24961 50873 41451 45415 41451"' BGP4MP|1768076675|A|91.206.52.252|42476|195.43.80.0/23|24961 50873 41451 45415 41451|IGP|91.206.52.217|0|100030|24961:4 24961:100 24961:200 24961:300|NAG|41451 185.46.172.254| BGP4MP|1768076675|A|91.206.52.252|42476|195.43.80.0/23|24961 50873 41451 45415 41451|IGP|91.206.53.33|0|100030|24961:4 24961:100 24961:200 24961:300|NAG|41451 185.46.172.254| BGP4MP|1768076675|A|91.206.52.252|42476|195.43.80.0/23|24961 50873 41451 45415 41451|IGP|91.206.52.217|0|100030|24961:4 24961:100 24961:200 24961:300 24961:9001|NAG|41451 185.46.172.254| martin@lab-svr:~$ Performance-wise this for-loop approach would take around 90 us per prefix if the AS path contains excessive 32 AS numbers and the as-set file contains 100k AS numbers. Or 8 - 10 us per prefix if the AS path contains 10 AS numbers and the as-set file contains 1k AS numbers. I tested using the clock_gettime() in BIRD version 3.2.1. In summary, I simply wanted to share this idea. Perhaps such stricter checking is applicable for small and regional exchanges. However, it requires that both route servers use BIRD, as to my knowledge, OpenBGPD or any NOS like Junos does not support checking each AS path element against some dataset. Also, wider adoption of ASPA on route servers would prevent such route leaks. [1] https://www.swissix.ch/resources/route-server-guide/ [2] https://www.lonap.net/tech/route-servers2#filterpolicy [3] https://github.com/pierky/arouteserver Martin