From 1ff21856514038c2fa5d4f9defa58bd3ee00ff3b Mon Sep 17 00:00:00 2001 From: Simon Marsh Date: Wed, 6 May 2020 21:19:32 +0100 Subject: [PATCH] - Sort filter{,6}.txt files by number rather than prefix length to be consistent with usage in registry - Add API endpoint for reporting filter contents in JSON --- API.md | 244 +++++++++++++++++++++++++++++++----------------------- roaapi.go | 60 +++++++++++--- 2 files changed, 187 insertions(+), 117 deletions(-) diff --git a/API.md b/API.md index ed2e105..6e4fc8c 100644 --- a/API.md +++ b/API.md @@ -1,109 +1,5 @@ # dn42regsrv API Description -## Route Origin Authorisation (ROA) API - -Route Origin Authorisation (ROA) data can be obtained from the server in -JSON and bird formats. - -### JSON format output - -``` -GET /api/roa/json -``` - -Provides IPv4 and IPv6 ROAs in JSON format, suitable for use with -[gortr](https://github.com/cloudflare/gortr). - -Example Output: -``` -wget -O - -q http://localhost:8042/api/roa/json | jq -``` - -``` -{ - "metadata": { - "counts": 1564, - "generated": 1550402199, - "valid": 1550445399 - }, - "roas": [ - { - "prefix": "172.23.128.0/26", - "maxLength": 29, - "asn": "AS4242422747" - }, - { - "prefix": "172.22.129.192/26", - "maxLength": 29, - "asn": "AS4242423976" - }, - { - "prefix": "10.110.0.0/16", - "maxLength": 24, - "asn": "AS65110" - }, - -... and so on -``` - -### Bird format output - -``` -GET /api/roa/bird/{bird version}/{IP family} -``` - -Provides ROA data suitable for including in to bird. - -{bird version} must be either 1 or 2 - -{IP family} can be 4, 6 or 46 to provide both IPv4 and IPv6 results - - -Example Output: -``` -wget -O - -q http://localhost:8042/api/roa/bird/1/4 -``` - -``` -# -# dn42regsrv ROA Generator -# Last Updated: 2019-02-17 11:16:39.668799525 +0000 GMT m=+0.279049704 -# Commit: 3cbc349bf770493c016888ff785227ded2a7d866 -# -roa 172.23.128.0/26 max 29 as 4242422747; -roa 172.22.129.192/26 max 29 as 4242423976; -roa 10.110.0.0/16 max 24 as 65110; -roa 172.20.164.0/26 max 29 as 4242423023; -roa 172.20.135.200/29 max 29 as 4242420448; -roa 10.65.0.0/20 max 24 as 4242420420; -roa 172.20.149.136/29 max 29 as 4242420234; -roa 10.160.0.0/13 max 24 as 65079; -roa 10.169.0.0/16 max 24 as 65534; - -... and so on -``` - -``` -wget -O - -q http://localhost:8042/api/roa/bird/2/6 -``` - -``` -# -# dn42regsrv ROA Generator -# Last Updated: 2019-02-17 11:16:39.668799525 +0000 GMT m=+0.279049704 -# Commit: 3cbc349bf770493c016888ff785227ded2a7d866 -# -route fdc3:10cd:ae9d::/48 max 64 as 4242420789; -route fd41:9805:7b69:4000::/51 max 64 as 4242420846; -route fd41:9805:7b69:4000::/51 max 64 as 4242420845; -route fd41:9805:7b69:4000::/51 max 64 as 4242420847; -route fddf:ebfd:a801:2331::/64 max 64 as 65530; -route fd42:1a2b:de57::/48 max 64 as 4242422454; -route fd42:7879:7879::/48 max 64 as 4242421787; - -... and so on -``` - ## Registry API The general form of the registry query API is: @@ -400,6 +296,146 @@ wget -O - -q http://localhost:8042/api/dns/.meta | jq } ``` +## Route Origin Authorisation (ROA) API + +Route Origin Authorisation (ROA) data can be obtained from the server in +JSON and bird formats. + +### JSON format output + +``` +GET /api/roa/json +``` + +Provides IPv4 and IPv6 ROAs in JSON format, suitable for use with +[gortr](https://github.com/cloudflare/gortr). + +Example Output: +``` +wget -O - -q http://localhost:8042/api/roa/json | jq +``` + +``` +{ + "metadata": { + "counts": 1564, + "generated": 1550402199, + "valid": 1550445399 + }, + "roas": [ + { + "prefix": "172.23.128.0/26", + "maxLength": 29, + "asn": "AS4242422747" + }, + { + "prefix": "172.22.129.192/26", + "maxLength": 29, + "asn": "AS4242423976" + }, + { + "prefix": "10.110.0.0/16", + "maxLength": 24, + "asn": "AS65110" + }, + +... and so on +``` + +### Bird format output + +``` +GET /api/roa/bird/{bird version}/{IP family} +``` + +Provides ROA data suitable for including in to bird. + +{bird version} must be either 1 or 2 + +{IP family} can be 4, 6 or 46 to provide both IPv4 and IPv6 results + + +Example Output: +``` +wget -O - -q http://localhost:8042/api/roa/bird/1/4 +``` + +``` +# +# dn42regsrv ROA Generator +# Last Updated: 2019-02-17 11:16:39.668799525 +0000 GMT m=+0.279049704 +# Commit: 3cbc349bf770493c016888ff785227ded2a7d866 +# +roa 172.23.128.0/26 max 29 as 4242422747; +roa 172.22.129.192/26 max 29 as 4242423976; +roa 10.110.0.0/16 max 24 as 65110; +roa 172.20.164.0/26 max 29 as 4242423023; +roa 172.20.135.200/29 max 29 as 4242420448; +roa 10.65.0.0/20 max 24 as 4242420420; +roa 172.20.149.136/29 max 29 as 4242420234; +roa 10.160.0.0/13 max 24 as 65079; +roa 10.169.0.0/16 max 24 as 65534; + +... and so on +``` + +``` +wget -O - -q http://localhost:8042/api/roa/bird/2/6 +``` + +``` +# +# dn42regsrv ROA Generator +# Last Updated: 2019-02-17 11:16:39.668799525 +0000 GMT m=+0.279049704 +# Commit: 3cbc349bf770493c016888ff785227ded2a7d866 +# +route fdc3:10cd:ae9d::/48 max 64 as 4242420789; +route fd41:9805:7b69:4000::/51 max 64 as 4242420846; +route fd41:9805:7b69:4000::/51 max 64 as 4242420845; +route fd41:9805:7b69:4000::/51 max 64 as 4242420847; +route fddf:ebfd:a801:2331::/64 max 64 as 65530; +route fd42:1a2b:de57::/48 max 64 as 4242422454; +route fd42:7879:7879::/48 max 64 as 4242421787; + +... and so on +``` + +### filter{,6}.txt + +``` +GET /api/roa/filter/{IP family} +``` + +Provides the contents of filter.txt and filter6.txt in json format. + +{IP family} can be 4, 6 or 46 to provide both IPv4 and IPv6 results + + +Example Output: +``` +wget -O - -q http://localhost:8042/api/roa/filter/6 | jq +``` + +``` +[ + { + "nr": 1001, + "action": "permit", + "prefix": "fd00::/8", + "minlen": 44, + "maxlen": 64 + }, + { + "nr": 9999, + "action": "deny", + "prefix": "::/0", + "minlen": 0, + "maxlen": 128 + } +] +``` + + ## DNS Root Zone API The DNS API provides a list of resource records that can be used to create a root zone for DN42 diff --git a/roaapi.go b/roaapi.go index 94d85b8..6d92e67 100644 --- a/roaapi.go +++ b/roaapi.go @@ -39,12 +39,13 @@ type PrefixROA struct { } type ROAFilter struct { - Number uint - Action string - Prefix string - MinLen uint8 - MaxLen uint8 - Network *net.IPNet + Number uint `json:"nr"` + Action string `json:"action"` + Prefix string `json:"prefix"` + MinLen uint8 `json:"minlen"` + MaxLen uint8 `json:"maxlen"` + Network *net.IPNet `json:"-"` + IPType uint8 `json:"-"` } type ROA struct { @@ -90,6 +91,7 @@ func InitROAAPI(params ...interface{}) { PathPrefix("/roa"). Subrouter() + s.HandleFunc("/filter/{ipv}", roaFilterHandler) s.HandleFunc("/json", roaJSONHandler) s.HandleFunc("/bird/{birdv}/{ipv}", roaBirdHandler) @@ -99,6 +101,38 @@ func InitROAAPI(params ...interface{}) { ////////////////////////////////////////////////////////////////////////// // api handlers +// return JSON formatted version of filter{,6}.txt +func roaFilterHandler(w http.ResponseWriter, r *http.Request) { + + vars := mux.Vars(r) + ipv := vars["ipv"] + + // pre-create an array to hold the result + filters := make([]*ROAFilter, 0, len(ROAData.Filters)) + + // helper closure to select from the filter array + fselect := func(a []*ROAFilter, t uint8) []*ROAFilter { + for _, f := range ROAData.Filters { + if f.IPType == t { + a = append(a, f) + } + } + return a + } + + // add ipv4 filters if required + if strings.ContainsRune(ipv, '4') { + filters = fselect(filters, 4) + } + + // add ipv6 filters if required + if strings.ContainsRune(ipv, '6') { + filters = fselect(filters, 6) + } + + ResponseJSON(w, filters) +} + // return JSON formatted ROA data suitable for use with GoRTR func roaJSONHandler(w http.ResponseWriter, r *http.Request) { @@ -164,12 +198,12 @@ func ROAUpdate(params ...interface{}) { } // load filter{,6}.txt files - if roa.loadFilter(path+"/filter.txt") != nil { + if roa.loadFilter(path+"/filter.txt", 4) != nil { // error loading IPv4 filter, don't update return } - if roa.loadFilter(path+"/filter6.txt") != nil { + if roa.loadFilter(path+"/filter6.txt", 6) != nil { // error loading IPv6 filter, don't update return } @@ -206,7 +240,7 @@ func ROAUpdate(params ...interface{}) { ////////////////////////////////////////////////////////////////////////// // load network filter definitions from a filter file -func (roa *ROA) loadFilter(path string) error { +func (roa *ROA) loadFilter(path string, iptype uint8) error { // open the file for reading file, err := os.Open(path) @@ -272,6 +306,7 @@ func (roa *ROA) loadFilter(path string) error { MinLen: uint8(convert(fields[3])), MaxLen: uint8(convert(fields[4])), Network: network, + IPType: iptype, } // add to list if no strconv error @@ -291,11 +326,10 @@ func (roa *ROA) loadFilter(path string) error { return err } - // sort the filters based on prefix length (largest first) + // filter.txt should be in order, + // but still sort by number just in case sort.Slice(filters, func(i, j int) bool { - leni, _ := filters[i].Network.Mask.Size() - lenj, _ := filters[j].Network.Mask.Size() - return leni > lenj + return filters[i].Number < filters[j].Number }) // add to the roa object