Control Service

control is the SCION control service. It discovers SCION paths by participating in the inter-domain path-dissemination process called “beaconing”. It signs and validates the path information based on the Control-Plane PKI.

The control service is also the recursive resolver for path information for endpoints in the local AS.

In ASes with the CA role, the control service also acts as the certificate authority from which ASes in the local ISD request renewed certificates (or as a proxy thereof).

See Control Plane for an introduction to the SCION control plane and the tasks of the control service.

Command line reference


control [--config <config.toml> | help | version]


--config <config.toml>

Specifes the configuration file and starts the control service.

help, -h, --help [subcommand]

Display help text for subcommand.


Display version information.

sample [file]

Display sample files.


Display a sample configuration file.


Display a sample beaconing policy file

completion [shell]

Generate the autocompletion script for control for the specified shell.

Run control help completion for a list of the available shells.

Run control help completion [shell] for usage information on the autocomplete script for a particular shell.

Environment variables


For testing only.

Override the global duration for Dynamically Recreatable Key (DRKey) Infrastructure epochs. This can only work correctly if the same value is set for all connected control services in the test network.

Also applies to the router.






The control service is configured with multiple files:

Control service configuration

In addition to the common .toml configuration options, the control service considers the following options.

general = <string> (Required)

An identifier for this control service.

This is used to identify which parts of the topology.json file are refering to self. Thus, id must match a key in the topology.json files’ control_service section.

general.config_dir = <string> (Required)

Path to a directory containing the remaining configuration files.

If this is a relative path, it is interpreted as relative to the current working directory of the program (i.e. not relative to the location of this .toml configuration file).

general.reconnect_to_dispatcher = <bool> (Default: false)

Transparently reconnect to the dispatcher on dispatcher failure or restarts.


This should be set to true, unless your service orchestration ensures that failures of the dispatcher also trigger a restart of control.


Features is a container for generic, boolean feature flags (usually for experimental or transitional features).

features.appropriate_digest_algorithm = <bool> (Default: false)

Enables the CA module to sign issued certificates with the appropriate digest algorithm instead of always using ECDSAWithSHA512.

Transition: This behaviour should be enabled unless there is a specific requirement to interface with older versions of SCION that don’t support these certificates. The default for this flag will be changed to true in future releases, and the flag will eventually be removed.

api.addr = <string> (Optional)

Address at which to expose the REST API, in the form host:port, ip:port or :port.


Tracing with OpenTracing / Jaeger. This is especially helpful when collecting the traces of multiple service instances, e.g. when running a local SCION topology.

tracing.enabled = <bool> (Default = false)
tracing.debug = <bool> (Default = false)
tracing.agent = <string> (Default = "localhost:6831")

Address of the local agent that handles the reported traces.

quic.address = <ip:port> (Optional)

Local SCION address for inter-AS communication by QUIC/gRPC. By default, the address used is that specified for this control service in its control_service entry of the topology.json.

beaconing.origination_interval = <duration> (Default = "5s")

Specifies the interval between originating beacons in a core AS.

beaconing.propagation_interval = <duration> (Default = "5s")

Specifies the interval between propagating beacons.

beaconing.registration_interval = <duration> (Default = "5s")

Specifies the interval between registering path segments.


File paths for Beaconing policies. If these are the empty string, the default policy is used.

The different policies may point to the same file(s).

beaconing.policies.propagation = <string>
beaconing.policies.core_registration = <string>
beaconing.policies.up_registration = <string>
beaconing.policies.down_registration = <string>
beaconing.epic = <bool> (Default: false)

Specifies whether the EPIC authenticators should be added to the beacons.

path.query_interval = <duration> (Default = "5m")

Specifies after how much time path segments for a destination AS should be refetched.

path.hidden_paths_cfg = <string> (Optional)

Location of the hidden paths configuration.

The location is specified as a file path (relative to the working directory of the program) or an HTTP/HTTPS URL.

ca.mode = "disabled"|"in-process"|"delegating" (Default: "disabled")

Mode defines whether the control should handle certificate issuance requests. This should be enabled in core ASes that are labeled as issuing ASes in the TRC.

If set to in-process, control handles certificate issuance requests on its own. If set to delegating, the certificate issuance is delegated to the service defined in ca.service.

ca.max_as_validity = <duration> (Default: "3d")

Defines the the maximum lifetime for renewed AS certificates.


Configuration for the CA service, effective with the ca.mode mode delegating.

The CA service is expected to implement the API described by spec/ca.gen.yml.


The scionproto/scion project does not include such a standalone CA service implementation.

The available options are:

ca.service.address = <string>

Address of the CA Service that handles the delegated certificate renewal requests. Specified with scheme, for example https://ca-service.local, and optional path relative to the server, such as https://ca-service.local/dev-test.

ca.service.shared_secret = <string>

Path to the PEM-encoded shared secret that is used to create JWT tokens.

The shared secret file is re-read from disk at 5 second intervals.

ca.service.lifetime = <duration> (Default: "10m")

Validity period (a duration) of JWT authorization tokens for the CA service.

ca.service.client_id = <string> (Default:

Client identifier for the CA service. Defaults to

beacon_db (Required)

Database connection configuration for received PCBs.

This database holds beacons that may be candidates for propagation. If it is destroyed, the control service may temporarily not have beacons to propagate to downstream neighbor ASes, until fresh PCBs are received from upstream neighbor ASes.

trust_db (Required)

Database connection configuration for Control-Plane PKI information.

This database file contains cached TRC and AS certificate chains. If it is destroyed, the control service will load locally available TRCs and certificate chains from the corresponding configuration directory, and fetch other certificate information from authoritative ASes on-demand.

path_db (Required)

Database connection configuration for Path Segment data.

This database contains path segments, both explicitly registered segments resulting from the beaconing process, as well as cached results from path segment queries. If it is destroyed, the explicitly registered paths may be lost until they are rediscovered by the beaconing process. The path segments from cached path segment queries will be re-fetched on-demand.


Control the experimental in-memory caching of ISD/AS attribute information extracted from TRCs.

trustengine.cache.disable = <bool> (Default: false)

Disable caching entirely.

trustengine.cache.expiration = <duration> (Default: "1m")

Expiration time for cached entries.


Configuration for the optional and still somewhat experimental Dynamically Recreatable Key (DRKey) infrastructure.


drkey.level1_db (Optional)

Enables the DRKey infrastructure if set.

Database connection configuration for cached AS-AS (Level 1) keys.

If it is destroyed, the control service may need to re-fetch keys from remote ASes.


Required if drkey.level1_db is set.

Database connection configuration for key epochs and the corresponding secret values (Level 0 keys) derived from the AS master keys.


This database is not a cache.

If it is destroyed, the control service loses track of previously created key epochs. As key derivation depends on the epoch, keys that have previously been requested / derived, will not match any newly created keys. The DRKey system is broken for this AS, at least until all entities have fetched new keys, which may only happen after multiple epochs.

drkey.delegation = <map[protocol-id]: list[ip-address]> (Optional)

Defines hosts with privileged access to obtain the protocol and epoch specific secret value (Level 0 key). These hosts can locally derive keys shared with any remote AS, without having to request them individually from the control service. However, the hosts must be trusted to not abuse this, as they can also create keys to impersonate any other host in the AS.

The set of hosts authorized to access the secret value for delegated key derivation are specified as a list of IP addresses per supported DRKey protocol identifier.

# Example

scmp: ["", ""]
drkey.prefetch_entries = <number> (Default: 10000)

Maximum number of Level 1 keys that will be re-fetched preemptively before their expiration.


The control service reads the control_service section of the topology.json file.

The entry referring to its own define the addresses that control will listen on.

The interface definitions in the border_router entries define the inter-AS links. These entries define the beacons that control will originate and propagate.

Beaconing policies

A beaconing policy is a YAML file, defining processing rules for path-segment construction and registration. There are four policies with different but related purposes, that can individually be configured with the beacon.policies options:


Propagation is the process of receiving a beacon from a neighbor AS, extending it with one’s own AS entry and forwarding it to downstream neighbor ASes. See Path Exploration (Beaconing).

The propagation policy determines which beacons are selected to be propagated and how they are extended.

Note that there is no separate policy type for beacon origination. The only policy value affecting origination is the MaxExpTime, which is read from the propagation policy.


Registration is the process of making beacons available as path-segments to the path lookup process. Beacons received from a neighbor AS are “terminated” by appending the own AS entry and registered in a path-segment database, from which it can be later found with path-segment queries. See Registration of Path Segments.


Applies to the registration of core-segments in the local path store of a core AS.


Applies to the registration of up-segments in the local path store of a non-core AS.


Applies to the registration of down-segments. The policy is used by a non-core AS to determine which down-segments it wants to make available to other ASes. Each selected down-segments is registered, via a segment registration request, in the core AS that originated it.


There is currently no corresponding policy that applies to the processing of segment registration requests in the core AS.

From the description above, it is already evident that not all four policies are applicable for core and non-core ASes. Summarizing this:

AS type

Applicable policies


Propagation, CoreRegistration


Propagation, UpRegistration, DownRegistration

The beaconing policy YAML configuration considers the following options:

Type = "Propagation"|"UpSegmentRegistration"|"DownSegmentRegistration"|"CoreSegmentRegistration" (Default: "")

Restrict this policy configuration file to be used exclusively as one of the beacon.policies options.

Only as sanity check and organization of configuration files. No operational effect.

BestSetSize = int (Default: 20)

Maximum number of segments to propagate/register per origin AS.

In the Propagation policy, this parameter determines the number of beacons propagated to neighbor ASes per origin AS. That is, for each originating AS, up to BestSetSize beacons are forwarded. For the core-beaconing process, the set of originating ASes are all other core ASes, which can be very numerous.


Keep this parameter reasonably low to avoid an explosion of beacon numbers.

CandidateSetSize = int (Default: 100)

Maximum number of segments to keep in beacon store and consider for selection to best set per origin AS.

MaxExpTime = uint8 (Default: 63)

Defines the maximum relative expiration time for the AS Entry when originating, propagating or terminating a PCB.


For beacon origination, the MaxExpTime value from the Propagation policy is used.

The 8 bit unsigned integer ExpTime fields represents an expiration relative to the origination timestamp of the segment, with a nonzero minimum and a maximum of 24 hours:

\[(1 + ExpTime) \cdot \frac{24\cdot60\cdot60}{256}\mathrm{s}\]

Every increment of ExpTime represents 5 minute and 37.5 seconds in duration.


Duration (h:m:s)




















Filters restrict the allowed beacons for the purposes of the policy (i.e. for propagation or the different forms of registration).

Filters are applied when a beacon is received, resulting in a “usage” classification of the beacon that is stored in the local beacon database. Therefore, when the policy is changed, it will only be effective for newly received beacons.


Filters are currently not very expressive. Specifically, they cannot express filtering rules that take into account the ingress or egress interface of the beacon.

There are plans to extend this functionality but so far there are no concrete proposals. If you’re interested in working on this, get in contact in the chat or create a proposal on github.

MaxHopsLength = <int>

Upper bound for the allowed number of AS entries in a received PCB.

Filters are applied for received PCBs, before extending the segment. Consequently, a propagated/terminated PCB may have up to MaxHopsLength + 1 AS entries.

AsBlackList = <List[AS identifier]>

Deny-list for ASes. PCBs with any AS entry from any of the specified AS identifiers will be rejected.

IsdBlackList = <List[ISD identifier]>

Deny-list for ISDs. PCBs with any AS entry from any of the specified ISD identifiers will be rejected.

AllowIsdLoop = <bool> (Default: true)

Specifies whether ISD loops are allowed.

A PCB is considered to be an ISD loop if it leaves and then re-enters an ISD.

Control-Plane PKI



The TRCs for the Control-Plane PKI are loaded from here. TRCs are also written back to the trust_db.

Any TRC loaded from this directory will be written back to the trust_db. Updated TRCs fetched from authoritative core ASes are stored both here in the filesystem and in the trust_db.

control scans this directory for new TRCs at startup, and also when requesting signing keys and the corresponding certificate chains.


control does not create TRCs. TRC creation is an offline process, the TRC Signing Ceremony.

However, the control does fetch new TRCs from neighbor ASes and store them into this directory (<config_dir>/certs).

AS Certificates and Keys


AS certificate chains and the corresponding keys, used for signing control-plane messages and authenticating TLS sessions to other control services, are loaded from here. Certificates are also written back to the trust_db (but keys are not).

control scans this directory for new certificates at startup, and also when loading keys on demand.

Keys are loaded from this directory on demand, with an in-memory cache with a lifetime of 5 seconds.


control does not request renewal of its AS certificates.

Certificate renewal can be requested using the scion-pki certificate renew tool. Because AS certificates have short lifetimes, this should be automated by the operator.

CA Certificates and Keys


If the in-process CA is used, ca.mode = "in-process", the CA certificates and corresponding keys are read from this directory on demand, whenever a certificate renewal request is handled.


Even if it is operating with active CA mode, control does not issue initial certificates for new ASes. Issuance of initial AS certificates is an offline process. See AS Certificates.

The control service is not directly involved in the creation of TRCs and consequently it is not concerned with voting certificates.


control loads the forwarding secret keys master0.key/master1.key from <config_dir>/keys.

The key files contain a base64-encoded high-entropy random string. The keys should be exactly 16 bytes long (corresponding to a base64 encoding of 24 bytes with two trailing pad bytes ==). These keys must be identical to the corresponding keys used by the routers.


The router and Control Service currently use these keys as input for PBKDF2 to generate the actual forwarding key. Consequently, keys of any size can currently be used. This may be changed to only accept high-entropy 16 byte keys directly in the future.

Path Metadata

The StaticInfoExtension PCB extension allows to announce path metadata in beacons.

control loads the information for the StaticInfoExtension for its AS entries from the optional JSON configuration file <config_dir>/staticInfoConfig.json if it exists.

This configuration is optional. If the file does not exist, or if the configuration does not specify values for certain metadata types or for certain interfaces, the corresponding StaticInfoExtension will either be omitted or include only partial metadata.

If the configuration file exists, it must be syntactically valid.

The structure of the configuration is presented as pseudo-JSON with a more detailed explanation of the individual fields below.

Pseudo-JSON description of the structure of the staticInfoConfig.json configuration file.
   "Latency": {
      <interface-id>: {
         "Inter": <duration>,
         "Intra": {
            <interface-id>: <duration>
            # ...
      # ...
   "Bandwidth": {
      <interface-id>: {
         "Inter": <number>,
         "Intra": {
            <interface-id>: <number>
            # ...
      # ...
   "Geo": {
      <interface-id>: {
         "Latitude": <number>,
         "Longitude": <number>,
         "Address": <string>
      # ...
   "Linktype": {
      <interface-id>: <"direct"|"multihop"|"opennet">
      # ...
   "Hops": {
      <interface-id>: {
         "Intra": {
            <inteface-id>: <number>
            # ...
      # ...
   "Note": <string>

There is one top-level entry for each type of metadata, all of which are optional. Interface ID keys must be specified as strings (not numbers), e.g. "5".


Object where the keys are Interface ID i and the values are objects with:

Inter = <duration>

Latency from interface i to the associated remote AS border router.

Intra = <map[interface-id j]: duration>

Latency from interface i to interface j.


Object where the keys are Interface ID i and the values are objects with:

Inter = <number>

Bandwidth in Kbit/s between interface i and the associated remote AS border router.

Intra = <map[interface-id j]: duration>

Bandwidth in Kbit/s between interface i to interface j.


Object where the keys are Interface ID i and the values are objects with:

Latitude = <number

Longitude GPS coordinates of interface i.

Longitude = <number>

Latitude GPS coordinate of interface i.

address = <string>

Free-form civic address of interface i.


Object where the keys are Interface ID i and the values describe the link associated with interface i as one of:


Direct physical connection.


Connection with local routing/switching.


Connection overlayed over publicly routed Internet.


Object where the keys are Interface ID i and the values are objects with:

Intra = map[interface-id j]: number

Number of internal hops (e.g. number of AS-internal IP routers) between interface i and interface j.

Note = <string>

A free form string to communicate interesting/important information to other network operators.

Port table




Application protocol

Service resolution



Resolution protobufs

Control-plane (inter-AS)

Discovery API



QUIC + gRPC with HTTP/2

Control-plane (intra-AS)

Health API



gRPC with HTTP/2







The list of control service metrics is incomplete.


Renewal requests

Name: renewal_received_requests_total

Type: Counter

Description: Total number of certificate renewal requests served. Only for control services with CA functionality enabled.

Labels: result.

Renewal requests per handler type

Name: renewal_handled_requests_total

Type: Counter

Description: Total number of renewal requests served by each handler type (legacy, in-process, delegating).

Labels: type and result.


The sum of all renewal_handled_requests_total is not necessarily equal to the sum of all renewal_received_requests_total. This is because renewal_received_requests_total counts all incoming request and renewal_handled_requests_total only counts requests that could have been parsed and delegated to a handler.

Renewal request registered handlers

Name: renewal_registered_handlers

Type: Gauge

Description: Exposes which handler type (legacy, in-process, delegating) is registered.

Labels: type.

TRC local filesystem writes

Name: trustengine_trc_file_writes_total

Type: Counter

Description: Total number of TRC local filesystem write results. A result can be one of (ok_success, err_write, err_stat).

Labels: result.



Note that this ad hoc HTTP API is separate from the partially redundant REST API. The REST API should be preferred. This HTTP API will be phased out.

The HTTP API is exposed by the control application on the IP address and port of the metrics.prometheus configuration setting.

The HTTP API does not support user authentication or HTTPS. Applications will want to firewall this port or bind to a loopback address.

In addition to the common HTTP API, the control application supports the following API calls:

  • /topology (EXPERIMENTAL)

    • Method GET. Prints a JSON representation of current topology state, displayed in a format that is similar to the topology file. Note that there are slight differences between the output format and the topology file format, which means the output cannot be copy/pasted and used as a topology file.

  • /signer (EXPERIMENTAL)

    • Method GET. Prints JSON data about the Subject Key (i.e., the key used by the application to sign messages) and the TRC in use, in addition to other miscellaneous data that is relevant for signing. Private keys are not printed. Example output:

        "subject": {
          "isd_as": "1-ff00:0:110"
        "subject_key_id": "21 36 9B 82 D3 B9 90 58 16 D0 90 C0 15 66 C3 DC 0E 46 A5 9B",
        "expiration": "2021-09-28T13:19:16Z",
        "trc_id": {
          "isd": 1,
          "base_number": 1,
          "serial_number": 1
        "chain_validity": {
          "not_before": "2020-09-28T13:19:16Z",
          "not_after": "2021-09-28T13:19:16Z"
        "in_grace_period": false

For ASes that operate as CAs, the following API calls are also exposed:


    • Method GET. Prints JSON data about the Subject Key (i.e., the key used by the CA to sign certificates) and the CA policy. Example output:

        "subject": {
          "isd_as": "1-ff00:0:110"
        "subject_key_id": "8C 5A 07 FF 83 F7 C8 69 0A 28 01 4F CF 0F BF AB FF D5 E6 FF",
        "policy": {
          "chain_lifetime": "72h0m0s"
        "cert_validity": {
          "not_before": "2020-09-28T13:19:16Z",
          "not_after": "2022-09-28T13:19:16Z"


The REST API described by the OpenAPI specification spec/control.gen.yml is exposed by control on the address defined by api.addr.

Note that this is separate from the partially redundant, ad hoc HTTP API.



GET /segments

List the SCION path segments

List the SCION path segments that are known to the service. The results can be filtered by the start and end AS of the segment. Inspect the individual segments for a more detailed view.

Query Parameters:
  • start_isd_as (string) – Start ISD-AS of segment.

  • end_isd_as (string) – Terminal AS of segment.

Status Codes:
GET /segments/{segment-id}

Get the SCION path segment description

Get the description of a specific SCION path segment.

  • segment-id (string) –

Status Codes:
GET /segments/{segment-id}/blob

Get the SCION path segment blob

Get the SCION path segment encoded as PEM bytes blob.

  • segment-id (string) –

Status Codes:


GET /signer

Prints information about the AS Certificate used to sign the control-plane message.

Status Codes:
GET /signer/blob

Get the certificate chain blob

Get the certificate chain blob encoded as PEM.

Status Codes:
GET /ca

Information about the CA.

Status Codes:
GET /trcs

List the TRCs

List the latest SCION Trust Root Configurations for each ISD that are known to the control service. The result can be filtered by ISD. Optionally, all TRCs can be requested instead of only the latest ones.

Query Parameters:
  • isd (array) –

  • all (boolean) –

Status Codes:
GET /trcs/isd{isd}-b{base}-s{serial}

Get the TRC

Get the SCION Trust Root Configuration.

  • isd (integer) –

  • base (integer) –

  • serial (integer) –

Status Codes:
GET /trcs/isd{isd}-b{base}-s{serial}/blob

Get the TRC blob

Get the SCION Trust Root Configuration as PEM encoded byte blob.

  • isd (integer) –

  • base (integer) –

  • serial (integer) –

Status Codes:
GET /certificates

List the certificate chains

List the currently active certificate chains that are known to the control service. The result can be filtered by ISD-AS. Furthermore, one can pass a particular point in time at which the certificate chains are valid as input. A boolean can be provided to return all certificates, regardless of their period of vailidity.

Query Parameters:
  • isd_as (string) –

  • valid_at (string) –

  • all (boolean) –

Status Codes:
GET /certificates/{chain-id}

Get the certificate chain

Get the certificate chain for a given ChainID.

  • chain-id (string) –

Status Codes:
GET /certificates/{chain-id}/blob

Get the certificate chain blob

Get the certificate chain encoded as PEM bytes blob for a given ChainID.

  • chain-id (string) –

Status Codes:


GET /info

Basic information page about the control service process.

Status Codes:
GET /log/level

Get logging level

Status Codes:
PUT /log/level

Set logging level

Status Codes:
GET /config

Prints the TOML configuration file.

Status Codes:
GET /topology

Prints the contents of the AS topology file.

Status Codes:


GET /health

Indicate the service health.

Present the health of the service along with the executed health checks.

Status Codes:


GET /beacons

List the SCION beacons

List the SCION beacons that are known to the control service. The results can be filtered by the start AS, ingress interface and usage of the beacon. By default, all unexpired beacons are returned. This behavior can be changed with the all and valid_at parameters.

Query Parameters:
  • start_isd_as (string) – Start ISD-AS of beacons. The address can include wildcards (0) both for the ISD and AS identifier.

  • usages (array) – Minimum allowed usages of the returned beacons. Only beacons that are allowed in all the usages in the list will be returned.

  • ingress_interface (integer) – Ingress interface id.

  • valid_at (string) – Timestamp at which returned beacons are valid. If unset then the current datetime is used. This only has an effect if all=false.

  • all (boolean) – Include beacons regardless of expiration and creation time.

  • desc (boolean) – Whether to reverse the sort order (ascending by default).

  • sort (string) – Attribute by which results are sorted. The value start_isd_as refers to the ISD-AS identifier of the first hop.

Status Codes:
GET /beacons/{segment-id}

Get the SCION beacon description

Get the description of a specific SCION beacon.

  • segment-id (string) – The segment ID of the beacon segment. If the input value is shorter than a segment ID, but matches the prefix of the segment ID of exactly one beacon, then this beacon is returned.

Status Codes:
GET /beacons/{segment-id}/blob

Get the SCION beacon blob

Get the SCION beacon blob in PEM encoding.

  • segment-id (string) –

Status Codes: