IPv6 BGP filter recommendations

This page is meant to give some recommendations and examples regarding BGP filter lists (prefix lists) that people might want to use to reduce the number of crappy routes in the global IPv6 network.

1. Motivation

Mistakes happen.... The goal of BGP prefix filtering is to contain the mistakes to the AS where they originate, and not distribute them all around the world.

There is nothing special about IPv6 here, all the things apply to IPv4 as well. The difference is just that the IPv6 world is small enough to be able to do get right in the early stages.

2. Filtering routes coming from customers

This is the easy part. In the IPv6 BGP world, it is to be expected that customer networks originate only a single prefix, or very few prefixes, from a single origin AS. So the list of ``permitted'' prefixes is quite short, and could even be maintained manually.

Such a prefix list would be very explicit: permit the customer's network(s), and deny everything else.

The following example uses the IPv6 documentation prefix, 2001:db8::/32, and must be adapted to the specific customer network.

Example, Cisco style:

ipv6 prefix-list ipv6-from-customer permit 2001:db8::/32
ipv6 prefix-list ipv6-from-customer deny 0::/0 le 128
Example, Juniper style:
policy-statement ipv6-from-customer {
    from {
        family inet6;
        route-filter 2001:db8::/32 exact next policy;
    then reject;

3. Filtering routes coming from Peers

Filtering peers is a bit more difficult, as they will usually announce more prefixes, and the set of prefixes changes more often. Also, peers will usually not announce new prefixes in their set of announcements to all their peers (unlike customers that have an interest in getting their networks propagated).

Consequently, there are two strategies to filtering peers:

3.1. Explicit route filter from peer, generated from an IRR

If your peer is a good netizen, they will register all routes into one of the public Internet Routing Registries (IRR), like the RIPE database. So you can use a tool like RtConfig (URL?) to generate the prefix filters for a given neighbour AS from the IRR database.

Creation of a route6 object in the RIPE DB is quite easy - generate the object as text template, send it to the RIPE DB in your favourite way (e-mail, RIR portal, sync update)... here's how our route6 object looks like:

    route6:       2001:608::/32
    descr:        DE-SPACE-2001-0608
    descr:        SpaceNET AG, Munich
    origin:       AS5539
    notify:       noc@space.net
    mnt-by:       SPACENET-N
    changed:      gert@space.net 20041230
    source:       RIPE
TODO: add links to the RIPE DB documentation documents.

This approach breaks when you peer with an AS that does not register their routes (including their customer routes!) -- yell at them! -- or if you live in a region where the regional RIR is not offering IRR DB support.

For the rest...

3.2. Max-Prefix plus Bogon-Filter

... the strategy to filter peers against major accidents can be similar to what many ASes do in IPv4 BGP today: This is not a perfect solution, but better than ``just accept anything that the peer sends to you''. Unqualified exchange of full routing tables is seriously hurting IPv6 BGP routing quality.

For an example of a ``bogon'' filter, see the examples after the next section.

4. Filtering routes coming from Upstream providers (the ``default free'' zone)

In theory, this could also be done using the IRR registries and building prefix-filters from the registered data. In practice, there will always be prefixes announced ``legitimately'' but not registered anywhere.

A pragmatic approach is to assume that an upstream provider will apply some decent filtering on their peers and customers. To avoid accidents, one should still apply a ``bogon'' filter against things that one never wants to see, but that might still end up in the upstream's BGP announcements, for whatever reason.

The next section will discuss bogon filters for (lazy) peers and upstreams.

5. Example Filters

Never assume that these filtering examples are the last word regarding filters. THEY CAN BE OUTDATED (if I haven't found time to incorporate recent developments yet).

The filter lists shown here are examples and should not be used verbatim without some consideration about what you want to achieve and whether these lists are what YOU need.

Some common aspects to all filters:

(Note: this introdocution needs more wording about the rationales behind the filters, and why the "relaxed" filter has changed to be default-permit nowadays. Waiting for some contributions.)

Currently, these filters are in Cisco/Zebra syntax. Juniper filters can be found below.

5.1. Case 1: relaxed

The following list is fairly relaxed. It accepts more specific routes up to a /48 from the RIR (2000::/3) ranges. I know that some people very harshly oppose announcing more specifics, but other people argue that it's better to do multihoming by announcing a /48 with a limited distribution (same region, for example) than to announce your own /32 globally.

The IPv6 documentation prefix 2001:db8::/32 (and all more specifics of it) is explicitely denied. That's for documentation, you don't want to see it in your routing table.

The 6bone prefixes out of 3FFE::/16 are explicit denied - this /16 is not in use anymore according to 6bone and ICANN rules, so anybody announcing space out of it is an address space hijacker. Period.

ipv6 prefix-list ipv6-ebgp-relaxed deny 3ffe::/16 le 128
ipv6 prefix-list ipv6-ebgp-relaxed deny 2001:db8::/32 le 128
ipv6 prefix-list ipv6-ebgp-relaxed permit 2001::/32
ipv6 prefix-list ipv6-ebgp-relaxed deny 2001::/32 le 128
ipv6 prefix-list ipv6-ebgp-relaxed permit 2002::/16
ipv6 prefix-list ipv6-ebgp-relaxed deny 2002::/16 le 128
ipv6 prefix-list ipv6-ebgp-relaxed deny 0000::/8 le 128
ipv6 prefix-list ipv6-ebgp-relaxed deny fe00::/9 le 128
ipv6 prefix-list ipv6-ebgp-relaxed deny ff00::/8 le 128
ipv6 prefix-list ipv6-ebgp-relaxed permit 2000::/3 le 48
ipv6 prefix-list ipv6-ebgp-relaxed deny 0::/0 le 128

5.2 Case 2: strict

Only routes matching the allocation sizes that the registries hand out are permitted.

WARNING: It is not recommended to use the strict filterset. Currently there are active prefixes that are not covered by this filter and that, in theory, violate the assignment policies of the respective RIR. You WILL loose connectivity to these prefixes!

This list is problematic, as it NEEDS regular updating. So only use it if you are prepared to do that. Otherwise use the relaxed filter.

In the RIR network block (2001::/16), this lists permit /35 (old policy) and /32 (new policy) up to a /19.

While most networks today will announce a /32 or /35, the global policy explicitely permits larger network blocks, and the filters must be prepared for that (actually, there are one /31 and /27 already allocated: 2001:1600::/31 and 2001:1700::/27).

UPDATE: 2001:2000::/20 has been allocated on 2004/05/10. The old filter was too strict here!

UPDATE: 2003::/18 has been allocated to RIPE on 2005/01/13.

UPDATE: ICANN/IANA has handed out /12s to the RIRs.

UPDATE: more blocks from 260x:: and 2a00:: have been allocated to ARIN and to RIPE. RIPE has allocated 2a00::/22 to Arcor. ARIN will allocate large blocks from 260x:: to various US DoD networks ``soon''.

UPDATE: APNIC has started allocating from 2400::/16. First big allocation is 2400:2000::/20 to SoftbankBB IPv6.

UPDATE: ARIN has started allocating IPv6 PI from 2620::/23

UPDATE: RIPE will allocate anycast /48s for DNS from 2001:0678::/29

UPDATE: RIPE will allocate IPv6 PI /48s or shorter from 2001:0678::/29 (e.g. 2001:67C:1400::/45), so the filter has been adjusted to permit "up to /48" now.

The current limit on a /19 is arbitrary. It's there to catch someone accidently announcing 2001::/16.

In addition to this, inside 2001:500::/30, the lists permits /48s. This network block is the ARIN critical internet infrastructure microallocation block, and ARIN is assigning /48s directly to end networks (like root name servers).

Note: the next block, 2001:504::/32, is the block from where ARIN does its Micro-allocations for Exchange Points. The filter does explicitely not make an exception for them - the IXP blocks are expected to be not routeable. Of course you're free to make a different choice for your local filters.

APNIC and RIPE currently don't do any IPv6 microallocations, so there is no exception rule for those two RIRs. APNIC IXP /48s come from 2001:07FA::/32, RIPE IXP /48 assignments come from 2001:07F8::/32.

UPDATE: AfriNIC is allocating PI space from 2001:43f8::/29 (2007/07/12).

UPDATE: Lacnic is allocating PI(-like) space from 2001:13c7:6000::/36 and 2001:13c7:7000::/36, in /36.../48 allocation sizes (2008/02/19). See also: http://www.lacnic.net/en/registro/.

UPDATE: APNIC also has PI assignments now, coming from 2001:c00::/23. Their announcement says "the minimum assignment size is /48".

UPDATE: LACNIC has changed their network blocks again, /48s (up to /48) are now assigned from 2801:0000::/24 (2008/08/08).

ipv6 prefix-list ipv6-ebgp-strict deny   3ffe::/16 le 128
ipv6 prefix-list ipv6-ebgp-strict permit 2001:500::/30 ge 48 le 48
ipv6 prefix-list ipv6-ebgp-strict deny   2001:db8::/32 le 128
ipv6 prefix-list ipv6-ebgp-strict permit 2001::/32 
ipv6 prefix-list ipv6-ebgp-strict permit 2001::/16 ge 35 le 35
ipv6 prefix-list ipv6-ebgp-strict permit 2001::/16 ge 19 le 32
ipv6 prefix-list ipv6-ebgp-strict permit 2001:0678::/29 le 48
ipv6 prefix-list ipv6-ebgp-strict permit 2001:0c00::/23 ge 48 le 48
ipv6 prefix-list ipv6-ebgp-strict permit 2001:13c7:6000::/36 le 48
ipv6 prefix-list ipv6-ebgp-strict permit 2001:13c7:7000::/36 le 48
ipv6 prefix-list ipv6-ebgp-strict permit 2001:43f8::/29 ge 40 le 48
ipv6 prefix-list ipv6-ebgp-strict permit 2002::/16 
ipv6 prefix-list ipv6-ebgp-strict permit 2003::/16 ge 19 le 32
ipv6 prefix-list ipv6-ebgp-strict permit 2400::/12 ge 19 le 32
ipv6 prefix-list ipv6-ebgp-strict permit 2600::/12 ge 19 le 32
ipv6 prefix-list ipv6-ebgp-strict permit 2610::/23 ge 24 le 32
ipv6 prefix-list ipv6-ebgp-strict permit 2620::/23 ge 40 le 48
ipv6 prefix-list ipv6-ebgp-strict permit 2800::/12 ge 19 le 32
ipv6 prefix-list ipv6-ebgp-strict permit 2a00::/12 ge 19 le 32
ipv6 prefix-list ipv6-ebgp-strict permit 2801:0000::/24 le 48
ipv6 prefix-list ipv6-ebgp-strict permit 2c00::/12 ge 19 le 32
ipv6 prefix-list ipv6-ebgp-strict deny 0::/0 le 128

5.3. JunOS configuration style

The following configuration examples for Juniper routers have been contributed by Daniel Roesen, dr@cluenet.de, and Jens Ott (fixing the bugs that I introduced into Daniel's examples) - thanks! - so please don't ask me about any details. If there is anything missing, let me know. Jens has also sent me a verbose version of the filter - which is quite long, but makes it more easy to understand. You can find it here.
policy-statement ipv6-ebgp-relaxed {
    from {
        family inet6;
        route-filter 3ffe::/16 orlonger;
        route-filter 0000::/8 orlonger;
        route-filter 2001:db8::/32 orlonger;
        route-filter 2001::/32 exact next policy;
        route-filter 2001::/32 longer;
        route-filter 2002::/16 exact next policy;
        route-filter 2002::/16 longer;
        route-filter fe00::/9 orlonger;
        route-filter ff00::/8 orlonger;
        route-filter 2000::/3 prefix-length-range /49-/128;
        route-filter 0::/0 orlonger;
    then {

policy-statement ipv6-ebgp-strict {
    term pass-some {
        from {
            family inet6;
            route-filter 3ffe::/16 orlonger reject;
            route-filter 2001:500::/30 prefix-length-range /48-/48;
            route-filter 2001:db8::/32 orlonger reject;
            route-filter 2001::/32 exact;
            route-filter 2001::/16 prefix-length-range /35-/35;
            route-filter 2001::/16 prefix-length-range /19-/32;
            route-filter 2001:0678::/29 prefix-length-range /29-/48;
            route-filter 2001:0c00::/23 prefix-length-range /48-/48;
            route-filter 2001:13c7:6000::/36 prefix-length-range /36-/48;
            route-filter 2001:13c7:7000::/36 prefix-length-range /36-/48;
            route-filter 2001:43f8::/29 prefix-length-range /48-/48;
            route-filter 2002::/16 exact;
            route-filter 2003::/16 prefix-length-range /19-/32;
            route-filter 2400::/12 prefix-length-range /19-/32;
            route-filter 2600::/12 prefix-length-range /19-/32;
            route-filter 2610::/23 prefix-length-range /24-/32;
            route-filter 2620::/23 prefix-length-range /40-/48;
            route-filter 2800::/12 prefix-length-range /19-/32;
            route-filter 2a00::/12 prefix-length-range /19-/32;
            route-filter 2801:0000::/24 prefix-length-range /24-/48;
            route-filter 2c00::/12 prefix-length-range /19-/32;
        then next policy;
    term reject-rest {
        from family inet6;
        then reject;

6. See Also / References

To verify that my filter list examples are meaningful, you can check the following sites:

Update: 2002/09/25. Gert Döring: initial version.
Update: 2003/05/12. Gert Döring: add ARIN microallocations.
Update: 2003/05/12. Gert Döring: fixup ARIN stuff (/32, not /29)
Update: 2003/12/12. Gert Döring: mention /31 and /27 allocations
Update: 2003/12/12. Matthew Ford: change 2001:500::/32 to be a /30
Update: 2004/02/13. Daniel Roesen: contribute JunOS style.
Update: 2004/05/10. Gert Döring: extend to /19 routes.
Update: 2004/05/24. Gert Döring: deny IPv6 documentation pfx.
Update: 2005/01/13. various: updates for 2003::/16 and RFC3513 (no more FP001).
Update: 2005/06/11. Gert Döring: fundamental rewrite.
Update: 2005/11/02. Daniel Roesen: fix JunOS ipv6-from-customer filter.
Update: 2005/11/02. Cougar: add 2400::/16 /19../32 to filters.
Update: 2005/12/21. add 2a01::/16 (RIPE)
Update: 2006/02/06. add 2001::/32 (Teredo prefix)
Update: 2006/02/11. Joe Abley: add 2404::/23 (APNIC)
Update: 2006/09/15. ARIN IPv6 PI blocks, 2620::/23
Update: 2006/09/15. drop 3FFE
Update: 2006/10/09. add 2001:0678::/29 for Ancast DNS
Update: 2007/02/02. add /12 allocations
Update: 2007/08/17. fix 2620::/23 filters, add 2001:43f8::/29 AfriNic PI
Update: 2008/04/25. add LACNIC and APNIC PI ranges, add route6 example
Update: 2008/08/18. add new LACNIC PI ranges
Update: 2009/08/11. change 0::/0 to 2000::/3 in relaxed filter
Update: 2009/11/10. change rules for 2001:0678::/29 to allow /29.../48
Update: 2009/11/18. Jens Ott: fix juniper "relaxed" filters, add link to verbose filter
Update: 2013/06/03. Sebastian Wiesinger: change Juniper relaxed filter to correctly match 2000::/3 subnets and add warning to strict filters