Commit b92d25a1 authored by glucas's avatar glucas

Add routing configurations.

parent c7c03699
# Configure logging
log syslog { warning, error, fatal, bug };
# Turn on global debugging of all protocols
# debug protocols all;
# Override router ID and store ASN
router id 89.234.141.131;
define myasn = 60630;
#####################
# GENERAL PROTOCOLS #
#####################
# This pseudo-protocol watches all interface up/down events.
protocol device
{
# Scan interfaces every 5 seconds
scan time 5;
}
# The direct protocol automatically generates device routes to network
# interfaces (directly connected). We need it to export loopback IP
# and ganeti master IP in iBGP
protocol direct
{
# Restrict network interfaces we work on
interface "loopback1";
}
# This pseudo-protocol performs synchronization between BIRD's routing tables and the kernel.
protocol kernel
{
# Learn all routes from the kernel because we need to learn VM and housing routes.
# We cannot use direct protocol because of link-local use on theses interfaces.
learn;
# Don't remove routes on BIRD shutdown
persist;
# Scan kernel routing table every 5 seconds (to detect ganeti live migration ASAP)
scan time 5;
# Only import routes in ARN allocations (89.234.141.0/24-32) from kernel
import filter {
if (net ~ [89.234.141.0/24+]) then accept;
else reject;
};
# Export to the kernel. This host must use his IP as source IP when it initiates
# connections to the world
export filter {
krt_prefsrc = 89.234.141.131;
accept;
};
# Housing: same route exists for one ARN member in the kernel of our two routers.
# So, when BIRD receives the route from iBGP, it tries to overwrite it and print
# "Netlink: File exists" in the logs. @see: http://shaarli.guiguishow.info/?zIvC0Q
# A route learned via the kernel is more important than a route learned in iBGP.
preference 110;
}
# Static routes
# Used to announce our IP allocations and drop traffic for non-allocated IPs
# (if we don't have a more specific route). Without it, traffic for our allocations go out of our AS.
protocol static static_arn_allocations
{
import all;
route 89.234.141.0/24 unreachable;
}
###############
# BGP FILTERS #
###############
function check_import(int peeras; ip nexthop)
prefix set martians;
int set reserved_asn;
prefix set our_prefixes;
{
martians = [ 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.0.0/24+, 192.0.2.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+, 255.255.255.255/32 ];
reserved_asn = [ 0, 64297..131071, 4200000000..4294967294, 4294967295 ];
our_prefixes = [ 89.234.141.0/24+, 149.11.26.40/29+, 195.81.226.224/29+ ];
# Avoid too short and too long prefixes
if (net.len < 8) || (net.len > 24) then return false;
# Avoid 0.0.0.0/X (default route + 0.0.0.0/8)
if net.ip = 0.0.0.0 then return false;
# Avoid reserved networks
if net ~ martians then return false;
# Remove our prefixes. Only us can announce them
# Remove also our interconnection prefixes. We are directly connected.
if net ~ our_prefixes then return false;
# Check that the next AS is our neighbour's.
# Same for next-hop
if bgp_path.first != peeras then return false;
if bgp_next_hop != nexthop then return false;
# AS_PATH too long (max seen in real life = 54)
if bgp_path.len > 64 then return false;
# Don't accept if path contains a reserved AS
# Disabled because it removes legit prefixes
# if bgp_path ~ reserved_asn then return false;
return true;
}
filter bgp_filter_cogent_in
{
if (check_import(174, 149.11.26.41)) then
{
# Here we can set localpref or remove a prefix, for example
accept;
}
else
{
reject "Prefix filtered IN Cogent";
}
}
filter bgp_filter_interoute_in
{
if (check_import(8928, 195.81.226.225)) then
{
# Here we can set localpref or remove a prefix, for example
accept;
}
else
{
reject "Prefix filtered IN Interoute";
}
}
filter bgp_filter_grifon_in
{
if net = 89.234.186.0/24 then accept;
else reject;
}
##################
# eBGP NEIGHBORS #
# UPSTREAMS #
##################
template bgp UPSTREAM
{
local as myasn;
# Be able to see filtered routes with "sh route filtered" command
import keep filtered;
# Protect ourselves from massive routes leaks
receive limit 620000 action block;
# Announce only our IP allocations and Grifon ones
export where proto = "static_arn_allocations" || proto = "bgp_grifon" ;
export limit 2 action disable;
}
protocol bgp bgp_cogent from UPSTREAM
{
description "Cogent";
neighbor 149.11.26.41 as 174;
# Local address we use to establish the BGP session
source address 149.11.26.42;
# Password used for MD5 authentication
password "";
# Accept all routes from Cogent except bogons and other bad stuff
import filter bgp_filter_cogent_in;
}
protocol bgp bgp_interoute from UPSTREAM
{
description "Interoute";
neighbor 195.81.226.225 as 8928;
source address 195.81.226.226;
password "";
import filter bgp_filter_interoute_in;
}
##################
# eBGP NEIGHBORS #
# DOWNSTREAMS #
##################
protocol bgp bgp_grifon
{
description "Grifon";
local as myasn;
neighbor 89.234.141.143 as 204092;
source address 89.234.141.142;
# Accept only Grifon's IP allocations
import keep filtered;
import filter bgp_filter_grifon_in;
receive limit 1 action block;
# Export our two BGP feeds + our allocations to Grifon
export where proto = "static_arn_allocations" || proto = "bgp_interoute" || proto = "bgp_cogent";
export limit 620000 action disable;
# We must prefer our private interconnection to receive Grifon's allocations.
# Without, we will have problems to redistribute Grifon's allocations to our providers.
preference 150;
}
################
# iBGP #
################
protocol bgp ibgp
{
description "iBGP";
local as myasn;
neighbor 169.254.69.2 as 60630;
source address 169.254.69.1;
password "";
# If Cogent or Interoute interconnection fails on our other router,
# it must forward its traffic to us. So, this router is the next-hop
# of other ARN's router. Without this line, the other router
# will learn Internet's routes in iBGP and will try to use
# its failed interconnection to forward its network traffic.
next hop self;
# We want to know everything the peer knows
import all;
export all;
# It's a direct (no-multihop) iBGP session.
# Without it, we have unreachable routes (on no-link-local links)
direct;
}
# Configure logging
log syslog { warning, error, fatal, bug };
# Turn on global debugging of all protocols
# debug protocols all;
# Override router ID and store ASN
router id 89.234.141.131;
define myasn = 60630;
#####################
# GENERAL PROTOCOLS #
#####################
# This pseudo-protocol watches all interface up/down events.
protocol device
{
# Scan interfaces every 5 seconds
scan time 5;
}
# The direct protocol automatically generates device routes to network
# interfaces (directly connected). We need it to export loopback IP.
protocol direct
{
# Restrict network interfaces we work on
interface "loopback1";
}
# This pseudo-protocol performs synchronization between BIRD's routing tables and the kernel.
protocol kernel
{
# Learn all routes from the kernel because we need to learn VM and housing routes.
# We cannot use direct protocol because of link-local use on theses interfaces.
learn;
# Don't remove routes on bird shutdown
persist;
# Scan kernel routing table every 5 seconds (to detect ganeti live migration ASAP)
scan time 5;
# Only import routes in ARN allocations (2a00:5881:8100::/40) from kernel
import filter {
if (net ~ [2a00:5881:8100::/40+]) then accept;
else reject;
};
# Export to the kernel. This host must use his IP as source IP when it initiates
# connections to the world
export filter {
krt_prefsrc = 2a00:5881:8100::131;
accept;
};
# Housing: same route exists for one ARN member in the kernel of our two routers.
# So, when BIRD receives the route from iBGP, it tries to overwrite it and print
# "Netlink: File exists" in the logs. @see: http://shaarli.guiguishow.info/?zIvC0Q
# A route learned via the kernel is more important than a route learned in iBGP.
preference 110;
}
# Static routes
# Used to announce our IP allocations and drop traffic for non-allocated IPs
# (we don't have more a specific route). Without it, traffic for our allocation go out of our AS.
protocol static static_arn_allocations
{
import all;
route 2a00:5881:8100::/40 unreachable;
}
###############
# BGP FILTERS #
###############
function check_import(int peeras; ip nexthop)
prefix set martians;
int set reserved_asn;
prefix set our_prefixes;
{
# 2001::/23 contains for example 2001:4:112::/48, belonging to AS112
# so we mustn't filter more specific
# 3FFE::/16 et 5F00::/8 = formerly 6bone (IPv6 tests)
martians = [ ::1/128, ::/128, ::ffff:0:0/96+, 100::/64+,
2001:db8::/32+, 2001::/23, 2001:2::/48+,
2001:10::/28+, 2002::/17+, fc00::/7, fe80::/10, ff00::/8+,
3FFE::/16+, 5F00::/8+ ];
reserved_asn = [ 0, 64297..131071, 4200000000..4294967294, 4294967295 ];
our_prefixes = [ 2a00:5881:8100::/40+, 2001:978:2:57:0:0:7:0/112+,
2001:1478:15:6::/64+, 2001:470:12:74::/64+, 2001:470:11:29::/64+ ];
# Avoid too short and too long prefixes
if (net.len < 16) || (net.len > 48) then return false;
# Remove default route
if net = ::/0 then return false;
# Avoid reserved networks
if net ~ martians then return false;
# Avoid bogons. IANA didn't allocate outside of 2000::/3
# but there are already announces there
if ! (net.ip ~ 2000::/3) then return false;
# Remove our prefixes. Only us can announce them
# Remove our interconnection prefixes. We are directly connected
if net ~ our_prefixes then return false;
# Check that the next AS is our neighbour's.
# Same for next-hop
if bgp_path.first != peeras then return false;
if bgp_next_hop != nexthop then return false;
# AS_PATH too long (max seen in real life = 54)
if bgp_path.len > 64 then return false;
# Don't accept if path contains a reserved AS
# Disabled because it removes legit prefixes
# if bgp_path ~ reserved_asn then return false;
return true;
}
filter bgp_filter_cogent_in
{
if (check_import(174, 2001:978:2:57::7:1)) then
{
# Here you can set localpref or remove a prefix, for example
accept;
}
else
{
reject "Prefix filtered IN Cogent";
}
}
filter bgp_filter_interoute_in
{
if (check_import(8928, 2001:1478:15:6::1)) then
{
# Here you can set localpref or remove a prefix, for example
accept;
}
else
{
reject "Prefix filtered IN Interoute";
}
}
filter bgp_filter_hurricane_electric_in
{
# Import only IP prefixes originated by HE
if bgp_path.last = 6939 then
{
# Usual checks
if (check_import(6939, 2001:470:12:74::1)) then
{
# Here you can set localpref or remove a prefix, for example
bgp_local_pref = 90;
accept;
}
else
{
reject "Prefix filtered IN HE";
}
}
}
# "_ou" means "out" but symbol too long for BIRD
filter bgp_filter_hurricane_electric_ou
{
if (proto = "static_arn_allocations") then
{
# Here you can set community or do AS-prepending
# AS-prepending
bgp_path.prepend(60630);
bgp_path.prepend(60630);
# Add "no-export" BGP community
# (HE learns our IP allocations but cannot redistribute them)
bgp_community.add((65535,65281));
accept;
}
else
{
reject "Prefix filtered OUT HE";
}
}
filter bgp_filter_grifon_in
{
if net = 2a00:5884::/32 then accept;
else reject;
}
##################
# eBGP NEIGHBORS #
# UPSTREAMS #
##################
template bgp UPSTREAM
{
local as myasn;
# Be able to see filtered routes with "sh route filtered" command
import keep filtered;
# Protect ourselves from massive routes leaks
receive limit 50000 action block;
# Announce only our IP allocations and Grifon ones
export where proto = "static_arn_allocations" || proto = "bgp_grifon";
export limit 2 action disable;
}
protocol bgp bgp_cogent from UPSTREAM
{
description "Cogent";
neighbor 2001:978:2:57::7:1 as 174;
# Local address we use to establish the BGP session
source address 2001:978:2:57::7:2;
# Password used for MD5 authentication
password "";
# Accept all routes from Cogent except bogons and other bad stuff
import filter bgp_filter_cogent_in;
}
protocol bgp bgp_interoute from UPSTREAM
{
description "Interoute";
neighbor 2001:1478:15:6::1 as 8928;
source address 2001:1478:15:6::2;
password "";
import filter bgp_filter_interoute_in;
}
protocol bgp bgp_hurricane_electric from UPSTREAM
{
description "Hurricane_Electric";
neighbor 2001:470:12:74::1 as 6939;
source address 2001:470:12:74::2;
import filter bgp_filter_hurricane_electric_in;
# AS-prepending + no-export + export only ARN's IP allocations
export filter bgp_filter_hurricane_electric_ou;
export limit 1 action disable;
}
##################
# eBGP NEIGHBORS #
# DOWNSTREAMS #
##################
protocol bgp bgp_grifon
{
description "Grifon";
local as myasn;
neighbor 2a00:5881:8100:ff00::143 as 204092;
source address 2a00:5881:8100:ff00::142;
# Accept only the Grifon's IP allocations
import keep filtered;
import filter bgp_filter_grifon_in;
receive limit 1 action block;
# Export our two BGP feeds + our allocations to Grifon
export where proto = "static_arn_allocations" || proto = "bgp_interoute" || proto = "bgp_cogent";
export limit 600000 action disable;
# We must prefer our private interconnection to receive Grifon's allocations.
# Without, we will have problems to redistribute Grifon's allocations to our providers.
preference 150;
}
################
# iBGP #
################
protocol bgp ibgp
{
description "iBGP";
local as myasn;
neighbor fe80::69:2%eth1 as 60630;
source address fe80::69:1;
password "";
# If Cogent or Interoute interconnection fails on our other router,
# it must forward its traffic to us. So, this router is the next-hop
# of other ARN's router. Without this line, the other router
# will learn Internet's routes in iBGP and will try to use
# its failed interconnection to forward its network traffic.
next hop self;
# We want to know everything the peer knows
import all;
export all;
# It's a direct (no-multihop) iBGP session.
# Without it, we have unreachable routes (on no-link-local links).
direct;
}
This diff is collapsed.
hostname zebra
! No password prompt on telnet/vtysh
line vty
no login
log syslog warnings
! Used to announce our IP allocations and drop traffic for non-allocated IPs
! (if we haven't more specific route). Without it, traffic for our allocations go out of our AS.
ip route 89.234.141.0 255.255.255.0 Null0
! "blackhole" route target doesn't exist in "old" (3.2) kernel.
! Quagga want to be compatible so we need this trick to emulate blackhole behaviour
ipv6 route 2a00:5881:8100::/40 ::1 reject
! This host must use his IP as source IP when it initiates connections to the world
! There aren't no equivalent in IPv6...
ip prefix-list ANY permit 0.0.0.0/0 le 32
route-map SET-SRC permit 10
match ip address prefix-list ANY
set src 89.234.141.132
ip protocol bgp route-map SET-SRC
For explanations, use-case presentation and how-to, see https://wiki.arn-fai.net/technique:routage (in french, sorry).
Systemd unit files for BIRD-lg software (see https://github.com/sileht/bird-lg ).
# Copyright (C) 2015-2016 Alsace Réseau Neutre
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Debian GNU/Linux: store this in /etc/systemd/system/
[Unit]
Description=BIRD Looking-Glass proxy
After=bird.service bird6.service
[Service]
Type=simple
ExecStart=/usr/local/lookingglass/lgproxy.py
Restart=on-failure
[Install]
WantedBy=multi-user.target
# Copyright (C) 2015-2016 Alsace Réseau Neutre
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Debian GNU/Linux: store this in /etc/systemd/system/
[Unit]
Description=BIRD Looking-Glass service
After=apache2.service
[Service]
Type=simple
User=lookingglass
ExecStart=/usr/local/lookingglass/lg.py
Restart=on-failure
[Install]
WantedBy=multi-user.target
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment