BIRD2 BGP on Linux: Dual-Stack Configuration and Filters - 夜莺博客

BIRD2 BGP on Linux: Dual-Stack Configuration and Filters

BIRD is CZ.NIC's routing daemon, and BIRD 2 collapsed the old BIRD/BIRD6 split into a single process with IPv4 and IPv6 as channels inside each protocol block. It is the lightest way to speak BGP from a Linux host — useful for anycast services, announcing your own prefixes, or building a route server. This guide covers the bird.conf structure, a complete dual-stack upstream session, the filter language that protects you from route leaks, and the troubleshooting steps for the session states you will actually see.

Install and know where things live

apt install bird2                 # Debian 12 / Ubuntu 24.04 default repo
bird --version
ls -l /etc/bird/bird.conf         # single config file in BIRD 2
ls -l /run/bird/bird.ctl          # single control socket

BIRD 1.x shipped separate binaries and separate configs for IPv4 and IPv6. In BIRD 2 there is one daemon, one config, one socket — a detail that matters when you copy configuration from older tutorials.

The five blocks of a BGP-ready bird.conf

log syslog all;
router id 198.51.100.2;

protocol device {
    scan time 10;
}

protocol direct {
    ipv4; ipv6;
    interface "dummy0", "eth0";
}

protocol kernel {
    ipv4 { export all; import all; };
    learn;
    scan time 15;
}

protocol bgp upstream1 {
    description "Upstream Provider";
    local 198.51.100.2 as 65400;
    neighbor 198.51.100.1 as 64496;
    hold time 90;
    keepalive time 30;
    password "your-md5-secret";
    ipv4 { import all; export filter export_bgp_v4; next hop self; };
    ipv6 { import all; export filter export_bgp_v6; next hop self; };
}

Each protocol runs independently and communicates through routing tables. device watches interface state, direct imports connected routes (needed for next-hop resolution), and kernel synchronises BIRD's decision with the Linux routing table so the routes you learn actually get installed and forwarded.

Export filters: announce only what you own

define OWN_V4_PREFIX = 203.0.113.0/24;
define OWN_V6_PREFIX = 2001:db8:1000::/48;

filter export_bgp_v4 {
    if net = OWN_V4_PREFIX then accept;
    reject;
}

filter export_bgp_v6 {
    if net = OWN_V6_PREFIX then accept;
    reject;
}

The trailing reject is a default deny and it is not optional. An export filter without a final reject will, at some point, announce a route you never intended — a mistake measured in outage minutes across the internet.

Import filters: protect against leaks and hijacks

define BOGON_PREFIXES = [
    0.0.0.0/8+, 10.0.0.0/8+, 127.0.0.0/8+,
    169.254.0.0/16+, 172.16.0.0/12+,
    192.168.0.0/16+, 224.0.0.0/4+
];
define PRIVATE_ASNS = [ 64512..65534, 4200000000..4294967294 ];

filter import_safe {
    if net ~ MY_PREFIXES then reject;        # never accept what we originate
    if net.len > 24 then reject;             # drop overly specific IPv4 space
    if net = 0.0.0.0/0 then reject;
    if net ~ BOGON_PREFIXES then reject;
    if bgp_path ~ PRIVATE_ASNS then reject;
    if bgp_path.len > 50 then reject;
    accept;
}

BIRD's filter language supports sets, ranges and functions, which makes these checks concise. AS-path prepending for traffic engineering is just bgp_path.prepend(MY_AS); inside an export filter.

Validate, apply and verify

birdc configure check
birdc configure
birdc show protocols
birdc show route export upstream1
birdc show route protocol upstream1
Name       Proto Table State Since       Info
kernel1    Kernel master4 up   12:00:00.000
upstream1  BGP   ---     up   12:00:05.000 Established

birdc configure check before every reload is the cheapest insurance in the whole workflow: BIRD reports the offending line number and refuses to load a broken config. For filter-only changes, birdc reload upstream1 re-applies policy without tearing down the TCP session.

Common session problems

  • Stuck in Connect/Active — nothing is listening on TCP/179, or a firewall is blocking. Check the nftables/iptables policy on the device, not just the upstream.
  • Stuck in OpenSent or bouncing between OpenSent/OpenConfirm — authentication mismatch (MD5 password), or the neighbour is configured with the wrong local AS.
  • Session up but no routes exported — run birdc show route export upstream1. If it is empty, the export filter is rejecting everything; check that the connected route for your prefix is actually in master4.
  • Prefixes announced but not visible on a looking glass — the speaker has not accepted them yet, or your IRR/ROA records are missing and the upstream filters pass them nowhere.

If your team standardises on FRR instead, the equivalent configuration is in FRRouting BGP on Linux; the RPKI validation and origin checks that complete the security story are covered in BGP route reflector cluster ID configuration.

原文链接:https://virtua.cloud/learn/en/tutorials/bird2-bgp-configuration-linux-vps