BGP路由过滤:前缀列表、AS路径过滤、Bogon拒绝与GTSM
面向Linux BGP会话加固的实用参考。涵盖前缀列表、bogon拒绝、AS路径过滤、最大前缀限制和GTSM,同时提供BIRD2与FRR语法及验证步骤。
RPKI验证AS是否有权发起某个前缀的通告。它无法防护路由泄露、bogon注入、配置错误对端导致的路由表爆炸,也无法防护来自非直连主机的伪造BGP数据包。本文涵盖RPKI未覆盖的其他过滤手段。
每项过滤器均以BIRD2和FRR两种语法展示,包含IPv4和IPv6示例。每节先说明该过滤器能防止什么,再给出配置,最后说明如何验证其有效性。
如果尚未完成RPKI源验证,请先完成该步骤。参见RPKI ROA Setup for BGP。
基础BGP会话配置请参见BIRD2 BGP Configuration on Linux(BIRD2)或FRR BGP Configuration on Linux(FRR)。本文假设你已有一个正常运行的BGP会话,现在需要对其进行加固。
为什么BGP路由过滤需要在RPKI之外做更多?
BGP路由过滤是基于前缀、AS路径或源属性来接受或拒绝BGP通告的做法。它防止路由泄露、前缀劫持、bogon注入和路由表爆炸。RPKI只覆盖源验证。没有额外过滤器,你的路由器会暴露于其他所有类别的BGP安全事件。
各层过滤器的防护目标如下:
| 过滤器类型 | 阻断的威胁 | 不使用的后果 |
|---|---|---|
| Bogon前缀拒绝 | DFZ中的私有/保留地址空间 | 路由器将流量转发到RFC 1918地址,形成黑洞。 |
| 小前缀拒绝 | 更精确的劫持路由(/25+,/49+) | 攻击者通告覆盖你接受的/24中一部分的/32路由,以最长匹配方式赢得竞争。 |
| AS路径bogon过滤 | 路径中包含私有/保留ASN | AS 65535或AS 4200000000的路由泄漏进你的路由表,转发基于无效路径。 |
| AS路径长度限制 | 路径膨胀攻击、路由表臃肿 | 对端发送超过50个AS跳的路由,占满内存。 |
| 最大前缀限制 | 路由泄露、会话过载 | 对端将完整路由表(100万+前缀)泄漏进你的会话,路由器内存耗尽。 |
| GTSM(TTL安全) | 来自远程主机的伪造BGP数据包 | 多跳之外的攻击者向你的会话注入BGP OPEN或UPDATE数据包。 |
| RPKI源验证 | 源劫持 | 他人从其AS发起你的前缀通告。已在RPKI ROA Setup for BGP中覆盖。 |
真实事件说明了每层防护的重要性。2008年,巴基斯坦电信(Pakistan Telecom)为执行国内审查令,通告了YouTube前缀的更精确路由。这些路由泄漏到国际传输提供商,导致YouTube在全球范围内黑洞化数小时。传输提供商处的bogon或小前缀过滤器本可丢弃这些通告。2019年6月,宾夕法尼亚州一家小型ISP(AS396531)意外将Cloudflare、Amazon和Linode的路由泄露给Verizon,并扩散至全球。最大前缀限制本可在泄露扩散前拆除该会话。
如何在BIRD2和FRR中过滤bogon前缀?
Bogon前缀是绝对不应出现在全球路由表中的地址范围。包括RFC 1918私有地址空间、链路本地地址、文档用地址段和保留块。接受这些前缀意味着路由器会尝试将流量转发到没有合法全局目的地的地址,形成黑洞。
IPv4 bogon前缀
| 前缀 | 参考标准 | 用途 |
|---|---|---|
| 0.0.0.0/8 | RFC 1122 | "本"网络 |
| 10.0.0.0/8 | RFC 1918 | 私有地址空间 |
| 100.64.0.0/10 | RFC 6598 | 运营商级NAT |
| 127.0.0.0/8 | RFC 1122 | 回环地址 |
| 169.254.0.0/16 | RFC 3927 | 链路本地 |
| 172.16.0.0/12 | RFC 1918 | 私有地址空间 |
| 192.0.2.0/24 | RFC 5737 | TEST-NET-1 |
| 192.88.99.0/24 | RFC 7526 | 已废弃的6to4中继 |
| 192.168.0.0/16 | RFC 1918 | 私有地址空间 |
| 198.18.0.0/15 | RFC 2544 | 基准测试 |
| 198.51.100.0/24 | RFC 5737 | TEST-NET-2 |
| 203.0.113.0/24 | RFC 5737 | TEST-NET-3 |
| 224.0.0.0/4 | RFC 5771 | 组播 |
| 240.0.0.0/4 | RFC 1112 | 保留供未来使用 |
IPv6 bogon前缀
| 前缀 | 参考标准 | 用途 |
|---|---|---|
| ::/8 | 各类标准 | IPv4兼容、回环、映射地址 |
| 100::/64 | RFC 6666 | 仅丢弃 |
| 2001:2::/48 | RFC 5180 | BMWG基准测试 |
| 2001:10::/28 | RFC 4843 | ORCHID |
| 2001:db8::/32 | RFC 3849 | 文档用 |
| 3fff::/20 | RFC 9637 | 文档用 |
| 2002::/16 | RFC 7526 | 已废弃的6to4 |
| 3ffe::/16 | RFC 3701 | 原6bone |
| 5f00::/16 | RFC 9602 | SRv6 SIDs |
| fc00::/7 | RFC 4193 | 唯一本地单播 |
| fe80::/10 | RFC 4291 | 链路本地单播 |
| fec0::/10 | RFC 3879 | 已废弃的站点本地 |
| ff00::/8 | RFC 4291 | 组播 |
当IANA分配新块或废弃旧块时,这些列表会发生变化。Team Cymru bogon参考提供自动更新的fullbogons(未分配+保留空间)BGP Feed。静态列表请定期检查NLNOG BGP过滤指南。
BIRD2 bogon过滤器
# /etc/bird/bogons.conf - include this from your main bird.conf
define BOGON_PREFIXES_V4 = [
0.0.0.0/8+,
10.0.0.0/8+,
100.64.0.0/10+,
127.0.0.0/8+,
169.254.0.0/16+,
172.16.0.0/12+,
192.0.2.0/24+,
192.88.99.0/24+,
192.168.0.0/16+,
198.18.0.0/15+,
198.51.100.0/24+,
203.0.113.0/24+,
224.0.0.0/4+,
240.0.0.0/4+
];
define BOGON_PREFIXES_V6 = [
::/8+,
0100::/64+,
2001:2::/48+,
2001:10::/28+,
2001:db8::/32+,
3fff::/20+,
2002::/16+,
3ffe::/16+,
5f00::/16+,
fc00::/7+,
fe80::/10+,
fec0::/10+,
ff00::/8+
];
function reject_bogon_prefixes_v4() {
if (net ~ BOGON_PREFIXES_V4) then {
print "REJECTED bogon prefix: ", net, " path: ", bgp_path;
reject;
}
}
function reject_bogon_prefixes_v6() {
if (net ~ BOGON_PREFIXES_V6) then {
print "REJECTED bogon prefix: ", net, " path: ", bgp_path;
reject;
}
}
每个前缀后的+表示"此前缀及所有更精确子网"。10.0.0.0/8+匹配10.0.0.0/8、10.0.0.0/9、10.1.0.0/16等。这样可以拦截攻击者通告RFC 1918空间内某个/24的情况。
在导入过滤器中调用这些函数:
filter import_from_upstream_v4 {
reject_bogon_prefixes_v4();
# ... other filters ...
accept;
}
protocol bgp upstream_v4 {
local as 64500;
neighbor 198.51.100.1 as 64501;
ipv4 {
import filter import_from_upstream_v4;
export none;
};
}
FRR bogon过滤器
! IPv4 bogon prefix-list
ip prefix-list BOGONS_v4 seq 10 deny 0.0.0.0/8 le 32
ip prefix-list BOGONS_v4 seq 20 deny 10.0.0.0/8 le 32
ip prefix-list BOGONS_v4 seq 30 deny 100.64.0.0/10 le 32
ip prefix-list BOGONS_v4 seq 40 deny 127.0.0.0/8 le 32
ip prefix-list BOGONS_v4 seq 50 deny 169.254.0.0/16 le 32
ip prefix-list BOGONS_v4 seq 60 deny 172.16.0.0/12 le 32
ip prefix-list BOGONS_v4 seq 70 deny 192.0.2.0/24 le 32
ip prefix-list BOGONS_v4 seq 80 deny 192.88.99.0/24 le 32
ip prefix-list BOGONS_v4 seq 90 deny 192.168.0.0/16 le 32
ip prefix-list BOGONS_v4 seq 100 deny 198.18.0.0/15 le 32
ip prefix-list BOGONS_v4 seq 110 deny 198.51.100.0/24 le 32
ip prefix-list BOGONS_v4 seq 120 deny 203.0.113.0/24 le 32
ip prefix-list BOGONS_v4 seq 130 deny 224.0.0.0/4 le 32
ip prefix-list BOGONS_v4 seq 140 deny 240.0.0.0/4 le 32
ip prefix-list BOGONS_v4 seq 999 permit 0.0.0.0/0 le 32
! IPv6 bogon prefix-list
ipv6 prefix-list BOGONS_v6 seq 10 deny ::/8 le 128
ipv6 prefix-list BOGONS_v6 seq 20 deny 100::/64 le 128
ipv6 prefix-list BOGONS_v6 seq 30 deny 2001:2::/48 le 128
ipv6 prefix-list BOGONS_v6 seq 40 deny 2001:10::/28 le 128
ipv6 prefix-list BOGONS_v6 seq 50 deny 2001:db8::/32 le 128
ipv6 prefix-list BOGONS_v6 seq 60 deny 3fff::/20 le 128
ipv6 prefix-list BOGONS_v6 seq 70 deny 2002::/16 le 128
ipv6 prefix-list BOGONS_v6 seq 80 deny 3ffe::/16 le 128
ipv6 prefix-list BOGONS_v6 seq 90 deny 5f00::/16 le 128
ipv6 prefix-list BOGONS_v6 seq 100 deny fc00::/7 le 128
ipv6 prefix-list BOGONS_v6 seq 110 deny fe80::/10 le 128
ipv6 prefix-list BOGONS_v6 seq 120 deny fec0::/10 le 128
ipv6 prefix-list BOGONS_v6 seq 130 deny ff00::/8 le 128
ipv6 prefix-list BOGONS_v6 seq 999 permit ::/0 le 128
le 32(IPv4)和le 128(IPv6)子句与前缀及所有更精确子网匹配,与BIRD2中的+运算符相同。最后seq 999处的permit条目允许所有未被拒绝的路由通过。
将前缀列表应用到邻居:
router bgp 64500
neighbor 198.51.100.1 remote-as 64501
address-family ipv4 unicast
neighbor 198.51.100.1 prefix-list BOGONS_v4 in
address-family ipv6 unicast
neighbor 2001:db8::1 prefix-list BOGONS_v6 in
注意:2001:db8::/32条目在bogon列表中。生产环境不要使用文档地址。将上面的邻居地址替换为实际的对端IP。
拒绝过小的前缀
小于/24(IPv4)或/48(IPv6)的路由在全球DFZ中无法可靠传播。更重要的是,接受这些路由会使你暴露于更精确前缀劫持攻击。在入站方向过滤。
BIRD2:
function reject_small_prefixes_v4() {
if (net.len > 24) then {
print "REJECTED too-small prefix: ", net, " path: ", bgp_path;
reject;
}
}
function reject_small_prefixes_v6() {
if (net.len > 48) then {
print "REJECTED too-small prefix: ", net, " path: ", bgp_path;
reject;
}
}
FRR:
! Add to the same prefix-lists, before the final permit
ip prefix-list BOGONS_v4 seq 150 deny 0.0.0.0/0 ge 25 le 32
ipv6 prefix-list BOGONS_v6 seq 140 deny ::/0 ge 49 le 128
这会拦截所有比/24(IPv4)或/48(IPv6)更精确的前缀。将这些条目放在seq 999 permit条目之前。
AS路径过滤器如何防止路由泄露?
AS路径过滤器检查路由所经过的自治系统序列。它能发现三类问题:不应出现在路径中的bogon ASN、表明泄露或操纵的过长路径,以及通告前未被剥离的私有ASN。
过滤bogon ASN
Bogon ASN是在公共互联网的BGP路径中不应出现的保留编号:
| ASN范围 | 参考标准 | 用途 |
|---|---|---|
| 0 | RFC 7607 | 保留 |
| 23456 | RFC 4893 | AS_TRANS(4字节AS过渡) |
| 64496-64511 | RFC 5398 | 文档/示例 |
| 64512-65534 | RFC 6996 | 私有使用(16位) |
| 65535 | RFC 7300 | 最后一个16位ASN |
| 65536-65551 | RFC 5398 | 文档/示例(32位) |
| 65552-131071 | IANA | 保留 |
| 4200000000-4294967294 | RFC 6996 | 私有使用(32位) |
| 4294967295 | RFC 7300 | 最后一个32位ASN |
BIRD2:
define BOGON_ASNS = [
0,
23456,
64496..64511,
64512..65534,
65535,
65536..65551,
65552..131071,
4200000000..4294967294,
4294967295
];
function reject_bogon_asns()
int set bogon_asns;
{
bogon_asns = BOGON_ASNS;
if (bgp_path ~ bogon_asns) then {
print "REJECTED bogon ASN in path: ", net, " path: ", bgp_path;
reject;
}
}
bgp_path ~ bogon_asns运算符检查路径中是否有任何ASN属于该集合。路径中任意位置出现一个bogon ASN即触发拒绝。
FRR:
bgp as-path access-list BOGON_ASNS deny _0_
bgp as-path access-list BOGON_ASNS deny _23456_
bgp as-path access-list BOGON_ASNS deny _6449[6-9]_
bgp as-path access-list BOGON_ASNS deny _6450[0-9]_
bgp as-path access-list BOGON_ASNS deny _6451[01]_
bgp as-path access-list BOGON_ASNS deny _64[5-9][1-9][2-9]_
bgp as-path access-list BOGON_ASNS deny _6[5-9][0-9][0-9][0-9]_
bgp as-path access-list BOGON_ASNS deny _[1-9][0-9][0-9][0-9][0-9]_
bgp as-path access-list BOGON_ASNS deny _[1-3][0-9][0-9][0-9][0-9][0-9]_
bgp as-path access-list BOGON_ASNS permit .*
FRR对AS路径字符串使用正则匹配。下划线_匹配AS路径分隔符(空格、开始、结束)。这种正则方式不如BIRD2的整数集合匹配精确。使用route-map配合as-path access-list:
route-map IMPORT_FILTER deny 10
match as-path BOGON_ASNS
route-map IMPORT_FILTER permit 100
router bgp 64500
address-family ipv4 unicast
neighbor 198.51.100.1 route-map IMPORT_FILTER in
注意:上述正则模式已经过简化。用正则完整匹配32位私有ASN范围(4200000000-4294967294)容易出错。生产部署建议使用bgpq4从IRR数据生成前缀列表和AS路径过滤器,这样更准确且可自动化。
限制AS路径长度
合法的BGP路径很少超过10-15个ASN。超过这个长度通常表明存在路由泄露、路径操纵或错误的路径预置。设置一个硬限制。
BIRD2:
function reject_long_paths() {
if (bgp_path.len > 25) then {
print "REJECTED long AS-path (", bgp_path.len, "): ", net, " path: ", bgp_path;
reject;
}
}
FRR:
bgp as-path access-list LONG_PATHS deny ^([0-9]+_){25,}
bgp as-path access-list LONG_PATHS permit .*
route-map IMPORT_FILTER deny 20
match as-path LONG_PATHS
25的限制是保守值。大多数合法路由的路径在10以下。如果你接收完整路由表,在确定阈值前先检查RIB中最长的路径:
# BIRD2
birdc 'show route where bgp_path.len > 15' | head -20
# FRR
vtysh -c "show ip bgp regexp ^([0-9]+_){15,}"
在出站方向剥离私有ASN
如果你在内部使用私有ASN运行iBGP,确保它们不会泄漏到上游。
BIRD2:
filter export_to_upstream_v4 {
# Strip private ASNs before advertising
bgp_path.delete([64512..65534, 4200000000..4294967294]);
# ... your export policy ...
accept;
}
FRR:
router bgp 64500
address-family ipv4 unicast
neighbor 198.51.100.1 remove-private-AS all
all关键字即使在路径中存在公共ASN时也会移除所有私有ASN。不加all,FRR仅在整个路径全部为私有ASN时才剥离。
BGP会话的最大前缀限制应如何设置?
最大前缀限制是一个安全阀,当对端通告的前缀数超过配置阈值时拆除BGP会话。它能防止对端意外泄露完整路由表或被劫持时导致路由表爆炸。没有这个限制,单个配置错误的对端就可能耗尽路由器内存。
根据对每个对端的预期来设置限制:
| 对端类型 | 预期前缀数(IPv4) | 建议限制 | 建议限制(IPv6) |
|---|---|---|---|
| 完整路由表上游 | ~1,200,000(2026年3月) | 1,500,000 | 300,000 |
| 部分路由表 / IXP对端 | 不固定 | 当前数量的1.5倍 | 当前数量的1.5倍 |
| 单宿客户 | 1-10 | 50 | 50 |
| 多宿客户 | 10-100 | 200 | 200 |
设置上游限制前请在bgp.potaroo.net检查当前完整路由表大小。将限制设置为预期数量的约1.2倍,以吸收正常增长而不触发误报。
BIRD2:
protocol bgp upstream_v4 {
local as 64500;
neighbor 198.51.100.1 as 64501;
ipv4 {
import limit 1500000 action restart;
import filter import_from_upstream_v4;
export none;
};
}
protocol bgp customer_v4 {
local as 64500;
neighbor 203.0.113.10 as 64502;
ipv4 {
import limit 50 action disable;
import filter import_from_customer_v4;
export filter export_to_customer_v4;
};
}
BIRD2在达到限制时提供三种动作:
action restart- 拆除会话并在延迟后重启。适合上游对端。action disable- 拆除并禁用协议。需要手动执行birdc enable恢复。适合客户对端,触发限制意味着出现严重问题。action block- 停止导入新路由但保持会话。适合在调查期间保留现有路由。
FRR:
router bgp 64500
neighbor 198.51.100.1 remote-as 64501
address-family ipv4 unicast
neighbor 198.51.100.1 maximum-prefix 1500000 90 restart 5
neighbor 203.0.113.10 remote-as 64502
address-family ipv4 unicast
neighbor 203.0.113.10 maximum-prefix 50 80
FRR中,maximum-prefix 1500000 90 restart 5的含义:在90%时(1,350,000个前缀)警告,达到1,500,000时拆除,5分钟后重启会话。不加restart关键字,FRR会拆除会话并需要手动执行clear bgp neighbor才能恢复。
验证最大前缀配置
# BIRD2 - check current prefix count and limit
birdc show protocols all upstream_v4 | grep -E "Routes|Limit"
# FRR - check prefix count per neighbor
vtysh -c "show ip bgp summary"
输出会在配置限制旁显示当前前缀数。如果数量接近限制,在触发之前增大阈值。
GTSM如何保护BGP会话免受伪造数据包攻击?
GTSM(通用TTL安全机制,Generalized TTL Security Mechanism,RFC 5082)通过检查TTL/Hop Limit字段,将接受的BGP数据包限制为直连对端。启用后,BGP数据包以TTL 255发送。接收方丢弃所有TTL低于254的BGP数据包(对于直连对端)。由于路由器在每跳都会递减TTL,多跳之外的攻击者无法发送到达时TTL为255的数据包。
这可阻断远程TCP RST注入、针对BGP 179端口的SYN洪泛,以及来自非直连攻击者的伪造BGP OPEN/UPDATE数据包。GTSM与同一会话上的eBGP multihop互斥。双方都必须启用。
BIRD2:
protocol bgp upstream_v4 {
local as 64500;
neighbor 198.51.100.1 as 64501;
ttl security yes;
ipv4 {
import limit 1500000 action restart;
import filter import_from_upstream_v4;
export none;
};
}
FRR:
router bgp 64500
neighbor 198.51.100.1 remote-as 64501
neighbor 198.51.100.1 ttl-security hops 1
hops 1表示对端必须恰好距离1跳(直连)。根据实际跳数设置此值。对于IXP交换结构上的eBGP对端,hops 1是正确的。对于多跳会话(如BGP over GRE隧道),无法使用GTSM。改用MD5认证:
BIRD2 MD5替代方案:
protocol bgp multihop_peer {
local as 64500;
neighbor 198.51.100.5 as 64503;
multihop 2;
password "your-md5-secret";
# ...
}
FRR MD5替代方案:
router bgp 64500
neighbor 198.51.100.5 remote-as 64503
neighbor 198.51.100.5 ebgp-multihop 2
neighbor 198.51.100.5 password your-md5-secret
将MD5密码存储在受限文件(chmod 600)中,而不是主配置文件里。对于FRR,在/etc/frr/frr.conf中引用,该文件应已设置为640并由frr:frr拥有。对于BIRD2,保持/etc/bird/bird.conf为640并由bird:bird拥有。
MANRS要求哪些BGP过滤器?
MANRS(路由安全的共识规范,Mutually Agreed Norms for Routing Security)定义了网络运营商的基准行动。行动1、3和4是成为MANRS参与者的必要条件。本文中的过滤器与MANRS行动的对应关系如下。
行动1:防止传播不正确的路由信息。
这是核心过滤行动。要求对客户连接实施明确的前缀级过滤,并推荐使用AS路径过滤器防止路由泄露。
| 本文中的过滤器 | MANRS行动1覆盖 |
|---|---|
| 前缀列表过滤(bogons) | 防止通告/接受保留地址空间 |
| 小前缀拒绝 | 阻断表明劫持的更精确路由 |
| AS路径bogon过滤 | 拒绝包含私有/保留ASN的路由 |
| 最大前缀限制 | 阻止泄露的完整路由表传播 |
| 客户前缀过滤器 | 本文未涵盖。使用bgpq4从IRR数据为每个客户构建。 |
行动2(推荐):防止带有伪造源地址的流量。
不属于BGP过滤器。这是BCP 38/84源地址验证(uRPF)。超出本文范围,但同样重要。
行动3:促进全球运营通信。
在PeeringDB和RIR数据库中保持联系方式最新。不是过滤器,但运行正确过滤器的运营商通常也会维护联系信息。
行动4:在全球范围内促进路由信息共享。
使用RPSL对象在IRR(RIPE、RADB)中发布路由策略。为RPKI创建ROA。这使得对端能够为你的通告构建准确的前缀过滤器。
bogon过滤(前缀+ASN)+ 小前缀拒绝 + 最大前缀限制 + 客户前缀列表的组合覆盖MANRS行动1。添加RPKI(RPKI ROA Setup for BGP)和IRR注册可覆盖行动4。
综合应用:完整的导入过滤器
下面是综合使用上述所有技术的完整导入过滤器。
BIRD2完整导入过滤器
# /etc/bird/filters.conf
include "/etc/bird/bogons.conf"; # BOGON_PREFIXES_V4, BOGON_PREFIXES_V6, BOGON_ASNS
function import_checks_v4() {
# 1. Reject bogon prefixes
if (net ~ BOGON_PREFIXES_V4) then {
print "REJECT bogon prefix: ", net, " ", bgp_path;
reject;
}
# 2. Reject too-small prefixes
if (net.len > 24) then {
print "REJECT small prefix: ", net, " ", bgp_path;
reject;
}
# 3. Reject bogon ASNs in path
if (bgp_path ~ [0, 23456, 64496..64511, 64512..65534, 65535,
65536..65551, 65552..131071,
4200000000..4294967294, 4294967295]) then {
print "REJECT bogon ASN: ", net, " ", bgp_path;
reject;
}
# 4. Reject excessively long paths
if (bgp_path.len > 25) then {
print "REJECT long path: ", net, " ", bgp_path;
reject;
}
# 5. Reject RPKI invalid (if RPKI is configured)
if (roa_check(rpki4, net, bgp_path.last) = ROA_INVALID) then {
print "REJECT RPKI invalid: ", net, " ", bgp_path;
reject;
}
}
filter import_upstream_v4 {
import_checks_v4();
accept;
}
protocol bgp upstream_v4 {
local as 64500;
neighbor 198.51.100.1 as 64501;
ttl security yes;
ipv4 {
import limit 1500000 action restart;
import filter import_upstream_v4;
export none;
};
}
FRR完整导入过滤器
! /etc/frr/frr.conf
! --- Prefix lists (bogons + small prefix rejection) ---
ip prefix-list IMPORT_V4 seq 10 deny 0.0.0.0/8 le 32
ip prefix-list IMPORT_V4 seq 20 deny 10.0.0.0/8 le 32
ip prefix-list IMPORT_V4 seq 30 deny 100.64.0.0/10 le 32
ip prefix-list IMPORT_V4 seq 40 deny 127.0.0.0/8 le 32
ip prefix-list IMPORT_V4 seq 50 deny 169.254.0.0/16 le 32
ip prefix-list IMPORT_V4 seq 60 deny 172.16.0.0/12 le 32
ip prefix-list IMPORT_V4 seq 70 deny 192.0.2.0/24 le 32
ip prefix-list IMPORT_V4 seq 80 deny 192.88.99.0/24 le 32
ip prefix-list IMPORT_V4 seq 90 deny 192.168.0.0/16 le 32
ip prefix-list IMPORT_V4 seq 100 deny 198.18.0.0/15 le 32
ip prefix-list IMPORT_V4 seq 110 deny 198.51.100.0/24 le 32
ip prefix-list IMPORT_V4 seq 120 deny 203.0.113.0/24 le 32
ip prefix-list IMPORT_V4 seq 130 deny 224.0.0.0/4 le 32
ip prefix-list IMPORT_V4 seq 140 deny 240.0.0.0/4 le 32
ip prefix-list IMPORT_V4 seq 150 deny 0.0.0.0/0 ge 25 le 32
ip prefix-list IMPORT_V4 seq 999 permit 0.0.0.0/0 le 32
! --- AS-path filters (bogon ASNs + path length) ---
bgp as-path access-list BOGON_ASNS deny _0_
bgp as-path access-list BOGON_ASNS deny _23456_
bgp as-path access-list BOGON_ASNS deny _6449[6-9]_
bgp as-path access-list BOGON_ASNS deny _6450[0-9]_
bgp as-path access-list BOGON_ASNS deny _6451[01]_
bgp as-path access-list BOGON_ASNS permit .*
bgp as-path access-list LONG_PATHS deny ^([0-9]+_){25,}
bgp as-path access-list LONG_PATHS permit .*
! --- Route-map combining all checks ---
route-map IMPORT_UPSTREAM deny 10
match as-path BOGON_ASNS
route-map IMPORT_UPSTREAM deny 20
match as-path LONG_PATHS
route-map IMPORT_UPSTREAM permit 100
! --- BGP neighbor configuration ---
router bgp 64500
neighbor 198.51.100.1 remote-as 64501
neighbor 198.51.100.1 ttl-security hops 1
address-family ipv4 unicast
neighbor 198.51.100.1 prefix-list IMPORT_V4 in
neighbor 198.51.100.1 route-map IMPORT_UPSTREAM in
neighbor 198.51.100.1 maximum-prefix 1500000 90 restart 5
FRR中,前缀列表和route-map都会被评估。前缀列表先运行,丢弃bogon前缀和小前缀。通过前缀列表的路由再经过route-map检查AS路径过滤器。两者都必须允许路由才能被接受。
如何验证BGP路由过滤器有效?
过滤器只有在真正拒绝应拒绝的内容时才有用。每次变更后都要验证。
BIRD2验证
# Check what routes were rejected (requires print statements in filters)
grep "REJECT" /var/log/bird.log | tail -20
# Show the routing table with filter details
birdc show route filtered
# Show routes from a specific protocol
birdc show route protocol upstream_v4
# Count accepted routes per protocol
birdc show protocols all upstream_v4 | grep "Routes:"
# Test a specific prefix against your import filter
birdc show route for 10.0.0.0/8 all
show route filtered命令显示已收到但被导入过滤器拒绝的路由。如果bogon过滤器正常工作,接受的路由表中应该看不到bogon前缀,所有收到的bogon路由应出现在filtered表中。
FRR验证
# Show accepted routes from a neighbor
vtysh -c "show ip bgp neighbors 198.51.100.1 received-routes"
# Show routes filtered by inbound policy
vtysh -c "show ip bgp neighbors 198.51.100.1 filtered-routes"
# Check the prefix count per neighbor
vtysh -c "show ip bgp summary"
# Test if a specific prefix is accepted
vtysh -c "show ip bgp 10.0.0.0/8"
# Check max-prefix status
vtysh -c "show ip bgp neighbors 198.51.100.1" | grep -A2 "Maximum prefix"
要使received-routes和filtered-routes生效,必须在邻居上启用软重配入站:
router bgp 64500
address-family ipv4 unicast
neighbor 198.51.100.1 soft-reconfiguration inbound
这会使用额外内存(存储过滤前的所有已收路由)。对于完整路由表会话,大约是RIB内存的2倍。在RAM有限的生产路由器上,选择性使用。
外部验证
你的过滤器保护自己的RIB。要验证你向外界通告了什么,使用外部looking glass:
- bgp.tools - 搜索你的ASN,查看全球范围内你通告的前缀
- RIPE RIS - BGP路由信息服务,显示跨收集器的路由可见性
- Hurricane Electric BGP Toolkit - 前缀和ASN查询
过滤器变更后检查这些工具,确认你没有意外过滤掉合法路由,也没有泄漏不应通告的路由。
如需自动化监控,参见 。
BIRD2与FRR语法对照
两种路由守护进程之间的快速参考:
| 过滤器类型 | BIRD2 | FRR |
|---|---|---|
| Bogon前缀 | if (net ~ BOGON_PREFIXES) then reject |
ip prefix-list BOGONS deny 10.0.0.0/8 le 32 |
| 小前缀 | if (net.len > 24) then reject |
ip prefix-list X deny 0.0.0.0/0 ge 25 le 32 |
| Bogon ASN | if (bgp_path ~ [64512..65534]) then reject |
bgp as-path access-list X deny _64[5-9][1-9][2-9]_ |
| 路径长度 | if (bgp_path.len > 25) then reject |
bgp as-path access-list X deny ^([0-9]+_){25,} |
| 最大前缀 | import limit 50 action disable |
neighbor X maximum-prefix 50 |
| GTSM | ttl security yes |
neighbor X ttl-security hops 1 |
| MD5认证 | password "secret" |
neighbor X password secret |
| 剥离私有AS | bgp_path.delete([64512..65534]) |
neighbor X remove-private-AS all |
| 应用过滤器 | import filter name |
neighbor X prefix-list/route-map name in |
BIRD2使用单一过滤器函数组合所有检查。FRR将检查分散在前缀列表(前缀匹配)、as-path access-list(路径匹配)和route-map(组合多个匹配条件)之间。两种方法都可用。BIRD2的方式在处理复杂策略时更易读。FRR的方式对Cisco运维人员更熟悉。
出现问题了?
max-prefix触发会话拆除: 检查journalctl -u bird或journalctl -u frr中的限制触发消息。如果对端确实增长则增大限制,否则调查是否为泄漏。BIRD2中用birdc enable upstream_v4重新启用。FRR中用vtysh -c "clear bgp 198.51.100.1"清除。
合法路由被过滤: 检查birdc show route filtered或vtysh -c "show ip bgp neighbors X filtered-routes"查看被丢弃的内容。常见原因:bogon列表过于激进,或小前缀阈值拒绝了来自客户的合法/25路由。调整过滤器并重新加载:birdc configure或vtysh -c "write memory"后执行systemctl reload frr。
GTSM拒绝有效对端: 双方都必须启用GTSM。如果一方启用另一方未启用,数据包到达时TTL为1,被启用GTSM的一方丢弃。用tcpdump -i eth0 port 179 -v检查TTL值。
变更后过滤器未生效: BIRD2中运行birdc configure重新加载。FRR中,如果更改了前缀列表或route-map,触发软重置:vtysh -c "clear bgp 198.51.100.1 in"。不执行此操作,RIB中的现有路由不会对新过滤器重新评估。
日志: 两个守护进程默认通过systemd journal记录日志。
# BIRD2
journalctl -u bird -f
# FRR
journalctl -u frr -f
BIRD2过滤器函数中的print语句写入bird日志。FRR中,在vtysh中使用debug bgp updates启用调试日志进行临时排查。排查完成后禁用,因为它会产生大量日志输出。
本文是BGP Bring Your Own IP on a VPS系列的一部分。
Copyright 2026 Virtua.Cloud. All rights reserved.