From f222daa08ff95447c4647e522eab052ae90f7bbf Mon Sep 17 00:00:00 2001 From: Lorenzo Cogotti Date: Wed, 4 Aug 2021 19:31:11 +0200 Subject: [PATCH] [tools/bgpgrep] Add bogon ASN filtering option: -bogon-asn --- tools/bgpgrep/bgpgrep.1.in | 33 ++++++++++++++++++ tools/bgpgrep/bgpgrep_compile.c | 10 ++++++ tools/bgpgrep/bgpgrep_local.h | 1 + tools/bgpgrep/bgpgrep_vmfunc.c | 60 +++++++++++++++++++++++++++++++-- 4 files changed, 101 insertions(+), 3 deletions(-) diff --git a/tools/bgpgrep/bgpgrep.1.in b/tools/bgpgrep/bgpgrep.1.in index 30f703d..3f098a3 100755 --- a/tools/bgpgrep/bgpgrep.1.in +++ b/tools/bgpgrep/bgpgrep.1.in @@ -155,6 +155,39 @@ section below. .IP "\fB\-loops\fR" 10 Evaluates as true if BGP message is an UPDATE whose AS_PATH contains loops. +.IP "\fB\-bogon\-asn\fR" 10 +Evaluates as true if BGP message is an UPDATE whose AS_PATH contains bogon ASN. +Any of the following is classified as a bogon ASN: +.RS +.IP "\fI0\fR" 25 +Reserved by +.IR "RFC 7607" . +.IP "\fI23456\fR" 25 +.IR AS_TRANS , +see +.IR "RFC 6793" . +.IP "\fI64496\-64511\fR" 25 +Reserved for use in docs and code by +.IR "RFC 5398" . +.IP "\fI64512\-65534\fR" 25 +Reserved for private use by +.IR "RFC 6996" . +.IP "\fI65535\fR" 25 +Reserved by +.IR "RFC 7300" . +.IP "\fI65536\-65551\fR" 25 +Reserved for use in docs and code by +.IR "RFC 5398" . +.IP "\fI65552\-131071\fR" 25 +Reserved by IANA. +.IP "\fI4200000000\-4294967294\fR" 25 +Reserved for private use by +.IR "RFC 6996" . +.IP "\fI4294967295\fR" 25 +Reserved by +.IR "RFC 7300" . +.RE + .IP "\fB\-exact\ \fIprefix\-expression\fR" 10 Evaluates as true if BGP message is an UPDATE and contains at least one of the relevant networks of interest specified in diff --git a/tools/bgpgrep/bgpgrep_compile.c b/tools/bgpgrep/bgpgrep_compile.c index d79d8ba..01d6170 100755 --- a/tools/bgpgrep/bgpgrep_compile.c +++ b/tools/bgpgrep/bgpgrep_compile.c @@ -62,6 +62,7 @@ typedef struct { Sint32 loopsFn; Sint32 peerMatchFn; Sint32 timestampCmpFn; + Sint32 bogonAsnFn; Uint16 ncode; Boolean8 wasImplicitAnd; @@ -332,6 +333,10 @@ static Expridx GetTerm(void) c[n++] = BGP_VMOP(BGP_VMOP_CALL, C.loopsFn); return PushLeaf(c, n); + } else if (strcmp(C.curterm, "-bogon-asn") == 0) { + c[n++] = BGP_VMOP(BGP_VMOP_CALL, C.bogonAsnFn); + return PushLeaf(c, n); + } else if (strcmp(C.curterm, "-exact") == 0) { return ParsePrefixOp(BGP_VMOP_EXCT); @@ -710,9 +715,14 @@ void Bgpgrep_CompileVmProgram(int argc, char **argv) C.timestampCmpFn = BGP_VMSETFN(&S.vm, Bgp_VmNewFn(&S.vm), BgpgrepF_TimestampCompare); + C.bogonAsnFn = BGP_VMSETFN(&S.vm, + Bgp_VmNewFn(&S.vm), + BgpgrepF_BogonAsn); + assert(C.loopsFn >= 0); assert(C.peerMatchFn >= 0); assert(C.timestampCmpFn >= 0); + assert(C.bogonFn >= 0); // Actual compilation if (C.argc > 0) { diff --git a/tools/bgpgrep/bgpgrep_local.h b/tools/bgpgrep/bgpgrep_local.h index 2490a68..0048be1 100755 --- a/tools/bgpgrep/bgpgrep_local.h +++ b/tools/bgpgrep/bgpgrep_local.h @@ -177,6 +177,7 @@ Sint32 BgpgrepC_ParseCommunity(BgpVmOpt); void BgpgrepF_FindAsLoops(Bgpvm *); void BgpgrepF_PeerAddrMatch(Bgpvm *); void BgpgrepF_TimestampCompare(Bgpvm *); +void BgpgrepF_BogonAsn(Bgpvm *); // ================== // MRT Dump functions diff --git a/tools/bgpgrep/bgpgrep_vmfunc.c b/tools/bgpgrep/bgpgrep_vmfunc.c index a9cfa34..ecafb78 100755 --- a/tools/bgpgrep/bgpgrep_vmfunc.c +++ b/tools/bgpgrep/bgpgrep_vmfunc.c @@ -12,6 +12,7 @@ #include "bgpgrep_local.h" #include "bgp/vmintrin.h" +#include "sys/endian.h" #include #include @@ -156,8 +157,8 @@ void BgpgrepF_TimestampCompare(Bgpvm *vm) } nomatch: - // XXX: include match info + BGP_VMPUSH(vm, res); } @@ -169,6 +170,7 @@ void BgpgrepF_FindAsLoops(Bgpvm *vm) * PUSHES: * TRUE if loops are found inside AS PATH, FALSE otherwise */ + Aspathiter it; Asntree t; @@ -188,7 +190,7 @@ void BgpgrepF_FindAsLoops(Bgpvm *vm) while ((asn = Bgp_NextAsPath(&it)) != -1) { Asn32 as32 = ASN(asn); if (as32 == AS4_TRANS) { - // AS_TRANS are irrelevant for loops + // AS_TRANS are irrelevant for loops (they are, in fact, bogons) pos++; continue; } @@ -212,8 +214,60 @@ void BgpgrepF_FindAsLoops(Bgpvm *vm) Bgp_VmTempFree(vm, t.n * ALIGNEDNODESIZ); nomatch: - // XXX: include match info if (BGP_VMCHKSTK(vm, 1)) BGP_VMPUSH(vm, foundLoop); } + +void BgpgrepF_BogonAsn(Bgpvm *vm) +{ + /* POPS: + * NONE + * + * PUSHES: + * TRUE if bogons are found inside AS PATH, FALSE otherwise + */ + + Aspathiter it; + Asn asn; + + Boolean foundBogon = FALSE; + + const Bgphdr *hdr = BGP_HDR(vm->msg); + if (hdr->type != BGP_UPDATE) + goto nomatch; + + if (Bgp_StartMsgRealAsPath(&it, vm->msg) != OK) + goto nomatch; + + while ((asn = Bgp_NextAsPath(&it)) != -1) { + Asn32 n = beswap32(ASN(asn)); + + // https://ripe72.ripe.net/wp-content/uploads/presentations/151-RIPE72_bogon_ASNs_JobSnijders.pdf + // https://www.manrs.org/2021/01/routing-security-terms-bogons-vogons-and-martians/ + // Breakdown: + // 0 Reserved can't use in BGP RFC 7607 + // 23456 AS_TRANS RFC 6793 + // 64496-64511 Reserved for use in docs and code RFC 5398 + // 64512-65534 Reserved for Private Use RFC 6996 + // 65535 Reserved RFC 7300 + // 65536-65551 Reserved for use in docs and code RFC 5398 + // 65552-131071 Reserved by IANA + // 4200000000-4294967294 Reserved for Private Use RFC 6996 + // 4294967295 Reserved RFC 7300 + foundBogon |= (n == 0u || n == 23456u); + foundBogon |= (n >= 64496u && n <= 131071u); + foundBogon |= (n >= 4200000000u && n <= 4294967295u); + if (foundBogon) + break; + } + if (Bgp_GetErrStat(NULL)) { + vm->errCode = BGPEVMMSGERR; + return; + } + +nomatch: + // XXX: include match info + if (BGP_VMCHKSTK(vm, 1)) + BGP_VMPUSH(vm, foundBogon); +}