Commit ad88b94b authored by Jan Moskyto Matejka's avatar Jan Moskyto Matejka
Browse files

Merge branch 'int-new-rpki-squashed' (early part) into int-new

parents d15b0b0a af62c0f9
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@ CPPFLAGS=-I$(objdir) -I$(srcdir) @CPPFLAGS@
CFLAGS=$(CPPFLAGS) @CFLAGS@
LDFLAGS=@LDFLAGS@
LIBS=@LIBS@
DAEMON_LIBS=@DAEMON_LIBS@
CLIENT_LIBS=@CLIENT_LIBS@
CC=@CC@
M4=@M4@
@@ -58,6 +59,8 @@ all: daemon cli
daemon: $(daemon)
cli: $(client)

$(daemon): LIBS += $(DAEMON_LIBS)

# Include directories
dirs := client conf doc filter lib nest test $(addprefix proto/,$(protocols)) @sysdep_dirs@

+21 −2
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@ AC_ARG_ENABLE(debug, [ --enable-debug enable internal debugging routin
AC_ARG_ENABLE(memcheck,	[  --enable-memcheck       check memory allocations when debugging (default: enabled)],,enable_memcheck=yes)
AC_ARG_ENABLE(client,	[  --enable-client         enable building of BIRD client (default: enabled)],,enable_client=yes)
AC_ARG_ENABLE(pthreads,	[  --enable-pthreads       enable POSIX threads support (default: detect)],,enable_pthreads=try)
AC_ARG_ENABLE(libssh,	[  --enable-libssh	   enable LibSSH support together with RPKI protocol (default: detect)],,enable_libssh=try)
AC_ARG_WITH(sysconfig,	[  --with-sysconfig=FILE   use specified BIRD system configuration file])
AC_ARG_WITH(protocols,	[  --with-protocols=LIST   include specified routing protocols (default: all)],,[with_protocols="all"])
AC_ARG_WITH(sysinclude,	[  --with-sysinclude=PATH  search for system includes on specified place])
@@ -86,6 +87,21 @@ if test "$enable_pthreads" != no ; then
	fi
fi

if test "$enable_libssh" != no ; then
	AC_CHECK_LIB(ssh, ssh_connect)
	if test $ac_cv_lib_ssh_ssh_connect = yes ; then
		proto_rpki=rpki
		enable_libssh=yes
		AC_DEFINE(HAVE_LIBSSH)
	else
		if test "$enable_libssh" = yes ; then
			AC_MSG_ERROR([LibSSH not available.])
		else
			enable_libssh=no
		fi
	fi
fi
	
if test "$bird_cflags_default" = yes ; then
	BIRD_CHECK_GCC_OPTION(bird_cv_c_option_wno_pointer_sign, -Wno-pointer-sign, -Wall)
	BIRD_CHECK_GCC_OPTION(bird_cv_c_option_wno_missing_init, -Wno-missing-field-initializers, -Wall -Wextra)
@@ -169,8 +185,8 @@ fi

AC_SUBST(iproutedir)

# all_protocols="$proto_bfd babel bgp ospf pipe radv rip static"
all_protocols="$proto_bfd bgp ospf pipe radv rip static"
# all_protocols="$proto_bfd babel bgp ospf pipe radv rip $proto_rpki static"
all_protocols="$proto_bfd bgp ospf pipe radv rip $proto_rpki static "

all_protocols=`echo $all_protocols | sed 's/ /,/g'`

@@ -231,6 +247,9 @@ if test "$enable_debug" = yes ; then
	fi
fi

DAEMON_LIBS=
AC_SUBST(DAEMON_LIBS)

CLIENT=birdcl
CLIENT_LIBS=
if test "$enable_client" = yes ; then
+180 −2
Original line number Diff line number Diff line
@@ -3788,7 +3788,7 @@ protocol rip [<name>] {
<p>RIP defines two route attributes:

<descrip>
	<tag><label id="rta-rip-metric">int rip_metric/</tag>
	<tag>int <cf/rip_metric/</tag>
	RIP metric of the route (ranging from 0 to <cf/infinity/). When routes
	from different RIP instances are available and all of them have the same
	preference, BIRD prefers the route with lowest <cf/rip_metric/. When a
@@ -3819,6 +3819,184 @@ protocol rip {
}
</code>

<sect>RPKI

<sect1>Introduction

<p>The Resource Public Key Infrastructure (RPKI) is mechanism for origin
validation of BGP routes (RFC 6480). BIRD supports only so-called RPKI-based
origin validation. There is implemented RPKI to Router (RPKI-RTR) protocol (RFC
6810).  It uses some of the RPKI data to allow a router to verify that the
autonomous system announcing an IP address prefix is in fact authorized to do
so. This is not crypto checked so can be violated. But it should prevent the
vast majority of accidental hijackings on the Internet today, e.g. the famous
Pakastani accidental announcement of YouTube's address space.

<p>The RPKI-RTR protocol receives and maintains a set of ROAs from a cache
server (also called validator). You can validate routes (RFC 6483) using
function <cf/roa_check()/ in filter and set it as import filter at the BGP
protocol. BIRD should re-validate all of affected routes after RPKI update by
RFC 6811, but we don't support it yet! You can use a BIRD's client command
<cf>reload in <m/bgp_protocol_name/</cf> for manual call of revalidation of all
routes.

<sect1>Supported transports
<itemize>
        <item>Unprotected transport over TCP uses a port 323. The cache server
        and BIRD router should be on the same trusted and controlled network
        for security reasons.
        <item>SSHv2 encrypted transport connection uses the normal SSH port
        22.
</itemize>

<sect1>Configuration

<p>We currently support just one cache server per protocol. However you can
define more RPKI protocols generally.

<code>
protocol rpki [&lt;name&gt;] {
        roa4 { table &lt;tab&gt;; };
        roa6 { table &lt;tab&gt;; };
        remote &lt;ip&gt; | "&lt;domain&gt;" [port &lt;num&gt;];
        port &lt;num&gt;;
        refresh [keep] &lt;num&gt;;
        retry [keep] &lt;num&gt;;
        expire [keep] &lt;num&gt;;
        transport tcp;
        transport ssh {
                bird private key "&lt;/path/to/id_rsa&gt;";
                remote public key "&lt;/path/to/known_host&gt;";
                user "&lt;name&gt;";
        };
}
</code>

<p>Alse note that you have to specify ROA table into which will be imported
routes from a cache server. If you want to import only IPv4 prefixes you have
to specify only roa4 table. Similarly with IPv6 prefixes only. If you want to
fetch both IPv4 and even IPv6 ROAs you have to specify both types of ROA
tables.

<sect2>RPKI protocol options

<descrip>
        <tag>remote <m/ip/ | "<m/hostname/" [port <m/num/]</tag> Specifies
        a destination address of the cache server.  Can be specified by an IP
        address or by full domain name string.  Only one cache can be specified
        per protocol. This option is required.

        <tag>port <m/num/</tag> Specifies the port number. The default port
        number is 323 for transport without any encryption and 22 for transport
        with SSH encryption.

        <tag>refresh [keep] <m/num/</tag> Time period in seconds. Tells how
        long to wait before next attempting to poll the cache using a Serial
        Query or a Reset Query packet. Must be lower than 86400 seconds (one
        day). Too low value can caused a false positive detection of
        network connection problems.  A keyword <cf/keep/ suppresses updating
        this value by a cache server.
        Default: 3600 seconds

        <tag>retry [keep] <m/num/</tag> Time period in seconds between a failed
        Serial/Reset Query and a next attempt.  Maximum allowed value is 7200
        seconds (two hours). Too low value can caused a false positive
        detection of network connection problems.  A keyword <cf/keep/
        suppresses updating this value by a cache server.
        Default: 600 seconds

        <tag>expire [keep] <m/num/</tag> Time period in seconds. Received
        records are deleted if the client was unable to successfully refresh
        data for this time period.  Must be in range from 600 seconds (ten
        minutes) to 172800 seconds (two days).  A keyword <cf/keep/
        suppresses updating this value by a cache server.
        Default: 7200 seconds

        <tag>transport tcp</tag> Unprotected transport over TCP. It's a default
        transport. Should be used only on secure private networks.
        Default: tcp

        <tag>transport ssh { <m/SSH transport options.../ }</tag> It enables a
        SSHv2 transport encryption. Cannot be combined with a TCP transport.
        Default: off
</descrip>

<sect3>SSH transport options
<descrip>
	<tag>bird private key "<m>/path/to/id_rsa</m>"</tag>
	A path to the BIRD's private SSH key for authentication.
	It can be a <cf><m>id_rsa</m></cf> file.

	<tag>remote public key "<m>/path/to/known_host</m>"</tag>
	A path to the cache's public SSH key for verification identity
	of the cache server. It could be a path to <cf><m>known_host</m></cf> file.

	<tag>user "<m/name/"</tag>
	A SSH user name for authentication. This option is a required.
</descrip>

<sect1>Examples
<sect2>BGP origin validation
<p>Policy: Don't import <cf/ROA_INVALID/ routes.
<code>
roa4 table r4;
roa6 table r6;

protocol rpki {
	debug all;
	
	roa4 { table r4; };
	roa6 { table r6; };

	# Please, do not use rpki-validator.realmv6.org in production
	remote "rpki-validator.realmv6.org" port 8282;
	
	retry keep 5;
	refresh keep 30;
	expire 600;
}

filter peer_in {
	if (roa_check(r4, net, bgp_path.last) = ROA_INVALID ||
	    roa_check(r6, net, bgp_path.last) = ROA_INVALID) then
	{
		print "Ignore invalid ROA ", net, " for ASN ", bgp_path.last;
		reject;
	}
	accept;
}

protocol bgp {
	debug all;
	local as 65000;
	neighbor 192.168.2.1 as 65001;
	import filter peer_in;
}
</code>

<sect2>SSHv2 transport encryption
<code>
roa4 table r4;
roa6 table r6;

protocol rpki {
	debug all;
	
	roa4 { table r4; };
	roa6 { table r6; };
	
	remote 127.0.0.1 port 2345;
	transport ssh {
		bird private key "/home/birdgeek/.ssh/id_rsa";
		remote public key "/home/birdgeek/.ssh/known_hosts";
		user "birdgeek";
	};
	
	# Default interval values
}
</code>



<sect>Static
<label id="static">
+4 −2
Original line number Diff line number Diff line
@@ -399,8 +399,8 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
	TRUE, FALSE, RT, RO, UNKNOWN, GENERIC,
	FROM, GW, NET, MASK, PROTO, SOURCE, SCOPE, CAST, DEST, IFNAME, IFINDEX,
	PREFERENCE,
	ROA_CHECK,
	LEN,
	ROA_CHECK, ASN,
	LEN, MAXLEN,
	DEFINED,
	ADD, DELETE, CONTAINS, RESET,
	PREPEND, FIRST, LAST, LAST_NONAGGREGATED, MATCH,
@@ -891,6 +891,8 @@ term:

 | term '.' IP { $$ = f_new_inst(); $$->code = P('c','p'); $$->a1.p = $1; $$->aux = T_IP; }
 | term '.' LEN { $$ = f_new_inst(); $$->code = 'L'; $$->a1.p = $1; }
 | term '.' MAXLEN { $$ = f_new_inst(); $$->code = P('R','m'); $$->a1.p = $1; }
 | term '.' ASN { $$ = f_new_inst(); $$->code = P('R','a'); $$->a1.p = $1; }
 | term '.' MASK '(' term ')' { $$ = f_new_inst(); $$->code = P('i','M'); $$->a1.p = $1; $$->a2.p = $5; }
 | term '.' FIRST { $$ = f_new_inst(); $$->code = P('a','f'); $$->a1.p = $1; }
 | term '.' LAST  { $$ = f_new_inst(); $$->code = P('a','l'); $$->a1.p = $1; }
+27 −4
Original line number Diff line number Diff line
@@ -1183,6 +1183,26 @@ interpret(struct f_inst *what)
    default: runtime( "Prefix, path, clist or eclist expected" );
    }
    break;
  case P('R','m'): 	/* Get ROA max prefix length */
    ONEARG;
    if (v1.type != T_NET || !net_is_roa(v1.val.net))
      runtime( "ROA expected" );

    res.type = T_INT;
    res.val.i = (v1.val.net->type == NET_ROA4) ?
      ((net_addr_roa4 *) v1.val.net)->max_pxlen :
      ((net_addr_roa6 *) v1.val.net)->max_pxlen;
    break;
  case P('R','a'): 	/* Get ROA ASN */
    ONEARG;
    if (v1.type != T_NET || !net_is_roa(v1.val.net))
      runtime( "ROA expected" );

    res.type = T_INT;
    res.val.i = (v1.val.net->type == NET_ROA4) ?
      ((net_addr_roa4 *) v1.val.net)->asn :
      ((net_addr_roa6 *) v1.val.net)->asn;
    break;
  case P('c','p'):	/* Convert prefix to ... */
    ONEARG;
    if (v1.type != T_NET)
@@ -1476,11 +1496,14 @@ interpret(struct f_inst *what)
    if (!table)
      runtime("Missing ROA table");

    /* Table type is either NET_ROA4 or NET_ROA6, checked in parser */
    if (v1.val.net->type != ((table->addr_type == NET_ROA4) ? NET_IP4 : NET_IP6))
      runtime("Incompatible net type");
    if (table->addr_type != NET_ROA4 && table->addr_type != NET_ROA6)
      runtime("Table type must be either ROA4 or ROA6");

    res.type = T_ENUM_ROA;

    if (table->addr_type != (v1.val.net->type == NET_IP4 ? NET_ROA4 : NET_ROA6))
      res.val.i = ROA_UNKNOWN; /* Prefix and table type mismatch */
    else
      res.val.i = net_roa_check(table, v1.val.net, as);

    break;
Loading