三、与他人连接
Lab 示例
互联实验的完整演示
让我们建立一个 Lab,同时包含三种角色:
全部配置
这里我们将一些常量和定义分到了 utils.conf,将函数整理到了 functions.conf并按照对应机器的 ASN 进行更改,省略 irr.conf
roa4 table rpki4;
roa6 table rpki6;
protocol rpki rpki_cloudflare {
roa4 {
table rpki4;
};
roa6 {
table rpki6;
};
remote 172.65.0.2 port 8282;
retry keep 5;
refresh keep 30;
expire 600;
transport tcp;
}
define BOGON_ASNS = [
0, # RFC 7607
23456, # RFC 4893 AS_TRANS
64496..64511, # RFC 5398 and documentation/example ASNs
# 64512..65534, # RFC 6996 Private ASNs 这里我们注释掉,但你在公网上不行!
65535, # RFC 7300 Last 16 bit ASN
65536..65551, # RFC 5398 and documentation/example ASNs
65552..131071, # RFC IANA reserved ASNs
4200000000..4294967294, # RFC 6996 Private ASNs
4294967295 # RFC 7300 Last 32 bit ASN
];
define BOGON_PREFIXES_V4 = [
0.0.0.0/8+, # RFC 1122 'this' network
10.0.0.0/8+, # RFC 1918 private space
100.64.0.0/10+, # RFC 6598 Carrier grade nat space
127.0.0.0/8+, # RFC 1122 localhost
169.254.0.0/16+, # RFC 3927 link local
172.16.0.0/12+, # RFC 1918 private space
192.0.2.0/24+, # RFC 5737 TEST-NET-1
192.88.99.0/24{25,32}, # RFC 7526 deprecated 6to4 relay anycast. If you wish to allow this, change `24+` to `24{25,32}`(no more specific)
192.168.0.0/16+, # RFC 1918 private space
198.18.0.0/15+, # RFC 2544 benchmarking
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+ # multicast
];
define BOGON_PREFIXES_V6 = [
::/8+, # RFC 4291 IPv4-compatible, loopback, et al
0064:ff9b::/96+, # RFC 6052 IPv4/IPv6 Translation
0064:ff9b:1::/48+, # RFC 8215 Local-Use IPv4/IPv6 Translation
0100::/64+, # RFC 6666 Discard-Only
2001::/32{33,128}, # RFC 4380 Teredo, no more specific
2001:2::/48+, # RFC 5180 BMWG
2001:10::/28+, # RFC 4843 ORCHID
# 2001:db8::/32+, # RFC 3849 documentation 这里我们注释掉,但你在公网上不行!
2002::/16{17,128}, # RFC 7526 deprecated 6to4 relay anycast. If you wish to allow this, change `16+` to `16{17,128}`(no more specific)
3ffe::/16+, 5f00::/8+, # RFC 3701 old 6bone
fc00::/7+, # RFC 4193 unique local unicast
fe80::/10+, # RFC 4291 link local unicast
fec0::/10+, # RFC 3879 old site local unicast
ff00::/8+ # RFC 4291 multicast
];
include "utils.conf";
function net_len_too_long() -> bool {
case net.type {
NET_IP4: return net.len > 24; # IPv4 CIDR 大于 /24 为太长
NET_IP6: return net.len > 48; # IPv6 CIDR 大于 /48 为太长
else: print "net_len_too_long: unexpected net.type ", net.type, " ", net; return false;
}
}
function is_not_valid_prefix() -> bool {
case net.type {
NET_IP4: return net ~ BOGON_PREFIXES_V4;
NET_IP6: return net ~ BOGON_PREFIXES_V6;
else: print "is_not_valid_prefix: unexpected net.type ", net.type, " ", net; return false;
}
}
function is_not_valid_asn() -> bool {
if bgp_path ~ BOGON_ASNS then return true;
return false;
}
function rpki_check() -> bool {
if ( net.type = NET_IP4 && roa_check(rpki4, net, bgp_path.last) = ROA_INVALID ) then {
return false;
}
else if ( net.type = NET_IP6 && roa_check(rpki6, net, bgp_path.last) = ROA_INVALID ) then {
return false;
}
else {
return true;
}
}
include "irr.conf";
function import_filter_upstream() -> bool {
if net_len_too_long() || is_not_valid_asn() || is_not_valid_prefix() then {
print net, " invalid prefix, reject";
return false;
}
if !rpki_check() then return false;
bgp_large_community.add((114514,1,1)); # 添加区分 Community
bgp_local_pref = 100; # 设置路由优先级为比较靠后
return true;
}
function export_filter_upstream() -> bool {
if net_len_too_long() || is_not_valid_asn() || is_not_valid_prefix() then {
print net, " export invalid prefix, reject";
return false;
}
if bgp_large_community ~ [(114514, 1, 3), (114514, 1, 4)] then return true;
return false;
}
function import_filter_peer(string s_name) -> bool {
if net_len_too_long() || is_not_valid_asn() || is_not_valid_prefix() then {
print net, " invalid prefix, reject";
return false;
}
if !rpki_check() then return false;
if inet_irr_check(s_name) then {
bgp_large_community.add((114514,1,2));
bgp_local_pref = 200;
return true;
}
return false;
}
function export_filter_peer() -> bool {
if net_len_too_long() || is_not_valid_asn() || is_not_valid_prefix() then {
print net, " export invalid prefix, reject";
return false;
}
if bgp_large_community ~ [(114514, 1, 3), (114514, 1, 4)] then return true;
return false;
}
function import_filter_downstream(string s_name) -> bool {
if net_len_too_long() || is_not_valid_asn() || is_not_valid_prefix() then {
print net, " invalid prefix, reject";
return false;
}
if !rpki_check() then return false;
if inet_irr_check(s_name) then {
bgp_large_community.add((114514,1,4));
bgp_local_pref = 400;
return true;
}
return false;
}
function export_filter_downstream() -> bool {
if net_len_too_long() || is_not_valid_asn() || is_not_valid_prefix() then {
print net, " export invalid prefix, reject";
return false;
}
if bgp_large_community ~ [(114514, 1, 1), (114514, 1, 2), (114514, 1, 3), (114514, 1, 4)] then return true;
return false;
}
include "functions.conf";
log syslog all;
router id 1.1.1.1;
protocol device {
};
protocol kernel {
ipv6 {
export all;
};
};
protocol static static_v6 {
ipv6;
route 2001:db8:1::/48 reject {bgp_large_community.add((65001,1,3));};
};
protocol bgp upstream {
local fd00::1:1 as 65001;
neighbor fd00::1:2 as 65002;
direct;
ipv6 {
import where import_filter_downstream("AS65001");
export where export_filter_downstream();
};
graceful restart;
};
include "functions.conf";
log syslog all;
router id 1.1.1.2;
protocol device {
};
protocol kernel {
ipv6 {
export all;
};
};
protocol static static_v6 {
ipv6;
route 2001:db8:2::/48 reject {bgp_large_community.add((65002,1,3));};
};
protocol bgp upstream {
local fd00::1:2 as 65002;
neighbor fd00::1:1 as 65001;
direct;
ipv6 {
import where import_filter_upstream();
export where export_filter_upstream();
};
graceful restart;
};
protocol bgp peer {
local fd00::2:1 as 65002;
neighbor fd00::2:2 as 65003;
direct;
ipv6 {
import where import_filter_peer("AS65003");
export where export_filter_peer();
};
graceful restart;
};
include "functions.conf";
log syslog all;
router id 1.1.1.3;
protocol device {
};
protocol kernel {
ipv6 {
export all;
};
};
protocol static static_v6 {
ipv6;
route 2001:db8:3::/48 reject {bgp_large_community.add((65003,1,3));};
};
protocol bgp peer {
local fd00::2:2 as 65003;
neighbor fd00::2:1 as 65002;
direct;
ipv6 {
import where import_filter_peer("AS65002");
export where export_filter_peer();
};
graceful restart;
};
结果
root@debian:~# birdc s r
BIRD 2.17.1 ready.
Table master6:
2001:db8:1::/48 unreachable [static_v6 13:08:09.860] * (200)
2001:db8:2::/48 unicast [upstream 13:09:27.800] * (100) [AS65002i]
via fd00::1:2 on ens3
root@debian:~#root@debian:~# birdc s r
BIRD 2.17.1 ready.
Table master6:
2001:db8:1::/48 unicast [upstream 13:09:27.861] * (100) [AS65001i]
via fd00::1:1 on ens3
2001:db8:2::/48 unreachable [static_v6 13:04:01.157] * (200)
2001:db8:3::/48 unicast [peer 00:46:07.340] * (100) [AS65003i]
via fd00::2:2 on ens4
root@debian:~#root@debian:~# birdc s r
BIRD 2.17.1 ready.
Table master6:
2001:db8:2::/48 unicast [peer 00:47:21.551] * (100) [AS65002i]
via fd00::2:1 on ens3
2001:db8:3::/48 unreachable [static_v6 00:44:32.293] * (200)
root@debian:~#可以看到路由成功地被传递,并且没有泄露。