Linux VPS上配置BIRD2 BGP路由

3 分钟阅读·Matthieu|

在Debian 12或Ubuntu 24.04上安装BIRD2并配置BGP会话来宣告自有IP前缀。涵盖双栈配置、导出过滤器、持久化dummy接口、nftables规则和birdc验证。

BIRD是由CZ.NIC维护的路由守护进程。版本2将IPv4和IPv6统一到单一守护进程中,取代了1.x时期分离的BIRD/BIRD6架构,并新增了强大的过滤器语言。本指南涵盖在Linux VPS上安装BIRD2、配置与上游提供商的BGP会话、宣告你的IP前缀,以及验证所有配置是否正常工作。

所有示例均为双栈(IPv4 + IPv6)。请将文中所有占位ASN、IP和前缀替换为你自己的实际值。

配置BIRD2 BGP前需要准备什么?

在修改bird.conf之前,你需要一个ASN、已分配的IP地址空间,以及一个在VPS上提供BGP会话的服务商。三者缺一不可,否则BIRD2既没有前缀可宣告,也没有对端可以建立对等关系。

从你的服务商或RIR分配中收集以下信息:

项目 示例值 获取途径
你的ASN AS65400 RIPE NCC、ARIN或你的LIR
你的IPv4前缀 203.0.113.0/24 RIR分配或服务商的PA地址
你的IPv6前缀 2001:db8:1000::/48 RIR分配或服务商的PA地址
上游ASN AS64496 服务商的BGP会话详情
上游对等IPv4 198.51.100.1 服务商的BGP会话详情
上游对等IPv6 2001:db8::1 服务商的BGP会话详情
你的对等IPv4 198.51.100.2 服务商的BGP会话详情
你的对等IPv6 2001:db8::2 服务商的BGP会话详情
MD5密码 (共享密钥) 与服务商协商确定

你还需要在下游网络对你的路由执行RPKI验证之前,发布你前缀的ROA记录。相关设置参见。

确认你的服务商已将你的前缀加入其IRR过滤器。否则即使BGP会话建立成功,你的宣告也会被过滤掉。

一台至少1 GB内存的VPS足以运行BIRD2并承载全表(超过100万条IPv4路由)。如果你只接受上游的默认路由,内存占用会低于100 MB。

如何在Debian 12和Ubuntu 24.04上安装BIRD2?

两个发行版的默认仓库都包含BIRD2。Debian 12提供2.0.12版本,Ubuntu 24.04提供2.14版本。两者都能满足基本BGP需求,但CZ.NIC官方仓库提供的BIRD 2.18(2026年1月发布)支持BGP动态无编号功能、性能改进和最新bug修复。生产环境建议使用CZ.NIC仓库。

注意: CZ.NIC以bird2项目名发布BIRD2软件包。不要与bird项目(仅覆盖Debian)或bird3(BIRD 3.x)混淆。

从CZ.NIC仓库安装(推荐)

添加官方仓库后安装:

sudo apt-get update
sudo apt-get -y install apt-transport-https ca-certificates wget

导入CZ.NIC GPG密钥:

sudo wget -O /usr/share/keyrings/cznic-labs-pkg.gpg https://pkg.labs.nic.cz/gpg

添加仓库。Debian 12:

echo "deb [signed-by=/usr/share/keyrings/cznic-labs-pkg.gpg] https://pkg.labs.nic.cz/bird2 bookworm main" | sudo tee /etc/apt/sources.list.d/cznic-labs-bird.list

Ubuntu 24.04:

echo "deb [signed-by=/usr/share/keyrings/cznic-labs-pkg.gpg] https://pkg.labs.nic.cz/bird2 noble main" | sudo tee /etc/apt/sources.list.d/cznic-labs-bird.list

安装BIRD2:

sudo apt-get update
sudo apt-get -y install bird2

从默认仓库安装

如果你偏好使用发行版自带的软件包:

sudo apt-get update
sudo apt-get -y install bird2

验证安装

bird --version

预期输出(CZ.NIC仓库):

BIRD version 2.18

检查服务是否正在运行:

sudo systemctl status bird

BIRD在安装后会自动启动。/etc/bird/bird.conf中的默认配置只是一个骨架。下一节你将完全替换它。

bird.conf的BGP配置结构是怎样的?

面向BGP的bird.conf包含五个部分: 全局设置和四个协议段(device、direct、kernel、bgp)。每个协议独立运行,通过路由表相互通信。

以下是双栈BGP配置的完整bird.conf。先通读一遍,随后各小节会逐块讲解。

sudo cp /etc/bird/bird.conf /etc/bird/bird.conf.bak
sudo tee /etc/bird/bird.conf > /dev/null << 'BIRDCONF'
# /etc/bird/bird.conf - BIRD2 BGP configuration
# Replace all placeholder values with your own

log syslog all;

router id 198.51.100.2;

# Watch interface state changes
protocol device {
    scan time 10;
}

# Import connected routes (needed for next-hop resolution)
protocol direct {
    ipv4;
    ipv6;
    interface "dummy0";
    interface "eth0";
}

# Sync BIRD routes to kernel routing table
protocol kernel {
    ipv4 {
        export all;
        import all;
    };
    learn;
    scan time 15;
    merge paths on;
}

protocol kernel {
    ipv6 {
        export all;
        import all;
    };
    learn;
    scan time 15;
    merge paths on;
}

# Define your prefixes
define OWN_V4_PREFIX = 203.0.113.0/24;
define OWN_V6_PREFIX = 2001:db8:1000::/48;

# Export filter: only announce your own prefixes
filter export_bgp_v4 {
    if net = OWN_V4_PREFIX then accept;
    reject;
}

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

# Static routes for prefix origination (point to dummy0)
protocol static static_v4 {
    ipv4;
    route 203.0.113.0/24 via "dummy0";
}

protocol static static_v6 {
    ipv6;
    route 2001:db8:1000::/48 via "dummy0";
}

# BGP session with upstream provider
protocol bgp upstream1 {
    description "Upstream Provider";
    local 198.51.100.2 as 65400;
    neighbor 198.51.100.1 as 64496;
    source address 198.51.100.2;
    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;
    };
}
BIRDCONF

设置配置文件权限。只有root和bird用户需要访问:

sudo chown root:bird /etc/bird/bird.conf
sudo chmod 640 /etc/bird/bird.conf

验证权限:

ls -la /etc/bird/bird.conf

预期输出:

-rw-r----- 1 root bird 1247 Mar 19 12:00 /etc/bird/bird.conf

全局设置

log syslog all;
router id 198.51.100.2;

router id必须是全局唯一的IPv4地址。使用你分配到的IP之一。BIRD可以从接口自动检测,但显式指定更可靠。

log syslog all将所有日志发送到系统日志。通过journalctl -u bird -f查看。如果调试某个协议时需要详细输出,可以临时添加debug protocols all;。会话正常后记得删除它。Debug级别的日志量很大,可能会占满日志存储空间。

Protocol device

protocol device {
    scan time 10;
}

每10秒扫描接口状态变化。这是必需的。没有它,BIRD无法感知接口的上线或下线。

Protocol direct

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

从列出的接口导入直连路由。BIRD需要这些路由来解析下一跳。只列出与BGP相关的接口即可。

Protocol kernel

需要两个kernel协议块: 一个用于IPv4,一个用于IPv6。各自在BIRD路由表和Linux内核路由表之间同步对应的地址族。

merge paths on在你有多个上游时启用ECMP(等价多路径)。learn将已有的内核路由导入BIRD。

protocol bgp块的作用是什么?

protocol bgp块定义与一个邻居的对等会话。它指定你是谁(local ... as)、你的对端是谁(neighbor ... as)、认证方式(password),以及交换哪些路由(channel块)。

关键指令:

指令 用途
local <ip> as <ASN> 你的对等IP和ASN
neighbor <ip> as <ASN> 上游的对等IP和ASN
source address <ip> TCP连接的源IP
hold time 90 多少秒后宣布对端失联(keepalive的3倍)
keepalive time 30 keepalive消息发送间隔
password "..." MD5认证(RFC 2385)

MD5认证保护BGP会话免受伪造TCP RST和注入攻击。双方必须配置相同的密码。向你的服务商索取共享密钥。

如何配置双栈IPv4和IPv6通道?

BIRD2将IPv4和IPv6作为同一协议块内的独立通道(channel)处理。每个通道有自己的导入/导出策略:

ipv4 {
    import all;
    export filter export_bgp_v4;
    next hop self;
};

ipv6 {
    import all;
    export filter export_bgp_v6;
    next hop self;
};

import all接受上游的所有路由。在生产环境中,你也应该过滤导入的路由。参见获取导入过滤器示例。

next hop self将下一跳属性重写为你的对等IP。当上游期望流量通过你的地址转发时需要此设置,这是VPS上的标准配置。

如果你的服务商为IPv4和IPv6运行独立的BGP会话(每个地址族使用不同的邻居IP),则应拆分为两个protocol bgp块。

如何编写导出过滤器只宣告自己的前缀?

导出过滤器(export filter)控制BIRD向上游发送哪些路由。配置错误的导出过滤器可能会泄露你不拥有的路由,这将导致你的会话被关闭,甚至可能收到上游NOC的电话。

上述配置中的过滤器使用简单的前缀匹配:

define OWN_V4_PREFIX = 203.0.113.0/24;

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

这只接受精确的/24。其他一律拒绝。末尾的reject是默认拒绝策略。

对于多个前缀,使用集合(set):

define OWN_V4_PREFIXES = [ 203.0.113.0/24, 198.51.100.0/24 ];

filter export_bgp_v4 {
    if net ~ OWN_V4_PREFIXES then accept;
    reject;
}

~运算符对前缀集合进行匹配。它还支持范围表示法:

define OWN_V4_PREFIXES = [ 203.0.113.0/24{24,24} ];

{24,24}将匹配限制为恰好是/24。如果你需要为流量工程宣告更具体的路由,可以用{24,28}允许分解到/28。

IPv6的模式完全相同:

define OWN_V6_PREFIXES = [ 2001:db8:1000::/48{48,48} ];

filter export_bgp_v6 {
    if net ~ OWN_V6_PREFIXES then accept;
    reject;
}

始终保持导出过滤器尽可能严格。只宣告你拥有的前缀,使用你计划的精确前缀长度。如果过滤器末尾缺少reject,BIRD将使用通道的默认动作,而默认动作可能是accept。始终以显式的reject结尾。

你可以在不应用配置的情况下测试过滤器:

sudo birdc eval '203.0.113.0/24 ~ [ 203.0.113.0/24 ]'

这会返回TRUEFALSE,帮助你在重载配置前调试过滤器逻辑。

如何创建持久化dummy接口用于前缀起源?

BGP宣告路由表中存在的前缀。你需要一个分配了你的前缀的接口,这样BIRD才能生成路由。dummy接口就是为此设计的: 它始终处于UP状态,没有物理链路,通过systemd-networkd配置后可以在重启后保留。

临时的ip link add命令会在重启后丢失。请改用systemd-networkd。

创建.netdev文件

sudo tee /etc/systemd/network/10-dummy0.netdev > /dev/null << 'EOF'
[NetDev]
Name=dummy0
Kind=dummy
EOF

创建.network文件

sudo tee /etc/systemd/network/10-dummy0.network > /dev/null << 'EOF'
[Match]
Name=dummy0

[Network]
Address=203.0.113.1/32
Address=2001:db8:1000::1/128
EOF

从你分配的前缀中选一个/32(IPv6选/128)分配给dummy接口。这个地址不需要从外部可达。它存在的唯一目的是让BIRD拥有该前缀的直连路由。

应用并验证

sudo systemctl restart systemd-networkd

等待几秒后检查:

ip addr show dummy0

预期输出:

3: dummy0: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default qlen 1000
    link/ether aa:bb:cc:dd:ee:ff brd ff:ff:ff:ff:ff:ff
    inet 203.0.113.1/32 scope global dummy0
       valid_lft forever preferred_lft forever
    inet6 2001:db8:1000::1/128 scope global
       valid_lft forever preferred_lft forever

dummy接口显示state UNKNOWN是正常的。这表示链路层没有物理载波可跟踪,但接口处于UP状态且可以转发数据。MAC地址由systemd-networkd随机生成,你的系统上会不同。

如果你使用的是ifupdown而不是systemd-networkd(通过networkctl status检查),可能需要先启用systemd-networkd:

sudo systemctl enable --now systemd-networkd

验证文件已就位,确保下次重启后生效:

ls -la /etc/systemd/network/10-dummy0.*
-rw-r--r-- 1 root root  42 Mar 19 12:00 /etc/systemd/network/10-dummy0.netdev
-rw-r--r-- 1 root root  89 Mar 19 12:00 /etc/systemd/network/10-dummy0.network

如何用nftables防火墙规则保护BGP?

BGP运行在TCP端口179上。没有防火墙规则的话,互联网上任何主机都可以尝试与你的路由器建立BGP会话。自动扫描工具会在VPS上线数小时内发现开放的179端口。必须将179端口限制为仅允许你的对等IP访问。

Ubuntu 24.04默认可能未安装nftables。先安装:

sudo apt-get -y install nftables

创建nftables规则集

sudo tee /etc/nftables.d/bgp.conf > /dev/null << 'EOF'
table inet bgp_filter {
    set bgp_peers_v4 {
        type ipv4_addr
        elements = { 198.51.100.1 }
    }

    set bgp_peers_v6 {
        type ipv6_addr
        elements = { 2001:db8::1 }
    }

    chain input {
        type filter hook input priority 0; policy accept;

        # Allow BGP from known peers only
        tcp dport 179 ip saddr @bgp_peers_v4 accept
        tcp dport 179 ip6 saddr @bgp_peers_v6 accept

        # Drop BGP from everyone else
        tcp dport 179 drop
    }
}
EOF

添加更多上游时,只需向集合中添加对等IP。命名集合(named set)让你无需重写规则即可更新对等列表。

集成到现有nftables配置

如果你已有/etc/nftables.conf,引入BGP规则:

echo 'include "/etc/nftables.d/bgp.conf"' | sudo tee -a /etc/nftables.conf

如果你还没有设置nftables,创建目录并加载配置:

sudo mkdir -p /etc/nftables.d
sudo systemctl enable --now nftables

enable --now会立即启动nftables并确保每次开机自动加载。

应用规则:

sudo nft -f /etc/nftables.d/bgp.conf

验证规则

sudo nft list table inet bgp_filter

预期输出:

table inet bgp_filter {
	set bgp_peers_v4 {
		type ipv4_addr
		elements = { 198.51.100.1 }
	}

	set bgp_peers_v6 {
		type ipv6_addr
		elements = { 2001:db8::1 }
	}

	chain input {
		type filter hook input priority filter; policy accept;
		tcp dport 179 ip saddr @bgp_peers_v4 accept
		tcp dport 179 ip6 saddr @bgp_peers_v6 accept
		tcp dport 179 drop
	}
}

nft list会将priority 0标准化为priority filter并去除注释。这是正常行为。

测试规则是否生效,从VPS上检查:

sudo nft list ruleset | grep -c "179"

返回值应与你创建的179端口规则数量一致。

同时确认BGP流量在你和对端之间没有被阻断。上述规则只影响入站连接。BIRD发起的到对端的出站连接由established/related conntrack条目处理。如果你有严格的出站策略,添加:

sudo nft add rule inet bgp_filter input ct state established,related accept

这条规则通常已存在于你的基础防火墙规则集中。如果没有,将它添加在BGP规则之前。

如何应用BIRD2配置?

加载新配置前先验证:

sudo birdc configure check

预期输出:

BIRD 2.18 ready.
Reading configuration from /etc/bird/bird.conf
Configuration OK

如果有语法错误,BIRD会报告行号和问题。修正后重新检查。

应用配置:

sudo birdc configure
BIRD 2.18 ready.
Reading configuration from /etc/bird/bird.conf
Reconfigured

你可能看到Reconfiguration in progress而不是Reconfigured。当BIRD仍在处理协议变更(如建立新BGP会话)时会出现这种情况。两者都是正常的。

BIRD在不重启的情况下应用新配置。现有会话会尽可能进行软重配置(soft reconfiguration)。如果你修改了邻居IP或本地AS,BIRD会自动重启受影响的协议。

对于不应中断运行中会话的配置变更(过滤器修改、静态路由添加),使用:

sudo birdc reload upstream1

这会对现有路由重新应用导入/导出过滤器,而不拆除TCP会话。

如何验证BGP会话和路由宣告?

应用配置后,使用birdc检查会话是否已建立以及路由是否正在被宣告。这些命令是你的主要调试工具。

命令 显示内容 使用时机
show protocols 协议状态摘要(Established、Active等) 配置变更后的首次检查
show protocols all upstream1 完整的会话详情、计数器、定时器 调试特定会话
show route BIRD表中的所有路由 验证接收到的路由和静态路由
show route export upstream1 正在发送给上游的路由 确认你的前缀已被宣告
show route for 203.0.113.0/24 特定前缀的最佳路由 追踪路径选择
show route protocol static_v4 来自特定协议的路由 验证静态路由已加载

检查会话状态

sudo birdc show protocols

正常工作时的预期输出:

BIRD 2.18 ready.
Name       Proto      Table      State  Since         Info
device1    Device     ---        up     12:00:00.000
direct1    Direct     ---        up     12:00:00.000
kernel1    Kernel     master4    up     12:00:00.000
kernel2    Kernel     master6    up     12:00:00.000
static_v4  Static     master4    up     12:00:00.000
static_v6  Static     master6    up     12:00:00.000
upstream1  BGP        ---        up     12:00:05.000  Established

Established状态表示BGP会话已建立并可以交换路由。其他任何状态都意味着存在问题。

检查导出的路由

sudo birdc show route export upstream1
BIRD 2.18 ready.
Table master4:
203.0.113.0/24       unicast [static_v4 12:00:00.000] * (200)
	dev dummy0
Table master6:
2001:db8:1000::/48   unicast [static_v6 12:00:00.000] * (200)
	dev dummy0

你的IPv4和IPv6前缀都应该出现在这里。如果某个前缀缺失,说明导出过滤器将其拒绝了。

查看完整会话详情

sudo birdc show protocols all upstream1

查找Routes:行:

  Routes:         2 imported, 0 filtered, 2 exported, 0 preferred

exported计数应与你计划宣告的前缀数量一致。

从外部验证

使用公共Looking Glass确认你的前缀在互联网上可见。NLNOG Looking Glass或PeeringDB可以帮助你。搜索你的前缀并验证:

  • Origin AS与你的一致
  • AS路径经过你的上游
  • 没有出现RPKI invalid状态

同时检查内核路由表:

ip route show | grep 203.0.113
ip -6 route show | grep 2001:db8:1000

你应该看到路由指向dummy0接口。

如何排查常见的BIRD2 BGP问题?

大多数BGP问题归结为几类。按以下顺序排查。

BGP会话状态参考

状态 含义 排查方向
Idle BIRD未尝试连接 配置错误、协议被禁用
Connect TCP连接进行中 防火墙阻断179端口、邻居IP错误
Active TCP连接失败,正在重试 对端不可达、防火墙、源地址错误
OpenSent TCP已连接,等待OPEN回复 MD5密码不匹配、对端ASN配置错误
OpenConfirm 已收到OPEN,等待KEEPALIVE 很少停留在此状态,通常快速转换
Established 会话已建立,正在交换路由 正常工作

会话停留在Connect或Active状态

这表示TCP无法到达对端的179端口。排查:

# Can you reach the peer at all?
ping -c 3 198.51.100.1

# Is port 179 open on the peer?
nc -zv 198.51.100.1 179

# Are your nftables rules blocking outbound?
sudo nft list ruleset | grep 179

# Check BIRD logs
journalctl -u bird --since "5 minutes ago" --no-pager

常见原因: BGP块中source address配置错误、对端尚未完成其侧的配置,或你的防火墙阻断了出站连接。

会话停留在OpenSent状态

TCP连接正常但BGP OPEN消息被拒绝。几乎可以确定是MD5密码不匹配。验证:

  1. bird.conf中的password与服务商提供的完全一致(区分大小写,注意末尾空格)
  2. 双方就ASN达成一致

查看日志获取详细信息:

journalctl -u bird | grep -i "error\|md5\|password"

前缀未出现在show route export

你的前缀存在于BIRD的路由表中,但导出过滤器未接受它。调试过滤器:

sudo birdc show route 203.0.113.0/24 all

检查路由来源。如果显示的是[device1][direct1]而不是[static_v4],说明静态路由配置不正确。导出过滤器匹配的是路由本身,因此路由必须来自正确的协议。

sudo birdc show route noexport upstream1

这会显示被过滤器明确拒绝的路由。如果你的前缀出现在这里,说明过滤器逻辑有bug。

前缀已宣告但在Looking Glass上不可见

你的导出正常工作,但路由未在传播。可能的原因:

  • 没有ROA记录: 你的上游或其对等方会过滤RPKI invalid的路由。先发布ROA记录
  • IRR过滤: 你的上游基于IRR对象(RIPE DB、RADB)进行过滤。创建或更新你的route/route6对象
  • 最大前缀限制: 你的上游可能配置了前缀限制。如果达到限制,联系他们
  • 传播延迟: BGP收敛需要几分钟。等待5-10分钟后再检查

查看日志

BIRD将日志写入系统日志。实时排障:

journalctl -u bird -f

查看过去一小时的事件:

journalctl -u bird --since "1 hour ago" --no-pager

查找包含ErrorBGPsessionReceived的行。它们会告诉你BIRD正在做什么以及出了什么问题。

BIRD2与BIRD 1.x: 迁移注意事项

如果你从BIRD 1.x迁移,主要区别如下:

  • 单一守护进程: BIRD2用一个进程替代了birdbird6
  • 通道语法: IPv4和IPv6作为协议块内的通道配置,而非独立的协议
  • 过滤器语法: 大部分兼容,但部分函数改了名。查阅BIRD2文档获取完整的过滤器参考
  • 配置文件: 默认路径从/etc/bird/bird.conf/etc/bird/bird6.conf合并为单一的/etc/bird/bird.conf
  • birdc套接字: 使用/run/bird/bird.ctl单一套接字,而非分离的IPv4/IPv6套接字

后续步骤

BGP会话已建立并开始宣告前缀后,还有几项配置需要完成:

  • RPKI验证: 设置RTR协议,基于ROA数据验证收到的路由
  • 导入过滤器: 过滤收到的路由,防止路由泄露和劫持
  • 多上游冗余: 添加第二个protocol bgp块实现冗余。使用preference设置主备优先级
  • BFD: 启用Bidirectional Forwarding Detection(双向转发检测),实现上游之间亚秒级故障切换
  • 监控: 使用bird_exporter将BIRD指标导出到Prometheus

关于替代路由守护进程,参见。完整的BYOIP流程请从BYOIP指南开始。


Copyright 2026 Virtua.Cloud. All rights reserved.

准备好亲自尝试了吗?

几秒内部署您自己的服务器。支持 Linux、Windows 或 FreeBSD。

查看 VPS 方案