文章目录
原文章:https://dn42.dev/howto/Bird2
Debian 11 安装 bird2 最新版本
#第一:为debain 11 添加 bullseye-backports 源
echo 'deb http://deb.debian.org/debian bullseye-backports main' >> /etc/apt/sources.list
#第二:安装 bullseye-backports 源中的 bird2 (里面是最新的bird2.0.10)
apt install -t bullseye-backports bird2
Bird2的安装
#注意,bird2只有一个进程,可以管理ipv4和ipv6,而bird1是两个分开的进程
yum install epel* -y
yum update -y
yum install bird2
递归创建目录,备份默认配置文件,因为这两个目录默认都没有
mkdir /etc/bird/peer -p
mv /etc/bird.conf /etc/bird.conf.bak
创建bird的主配置文件(/etc/bird.conf)并根据自己的情况进行修改(这是我取自DN42 wiki上的模板)
#日志调试部分
log "/var/log/bird.log" { debug, trace, info, remote, warning, error, auth, fatal, bug };
log stderr all;
log syslog all;
#打开所有协议的全局调试,调试协议{事件,状态};
debug protocols all;
debug protocols { events, states };
################# 变量定义 ###################
define LOCAL_IP = 172.20.58.194;
define BACKBONE = 172.20.58.194/32; #ospf将宣告此骨干节点给其他骨干节点
define MYASN = 4242420524;
define OWNIPv6 = fe80::f816:3eff:fe16:3c43;
define OWNNET = 172.20.58.192/27;
define OWNNETv6 = fd91:7b3d:8d19::/48;
define OWNNETSET = 172.20.58.192/27;
define OWNNETSETv6 = fd91:7b3d:8d19::/48;
################################################
# Header end #
################################################
router id LOCAL_IP;
#include "/etc/bird/local6.conf";
#include "/etc/bird/filter6.conf";
function is_valid_network() {
return net ~ [
172.20.0.0/14{21,29}, # dn42
172.20.0.0/24{28,32}, # dn42 Anycast
172.21.0.0/24{28,32}, # dn42 Anycast
172.22.0.0/24{28,32}, # dn42 Anycast
172.23.0.0/24{28,32}, # dn42 Anycast
172.31.0.0/16+, # ChaosVPN
10.100.0.0/14+, # ChaosVPN
10.0.0.0/8{15,24} # Freifunk.net
];
}
function is_self_net() {
return net ~ OWNNETSET;
}
function is_self_net_v6() {
return net ~ OWNNETSETv6;
}
roa4 table dn42_roa;
roa6 table dn42_roa_v6;
protocol static {
roa4 { table dn42_roa; };
include "/etc/bird/roa_dn42.conf";
};
protocol static {
roa6 { table dn42_roa_v6; };
include "/etc/bird/roa_dn42_v6.conf";
};
protocol static {
route OWNNET reject;
ipv4 {
import all;
export none;
};
}
protocol static {
route OWNNETv6 reject;
ipv6 {
import all;
export none;
};
}
function is_valid_network_v6() {
return net ~ [
fd00::/8{44,64} # ULA address space as per RFC 4193
];
}
#device不是真正路由表
protocol device {
scan time 10;
}
#direct不是真正路由表
protocol direct {
ipv4; # Connect to default IPv4 table
ipv6; # Connect to default IPv4 table
}
protocol kernel {
scan time 10;
ipv6 {
import none;
export filter {
if source = RTS_STATIC then reject;
krt_prefsrc = OWNIPv6;
accept;
};
};
};
#kernel不是真正路由表,它不与网络中的其他路由器通信,而是执行BIRD路由表与OS内核的同步
protocol kernel {
learn;
scan time 10;
ipv4 {
#是将OS内核路由表导入到bird的路由表(默认不同步)
import none;
#是让bird路由表导出到OS内核路由表上
export filter {
#if source = RTS_STATIC then reject;
#可用协议字段RTS_STATIC, RTS_INHERIT, RTS_DEVICE, RTS_STATIC_DEVICE, RTS_REDIRECT,
#RTS_DUMMY, RTS_RIP, RTS_OSPF, RTS_OSPF_IA, RTS_OSPF_EXT1, RTS_OSPF_EXT2, RTS_BGP, RTS_PIPE, RTS_BABEL.
#匹配到是device路由的直接拒绝,其他的就可以导入
if source = RTS_DEVICE then reject;
accept;
};
};
}
protocol ospf I_OSPF {
ipv4 {
#不要把默认路由导入本机OSPF路由表中,不然后果很严重,可能会覆盖你自己的默认路由
import filter { if net = 0.0.0.0/0 then reject; else accept; };
#设置好导出条件,只有当我们的直连和内核路由才通告给OSPF邻居(若是不配置 export,默认也是会导出接口地址/32给邻居的)
#若是你这个节点没有服务可以给别人提供,不管是公网的ipv4服务还是,私网的不限于dn42的私网,就可以不到出
#抱歉我还不会如何将手动写的静态路由导入到ospf传递出去
export filter {
#if (proto = "kernel1" || proto = "direct1") then accept;
#导出你的直连路由,默认情况,你网关IP所在的子网路由会被匹配到,因为这个是直连路由,对于sub场景非常方便,就是你在网关上这样配置下,对方就有到你内网段儿的路由了
if proto = "direct1" then accept;
else reject;
};
};
area 0.0.0.0 {
stubnet BackBone;
interface "*FNK";
};
}
#其他pop点,没有服务器,ospf不需要导出本地网端,不设置export,用程序默认的
#protocol ospf I_OSPF {
# ipv4 {
# import filter { if net = 0.0.0.0/0 then reject; else accept; };
# };
# area 0.0.0.0 {
# stubnet BackBone;
# interface "*FNK";
# };
#}
template bgp dnpeers {
local as MYASN;
path metric 1;
ipv4 {
import filter {
if is_valid_network() && !is_self_net() then {
if (roa_check(dn42_roa, net, bgp_path.last) != ROA_VALID) then {
print "[dn42] ROA check failed for ", net, " ASN ", bgp_path.last;
reject;
} else accept;
} else reject;
};
export filter { if is_valid_network() then accept; else reject; };
import limit 1000 action block;
next hop self;
};
ipv6 {
import filter {
if is_valid_network_v6() && !is_self_net_v6() then {
if (roa_check(dn42_roa_v6, net, bgp_path.last) != ROA_VALID) then {
print "[dn42] ROA check failed for ", net, " ASN ", bgp_path.last;
reject;
} else accept;
} else reject;
};
export filter { if is_valid_network_v6() then accept; else reject; };
import limit 1000 action block;
};
}
#注意这个要放在后面,我就踩过坑放前面,要出错
include "/etc/bird/peers/*";
路线原点授权
上面的示例config依赖于中的ROA配置文件/etc/bird/roa_dn42{,_v6}.conf。这些应该每隔一段时间自动下载和更新,以防止BGP劫持,可以使用简单的cronjob来实现:
*/15 * * * * root curl -sfSLR {-o,-z}/etc/bird/roa_dn42_v6.conf https://dn42.tech9.io/roa/bird6_roa_dn42.conf && curl -sfSLR {-o,-z}/etc/bird/roa_dn42.conf https://dn42.tech9.io/roa/bird_roa_dn42.conf && sed -i 's/roa/route/g' /etc/bird/roa_dn42{,_v6}.conf && birdc configure
配置peer
#由于IPv6的特殊链接本地地址,如果使用了链接本地地址,则必须使用%语法指定接口(建议使用)
cat /etc/bird/peers/<NEIGHBOR_NAME>.conf
protocol bgp <NEIGHBOR_NAME> from dnpeers {
neighbor <NEIGHBOR_IP> as <NEIGHBOR_ASN>;
}
protocol bgp <NEIGHBOR_NAME>_v6 from dnpeers {
neighbor <NEIGHBOR_IPv6>%<NEIGHBOR_INTERFACE> as <NEIGHBOR_ASN>;
}
如果文章对你有帮助,欢迎点击上方按钮打赏作者
暂无评论