Commit b1b19433 authored by Ondrej Zajicek's avatar Ondrej Zajicek
Browse files

The generalized TTL security mechanism (RFC 5082) support.

Thanks to Alexander V. Chernikov for the patch.
parent a52d52fa
Loading
Loading
Loading
Loading
+17 −3
Original line number Diff line number Diff line
@@ -1120,9 +1120,11 @@ for each neighbor using the following configuration parameters:
	subnets. Such IP address have to be reachable through system
	routing table. For multihop BGP it is recommended to
	explicitly configure <cf/source address/ to have it
	stable. Optional <cf/number/ argument can be used to limit TTL
	(the number of hops).
	Default: switched off.
	stable. Optional <cf/number/ argument can be used to specify
	the number of hops (used for TTL). Note that the number of
	networks (edges) in a path is counted, i.e. if two BGP
	speakers are separated by one router, the number of hops is
	2. Default: switched off.

	<tag>source address <m/ip/</tag> Define local address we
	should use for next hop calculation and as a source address
@@ -1169,6 +1171,18 @@ for each neighbor using the following configuration parameters:
	as an IGP routing table. Default: the same as the table BGP is
	connected to.
	
	<tag>ttl security <m/switch/</tag> Use GTSM (RFC 5082 - the
	generalized TTL security mechanism). GTSM protects against
	spoofed packets by ignoring received packets with a smaller
	than expected TTL. To work properly, GTSM have to be enabled
	on both sides of a BGP session. If both <cf/ttl security/ and
	<cf/multihop/ options are enabled, <cf/multihop/ option should
	specify proper hop value to compute expected TTL. Kernel
	support required: Linux: 2.6.34+ (IPv4), 2.6.35+ (IPv6), BSD:
	since long ago, IPv4 only. Note that full (ICMP protection,
	for example) RFC 5082 support is provided by Linux
	only. Default: disabled.
	
	<tag>password <m/string/</tag> Use this password for MD5 authentication
	of BGP sessions. Default: no authentication. Password has to be set by
	external utility (e.g. setkey(8)) on BSD systems.
+2 −1
Original line number Diff line number Diff line
@@ -54,7 +54,8 @@ int sk_send(sock *, unsigned len); /* Send data, <0=err, >0=ok, 0=sleep */
int sk_send_to(sock *, unsigned len, ip_addr to, unsigned port); /* sk_send to given destination */
void sk_reallocate(sock *);		/* Free and allocate tbuf & rbuf */
void sk_dump_all(void);
int sk_set_ttl(sock *s, int ttl);	/* Set TTL for given socket */
int sk_set_ttl(sock *s, int ttl);	/* Set transmit TTL for given socket */
int sk_set_min_ttl(sock *s, int ttl);	/* Set minimal accepted TTL for given socket */

/* Add or remove security associations for given passive socket */
int sk_set_md5_auth(sock *s, ip_addr a, char *passwd);
+48 −14
Original line number Diff line number Diff line
@@ -92,6 +92,8 @@ static int
bgp_open(struct bgp_proto *p)
{
  struct config *cfg = p->cf->c.global;
  int errcode;

  bgp_counter++;

  if (!bgp_listen_sk)
@@ -100,10 +102,8 @@ bgp_open(struct bgp_proto *p)
  if (!bgp_listen_sk)
    {
      bgp_counter--;
      p->p.disabled = 1;
      bgp_store_error(p, NULL, BE_MISC, BEM_NO_SOCKET);
      proto_notify_state(&p->p, PS_DOWN);
      return -1;
      errcode = BEM_NO_SOCKET;
      goto err;
    }

  if (!bgp_linpool)
@@ -115,14 +115,18 @@ bgp_open(struct bgp_proto *p)
      if (rv < 0)
	{
	  bgp_close(p, 0);
	  p->p.disabled = 1;
	  bgp_store_error(p, NULL, BE_MISC, BEM_INVALID_MD5);
	  proto_notify_state(&p->p, PS_DOWN);
	  return -1;
	  errcode = BEM_INVALID_MD5;
	  goto err;
	}
    }

  return 0;

err:
  p->p.disabled = 1;
  bgp_store_error(p, NULL, BE_MISC, errcode);
  proto_notify_state(&p->p, PS_DOWN);
  return -1;
}

static void
@@ -567,6 +571,7 @@ bgp_connect(struct bgp_proto *p) /* Enter Connect state and start establishing c
{
  sock *s;
  struct bgp_conn *conn = &p->outgoing_conn;
  int hops = p->cf->multihop ? : 1;

  DBG("BGP: Connecting\n");
  s = sk_new(p->p.pool);
@@ -574,7 +579,7 @@ bgp_connect(struct bgp_proto *p) /* Enter Connect state and start establishing c
  s->saddr = p->source_addr;
  s->daddr = p->cf->remote_ip;
  s->dport = BGP_PORT;
  s->ttl = p->cf->multihop ? : 1;
  s->ttl = p->cf->ttl_security ? 255 : hops;
  s->rbsize = BGP_RX_BUFFER_SIZE;
  s->tbsize = BGP_TX_BUFFER_SIZE;
  s->tos = IP_PREC_INTERNET_CONTROL;
@@ -584,11 +589,25 @@ bgp_connect(struct bgp_proto *p) /* Enter Connect state and start establishing c
  bgp_setup_conn(p, conn);
  bgp_setup_sk(conn, s);
  bgp_conn_set_state(conn, BS_CONNECT);
  if (sk_open(s))

  if (sk_open(s) < 0)
    {
      bgp_sock_err(s, 0);
      return;
    }

  /* Set minimal receive TTL if needed */
  if (p->cf->ttl_security)
  {
    DBG("Setting minimum received TTL to %d", 256 - hops);
    if (sk_set_min_ttl(s, 256 - hops) < 0)
    {
      log(L_ERR "TTL security configuration failed, closing session");
      bgp_sock_err(s, 0);
      return;
    }
  }

  DBG("BGP: Waiting for connect success\n");
  bgp_start_timer(conn->connect_retry_timer, p->cf->connect_retry_time);
}
@@ -627,9 +646,22 @@ bgp_incoming_connection(sock *sk, int dummy UNUSED)
	    if (!acc)
	      goto err;

	    int hops = p->cf->multihop ? : 1;
	    if (p->cf->ttl_security)
	    {
	      /* TTL security support */
	      if ((sk_set_ttl(sk, 255) < 0) ||
		  (sk_set_min_ttl(sk, 256 - hops) < 0))
	      {
		log(L_ERR "TTL security configuration failed, closing session");
		goto err;
	      }
	    }
	    else
	      sk_set_ttl(sk, hops);

	    bgp_setup_conn(p, &p->incoming_conn);
	    bgp_setup_sk(&p->incoming_conn, sk);
	    sk_set_ttl(sk, p->cf->multihop ? : 1);
	    bgp_send_open(&p->incoming_conn);
	    return 0;
	  }
@@ -656,6 +688,7 @@ bgp_setup_listen_sk(ip_addr addr, unsigned port, u32 flags)
  sock *s = sk_new(&root_pool);
  DBG("BGP: Creating listening socket\n");
  s->type = SK_TCP_PASSIVE;
  s->ttl = 255;
  s->saddr = addr;
  s->sport = port ? port : BGP_PORT;
  s->flags = flags ? 0 : SKF_V6ONLY;
@@ -664,13 +697,14 @@ bgp_setup_listen_sk(ip_addr addr, unsigned port, u32 flags)
  s->tbsize = BGP_TX_BUFFER_SIZE;
  s->rx_hook = bgp_incoming_connection;
  s->err_hook = bgp_listen_sock_err;
  if (sk_open(s))

  if (sk_open(s) < 0)
    {
      log(L_ERR "BGP: Unable to open listening socket");
      rfree(s);
      return NULL;
    }
  else

  return s;
}

+1 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ struct bgp_config {
  u32 local_as, remote_as;
  ip_addr remote_ip;
  int multihop;				/* Number of hops if multihop */
  int ttl_security;			/* Enable TTL security [RFC5082] */
  ip_addr source_addr;			/* Source address to use */
  int next_hop_self;			/* Always set next hop to local IP address */
  int missing_lladdr;			/* What we will do when we don' know link-local addr, see MLL_* */
+3 −2
Original line number Diff line number Diff line
@@ -25,7 +25,7 @@ CF_KEYWORDS(BGP, LOCAL, NEIGHBOR, AS, HOLD, TIME, CONNECT, RETRY,
	CLUSTER, ID, AS4, ADVERTISE, IPV4, CAPABILITIES, LIMIT, PASSIVE,
	PREFER, OLDER, MISSING, LLADDR, DROP, IGNORE, ROUTE, REFRESH,
	INTERPRET, COMMUNITIES, BGP_ORIGINATOR_ID, BGP_CLUSTER_LIST, IGP,
	TABLE, GATEWAY, DIRECT, RECURSIVE, MED)
	TABLE, GATEWAY, DIRECT, RECURSIVE, MED, TTL, SECURITY)

CF_GRAMMAR

@@ -71,7 +71,7 @@ bgp_proto:
 | bgp_proto CONNECT RETRY TIME expr ';' { BGP_CFG->connect_retry_time = $5; }
 | bgp_proto KEEPALIVE TIME expr ';' { BGP_CFG->keepalive_time = $4; }
 | bgp_proto MULTIHOP ';' { BGP_CFG->multihop = 64; }
 | bgp_proto MULTIHOP expr ';' { BGP_CFG->multihop = $3; }
 | bgp_proto MULTIHOP expr ';' { BGP_CFG->multihop = $3; if (($3<1) || ($3>255)) cf_error("Multihop must be in range 1-255"); }
 | bgp_proto NEXT HOP SELF ';' { BGP_CFG->next_hop_self = 1; }
 | bgp_proto MISSING LLADDR SELF ';' { BGP_CFG->missing_lladdr = MLL_SELF; }
 | bgp_proto MISSING LLADDR DROP ';' { BGP_CFG->missing_lladdr = MLL_DROP; }
@@ -98,6 +98,7 @@ bgp_proto:
 | bgp_proto PASSIVE bool ';' { BGP_CFG->passive = $3; }
 | bgp_proto INTERPRET COMMUNITIES bool ';' { BGP_CFG->interpret_communities = $4; }
 | bgp_proto IGP TABLE rtable ';' { BGP_CFG->igp_table = $4; }
 | bgp_proto TTL SECURITY bool ';' { BGP_CFG->ttl_security = $4; }
 ;

CF_ADDTO(dynamic_attr, BGP_ORIGIN
Loading