npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

rpki-web-test

v0.6.2

Published

Lib, website and cli tool to test if your internet connection drops RPKI invalid ROAs somewhere along the way.

Downloads

2

Readme

rpki-web-test

RPKI web test tool testing valid ROA and invalid ROA http endpoint.

This is the repo that backs RPKI WEB TEST

This small tool tests whether the client running it is connected to the internet through upstream router that performs Route Origin Validation according (ROA) in accordance with the Routing Public Key Infrastructure (RPKI). You can read more about RPKI here.

How does this work?

This tool will try to retrieve information from a specially conifgured mutli-homed webserver through two different IP addresses. One of these IP addresses is part of a prefix that is part of a valid ROA and the other IP address is part of a prefix that explicitly has an invalid ROA. If the tool can reach the webserver through the prefix with the valid ROA, but it times out connecting to the the prefix with the invalid ROA, it will conclude that somewhere along the route from the client to the server the prefix with ROA invalid is actively being dropped. Be aware that we cannot infer where along the route this packet is dropped, nor can we infer which along which AS path the packet travels.

The specially configured webserver this test uses is kindly hosted by Job Snijders. You can however configure this tool to use any webserver that's configured to do this, provided you have access to IP addresses within a valid ROA and an invalid ROA.

What is in this repo?

This tool consists of three parts:

  • a web-client (that you can use here) that will run in a browser and show a frown, meh or smiley face based on the outcome of the test. You can also host it yourself if you wish.
  • a javascript library that can be run from both node.js and from webbrowsers. It can be used through ES6 modules or CJS module (for node.js).
  • a CLI tool that performs the test and outputs the result in JSON. It is rather clunky now, since it has a complete nodejs environment embedded in it. given enough interest I can port this to a compiled language, so you can have a small binary. Also, I could add a traceroute engine to this CLI tool, so we could obtain more information about where along the route the invalid ROAs are dropped.

Using the tool

Web client

You can build the webclient yourself. The prerequisites for this are node 12.x or higher. The you can:

npm install
npm run web

This will create a file /build/bundle.js that you'll need together with index.html, manifest.webmanifest from the /html directory. Note that for this to correctly function it should be hosted on a TLS backed website, i.e. https.

CLI Tool

The cli tool is also available under the Releases. I've only included it for MacOs. Deployments for Linux and Windows can be made with the excellent pkg:

npm -g install pkg@4
npm install
TARGET=<YOU_TARGET_ARCH> npm run cli

JS Library

Loading with CommonJs (node/require)

Under the Releases tab you can find a file librpkitest.js that contains a CJS library for use with webbrowsers (with require/r.js) and nodejs.

const fetch = require('cross-fetch');
const librpkitest = require('./librpkitest');

Loading with ES6 Modules

If you're using ES6 modules you can use the file librpkitest.js in /src directly, like so:

import { testRpkiInvalids } from "./librpkitest";

Bringing your own fetch implementation

For node.js you will have to bring your own fetch implementation. The cross-fetch package seems to be a good choice. You'll have to include the package and then pass it as an argument to the librpkitest library:

const rpkiResult = testRpkiInvalids({fetch: fetch}).then(...);

Using the library

The Library has only one public function named testRpkiInvalids.

Arguments

The testRpkiInvalids function accepts an arguments object with the following fields:

name | type | default | description ---- | ---- | ----------- | ----------- enrich | bool | false | Sets whether the prefix and ASN belonging to the client IP address will be retrieved postResult | bool | false | Sets whether the result will be posted to a logging server invalidTimeout | Number | 5000 | Timeout in milliseconds after which the invalid ROA request is considered blocked. fetch | function | window.fetch* | The fetch used to make the HTTP requests. callBacks | object with stageName:callBack Function pairs | {} | At the end of each stage a callBack can be invoked (i.e., to render stuff to the clientscreen)

Usage

The tesRpkiInvalids function returns a Promise wrapping a Result object.

// require:
// const librpkitest = require("./librpkitest");
// librpkitest.testRpkiInvalids(...)

// es6:
// import { testRpkiInvalids } from "librpkitest";

testRpkiInvalids({
    enrich: true,
    postResult: true
  }).then(
    rpkiResult => {
      console.log("rpki test result came in.");
      console.log(rpkiResult);
    },
    err => {
      console.log("errored out");
      console.log(err);
    }
  );

Output

the testRpkiInvalids function returns a Promise that resolved into a Result object:

Result object

  • rpki-valid-passed (bool) whether all rpki valid requests returned a non-error response
  • rpki-invalid-passed (bool) whether all rpki invalid requests returned a non-error response
  • events: (array of Event objects) all events of all stages appended. See down below for details
  • lastStage: (stageId) the last stage before returning the result, should be "finished"
  • lastErrorStage: (stageId) the stage where the last error occurred
  • lastError: (Error) the last encountered error
  • pfx: (string) Prefix that the client IP address is routed from
  • asn: (string) Autonomous System Number that the prefix is announced from
  • ip: ((string) (public) IP address of the connection of the client as seen by the consulted webserver

Event object

  • stage (string) id of the final state of the stage
  • error (Error) error if thrown, otherwise null
  • successs (bool) if true stage finished without errors
  • data (object) if any data returned by this stage, otherwise null

The data object for each stage, will always have either a startDateTime field that represents the start of a timer or a duration field, the time in ms from the start of that timer.

Stage/State machine

The testRpkiInvalids function will go concurrently through a few stages and will report on the final state of each of these stages. Each stage will go through one or more states and will setlle on a final state that will end up in the events object in the returned result.

Here are the stages and their encapsulated states, like [state A] -> [state B | state C]. Stages are encapsulated in square brackets, are unnamed and can either have one possible final state (the names inside the brackets). So, [initialized] in a stage with one possible final state, whereas [validAwait | validReceived] is a stage with two possible final states.

                                   [initialized]
                                         |
                             + --------- + --------- +
                             |                       |
      [validAwait | validReceived]             [invalidAwait | invalidReceived | invalidBlocked]
                             |                       |
                             + --------- + --------- +
                                         |
                          [enrichedAwait | enrichedReceived]
                                         |
                      [resultPostedAwait | resultPostedConfirmed]
                                         |
                                     [finished]

Sample output for a successful RPKI test

{
  "rpki-valid-passed": true,
  "rpki-invalid-passed": false,
  "lastStage": "finished",
  "lastErrorStage": null,
  "lastError": null,
  "ip": "83.160.104.137",
  "asn": ["3265"],
  "pfx": "83.160.0.0/14",
  "events": [
    {
      "stage": "initialized",
      "error": null,
      "success": true,
      "data": {
        "testUrls": [
          {
            "url": "https://038c8427-6c0e-4ad3-b42c-152d1f8c7343.rpki-valid-beacon.meerval.net/valid.json",
            "addressFamily": 4
          },
          {
            "url": "https://038c8427-6c0e-4ad3-b42c-152d1f8c7343.rpki-invalid-beacon.meerval.net/invalid.json",
            "addressFamily": 4
          }
        ],
        "startDateTime": "2019-10-31T17:06:28.153Z",
        "originLocation": null,
        "userAgent": "rpki-web-test-0.0.1",
        "options": {
          "enrich": true,
          "invalidTimeout": 5000,
          "postResult": true
        }
      }
    },
    {
      "stage": "validReceived",
      "error": null,
      "data": {
        "ip": "83.160.104.137",
        "rpki-valid-passed": true,
        "duration": 562,
        "testUrl": "https://038c8427-6c0e-4ad3-b42c-152d1f8c7343.rpki-valid-beacon.meerval.net/valid.json",
        "addressFamily": 4
      },
      "success": true
    },
    {
      "stage": "invalidBlocked",
      "data": {
        "rpki-invalid-passed": false,
        "lastError": null,
        "duration": 5026,
        "testUrl": "https://038c8427-6c0e-4ad3-b42c-152d1f8c7343.rpki-invalid-beacon.meerval.net/invalid.json",
        "addressFamily": 4
      },
      "success": true,
      "error": null
    },
    {
      "stage": "enrichedReceived",
      "data": {
        "ip": "83.160.104.137",
        "asns": ["3265"],
        "prefix": "83.160.0.0/14",
        "enrichUrl": "https://stat.ripe.net/data/network-info/data.json?resource=83.160.104.137",
        "duration": 5420
      },
      "error": null,
      "success": true
    },
    {
      "stage": "resultPostedConfirmed",
      "error": null,
      "successs": true,
      "data": {
        "postUrl": "https://rpki-browser.webmeasurements.net/results/",
        "duration": 6262
      }
    },
    {
      "stage": "finished",
      "data": { "duration": 6262 },
      "error": null,
      "success": true
    }
  ]
}