fort(8)

NAME
fort - RPKI certificate path validator

SYNOPSIS
fort [OPTIONS]

DESCRIPTION
FORT is an RPKI validator and a RTR server (RTR versions 0 and 1 are supported). In the RPKI context, FORT is also known as an RP (Relying Party). A simple resume of the actions performed by an RP can be read at RFC 6480 section 6 (https://tools.ietf.org/html/rfc6480#section-6).

The RTR (RPKI to Router Protocol) is basically "a protocol to deliver validated prefix origin data to routers", see RFC 6810 (https://tools.ietf.org/html/rfc6810) and RFC 8210 (https://tools.ietf.org/html/rfc8210).

So, FORT performs RPKI validations starting from a single or set of TALs (Trust Anchor Locators), either in a recurrent or single (standalone) way. Additionally, it can talk to routers using the RTR protocol (version will depend on the client, both 0 and 1 are supported) to provide them the VRPs (Validated ROA Payloads) and the BGPsec Router Keys resultant of the validation.

OPTIONS

-h, --help
    Print long usage message and exit.

--usage
    Print short usage message and exit.

-V, --version
    Print program version and exit.

-f, --configuration-file=FILE
    Path to a JSON file from where additional configuration will be read.

    The configuration options are mostly the same as the ones presented in this manual. Each property is mapped as a member of the main JSON object, the members that contain a dot '.' must be set as objects (eg. "--server.address=127.0.0.1" will be set as "{ "server": { "address": "127.0.0.1" } }".

    An example configuration file can be seen in this manual at the EXAMPLES section.

    Some configuration options can't be set at the JSON configuration file: --version, --help, --version, and --configuration-file.

    Other configuration options can be configured exclusively at the JSON configuration file:

    rsync.program
        Name of the program needed to invoke an rsync file transfer. The default value is "rsync".

    rsync.arguments-recursive
        Arguments needed by rsync.program to perform a recursive rsync. The arguments are specified as a JSON string array; its default value is: [ "--recursive", "--delete", "--times", "--contimeout=20", "$REMOTE", "$LOCAL" ]

        FORT will replace "$REMOTE" with the remote URL it needs to download, and "$LOCAL" with the target local directory where the file is supposed to be dropped.

        If rsync.program set is rsync (default value), see more about its arguments and behavior at rsync(1).

    rsync.arguments-flat
        Arguments needed by rsync.program to perform a single-file rsync. The arguments are specified as a JSON string array; its default value is: [ "--times", "--contimeout=20", "--dirs", "$REMOTE", "$LOCAL" ]

        FORT will replace "$REMOTE" with the remote URL it needs to download, and "$LOCAL" with the target local directory where the file is supposed to be dropped.

        If rsync.program set is rsync (default value), see more about its arguments and behavior at rsync(1).

    incidences
        A listing of actions to be performed by validation upon encountering certain common error conditions. This configuration is a means to modify FORTs validator behavior upon encountering profile violations that, from experience, are often overlooked.

        The incidences are configured inside the member "incidences" as a JSON array of objects, each with two members "name" and "action", eg:

        "incidences": [
            {
                "name": "incid-hashalg-has-params",
                "action": "warn"
            }
        ]

        An incidence contains a name and an action. The name is merely an identifier defined by FORT that states a particular error condition, and the action is an enumeration that states the outcome of a violation of the corresponding incidence.

        The action can have one of three values:
            error: Print error message in error log level, fail validation of the offending object (and all of its children).
            warn: Print error message in warning log level, continue validation as if nothing happened.
            ignore: Do not print error message, continue validation as if nothing happened.

        By default, all the incidences have an action of ignore. Currently there's only one registered incidence: incid-hashalg-has-params (Signed Object's hash algorithm has NULL object as parameters).

        More information about incidences can be consulted at FORT's web docs.

-t, --tal=(FILE|DIRECTORY)
    Path to the TAL file or directory the validation will sprawl from.

    If a DIRECTORY is specified, the files with the extension '.tal' are utilized by fort as TAL.

    The TAL ("Trust Anchor Locator") is a text file that lists a few URLs which can be used to access the "Trust Anchor" (the root of a particular RPKI tree) and its public key. (See RFC 7730.)

-r, --local-repository=DIRECTORY
    Path to a directory where the local cache of the repository will be stored and/or read.

    Right now, FORT accesses RPKI repositories by way of rsync. During each validation cycle, FORT will literally invoke an rsync command (see rsync.program and rsync.arguments-recursive), which will download the files into --local-repository. FORT’s validation operates on the resulting copy.

    Because rsync uses delta encoding, you’re advised to keep this cache around. It significantly speeds up subsequent validation cycles.

    By default, the path is /tmp/fort/repository.

--sync-strategy=(off|strict|root|root-except-ta)
    rsync download strategy; states the way rsync URLs are approached during downloads. It can have one of four values: off, strict, root(default value), root-except-ta.

    off
        Skip all RSYNCs. (Validate the existing cache repository pointed by --local-repository.)

    strict
        In order to enable this strategy, FORT must be compiled using the flag: ENABLE_STRICT_STRATEGY. e.g. $ make FORT_FLAGS='-DENABLE_STRICT_STRATEGY'

        RSYNC every repository publication point separately. Only skip publication points that have already been downloaded during the current validation cycle. (Assuming each synchronization is recursive.)

        For example, suppose the validator gets certificates whose caRepository access methods (in their Subject Information Access extensions) point to the following publication points:

        1. rsync://rpki.example.com/foo/bar/
        2. rsync://rpki.example.com/foo/qux/
        3. rsync://rpki.example.com/foo/bar/
        4. rsync://rpki.example.com/foo/corge/grault/
        5. rsync://rpki.example.com/foo/corge/
        6. rsync://rpki.example.com/foo/corge/waldo/

        A validator following the `strict` strategy would download `bar`, download `qux`, skip `bar`, download `corge/grault`, download `corge` and skip `corge/waldo`.

        This is the slowest, but also the strictly correct sync strategy.

    root
        For each publication point found, guess the root of its repository and RSYNC that instead. Then skip any subsequent children of said root.

        (To guess the root of a repository, the validator counts four slashes, and prunes the rest of the URL.)

        Reusing the caRepository URLs from the `strict` strategy (above) as example, a validator following the `root` strategy would download `rsync://rpki.example.com/foo`, and then skip everything else.

        Assuming that the repository is specifically structured to be found within as few roots as possible, and they contain minimal RPKI-unrelated noise files, this is the fastest synchronization strategy. At time of writing, this is true for all the current official repositories.

    root-except-ta
        Synchronizes the root certificate (the one pointed by the TAL) in 'strict' mode, and once it's validated, synchronizes the rest of the repository in 'root' mode.

        Useful if you want 'root', but the root certificate is separated from the rest of the repository. Also useful if you don't want the validator to download the entire repository without first confirming the integrity and legitimacy of the root certificate.

--shuffle-uris
    If enabled, FORT will access TAL URLs in random order. This is meant for load balancing. If disabled, FORT will access TAL URLs in sequential order.

    By default, the flag is disabled.

    This flag is only relevant if the TAL lists more than one URL. Regardless of this flag, FORT will stop iterating through the URLs as soon as it finds one that yields a successful traversal.

--maximum-certificate-depth=UNSIGNED_INTEGER
    Maximum allowable certificate chain length. Meant to protect FORT from iterating infinitely due to certificate chain loops.

    By default, it has a value of 32. The minimum allowed value is 5.

    (Required to prevent loops and "other degenerate forms of the logical RPKI hierarchy." (RFC 6481))

--slurm=(FILE|DIRECTORY)
    Path to the SLURM FILE or SLURMs DIRECTORY.

    In case a DIRECTORY is set, the files with extension '.slurm' will be the ones considered as SLURM files and FORT will use them.

    The SLURM definition is from RFC 8416. SLURM stands for "Simplified Local Internet Number Resource Management with the RPKI", basically is a document that can override (either as a filter or adding assertions) the global RPKI repository data fetched by FORT; potentially useful for network operators.

    A basic example of a SLURM file can be seen in this manual at the EXAMPLES section (it's almost the same as the one in RFC 8416).

    See more about SLURM configuration at FORT's web docs.

--mode=(server|standalone)
    Commands the way FORT executes the validation, its possible values are:

    server
        Enable the RTR server using the server.* arguments.

    standalone
        Disable the RTR server, the configuration options server.* are ignored and FORT performs an in-place standalone validation.

    By default, the mode is server.

--server.address=NODE
    Hostname or numeric host address the RTR server will be bound to. Must resolve to (or be) a bindable IP address. IPv4 and IPv6 are supported.

    If this field is omitted, FORT will attempt to bind the server using the IP address INADDR_ANY (for an IPv4 address) or IN6ADDR_ANY_INIT (for an IPv6 address). See getaddrinfo(3).

--server.port=SERVICE
    TCP port or service the server will be bound to.

    This is a string because a service alias can be used as a valid value. The alias are commonly located at /etc/services. See also getaddrinfo(3) and services(5).

    The default port (323) is privileged. To improve security, either change or jail it.

--server.backlog=UNSIGNED_INTEGER
    RTR server’s listen queue length. It’s the second argument of the function listen (see more at man listen(2)). This provides a hint to the implementation which the implementation shall use to limit the number of outstanding connections in the socket’s listen queue.

    By default, it has a value of SOMAXCONN.

--server.interval.validation=UNSIGNED_INTEGER
    Number of seconds that FORT will sleep between validation cycles. The timer starts counting every time a validation is finished, not every time it begins. Therefore, the actual validation loop is longer than this number.

    By default, it has a value of 3600.

--server.interval.refresh=UNSIGNED_INTEGER
    Number of seconds that a router should wait before the next attempt to poll FORT using either a Serial Query PDU or Reset Query PDU. Countdown for this timer starts upon receipt of an End Of Data PDU (this should be administered by the client).

    This value is utilized only on RTR version 1 sessions (more information at RFC 8210 section 6).

    By default, it has a value of 3600. Minimum allowed value: 1, maximum allowed value 86400.

--server.interval.retry=UNSIGNED_INTEGER
    Number of seconds that a router should wait before retrying a failed Serial Query PDU or Reset Query PDU. Countdown for this timer starts upon failure of the query and restarts after each subsequent failure until a query succeeds (this should be administered by the client).

    This value is utilized only on RTR version 1 sessions (more information at RFC 8210 section 6).

    By default, it has a value of 600. Minimum allowed value: 1, maximum allowed value 7200.

--server.interval.expire=UNSIGNED_INTEGER
    Number of seconds that a router can retain the current version of data while unable to perform a successful subsequent query. Countdown for this timer starts upon receipt of an End Of Data PDU (this should be administered by the client).

    This value is utilized only on RTR version 1 sessions (more information at RFC 8210 section 6).

    By default, it has a value of 7200. Minimum allowed value: 600, maximum allowed value 172800. It must be larger than server.interval.refresh and server.interval.retry.

-c, --log.color-output
    If enabled, the logging output will contain ANSI color codes. Meant for human consumption.

--log.file-name-format=(global-url|local-path|file-name)
    Decides which version of file names should be printed during most debug/error messages.

    Suppose a certificate was downloaded from `rsync://rpki.example.com/foo/bar/baz.cer` into the local cache `repository/`:

    global-url
        Will print the certificate's name as `rsync://rpki.example.com/foo/bar/baz.cer`.

    local-path
        Will print the certificate's name as `repository/rpki.example.com/foo/bar/baz.cer`.

    file-name
        Will print the certificate's name as `baz.cer`.

--output.roa=FILE
    File where the ROAs will be printed in CSV format.

    When the FILE is specified, its content will be overwritten by the resulting ROAs of the validation (if FILE doesn't exists, it'll be created).

    Each line of the result is printed in the following order: AS, Prefix, Max prefix length; the first line contains those column descriptors.

    In order to print the ROAs at console, use a hyphen as the FILE value, eg. --output.roa=-
--output.bgpsec=FILE
    File where the BGPsec Router Keys will be printed in CSV format. Since most of the data is binary (Subject Key Identifier and Subject Public Key Info), such data is base64url encoded without trailing pads.

    When the FILE is specified, its content will be overwritten by the resulting Router Keys of the validation (if FILE doesn't exists, it'll be created).

    Each line of the result is printed in the following order: AS, Subject Key Identifier, Subject Public Key Info; the first line contains those column descriptors.

    In order to print the Router Keys at console, use a hyphen as the FILE value, eg. --output.bgpsec=-

EXAMPLES
fort -t /tmp/tal -r /tmp/repository --server.port 9323
    Run FORT with all the default values, using a custom TALs directory, a custom repository directory as well, and binding the RTR server to port 9323.

fort -t /tmp/tal -r /tmp/repository --mode=standalone --output.roa -
    Run FORT as standalone and output ROAs CSV to the console.

fort -t /tmp/tal -r /tmp/repository \
     --mode=standalone \
     --slurm /tmp/myslurm.slurm
    Run FORT as standalone and using a SLURM file.

fort --configuration-file conf.json
    Run FORT using the JSON configuration file conf.json.

fort -t /tmp/tal -r /tmp/repository \
     --server.address ::1 --server.port 9323 \
     --server.interval.validation 1800 \
     --output.roa /tmp/roas.csv
    Run FORT with RTR server listening on IPv6 address ::1, port 9323, validating every 30 minutes, and printing the ROAs CSV in a file.

Complete configuration file
    This is an example of a valid JSON configuration file with all its members set to a specific value:
    {
      "tal": "/tmp/fort/tal/",
      "local-repository": "/tmp/fort/repository/",
      "sync-strategy": "root",
      "shuffle-uris": true,
      "maximum-certificate-depth": 32,
      "mode": "server",
      "slurm": "/tmp/fort/test.slurm",
      "server": {
        "address": "127.0.0.1",
        "port": "8323",
        "backlog": 64,
        "interval": {
          "validation": 3600,
          "refresh": 3600,
          "retry": 600,
          "expire": 7200
        }
      },
      "log": {
        "color-output": true,
        "file-name-format": "local-path"
      },
      "rsync": {
        "program": "rsync",
        "arguments-recursive": [
          "--recursive",
          "--delete",
          "--times",
          "--contimeout=20",
          "$REMOTE",
          "$LOCAL"
        ],
        "arguments-flat": [
          "--times",
          "--contimeout=20",
          "--dirs",
          "$REMOTE",
          "$LOCAL"
        ]
      },
      "incidences": [
        {
          "name": "incid-hashalg-has-params",
          "action": "ignore"
        }
      ],
      "output": {
        "roa": "/tmp/fort/roas.csv",
        "bgpsec": "/tmp/fort/bgpsec.csv"
      }
    }

Dummy SLURM file
    This is an example of a SLURM file with some prefix filters and assertions, as well as some dummy Router Keys (BGPsec) info:
    {
      "slurmVersion": 1,
      "validationOutputFilters": {
        "prefixFilters": [
          {
            "prefix": "192.0.2.0/24",
            "comment": "All VRPs encompassed by prefix"
          },
          {
            "asn": 64496,
            "comment": "All VRPs matching ASN"
          },
          {
            "prefix": "198.51.100.0/24",
            "asn": 64497,
            "comment": "All VRPs encompassed by prefix, matching ASN"
          }
        ],
        "bgpsecFilters": [
          {
            "asn": 64496,
            "comment": "All keys for ASN"
          },
          {
            "SKI": "Q8KMeBsCto1PJ6EuhowleIGNL7A",
            "comment": "Key matching Router SKI"
          },
          {
            "asn": 64497,
            "SKI": "g5RQYCnkMpDqEbt9WazTeB19nZs",
            "comment": "Key for ASN 64497 matching Router SKI"
          }
        ]
      },
      "locallyAddedAssertions": {
        "prefixAssertions": [
          {
            "asn": 64496,
            "prefix": "198.51.100.0/24",
            "comment": "My other important route"
          },
          {
            "asn": 64496,
            "prefix": "2001:DB8::/32",
            "maxPrefixLength": 48,
            "comment": "My other important de-aggregated routes"
          }
        ],
        "bgpsecAssertions": [
          {
            "asn": 64496,
            "SKI": "Dulqji-sUM5sX5M-3mqngKaFDjE",
            "routerPublicKey": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE-rkSLXlPpL_m-L7CfCfKrv1FHrM55FsIc8fMlnjHE6Y5nTuCn3UgWfCV6sYuGUZzPZ0Ey6AvezmfcELUB87eBA"
          }
        ]
      }
    }

SEE ALSO
Regular man pages
    getaddrinfo(3), services(5), listen(2), rsync(1)

FORTs official documentation
    More documentation about FORT validator can be consulted at github repository (https://github.com/NICMx/FORT-validator) and github website (https://nicmx.github.io/FORT-validator/)