Krill as a Trust Anchor
Krill can be set up to operate an RPKI Trust Anchor (TA). An RPKI TA serves as an entry point for RPKI validators. There are currently five globally used TAs operated by the five RIRs, where each RIR is responsible for IPv4, IPv6 and AS number resources that are allocated to them by IANA.
If you are not an RIR, then you will not need to run your own RPKI TA for normal RPKI operations. Instead, you would operate one or more RPKI CAs that get their IPv4, IPv6 and ASN number resources under one or more of the RIR operated TAs.
That said, some users may want to operate their own TA outside of the TAs provided by the RIRs for testing, study or research reasons. Or perhaps even to manage private use address space.
Furthermore, this documentation may be of interest to readers who simply wish to understand how Krill is used to operate a TA.
Overview
The Krill TA is logically separated into ‘Proxy’ and ‘Signer’ components which are associated with each other.
TA Online Host TA Disconnected Host
+---------------------------+ +--------------------+
| | | |
| krillc krillta proxy | | krillta signer |
| | | ^ | | ^ |
| +--> krill <--+ . | +---------.----------+
| . | .
+----------------------.----+ . offline
. . transport
+ . . . . . . . . . +
The TA Signer is responsible for generating and using the TA RPKI key. It
is designed to be operated using its own standalone command line tool
called krillta. For improved security this tool can be used on a
system that is kept disconnected from the network and offline when it is
not in use, and optionally an HSM could be used for handling the key.
The TA Proxy always lives inside Krill itself and is responsible for all online operations such as handling RFC 6492 communications with a child CA and publishing materials signed by the TA Signer using the RFC 8181 communication protocol with a Publication Server. The TA Proxy uses its own “identity” key and certificate for these protocols.
The TA Proxy is responsible for managing which child CA(s) can operate under the TA, and what resources they are entitled to. When the TA Proxy first receives an RFC 6492 request from a child it will reply with a dedicated not-performed-response (code 1104) indicating that the request is scheduled for processing. The child can (and does) keep sending the same request, and it will get a different dedicated not-performed-response (code 1101) indicating that the request was already scheduled.
Contrary to the other not-performed-responses these codes do not indicate that any error occurred. These codes exist to support the asynchronous signing by the offline TA Signer.
The actual signing process is initiated by the TA Proxy which generates a request for the signer through the CLI/API. The TA Signer then processes the request, does all the necessary signing and generates a response. This response is then given to the TA Proxy which will then publish any new signed objects. The TA Proxy will also keep the now completed response for the child CA, which will be returned the next time that the child CA sends their request to the TA Proxy.
Even though in principle there could be multiple child CAs under the TA Proxy our design is intended to use a single child CA only. Furthermore, theoretically, this child CA could access the TA Proxy from a remote system (another Krill or RPKI CA installation) - but at this time we only support a local Krill CA for this purpose.
One key advantage of this model is that it allows us to trigger a re-sync of the local CA child with its TA Proxy parent immediately after the latter processed the TA Signer response.
For now, we include all IPv4, IPv6 and AS number resources on the TA certificate, as well as the one immediate child CA. In future, we can add support for initialising a TA with a smaller set of resources, and changing that set of resources.
Set Up
At this time you can have only 1 Trust Anchor per Krill instance. We believe that there is not likely going to be a need for managing multiple TAs in a single installation.
Krillta Command Line Tool
A krillta command line tool is now available as a separate package.
It is not included in the main Krill package because it will likely only
be needed by a very small number of Krill users.
krillta can be used to manage both the TA Signer, in which case it
will expect to keep its state on a local disk, and the TA Proxy, in which
case it will connect to the Krill server in the same way that krillc
does.
The communication between the TA Proxy and Signer is done using signed CMS messages - much like the CMS used in RFC 6492 allowing both the TA Proxy and Signer to validate requests and responses. Furthermore, each request includes a nonce value that is expected to be repeated in the corresponding response. Nonce values may not be repeated. This helps to protect against replay attacks, although in practice it’s more likely to catch mistakes where the wrong request or response is used by accident.
Run Krill with TA Support
Set up an empty Krill installation following the normal installation
process. Add the following to your krill.conf files in addition to
any other set up that you need to do:
ta_support_enabled = true
Then run Krill as usual so that it can accessed by krillc, krillta
and the UI.
Optionally, timings can be adjusted by including the following snippet at
the end of your krill.conf:
[ta_timing]
certificate_validity_years = 100
issued_certificate_validity_weeks = 52
issued_certificate_reissue_weeks_before = 26
mft_next_update_weeks = 12
signed_message_validity_days = 14
Make sure that these timings match the ones in the configuration for your signer, as otherwise unexpected behaviour may occur.
Initialise TA Proxy
The first step in the actual set up of the Krill TA Signer and Proxy couple is to initialise the TA Proxy. This will create an empty TA Proxy that has an identity key for communication, and pretty much nothing else.
krillta proxy init
Initialise Publication Server
We recommend that you set up and use a Publication Server in the same Krill instance that hosts your TA Proxy, and online TA child for that matter, which we will get to in a bit.
The reason for this is that communication will be more efficient, and more importantly less error prone. I.e. it’s unlikely that the same Krill instance would work for the TA Proxy but refuse to work for its Publication Server.
The setup of a Krill Publication Server is described here.
TA Proxy Publisher Request
Get the TA Proxy RFC 8183 Publisher Request XML file and save it so it can be uploaded to the Publication Server:
krillta proxy repo request > ./pub-req.xml
Add TA Proxy as Publisher
Add the TA Proxy as a publisher and capture the RFC 8183 Repository Response XML:
krillc pubserver publishers add --request ./pub-req.xml >./repo-res.xml
Note
The Krill TA uses “ta” as its name (handle in RFC terms).
Krill Publication Servers normally add the handle name as a sub-dir
to the global base rsync path (sia_base in RFC terms). However,
if the handle is “ta”, then no sub-dir will be added. The reason is
that this way recursive rsync fetches for the TA certificate’s
publication point will get the full repository content in one go.
Configure Repository for TA Proxy
Now add the Publication Server (and its associated Repository) to the TA Proxy:
krillta proxy repo configure --response ./repo-res.xml
Configure the TA Signer
Create a working directory where your TA Signer can keep its state and
log file. Then create a configuration file. If you use /etc/krillta.conf
as the configuration file, then krillta will be able to find it
automatically, otherwise use -c /path/to/krillta.conf to override
this default.
The configuration file must at least contain a setting for the data directory. Other settings are optional - you only need to change them if you want to change the default logging and/or use an HSM.
Example configuration file:
######################################################################################
# #
# DATA #
# #
######################################################################################
# Specify the directory where the TA Signer will store its data.
data_dir = "/var/lib/krillta/data"
######################################################################################
# #
# LOGGING #
# #
######################################################################################
# Log level
#
# The maximum log level ("off", "error", "warn", "info", or "debug") for
# which to log messages.
#
# Defaults to "warn"
#
### log_level = "warn"
# Log type
#
# Where to log to. One of "stderr" for stderr, "syslog" for syslog, or "file"
# for a file in which case $data_dir/krillta.log will be used. This cannot (yet)
# be overridden.
#
# Defaults to "file"
#
### log_type = "file"
######################################################################################
# #
# SIGNER CONFIGURATION #
# #
######################################################################################
#
# By default OpenSSL is used for key generation and signing.
#
# But.. The usual Krill HSM support should also work in this context. If you want to
# use an HSM please read the documentation here:
# https://krill.docs.nlnetlabs.nl/en/stable/hsm.html
#
# Note that this configuration cannot be changed after the TA Signer has been
# initialised. Or rather.. where for normal Krill CAs defaults may be changed and
# key rolls can be used to start using a different signer, there is no key roll
# support for the TA. This may be implemented in future in which case we would
# also support RPKI Signed TALs for this process.
######################################################################################
# #
# TIMING #
# #
######################################################################################
#
# Include the following section '[timing_config]' if the default TA
# timing settings need to be changed.
#
# !!!!!IMPORTANT!!!!!!
#
# If you include this, make sure that both the TA signer and your Krill
# server where the TA Proxy lives use the same configuration.
#
[timing_config]
# The number of years the TA certificate is valid for. The TA certificate
# is only generated once, so set this value before initialising the TA.
#
### certificate_validity_years = 100,
# The validity time in weeks for certificates issued under the TA. Note
# that these certifcates get re-issued by request of the child before
# they would expire.
#
### issued_certificate_validity_weeks = 52
# The threshold in weeks before expiry of a current issued certificate
# used to determine when a new certificate should be requested.
# The hardcoded minimum is 10% more than the current expiration.
#
### issued_certificate_reissue_weeks_before = 26
# The time before the manifest and CRL expire for objects published by
# the TA. This determines the minimal re-signing frequency needed.
#
### mft_next_update_weeks = 12
# The validity time for signed messages between the online and offline
# TA components (TA Proxy and TA Signer). This determines how fast messages
# need to exchanged between the components.
#
# Note that there is replay protection in addition to this constraint, meaning
# that a message that has been previously processed cannot be applied again,
# even if it's still cryptographically valid.
#
### signed_message_validity_days = 14
Initialise the TA Signer
The TA Signer is always associated with a single TA Proxy. We initialised the TA Proxy and configured a repository for it in the earlier steps. We now need to export some of this information so that we can an initialise the one single TA Signer for that Proxy.
Step 1: Get the proxy ID
krillta proxy --format json id > ./proxy-id.json
Step 2: Get the proxy repo contact
krillta proxy --format json repo contact >./proxy-repo.json
Step 3: Initialise
Here you need to use the files saved in steps 1 and 2.
In addition to this you will need to specify the URIs that should be used on the Trust Anchor Locator (TAL). Of course that TA certificate does not yet exist - we need to know the URIs so it can be generated properly. You will be able to download the TA certificate at a later stage. For now, make sure that you choose URIs (rsync and HTTPS) where you will host a copy of that certificate later.
Note that TA certificate itself is not published using the RFC 8181 Publication Protocol. The Krill Publication Server expects that no other files are present in its RRDP and rsync directories besides except for the files published through this procotol.
For this reason you will need to use separate dedicated HTTPS and rsync endpoints for the TA certificate.
krillta signer init --proxy-id ./proxy-id.json \
--proxy-repository-contact ./proxy-repo.json \
--tal-https <HTTPS URI for TA cert on TAL> \
--tal-rsync <RSYNC URI for TA cert on TAL>
krillta signer init --proxy-id ./proxy-id.json \
--proxy-repository-contact ./proxy-repo.json \
--tal-https https://krillrepo.example.com/ta/ta.cer \
--tal-rsync rsync://krillrepo.example.com/ta/ta.cer
Associate the TA Signer with the Proxy
Get the TA Signer ‘info’ JSON file and save it:
krillta signer --format json show > ./signer-info.json
Then ‘initialise’ the signer associated with the TA Proxy. (we should probably rename this to ‘associate’ instead):
krillta proxy signer init --info ./signer-info.json
At this point you should see that the TAL is available under the /ta/ta.tal
endpoint. It will include the HTTPS and rsync URIs that were specified
when the signer was initialised. You can download a copy of the TA
certificate under the /ta/ta.cer endpoint. Copy it, and place it
where your web server and rsync daemon can serve it.
You should also see that a manifest and CRL were published for your TA. These files should be published in your Publication Server’s base rsync directory. As explained above, the “ta” does not use a sub-dir.
Create Child CA under TA
As mentioned in the overview section we recommend creating a single child CA under the TA, with all resources. This will in effect be the acting “online” TA.
Step 1: Create the “online” CA
krillc add --ca online
Step 2: Add “online” as a child of “ta”
krillc --format json show --ca online >./online.json
krillta proxy children add --info ./online.json >./res.xml
Note
You can specify the address space (ASNs, IPv4, IPv6) covered by
your child CA using the followings parameters:
- --asn The ASN resources for the child [default: AS0-AS4294967295]
- --ipv4 The IPv4 resources for the child [default: 0.0.0.0/0]
- --ipv6 The IPv6 resources for the child [default: ::/0]
Step 3: Add “ta” as a parent of “online”
krillta proxy children response --child online >./res.xml
krillc parents add --ca online --parent ta --response ./res.xml
Step 4: Add “online” as a Publisher
krillc repo request --ca online > ./pub-req.xml
krillc pubserver publishers add --request ./pub-req.xml > ./repo-res.xml
krillc repo configure --ca online --response ./repo-res.xml
If you now look at your CA using krillc show --ca online you should
see that the parent ta was added, but no resources were received. Instead,
you will see that the CA online has a key in state “pending”.
There will also be a pending Certificate Sign Request (CSR) from online
to its parent ta. The CSR will be re-sent periodically, but online
will get a not-performed-response from ta with codes 1104 or 1101,
indicating that the CSR is received and is scheduled for signing. You may
see messages to this effect in the log - this is not alarming.
If you follow the exchange process described below then the TA Signer will
sign the certificate. Since the online CA lives in the same Krill
instance as the TA Proxy it will be made aware of this update immediately
and get its signed certificate without further delay.
Typical Proxy Signer Exchange
The typical exchange between the Proxy and Signer follows these steps:
Make the request in the Proxy
Download the Proxy request
Process the Proxy request
Save the Signer response
Upload the Signer response
Make a TA Proxy Request
krillta proxy signer make-request
*Note that the krillta subcommand combination proxy signer is
used for actions for the proxy relating to its associated signer.
It might be worth to force all CAs to ask their parents for updated certificates first. This can be done using:
krillc bulk refresh
Download the TA Proxy Request
krillta proxy --format json signer show-request > ./request.json
Note
the request JSON includes both a readable representation of the
request that is made by the proxy for the signer, and a
base64 encoded signed (CMS) object containing that same request. Any
attempt to tamper with the clear text part of the request, the
corresponding response for that matter, will result in a validation
failure and rejection.
Process TA Proxy Request
krillta signer process --request ./request.json
Save the TA Signer Response
krillta signer --format json last > ./response.json
Upload the Signer Response
krillta proxy signer process-response --response ./response.json
Reissuing TA Certificates
Reissue the signer. This takes the same arguments as init. Any changes to ta_timing are also reflected here:
krillta signer -c ta.conf reissue --proxy-id proxy-id.json \
--proxy-repository-contact proxy-request.json \
--tal-rsync rsync://abcd.example.org/ta/ta.tal \
...
Get the TA Signer ‘info’ JSON file and save it:
krillta signer -f json show > ./signer-info.json
Then ‘update’ the signer associated with the TA Proxy:
krillta proxy signer update --info ./signer-info.json
At this point you should see that both /ta/ta.tal and /ta/ta.cer are updated.
Auditing
You can review the exchanges seen by the TA Signer. The default output uses JSON and contains a lot of information. The text output is somewhat friendlier to the human eye:
krillta signer exchanges --format text