forked from Mirror/frr
bgpd: Add RPKI/RTR support
This commit adds support for the RTR protocol to receive ROA information from a RPKI cache server. That information can than be used to validate the BGP origin AS of IP prefixes. Both features are implemented using [rtrlib](http://rtrlib.realmv6.org/). Signed-off-by: Marcel Röthke <marcel.roethke@haw-hamburg.de>
This commit is contained in:
parent
0db8196a96
commit
dabecd7c63
|
@ -114,6 +114,18 @@ bgpd_snmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS)
|
|||
bgpd_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
|
||||
bgpd_snmp_la_LIBADD = ../lib/libfrrsnmp.la
|
||||
|
||||
if RPKI
|
||||
module_LTLIBRARIES += bgpd_rpki.la
|
||||
endif
|
||||
|
||||
bgpd_rpki_la-bgp_rpki.o: bgp_rpki_clippy.c
|
||||
bgp_rpki.o: bgp_rpki_clippy.c
|
||||
|
||||
bgpd_rpki_la_SOURCES = bgp_rpki.c
|
||||
bgpd_rpki_la_CFLAGS = $(WERROR) $(RTRLIB_CFLAGS)
|
||||
bgpd_rpki_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
|
||||
bgpd_rpki_la_LIBADD = $(RTRLIB_LIBS)
|
||||
|
||||
examplesdir = $(exampledir)
|
||||
dist_examples_DATA = bgpd.conf.sample bgpd.conf.sample2 \
|
||||
bgpd.conf.vnc.sample
|
||||
|
|
1207
bgpd/bgp_rpki.c
Normal file
1207
bgpd/bgp_rpki.c
Normal file
File diff suppressed because it is too large
Load diff
26
configure.ac
26
configure.ac
|
@ -387,6 +387,8 @@ AC_ARG_ENABLE([protobuf],
|
|||
AS_HELP_STRING([--enable-protobuf], [Enable experimental protobuf support]))
|
||||
AC_ARG_ENABLE([oldvpn_commands],
|
||||
AS_HELP_STRING([--enable-oldvpn-commands], [Keep old vpn commands]))
|
||||
AC_ARG_ENABLE(rpki,
|
||||
AS_HELP_STRING([--enable-rpki], [enable RPKI prefix validation support]))
|
||||
|
||||
AC_CHECK_HEADERS(json-c/json.h)
|
||||
AC_CHECK_LIB(json-c, json_object_get, LIBS="$LIBS -ljson-c", [], [-lm])
|
||||
|
@ -1796,6 +1798,30 @@ AC_SUBST(CFG_STATE)
|
|||
AC_SUBST(CFG_MODULE)
|
||||
AC_DEFINE_UNQUOTED(MODULE_PATH, "$CFG_MODULE", path to modules)
|
||||
|
||||
dnl ------------------------------------
|
||||
dnl Enable RPKI and add librtr to libs
|
||||
dnl ------------------------------------
|
||||
if test "${enable_rpki}" = "yes"; then
|
||||
PKG_CHECK_MODULES(RTRLIB,[rtrlib >= 0.5.0],
|
||||
[AC_DEFINE(HAVE_RPKI,1,Enable RPKI prefix validation for BGP)
|
||||
RPKI=true],
|
||||
[RPKI=false
|
||||
AC_MSG_ERROR([rtrlib was not found on your system or is too old.])]
|
||||
)
|
||||
fi
|
||||
AM_CONDITIONAL([RPKI], test "x$RPKI" = "xtrue")
|
||||
|
||||
dnl ------------------------------------------
|
||||
dnl Check whether rtrlib was build with ssh support
|
||||
dnl ------------------------------------------
|
||||
AC_MSG_CHECKING([whether the RTR Library is compiled with SSH])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include "rtrlib/rtrlib.h"]],
|
||||
[[struct tr_ssh_config config;]])],
|
||||
[AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(FOUND_SSH,,found_ssh)],
|
||||
AC_MSG_RESULT(no)
|
||||
)
|
||||
|
||||
dnl ---------------------------
|
||||
dnl Check htonl works correctly
|
||||
dnl ---------------------------
|
||||
|
|
|
@ -37,6 +37,7 @@ BGP-4.
|
|||
* How to set up a 6-Bone connection::
|
||||
* Dump BGP packets and table::
|
||||
* BGP Configuration Examples::
|
||||
* Prefix Origin Validation Using RPKI::
|
||||
@end menu
|
||||
|
||||
@node Starting BGP
|
||||
|
@ -2144,3 +2145,5 @@ route-map rm-peer-out permit 10
|
|||
route-map rm-peer-in permit 10
|
||||
set community additive 64512:3200
|
||||
@end example
|
||||
|
||||
@include rpki.texi
|
||||
|
|
256
doc/rpki.texi
Normal file
256
doc/rpki.texi
Normal file
|
@ -0,0 +1,256 @@
|
|||
@c -*-texinfo-*-
|
||||
@c This is part of the FRR Manual.
|
||||
@c @value{COPYRIGHT_STR}
|
||||
@c See file frr.texi for copying conditions.
|
||||
@node Prefix Origin Validation Using RPKI
|
||||
@section Prefix Origin Validation Using RPKI
|
||||
|
||||
Prefix Origin Validation allows BGP routers to verify if the origin AS of
|
||||
an IP prefix is legitimate to announce this IP prefix. The required
|
||||
attestation objects are stored in the Resource Public Key Infrastructure
|
||||
(@acronym{RPKI}). However, RPKI-enabled routers do not store cryptographic
|
||||
data itself but only validation information. The validation of the
|
||||
cryptographic data (so called Route Origin Authorization, or short
|
||||
@acronym{ROA}, objects) will be performed by trusted cache servers. The
|
||||
RPKI/RTR protocol defines a standard mechanism to maintain the exchange of
|
||||
the prefix/origin AS mapping between the cache server and routers.
|
||||
In combination with a BGP Prefix Origin Validation scheme a router is able
|
||||
to verify received BGP updates without suffering from cryptographic
|
||||
complexity.
|
||||
|
||||
|
||||
The RPKI/RTR protocol is defined in @cite{RFC6810, The Resource Public Key
|
||||
Infrastructure (RPKI) to Router Protocol}, and the validation scheme in
|
||||
@cite{RFC6811, BGP Prefix Origin Validation}. The current version of Prefix
|
||||
Origin Validation in FRR implements both RFCs.
|
||||
|
||||
For a more detailed but still easy-to-read background, we suggest the
|
||||
following two articles:
|
||||
@enumerate
|
||||
@item @cite{Geoff Huston, Randy Bush: Securing BGP, In: The Internet
|
||||
Protocol Journal, Volume 14, No. 2, 2011.}
|
||||
@uref{http://www.cisco.com/web/about/ac123/ac147/archived_issues/ipj_14-2/142_bgp.html}
|
||||
|
||||
@item @cite{Geoff Huston: Resource Certification, In: The Internet Protocol
|
||||
Journal, Volume 12, No.1, 2009.}
|
||||
@uref{http://www.cisco.com/web/about/ac123/ac147/archived_issues/ipj_12-1/121_resource.html}
|
||||
@end enumerate
|
||||
|
||||
@menu
|
||||
* Features of the Current Implementation::
|
||||
* Enabling RPKI::
|
||||
* Configuring RPKI/RTR Cache Servers::
|
||||
* Validating BGP Updates::
|
||||
* Debugging::
|
||||
* Displaying RPKI::
|
||||
* RPKI Configuration Example::
|
||||
@end menu
|
||||
|
||||
@node Features of the Current Implementation
|
||||
@subsection Features of the Current Implementation
|
||||
|
||||
In a nutshell, the current implementation provides the following features
|
||||
@itemize @bullet
|
||||
@item The BGP router can connect to one or more RPKI cache servers to
|
||||
receive validated prefix to origin AS mappings.
|
||||
Advanced failover can be implemented by server sockets with different
|
||||
preference values.
|
||||
|
||||
@item If no connection to an RPKI cache server can be established after a
|
||||
pre-defined timeout, the router will process routes without prefix origin
|
||||
validation. It still will try to establish a connection to an RPKI cache
|
||||
server in the background.
|
||||
|
||||
@item By default, enabling RPKI does not change best path selection. In
|
||||
particular, invalid prefixes will still be considered during best path
|
||||
selection. However, the router can be configured to ignore all invalid
|
||||
prefixes.
|
||||
|
||||
@item Route maps can be configured to match a specific RPKI validation
|
||||
state. This allows the creation of local policies, which handle BGP routes
|
||||
based on the outcome of the Prefix Origin Validation.
|
||||
|
||||
@c @item When the router receives updated validation information from the RPKI
|
||||
@c cache server, all routes in the local routing table will be re-evaluated.
|
||||
|
||||
@end itemize
|
||||
|
||||
|
||||
@node Enabling RPKI
|
||||
@subsection Enabling RPKI
|
||||
@deffn {Command} {rpki} {}
|
||||
This command enables the RPKI configuration mode. Most commands that start
|
||||
with @command{rpki} can only be used in this mode.
|
||||
|
||||
When it is used in a telnet session, leaving of this mode cause rpki to be initialized.
|
||||
|
||||
Executing this command alone does not activate prefix
|
||||
validation. You need to configure at least one reachable cache server. See section
|
||||
@ref{Configuring RPKI/RTR Cache Servers} for configuring a cache server.
|
||||
@end deffn
|
||||
|
||||
@node Configuring RPKI/RTR Cache Servers
|
||||
@subsection Configuring RPKI/RTR Cache Servers
|
||||
|
||||
The following commands are independent of a specific cache server.
|
||||
|
||||
@deffn {RPKI Command} {rpki polling_period <1-3600>} {}
|
||||
@deffnx {RPKI Command} {no rpki polling_period} {}
|
||||
Set the number of seconds the router waits until the router asks the cache again
|
||||
for updated data.
|
||||
|
||||
The default value is 300 seconds.
|
||||
@end deffn
|
||||
|
||||
@deffn {RPKI Command} {rpki timeout <1-4,294,967,296>} {}
|
||||
@deffnx {RPKI Command} {no rpki timeout} {}
|
||||
Set the number of seconds the router waits for the cache reply. If the
|
||||
cache server is not replying within this time period, the router deletes
|
||||
all received prefix records from the prefix table.
|
||||
|
||||
The default value is 600 seconds.
|
||||
@end deffn
|
||||
|
||||
@deffn {RPKI Command} {rpki initial-synchronisation-timeout <1-4,294,967,296>} {}
|
||||
@deffnx {RPKI Command} {no rpki initial-synchronisation-timeout} {}
|
||||
Set the number of seconds until the first synchronization with the cache
|
||||
server needs to be completed. If the timeout expires, BGP routing is
|
||||
started without RPKI. The router will try to establish the cache server
|
||||
connection in the background.
|
||||
|
||||
The default value is 30 seconds.
|
||||
@end deffn
|
||||
|
||||
@noindent The following commands configure one or multiple cache servers.
|
||||
|
||||
@deffn {RPKI Socket Command} {rpki cache (@var{A.B.C.D}|@var{WORD}) @var{PORT} [@var{SSH_USERNAME}] [@var{SSH_PRIVKEY_PATH}] [@var{SSH_PUBKEY_PATH}] [@var{KNOWN_HOSTS_PATH}] @var{PREFERENCE}} {}
|
||||
@deffnx {RPKI Socket Command} {no rpki cache (@var{A.B.C.D}|@var{WORD}) [@var{PORT}] @var{PREFERENCE}} {}
|
||||
Add a cache server to the socket. By default, the connection between
|
||||
router and cache server is based on plain TCP. Protecting the connection
|
||||
between router and cache server by SSH is optional.
|
||||
Deleting a socket removes the associated cache server and
|
||||
terminates the existing connection.
|
||||
@end deffn
|
||||
|
||||
@table @code
|
||||
@item @var{A.B.C.D}|@var{WORD}
|
||||
Address of the cache server.
|
||||
|
||||
@item @var{PORT}
|
||||
Port number to connect to the cache server
|
||||
|
||||
@item @var{SSH_USERNAME}
|
||||
SSH username to establish an SSH connection to the cache server.
|
||||
|
||||
@item @var{SSH_PRIVKEY_PATH}
|
||||
Local path that includes the private key file of the router.
|
||||
|
||||
@item @var{SSH_PUBKEY_PATH}
|
||||
Local path that includes the public key file of the router.
|
||||
|
||||
@item @var{KNOWN_HOSTS_PATH}
|
||||
Local path that includes the known hosts file. The default value depends on the
|
||||
configuration of the operating system environment, usually
|
||||
@file{~/.ssh/known_hosts}.
|
||||
|
||||
@end table
|
||||
|
||||
@node Validating BGP Updates
|
||||
@subsection Validating BGP Updates
|
||||
|
||||
@deffn {Route Map Command} {match rpki @{notfound|invalid|valid@}} {}
|
||||
@deffnx {Route Map Command} {no match rpki @{notfound|invalid|valid@}} {}
|
||||
Create a clause for a route map to match prefixes with the specified RPKI state.
|
||||
|
||||
@strong{Note} that the matching of invalid prefixes requires that invalid
|
||||
prefixes are considered for best path selection, i.e., @command{bgp
|
||||
bestpath prefix-validate disallow-invalid} is not enabled.
|
||||
|
||||
In the following example, the router prefers valid routes over invalid
|
||||
prefixes because invalid routes have a lower local preference.
|
||||
@example
|
||||
! Allow for invalid routes in route selection process
|
||||
route bgp 60001
|
||||
!
|
||||
! Set local preference of invalid prefixes to 10
|
||||
route-map rpki permit 10
|
||||
match rpki invalid
|
||||
set local-preference 10
|
||||
!
|
||||
! Set local preference of valid prefixes to 500
|
||||
route-map rpki permit 500
|
||||
match rpki valid
|
||||
set local-preference 500
|
||||
@end example
|
||||
|
||||
@end deffn
|
||||
|
||||
@node Debugging
|
||||
@subsection Debugging
|
||||
|
||||
@deffn {Command} {debug rpki} {}
|
||||
@deffnx {Command} {no debug rpki} {}
|
||||
Enable or disable debugging output for RPKI.
|
||||
@end deffn
|
||||
|
||||
|
||||
@node Displaying RPKI
|
||||
@subsection Displaying RPKI
|
||||
|
||||
@deffn {Command} {show rpki prefix-table} {}
|
||||
Display all validated prefix to origin AS mappings/records which have been
|
||||
received from the cache servers and stored in the router. Based on this data,
|
||||
the router validates BGP Updates.
|
||||
@end deffn
|
||||
|
||||
@deffn {Command} {show rpki cache-connection} {}
|
||||
Display all configured cache servers, whether active or not.
|
||||
@end deffn
|
||||
|
||||
@node RPKI Configuration Example
|
||||
@subsection RPKI Configuration Example
|
||||
|
||||
|
||||
@example
|
||||
hostname bgpd1
|
||||
password zebra
|
||||
! log stdout
|
||||
debug bgp updates
|
||||
debug bgp keepalives
|
||||
debug rpki
|
||||
!
|
||||
rpki
|
||||
rpki polling_period 1000
|
||||
rpki timeout 10
|
||||
! SSH Example:
|
||||
rpki cache example.com 22 rtr-ssh ./ssh_key/id_rsa ./ssh_key/id_rsa.pub preference 1
|
||||
! TCP Example:
|
||||
rpki cache rpki-validator.realmv6.org 8282 preference 2
|
||||
exit
|
||||
!
|
||||
router bgp 60001
|
||||
bgp router-id 141.22.28.223
|
||||
network 192.168.0.0/16
|
||||
neighbor 123.123.123.0 remote-as 60002
|
||||
neighbor 123.123.123.0 route-map rpki in
|
||||
!
|
||||
address-family ipv6
|
||||
neighbor 123.123.123.0 activate
|
||||
neighbor 123.123.123.0 route-map rpki in
|
||||
exit-address-family
|
||||
!
|
||||
route-map rpki permit 10
|
||||
match rpki invalid
|
||||
set local-preference 10
|
||||
!
|
||||
route-map rpki permit 20
|
||||
match rpki notfound
|
||||
set local-preference 20
|
||||
!
|
||||
route-map rpki permit 30
|
||||
match rpki valid
|
||||
set local-preference 30
|
||||
!
|
||||
route-map rpki permit 40
|
||||
!
|
||||
@end example
|
|
@ -117,6 +117,7 @@ const char *node_names[] = {
|
|||
"vty", // VTY_NODE,
|
||||
"link-params", // LINK_PARAMS_NODE,
|
||||
"bgp evpn vni", // BGP_EVPN_VNI_NODE,
|
||||
"rpki", // RPKI_NODE
|
||||
};
|
||||
|
||||
/* Command vector which includes some level of command lists. Normally
|
||||
|
|
|
@ -140,6 +140,7 @@ enum node_type {
|
|||
VTY_NODE, /* Vty node. */
|
||||
LINK_PARAMS_NODE, /* Link-parameters node */
|
||||
BGP_EVPN_VNI_NODE, /* BGP EVPN VNI */
|
||||
RPKI_NODE, /* RPKI node for configuration of RPKI cache server connections.*/
|
||||
NODE_TYPE_MAX, /* maximum */
|
||||
};
|
||||
|
||||
|
|
|
@ -56,6 +56,10 @@ vtysh_scan += $(top_srcdir)/bgpd/bgp_routemap.c
|
|||
vtysh_scan += $(top_srcdir)/bgpd/bgp_vty.c
|
||||
endif
|
||||
|
||||
if RPKI
|
||||
vtysh_scan += $(top_srcdir)/bgpd/bgp_rpki.c
|
||||
endif
|
||||
|
||||
if ISISD
|
||||
vtysh_scan += $(top_srcdir)/isisd/isis_redist.c
|
||||
vtysh_scan += $(top_srcdir)/isisd/isis_spf.c
|
||||
|
|
|
@ -1045,6 +1045,8 @@ struct cmd_node link_params_node = {
|
|||
LINK_PARAMS_NODE, "%s(config-link-params)# ",
|
||||
};
|
||||
|
||||
static struct cmd_node rpki_node = {RPKI_NODE, "%s(config-rpki)# ", 1};
|
||||
|
||||
/* Defined in lib/vty.c */
|
||||
extern struct cmd_node vty_node;
|
||||
|
||||
|
@ -1181,6 +1183,35 @@ DEFUNSH(VTYSH_BGPD, address_family_ipv6_labeled_unicast,
|
|||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUNSH(VTYSH_BGPD,
|
||||
rpki,
|
||||
rpki_cmd,
|
||||
"rpki",
|
||||
"Enable rpki and enter rpki configuration mode\n")
|
||||
{
|
||||
vty->node = RPKI_NODE;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUNSH(VTYSH_BGPD,
|
||||
rpki_exit,
|
||||
rpki_exit_cmd,
|
||||
"exit",
|
||||
"Exit current mode and down to previous mode\n")
|
||||
{
|
||||
vty->node = CONFIG_NODE;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUNSH(VTYSH_BGPD,
|
||||
rpki_quit,
|
||||
rpki_quit_cmd,
|
||||
"quit",
|
||||
"Exit current mode and down to previous mode\n")
|
||||
{
|
||||
return rpki_exit(self, vty, argc, argv);
|
||||
}
|
||||
|
||||
DEFUNSH(VTYSH_BGPD, address_family_evpn, address_family_evpn_cmd,
|
||||
"address-family <l2vpn evpn>",
|
||||
"Enter Address Family command mode\n"
|
||||
|
@ -2979,6 +3010,7 @@ void vtysh_init_vty(void)
|
|||
install_node(&keychain_key_node, NULL);
|
||||
install_node(&isis_node, NULL);
|
||||
install_node(&vty_node, NULL);
|
||||
install_node(&rpki_node, NULL);
|
||||
|
||||
struct cmd_node *node;
|
||||
for (unsigned int i = 0; i < vector_active(cmdvec); i++) {
|
||||
|
@ -3177,6 +3209,11 @@ void vtysh_init_vty(void)
|
|||
install_element(BGP_EVPN_NODE, &exit_address_family_cmd);
|
||||
install_element(BGP_IPV6L_NODE, &exit_address_family_cmd);
|
||||
|
||||
install_element(CONFIG_NODE, &rpki_cmd);
|
||||
install_element(RPKI_NODE, &rpki_exit_cmd);
|
||||
install_element(RPKI_NODE, &rpki_quit_cmd);
|
||||
install_element(RPKI_NODE, &vtysh_end_all_cmd);
|
||||
|
||||
/* EVPN commands */
|
||||
install_element(BGP_EVPN_NODE, &bgp_evpn_vni_cmd);
|
||||
install_element(BGP_EVPN_VNI_NODE, &exit_vni_cmd);
|
||||
|
|
Loading…
Reference in a new issue