bgpd: add rpki source address configuration

Add the ability to configure the source address of rpki
connection. Proposed vty command is to add below parameter:

rpki cache <address> source <bindaddr> <port> preference <pref>
rpki cache <address> source <bindaddr> <port> <usernamessh> ...

This works for both tcp and ssh connections. In case the source
address is not available yet, the rpki retry interval will retry
in a defined amount of time.

Rtrlib library is the library in charge of the binding of the
tcp/ssh connection, and applies the getaddrinfo() and bind()
operations to the passed parameter bindaddr to the respective
tcp_config/ssh_config structures.

Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
This commit is contained in:
Philippe Guibert 2021-09-02 17:12:06 +02:00
parent 3e324ff419
commit 7253a7bcd8
2 changed files with 56 additions and 31 deletions

View File

@ -111,12 +111,12 @@ static int add_ssh_cache(const char *host, const unsigned int port,
const char *username, const char *client_privkey_path, const char *username, const char *client_privkey_path,
const char *client_pubkey_path, const char *client_pubkey_path,
const char *server_pubkey_path, const char *server_pubkey_path,
const uint8_t preference); const uint8_t preference, const char *bindaddr);
#endif #endif
static struct rtr_socket *create_rtr_socket(struct tr_socket *tr_socket); static struct rtr_socket *create_rtr_socket(struct tr_socket *tr_socket);
static struct cache *find_cache(const uint8_t preference); static struct cache *find_cache(const uint8_t preference);
static int add_tcp_cache(const char *host, const char *port, static int add_tcp_cache(const char *host, const char *port,
const uint8_t preference); const uint8_t preference, const char *bindaddr);
static void print_record(const struct pfx_record *record, struct vty *vty); static void print_record(const struct pfx_record *record, struct vty *vty);
static int is_synchronized(void); static int is_synchronized(void);
static int is_running(void); static int is_running(void);
@ -787,7 +787,7 @@ static int add_cache(struct cache *cache)
} }
static int add_tcp_cache(const char *host, const char *port, static int add_tcp_cache(const char *host, const char *port,
const uint8_t preference) const uint8_t preference, const char *bindaddr)
{ {
struct rtr_socket *rtr_socket; struct rtr_socket *rtr_socket;
struct tr_tcp_config *tcp_config = struct tr_tcp_config *tcp_config =
@ -799,7 +799,10 @@ static int add_tcp_cache(const char *host, const char *port,
tcp_config->host = XSTRDUP(MTYPE_BGP_RPKI_CACHE, host); tcp_config->host = XSTRDUP(MTYPE_BGP_RPKI_CACHE, host);
tcp_config->port = XSTRDUP(MTYPE_BGP_RPKI_CACHE, port); tcp_config->port = XSTRDUP(MTYPE_BGP_RPKI_CACHE, port);
tcp_config->bindaddr = NULL; if (bindaddr)
tcp_config->bindaddr = XSTRDUP(MTYPE_BGP_RPKI_CACHE, bindaddr);
else
tcp_config->bindaddr = NULL;
rtr_socket = create_rtr_socket(tr_socket); rtr_socket = create_rtr_socket(tr_socket);
@ -822,7 +825,7 @@ static int add_ssh_cache(const char *host, const unsigned int port,
const char *username, const char *client_privkey_path, const char *username, const char *client_privkey_path,
const char *client_pubkey_path, const char *client_pubkey_path,
const char *server_pubkey_path, const char *server_pubkey_path,
const uint8_t preference) const uint8_t preference, const char *bindaddr)
{ {
struct tr_ssh_config *ssh_config = struct tr_ssh_config *ssh_config =
XCALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct tr_ssh_config)); XCALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct tr_ssh_config));
@ -834,7 +837,10 @@ static int add_ssh_cache(const char *host, const unsigned int port,
ssh_config->port = port; ssh_config->port = port;
ssh_config->host = XSTRDUP(MTYPE_BGP_RPKI_CACHE, host); ssh_config->host = XSTRDUP(MTYPE_BGP_RPKI_CACHE, host);
ssh_config->bindaddr = NULL; if (bindaddr)
ssh_config->bindaddr = XSTRDUP(MTYPE_BGP_RPKI_CACHE, bindaddr);
else
ssh_config->bindaddr = NULL;
ssh_config->username = XSTRDUP(MTYPE_BGP_RPKI_CACHE, username); ssh_config->username = XSTRDUP(MTYPE_BGP_RPKI_CACHE, username);
ssh_config->client_privkey_path = ssh_config->client_privkey_path =
@ -864,6 +870,9 @@ static void free_cache(struct cache *cache)
if (cache->type == TCP) { if (cache->type == TCP) {
XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.tcp_config->host); XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.tcp_config->host);
XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.tcp_config->port); XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.tcp_config->port);
if (cache->tr_config.tcp_config->bindaddr)
XFREE(MTYPE_BGP_RPKI_CACHE,
cache->tr_config.tcp_config->bindaddr);
XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.tcp_config); XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.tcp_config);
} }
#if defined(FOUND_SSH) #if defined(FOUND_SSH)
@ -875,6 +884,9 @@ static void free_cache(struct cache *cache)
cache->tr_config.ssh_config->client_privkey_path); cache->tr_config.ssh_config->client_privkey_path);
XFREE(MTYPE_BGP_RPKI_CACHE, XFREE(MTYPE_BGP_RPKI_CACHE,
cache->tr_config.ssh_config->server_hostkey_path); cache->tr_config.ssh_config->server_hostkey_path);
if (cache->tr_config.ssh_config->bindaddr)
XFREE(MTYPE_BGP_RPKI_CACHE,
cache->tr_config.ssh_config->bindaddr);
XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.ssh_config); XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.ssh_config);
} }
#endif #endif
@ -911,15 +923,21 @@ static int config_write(struct vty *vty)
#endif #endif
case TCP: case TCP:
tcp_config = cache->tr_config.tcp_config; tcp_config = cache->tr_config.tcp_config;
vty_out(vty, " rpki cache %s %s ", tcp_config->host, vty_out(vty, " rpki cache %s%s%s %s ", tcp_config->host,
tcp_config->bindaddr ? " source " : "",
tcp_config->bindaddr ? tcp_config->bindaddr
: "",
tcp_config->port); tcp_config->port);
break; break;
#if defined(FOUND_SSH) #if defined(FOUND_SSH)
case SSH: case SSH:
ssh_config = cache->tr_config.ssh_config; ssh_config = cache->tr_config.ssh_config;
vty_out(vty, " rpki cache %s %u %s %s %s ", vty_out(vty, " rpki cache %s%s%s %u %s %s %s ",
ssh_config->host, ssh_config->port, ssh_config->host,
ssh_config->username, ssh_config->bindaddr ? "source " : "",
ssh_config->bindaddr ? ssh_config->bindaddr
: "",
ssh_config->port, ssh_config->username,
ssh_config->client_privkey_path, ssh_config->client_privkey_path,
ssh_config->server_hostkey_path != NULL ssh_config->server_hostkey_path != NULL
? ssh_config->server_hostkey_path ? ssh_config->server_hostkey_path
@ -1048,20 +1066,22 @@ DEFUN (no_rpki_retry_interval,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
DEFPY (rpki_cache, DEFPY(rpki_cache, rpki_cache_cmd,
rpki_cache_cmd, "rpki cache <A.B.C.D|WORD> [source <A.B.C.D>$bindaddr] "
"rpki cache <A.B.C.D|WORD><TCPPORT|(1-65535)$sshport SSH_UNAME SSH_PRIVKEY SSH_PUBKEY [SERVER_PUBKEY]> preference (1-255)", "<TCPPORT|(1-65535)$sshport SSH_UNAME SSH_PRIVKEY SSH_PUBKEY [SERVER_PUBKEY]> preference (1-255)",
RPKI_OUTPUT_STRING RPKI_OUTPUT_STRING
"Install a cache server to current group\n" "Install a cache server to current group\n"
"IP address of cache server\n Hostname of cache server\n" "IP address of cache server\n Hostname of cache server\n"
"TCP port number\n" "Configure source IP address of RPKI connection\n"
"SSH port number\n" "Define a Source IP Address\n"
"SSH user name\n" "TCP port number\n"
"Path to own SSH private key\n" "SSH port number\n"
"Path to own SSH public key\n" "SSH user name\n"
"Path to Public key of cache server\n" "Path to own SSH private key\n"
"Preference of the cache server\n" "Path to own SSH public key\n"
"Preference value\n") "Path to Public key of cache server\n"
"Preference of the cache server\n"
"Preference value\n")
{ {
int return_value; int return_value;
struct listnode *cache_node; struct listnode *cache_node;
@ -1080,16 +1100,17 @@ DEFPY (rpki_cache,
// use ssh connection // use ssh connection
if (ssh_uname) { if (ssh_uname) {
#if defined(FOUND_SSH) #if defined(FOUND_SSH)
return_value = return_value = add_ssh_cache(
add_ssh_cache(cache, sshport, ssh_uname, ssh_privkey, cache, sshport, ssh_uname, ssh_privkey, ssh_pubkey,
ssh_pubkey, server_pubkey, preference); server_pubkey, preference, bindaddr_str);
#else #else
return_value = SUCCESS; return_value = SUCCESS;
vty_out(vty, vty_out(vty,
"ssh sockets are not supported. Please recompile rtrlib and frr with ssh support. If you want to use it\n"); "ssh sockets are not supported. Please recompile rtrlib and frr with ssh support. If you want to use it\n");
#endif #endif
} else { // use tcp connection } else { // use tcp connection
return_value = add_tcp_cache(cache, tcpport, preference); return_value =
add_tcp_cache(cache, tcpport, preference, bindaddr_str);
} }
if (return_value == ERROR) { if (return_value == ERROR) {

View File

@ -109,7 +109,7 @@ The following commands are independent of a specific cache server.
The following commands configure one or multiple cache servers. The following commands configure one or multiple cache servers.
.. clicmd:: rpki cache (A.B.C.D|WORD) PORT [SSH_USERNAME] [SSH_PRIVKEY_PATH] [SSH_PUBKEY_PATH] [KNOWN_HOSTS_PATH] PREFERENCE .. clicmd:: rpki cache (A.B.C.D|WORD) [source A.B.C.D] PORT [SSH_USERNAME] [SSH_PRIVKEY_PATH] [SSH_PUBKEY_PATH] [KNOWN_HOSTS_PATH] PREFERENCE
Add a cache server to the socket. By default, the connection between router Add a cache server to the socket. By default, the connection between router
@ -120,6 +120,9 @@ The following commands are independent of a specific cache server.
A.B.C.D|WORD A.B.C.D|WORD
Address of the cache server. Address of the cache server.
source A.B.C.D
Source address of the RPKI connection to access cache server.
PORT PORT
Port number to connect to the cache server Port number to connect to the cache server
@ -230,7 +233,7 @@ RPKI Configuration Example
rpki polling_period 1000 rpki polling_period 1000
rpki timeout 10 rpki timeout 10
! SSH Example: ! SSH Example:
rpki cache example.com 22 rtr-ssh ./ssh_key/id_rsa ./ssh_key/id_rsa.pub preference 1 rpki cache example.com source 141.22.28.223 22 rtr-ssh ./ssh_key/id_rsa ./ssh_key/id_rsa.pub preference 1
! TCP Example: ! TCP Example:
rpki cache rpki-validator.realmv6.org 8282 preference 2 rpki cache rpki-validator.realmv6.org 8282 preference 2
exit exit
@ -240,10 +243,11 @@ RPKI Configuration Example
network 192.168.0.0/16 network 192.168.0.0/16
neighbor 123.123.123.0 remote-as 60002 neighbor 123.123.123.0 remote-as 60002
neighbor 123.123.123.0 route-map rpki in neighbor 123.123.123.0 route-map rpki in
neighbor 123.123.123.0 update-source 141.22.28.223
! !
address-family ipv6 address-family ipv6
neighbor 123.123.123.0 activate neighbor 123.123.123.0 activate
neighbor 123.123.123.0 route-map rpki in neighbor 123.123.123.0 route-map rpki in
exit-address-family exit-address-family
! !
route-map rpki permit 10 route-map rpki permit 10