Introduction
BIRD (BIRD Internet Routing Daemon) is one of the two reference open-source routing daemons in the operator world (FRR being the other). BIRD 2.x unifies IPv4 and IPv6 in a single daemon with clean syntax, and runs single-threaded very efficiently — it powers many Looking Glasses and IXP route-servers (FranceIX included).
This tutorial shows how to bring up a dual-stack BGP session to VeryCloud (AS198825) once your GRE/VXLAN/WireGuard tunnel is up.
Prerequisites
- A Linux server with an up tunnel to VeryCloud (see transport tutorials)
- VeryCloud's technical email with:
169.254.X.1(v4 peer),2a0e:XXXX:XXXX::0(v6 peer), MD5 password if chosen - Your ASN (public e.g.
AS65000or private64512-65534) - Your IPv4 and IPv6 prefixes to announce
- BIRD 2.x installed
Step 1: Install BIRD 2
# Debian / Ubuntu
sudo apt install -y bird2
# RHEL / Rocky / Alma
sudo dnf install -y bird
bird --version
💡 BIRD 1.x (legacy) had separate v4/v6 daemons (
birdandbird6). BIRD 2 unifies. If you still have BIRD 1, migrate now.
Step 2: Config structure
/etc/bird/bird.conf follows this logical structure:
1. Variables and global router-id
2. Base protocols (device, kernel, direct, static)
3. BGP templates (optional but clean)
4. Filters (in/out)
5. BGP sessions (one per peer)
BIRD works with routing tables (master4 and master6 by default) and each protocol imports/exports routes from/to these tables with filters.
Step 3: Variables and prefixes
At the top of /etc/bird/bird.conf:
log syslog all;
log "/var/log/bird.log" all;
router id 192.0.2.1;
define MY_PREFIXES_V4 = [
192.0.2.0/24,
198.51.100.0/24
];
define MY_PREFIXES_V6 = [
2001:db8::/32
];
define VC_ASN = 198825;
⚠️
router idmust be a unique IPv4 on your machine. If you only have IPv6, use an arbitrary internal/32(e.g.0.0.0.1).
Step 4: Base protocols
protocol device {
scan time 10;
}
protocol kernel {
ipv4 {
export all;
import none;
};
merge paths on;
}
protocol kernel {
ipv6 {
export all;
import none;
};
merge paths on;
}
protocol direct {
ipv4;
ipv6;
interface "lo", "eth0", "wg-vc", "gre-vc", "vxlan-vc";
}
protocol static static_v4 {
ipv4;
route 192.0.2.0/24 blackhole;
route 198.51.100.0/24 blackhole;
}
protocol static static_v6 {
ipv6;
route 2001:db8::/32 blackhole;
}
blackhole routes are perfect for "anchor" prefixes: they exist in BIRD's table, announced via BGP, traffic without a more specific route goes to null.
Step 5: Filters
filter bgp_in_v4 {
if net = 0.0.0.0/0 then accept;
if net.len > 24 then reject;
if net.len < 8 then reject;
accept;
}
filter bgp_in_v6 {
if net = ::/0 then accept;
if net.len > 48 then reject;
if net.len < 16 then reject;
accept;
}
filter bgp_out_v4 {
if net ~ MY_PREFIXES_V4 then accept;
reject;
}
filter bgp_out_v6 {
if net ~ MY_PREFIXES_V6 then accept;
reject;
}
💡 Always filter out. Without it, you risk announcing prefixes you don't own — major BGP incident.
Step 6: BGP template
template bgp vc_peers {
local as 65000;
multihop 2;
password "MD5_SECRET";
hold time 90;
keepalive time 30;
graceful restart on;
}
Step 7: BGP sessions
protocol bgp verycloud_v4 from vc_peers {
description "VeryCloud Transit v4";
neighbor 169.254.X.1 as VC_ASN;
ipv4 {
import filter bgp_in_v4;
export filter bgp_out_v4;
next hop self;
import limit 5000 action restart;
};
}
protocol bgp verycloud_v6 from vc_peers {
description "VeryCloud Transit v6";
neighbor 2a0e:XXXX:XXXX::0 as VC_ASN;
ipv6 {
import filter bgp_in_v6;
export filter bgp_out_v6;
next hop self;
import limit 1000 action restart;
};
}
Step 8: Start BIRD
sudo bird -p -c /etc/bird/bird.conf
sudo systemctl enable --now bird
sudo systemctl status bird
Step 9: Verify sessions
sudo birdc show protocols
Expected state:
Name Proto Table State Since Info
verycloud_v4 BGP --- up 16:45:12 Established
verycloud_v6 BGP --- up 16:45:12 Established
Details:
sudo birdc show protocols all verycloud_v4
Step 10: Verify routes
sudo birdc show route protocol verycloud_v4
sudo birdc show route protocol verycloud_v6
sudo birdc show route export verycloud_v4
sudo birdc show route export verycloud_v6
sudo birdc show route
Validate default route in kernel:
ip route show default
ip -6 route show default
Troubleshooting
Session stays Active or Connect
- Tunnel issue (see transport tutorials)
- TCP/179 firewalled
- MD5 password mismatch
Session Established but no routes received
- Filters too restrictive:
birdc show route filter bgp_in_v4 - VeryCloud hasn't activated route sending
Your prefixes not announced
birdc show route export verycloud_v4empty- Static/direct doesn't include your prefixes
Route limit exceeded
- More routes than expected — switch to full table or increase
import limit
Useful commands
sudo birdc configure # reload config without disruption
sudo birdc restart verycloud_v4 # restart a session
sudo birdc disable verycloud_v4
sudo birdc enable verycloud_v4
sudo birdc # interactive CLI
sudo journalctl -u bird -f
Conclusion
BIRD 2 = clean declarative config, powerful filters, single binary v4+v6. Once you understand the file structure (protocols, filters, tables), you set up BGP sessions in minutes. This tutorial's skeleton covers 95% of VeryCloud Remote Transit IP cases.
Going further: RPKI validation with routinator + RPKI protocol, BFD for fast failover, BGP communities for traffic engineering, multipath ECMP across multiple tunnels.


















