DNP3 TLS Setup Example

Full DNP3 mutual TLS walkthrough with AnyLog certificate commands — local CA, Operator client certs, outstation server certs, external org files, and optional Master/Operator remote signing.


Configure DNP3 TLS

Full worked example for securing AnyLog as a DNP3 master (TLS client) against an outstation (TLS server) using AnyLog id generate / id sign commands.

For OpenSSL-only lab files and opendnp3 demos, see DNP3 TLS Test Certificates. For the connector reference, see DNP3.

Roles (do not confuse):

Role Meaning
AnyLog Master node Network master — optional holder of the CA private key for remote signing
AnyLog Operator Runs run plc client / get dnp3 values as the DNP3 master (TLS client)
Outstation DNP3 device or demo (TLS server)

Local signing (CA key on the same node that signs) is enough for a single-node lab. Remote signing is optional — see Scenario: Master node + Operator with remote signing.

Create CA Authority for self-signed TLS certificates

<id generate certificate authority where country = US and
  state = CA and locality = "Redwood City" and
  org = AnyLogDNP3CA and
  output_name = "AnyLogDNP3CA" and
  expiration_days = 3650
>

Writes under !pem_dir: AnyLogDNP3CA.crt / AnyLogDNP3CA.key.

Create certificate request — AnyLog DNP3 master (TLS client)

On the Operator that will poll the outstation:

<id generate certificate request where country = US and state = CA and locality = "Redwood City"
  and org = "AnyLog DNP3 master"
  and hostname = master1
  and alt_name = 192.168.1.60
  and ip = 192.168.1.60 and
  output_name = "master1"
>

Sign certificate with above CA (local)

<id sign certificate request where ca_org = AnyLogDNP3CA and ca_output_name = "AnyLogDNP3CA"
  and server_org = "AnyLog DNP3 master" and output_name = "master1"
  and expiration_days = 3650
>

Writes under !pem_dir: master1.csr / .key / .pem, then master1.crt.

Create and sign outstation certificates (TLS servers)

<id generate certificate request where country = US and state = CA and locality = "Redwood City"
  and org = "AnyLog DNP3 outstation"
  and hostname = outstation1
  and alt_name = 192.168.1.70
  and ip = 192.168.1.70 and
  output_name = "outstation1"
>

<id sign certificate request where ca_org = AnyLogDNP3CA and ca_output_name = "AnyLogDNP3CA"
  and server_org = "AnyLog DNP3 outstation" and output_name = "outstation1"
  and expiration_days = 3650
>

<id generate certificate request where country = US and state = CA and locality = "Redwood City"
  and org = "AnyLog DNP3 outstation"
  and hostname = outstation2
  and alt_name = 192.168.1.71
  and ip = 192.168.1.71 and
  output_name = "outstation2"
>

<id sign certificate request where ca_org = AnyLogDNP3CA and ca_output_name = "AnyLogDNP3CA"
  and server_org = "AnyLog DNP3 outstation" and output_name = "outstation2"
  and expiration_days = 3650
>

Ship to each device owner (same CA public cert for both):

Outstation Ship
outstation1 outstation1.crt, outstation1.key, AnyLogDNP3CA.crt
outstation2 outstation2.crt, outstation2.key, AnyLogDNP3CA.crt

Do not ship AnyLogDNP3CA.key.

Connect AnyLog with the written certificates

Use the certificate files under !pem_dir (typically ./data/pem):

<get dnp3 values where
    hostname = 192.168.1.70 and
    port = 20001 and
    master_id = 1 and
    outstation_id = 10 and
    enable_tls = true and
    tls_ca = !pem_dir/AnyLogDNP3CA.crt and
    tls_cert = !pem_dir/master1.crt and
    tls_key = !pem_dir/master1.key and
    map = [{"name":"analog_0","type":"Analog","index":0}]
>

Continuous ingest:

<run plc client where type = dnp3 and
    hostname = 192.168.1.70 and
    port = 20001 and
    master_id = 1 and
    outstation_id = 10 and
    enable_tls = true and
    tls_ca = !pem_dir/AnyLogDNP3CA.crt and
    tls_cert = !pem_dir/master1.crt and
    tls_key = !pem_dir/master1.key and
    dbms = dnp3_db and
    table = dnp3_points and
    map = [{"name":"analog_0","type":"Analog","index":0},
           {"name":"binary_0","type":"Binary","index":0}]
>

All three of tls_ca, tls_cert, and tls_key are required when enable_tls = true.

Make use of existing certificate files, coming from an outside organization

If an outside organization already provides the DNP3 TLS material, place those files under !pem_dir (or another path). Use distinct names (for example an ext_ prefix) so they are not confused with certificates generated in the sections above:

Role Example files
Peer / CA ext_dnp3_ca.crt
AnyLog DNP3 master (client) cert / key ext_master1.crt / ext_master1.key
Outstation (server) cert / key ext_outstation1.crt / ext_outstation1.key (and optionally ext_outstation2.*)
<get dnp3 values where
    hostname = 127.0.0.1 and
    port = 20001 and
    master_id = 1 and
    outstation_id = 10 and
    enable_tls = true and
    tls_ca = !pem_dir/ext_dnp3_ca.crt and
    tls_cert = !pem_dir/ext_master1.crt and
    tls_key = !pem_dir/ext_master1.key and
    map = [{"name":"analog_0","type":"Analog","index":0}]
>

To generate OpenSSL-only lab files for opendnp3, see DNP3 TLS Test Certificates.

Scenario: Master node + Operator with remote signing

Remote signing is optional. Use it when the CA private key must stay on the AnyLog Master node. Background: Optional: remote signing with a master.

Operators do not get the CA private key (AnyLogDNP3CA.key). Copy the CA public cert from the Master for tls_ca.

Who Gets
Master Keeps AnyLogDNP3CA.key; creates CA and signs CSRs
Operator master1.crt / master1.key (remote sign) + copy of AnyLogDNP3CA.crt from Master
Device owner outstation*.crt / .key and AnyLogDNP3CA.crt

Topology

Node IP:port (example) Holds Does
Master 192.168.1.88:32048 AnyLogDNP3CA.key Creates CA; signs CSRs
Operator op1 192.168.1.60 master1.key Creates CSR; remote-signs; runs DNP3 client
Outstation outstation1 192.168.1.70:20001 outstation1.key TLS server for DNP3
Outstation outstation2 192.168.1.71:20001 outstation2.key Second TLS outstation (same CA)

On the Master — create CA once

<id generate certificate authority where country = US and
  state = CA and locality = "Redwood City" and
  org = AnyLogDNP3CA and
  output_name = "AnyLogDNP3CA" and
  expiration_days = 3650
>

Keep AnyLogDNP3CA.key on the Master only.

Create and sign the outstation certificates on the Master (local sign) — required when you use this CA for DNP3 TLS — then ship to each device owner: outstation*.crt / .key and AnyLogDNP3CA.crt. Do not ship AnyLogDNP3CA.key.

<id generate certificate request where country = US and state = CA and locality = "Redwood City"
  and org = "AnyLog DNP3 outstation"
  and hostname = outstation1
  and alt_name = 192.168.1.70
  and ip = 192.168.1.70 and
  output_name = "outstation1"
>

<id sign certificate request where ca_org = AnyLogDNP3CA and ca_output_name = "AnyLogDNP3CA"
  and server_org = "AnyLog DNP3 outstation" and output_name = "outstation1"
  and expiration_days = 3650
>

<id generate certificate request where country = US and state = CA and locality = "Redwood City"
  and org = "AnyLog DNP3 outstation"
  and hostname = outstation2
  and alt_name = 192.168.1.71
  and ip = 192.168.1.71 and
  output_name = "outstation2"
>

<id sign certificate request where ca_org = AnyLogDNP3CA and ca_output_name = "AnyLogDNP3CA"
  and server_org = "AnyLog DNP3 outstation" and output_name = "outstation2"
  and expiration_days = 3650
>

On the Operator — CSR + remote sign

set master_node = 192.168.1.88:32048

<id generate certificate request where country = US and state = CA and locality = "Redwood City"
  and org = "AnyLog DNP3 master"
  and hostname = master1
  and alt_name = 192.168.1.60
  and ip = 192.168.1.60 and
  output_name = "master1"
>

<id sign certificate request where ca_org = AnyLogDNP3CA and ca_output_name = "AnyLogDNP3CA"
  and server_org = "AnyLog DNP3 master" and output_name = "master1"
  and expiration_days = 3650
  and certificate_authority = !master_node
>

Result on the Operator: master1.crt under !pem_dir (with .csr / .key / .pem). The Operator never receives AnyLogDNP3CA.key.

On the Operator — copy CA public cert from Master

Copy AnyLogDNP3CA.crt from the Master’s !pem_dir into the Operator’s !pem_dir (for tls_ca). Do not copy AnyLogDNP3CA.key.

On the Operator — run DNP3 over TLS

<run plc client where type = dnp3 and
    hostname = 192.168.1.70 and
    port = 20001 and
    master_id = 1 and
    outstation_id = 10 and
    enable_tls = true and
    tls_ca = !pem_dir/AnyLogDNP3CA.crt and
    tls_cert = !pem_dir/master1.crt and
    tls_key = !pem_dir/master1.key and
    dbms = dnp3_db and
    table = dnp3_points and
    map = [{"name":"analog_0","type":"Analog","index":0}]
>

Additional Operators repeat the CSR + remote-sign steps with their own output_name (for example master2) and IP in alt_name / ip, and copy AnyLogDNP3CA.crt from the Master the same way.