-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathfilter_bgp.conf
333 lines (280 loc) · 10.5 KB
/
filter_bgp.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
roa4 table rpki4;
roa6 table rpki6;
attribute int export_downstream;
protocol static default_v4 {
ipv4 {};
route 0.0.0.0/0 reject;
}
protocol static default_v6 {
ipv6 {};
route ::/0 reject;
}
# FIXME: Change this to your ASN.
define MY_ASN = 64500;
define LC_IXP_ID = 1;
define LC_PEER_ASN = 2;
define LC_INFO = 3;
define LC_NO_EXPORT = 10;
define LC_PREPEND_1 = 11;
define LC_PREPEND_2 = 12;
define LC_PREPEND_3 = 13;
define LC_DOWNSTREAM_START = 10;
define LC_DOWNSTREAM_END = 13;
# FIXME: define your IXPs here:
# define IXP_EXAMPLE1 = 100;
# define IXP_EXAMPLE2 = 101;
define INFO_PEER = 100;
define INFO_IXP_RS = 101;
define INFO_TRANSIT = 102;
define INFO_DOWNSTREAM = 103;
define IPV4_BOGON = [
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+, # RFC 7526 6to4 anycast relay
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
240.0.0.0/4+ # reserved
];
define IPV6_BOGON = [
::/0, # Default
::/96, # IPv4-compatible IPv6 address - deprecated by RFC4291
::/128, # Unspecified address
::1/128, # Local host loopback address
::ffff:0.0.0.0/96+, # IPv4-mapped addresses
::224.0.0.0/100+, # Compatible address (IPv4 format)
::127.0.0.0/104+, # Compatible address (IPv4 format)
::0.0.0.0/104+, # Compatible address (IPv4 format)
::255.0.0.0/104+, # Compatible address (IPv4 format)
0000::/8+, # Pool used for unspecified, loopback and embedded IPv4 addresses
0100::/8+, # RFC 6666 - reserved for Discard-Only Address Block
0200::/7+, # OSI NSAP-mapped prefix set (RFC4548) - deprecated by RFC4048
0400::/6+, # RFC 4291 - Reserved by IETF
0800::/5+, # RFC 4291 - Reserved by IETF
1000::/4+, # RFC 4291 - Reserved by IETF
2001:10::/28+, # RFC 4843 - Deprecated (previously ORCHID)
2001:20::/28+, # RFC 7343 - ORCHIDv2
2001:db8::/32+, # Reserved by IANA for special purposes and documentation
2002:e000::/20+, # Invalid 6to4 packets (IPv4 multicast)
2002:7f00::/24+, # Invalid 6to4 packets (IPv4 loopback)
2002:0000::/24+, # Invalid 6to4 packets (IPv4 default)
2002:ff00::/24+, # Invalid 6to4 packets
2002:0a00::/24+, # Invalid 6to4 packets (IPv4 private 10.0.0.0/8 network)
2002:ac10::/28+, # Invalid 6to4 packets (IPv4 private 172.16.0.0/12 network)
2002:c0a8::/32+, # Invalid 6to4 packets (IPv4 private 192.168.0.0/16 network)
3ffe::/16+, # Former 6bone, now decommissioned
4000::/3+, # RFC 4291 - Reserved by IETF
5f00::/8+, # RFC 5156 - used for the 6bone but was returned
6000::/3+, # RFC 4291 - Reserved by IETF
8000::/3+, # RFC 4291 - Reserved by IETF
a000::/3+, # RFC 4291 - Reserved by IETF
c000::/3+, # RFC 4291 - Reserved by IETF
e000::/4+, # RFC 4291 - Reserved by IETF
f000::/5+, # RFC 4291 - Reserved by IETF
f800::/6+, # RFC 4291 - Reserved by IETF
fc00::/7+, # Unicast Unique Local Addresses (ULA) - RFC 4193
fe80::/10+, # Link-local Unicast
fec0::/10+, # Site-local Unicast - deprecated by RFC 3879 (replaced by ULA)
ff00::/8+ # Multicast
];
define ASN_BOGON = [
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
];
function ip_bogon() {
case net.type {
NET_IP4: return net ~ IPV4_BOGON;
NET_IP6: return net ~ IPV6_BOGON;
else: return true;
}
}
function rpki_invalid() {
case net.type {
NET_IP4: return roa_check(rpki4, net, bgp_path.last) = ROA_INVALID;
NET_IP6: return roa_check(rpki6, net, bgp_path.last) = ROA_INVALID;
else: return false;
}
}
function is_default_route() {
case net.type {
NET_IP4: return net = 0.0.0.0/0;
NET_IP6: return net = ::/0;
else: return false;
}
}
function bad_prefix_len() {
case net.type {
NET_IP4: return net.len > 24;
NET_IP6: return net.len > 48;
else: return false;
}
}
function clean_own_communities() {
bgp_large_community.delete([(MY_ASN, *, *)]);
}
function honour_graceful_shutdown() {
# RFC 8326: Graceful BGP Session Shutdown
if (65535, 0) ~ bgp_community then bgp_local_pref = 0;
}
function handle_prepend(int dest_asn) {
if (MY_ASN, LC_PREPEND_1, dest_asn) ~ bgp_large_community then {
bgp_path.prepend(MY_ASN);
}
if (MY_ASN, LC_PREPEND_2, dest_asn) ~ bgp_large_community then {
bgp_path.prepend(MY_ASN);
bgp_path.prepend(MY_ASN);
}
if (MY_ASN, LC_PREPEND_3, dest_asn) ~ bgp_large_community then {
bgp_path.prepend(MY_ASN);
bgp_path.prepend(MY_ASN);
bgp_path.prepend(MY_ASN);
}
}
function import_safe(bool allow_default) {
if is_default_route() then {
if allow_default then return true;
print proto, ": ", net, ": unexpected default route";
return false;
}
if ip_bogon() then {
print proto, ": ", net, ": bogon prefix";
return false;
}
if bgp_path ~ ASN_BOGON then {
print proto, ": ", net, ": bogon in AS path: ", bgp_path;
return false;
}
if bgp_path.len > 50 then {
print proto, ": ", net, ": AS path too long: ", bgp_path;
return false;
}
if bad_prefix_len() then {
print proto, ": ", net, ": invalid prefix length";
return false;
}
if rpki_invalid() then {
print proto, ": ", net, ": invalid RPKI origin: ", bgp_path.last;
return false;
}
export_downstream = 1;
honour_graceful_shutdown();
return true;
}
function import_peer_trusted(int peer_asn) {
clean_own_communities();
bgp_large_community.add((MY_ASN, LC_INFO, INFO_PEER));
bgp_large_community.add((MY_ASN, LC_PEER_ASN, peer_asn));
return import_safe(false);
}
function import_peer(int peer_asn; prefix set prefixes; int set as_set) {
if net !~ prefixes then {
print proto, ": ", net, ": prefix not in as-set for peer AS", peer_asn;
return false;
}
for int path_asn in bgp_path do {
if path_asn !~ as_set then {
print proto, ": ", net, ": AS", path_asn, " not in as-set for peer AS", peer_asn;
return false;
}
}
return import_peer_trusted(peer_asn);
}
function import_ixp_trusted(int ixp_id) {
clean_own_communities();
bgp_large_community.add((MY_ASN, LC_INFO, INFO_IXP_RS));
bgp_large_community.add((MY_ASN, LC_IXP_ID, ixp_id));
return import_safe(false);
}
function import_ixp(int ixp_id; prefix set prefixes; int set as_set) {
if net !~ prefixes then {
print proto, ": ", net, ": prefix not in as-set for IXP";
return false;
}
for int path_asn in bgp_path do {
if path_asn !~ as_set then {
print proto, ": ", net, ": not in as-set for IXP";
return false;
}
}
return import_ixp_trusted(ixp_id);
}
function import_transit(int transit_asn; bool default_route) {
clean_own_communities();
bgp_large_community.add((MY_ASN, LC_INFO, INFO_TRANSIT));
bgp_large_community.add((MY_ASN, LC_PEER_ASN, transit_asn));
return import_safe(default_route);
}
function import_downstream(int downstream_asn; prefix set prefixes; int set as_set) {
if net !~ prefixes then {
print proto, ": ", net, ": prefix not in as-set for downstream AS", downstream_asn;
return false;
}
for int path_asn in bgp_path do {
if path_asn !~ as_set then {
print proto, ": ", net, ": not in as-set for downstream AS", downstream_asn;
return false;
}
}
# If they don't want to export this to us, then we won't take it at all.
if (MY_ASN, LC_NO_EXPORT, MY_ASN) ~ bgp_large_community then {
print proto, ": ", net, ": rejected by no-export to AS", MY_ASN;
return false;
}
bgp_large_community.delete([
(MY_ASN, 0..LC_DOWNSTREAM_START-1, *),
(MY_ASN, LC_DOWNSTREAM_END+1..0xFFFFFFFF, *)
]);
bgp_large_community.add((MY_ASN, LC_INFO, INFO_DOWNSTREAM));
bgp_large_community.add((MY_ASN, LC_PEER_ASN, downstream_asn));
return import_safe(false);
}
function export_to_downstream() {
return (defined(export_downstream) && export_downstream = 1) ||
(source = RTS_STATIC && !bad_prefix_len() && (
proto = "node_v4" ||
proto = "node_v6" ||
proto = "node_v4_anycast" ||
proto = "node_v6_anycast"
));
}
function export_monitoring() {
return export_to_downstream();
}
function export_cone(int dest_asn) {
if (MY_ASN, LC_NO_EXPORT, dest_asn) ~ bgp_large_community then return false;
handle_prepend(dest_asn);
if (MY_ASN, LC_INFO, INFO_DOWNSTREAM) ~ bgp_large_community then return true;
case net.type {
NET_IP4: return source = RTS_STATIC && proto = "node_v4";
NET_IP6: return source = RTS_STATIC && proto = "node_v6";
else: return false;
}
}
function export_anycast() {
case net.type {
NET_IP4: return source = RTS_STATIC && proto = "node_v4_anycast";
NET_IP6: return source = RTS_STATIC && proto = "node_v6_anycast";
else: return false;
}
}
function export_default() {
case net.type {
NET_IP4: return source = RTS_STATIC && proto = "default_v4";
NET_IP6: return source = RTS_STATIC && proto = "default_v6";
else: return false;
}
}