DNP3 TLS Test Certificates

Generating a local CA chain for mutual TLS between an AnyLog DNP3 master and an outstation, for testing only


This page generates a small, local CA chain for mutual TLS between an AnyLog DNP3 master and an outstation — for example, opendnp3’s outstation-demo, configured for TLS. It produces a root CA plus one client certificate (the AnyLog master) and two server certificates (outstations), all signed by that CA.

For testing only. These are self-signed, lab-only credentials — do not reuse them in production, and do not commit the generated .cert/.key files to any repository. Run the script below in a working directory of your own, outside of version control, and regenerate a fresh chain whenever you need one.

Generating the chain

Save the following as create_certificates.sh in an empty working directory, then run bash create_certificates.sh. It has no dependencies beyond openssl.

#!/usr/bin/env bash
# Generate a small CA chain for DNP3 TLS lab tests (AnyLog master <-> outstation).
#
# Usage:
#   mkdir -p ~/dnp3-tls-test && cd ~/dnp3-tls-test
#   bash create_certificates.sh
#
# AnyLog master (TLS client):  anylogDNP3ca.cert, master1.cert, master1.key
# Outstation (TLS server):     anylogDNP3ca.cert, outstation1.cert, outstation1.key
#
set -euo pipefail
cd "$(dirname "$0")"

CA_CERT=anylogDNP3ca.cert
CA_KEY=anylogDNP3ca.key

echo "=== CA ==="
openssl req -x509 -new -nodes -newkey rsa:2048 \
  -keyout "${CA_KEY}" -sha256 -days 3600 -out "${CA_CERT}" \
  -subj "/C=US/ST=OR/L=Bend/O=AnyLog Certificate Corp"

echo "=== CSRs ==="
openssl req -newkey rsa:2048 -nodes -keyout master1.key -out master1.csr \
  -subj "/C=US/ST=OR/O=AnyLogDNP3/CN=master1"
openssl req -newkey rsa:2048 -nodes -keyout outstation1.key -out outstation1.csr \
  -subj "/C=US/ST=OR/O=AnyLogDNP3/CN=outstation1"
openssl req -newkey rsa:2048 -nodes -keyout outstation2.key -out outstation2.csr \
  -subj "/C=US/ST=OR/O=AnyLogDNP3/CN=outstation2"

echo "=== Signed certs ==="
openssl x509 -req -in master1.csr -CA "${CA_CERT}" -CAkey "${CA_KEY}" -CAcreateserial \
  -out master1.cert -days 3600 -sha256
openssl x509 -req -in outstation1.csr -CA "${CA_CERT}" -CAkey "${CA_KEY}" -CAcreateserial \
  -out outstation1.cert -days 3600 -sha256
openssl x509 -req -in outstation2.csr -CA "${CA_CERT}" -CAkey "${CA_KEY}" -CAcreateserial \
  -out outstation2.cert -days 3600 -sha256

rm -f master1.csr outstation1.csr outstation2.csr *.srl

echo "=== Verify chain ==="
openssl verify -CAfile "${CA_CERT}" master1.cert outstation1.cert outstation2.cert

echo "OK: certificates in $(pwd)"

This produces 8 files in your working directory:

File Role
anylogDNP3ca.cert / anylogDNP3ca.key Root CA
master1.cert / master1.key AnyLog master (TLS client)
outstation1.cert / outstation1.key Primary test outstation (TLS server)
outstation2.cert / outstation2.key Second outstation (optional)

The script’s own cleanup (rm -f ... *.srl) already removes the intermediate CSRs and OpenSSL’s serial file — so nothing but the certs and keys above is left behind, and there’s no separate .gitignore to maintain. If you do generate the chain inside a version-controlled directory for convenience, add *.cert, *.key, *.csr, and *.srl to that repo’s .gitignore before running the script.

Configuring the AnyLog master

Point the master’s TLS settings at your generated files (use the actual path to your working directory):

Keyword Path
tls_ca /path/to/your/working/dir/anylogDNP3ca.cert
tls_cert /path/to/your/working/dir/master1.cert
tls_key /path/to/your/working/dir/master1.key

Configuring the outstation (TLS server)

Setting File
Peer / CA anylogDNP3ca.cert
Local certificate outstation1.cert
Private key outstation1.key

With opendnp3 built at ~/opendnp3/build, after generating the chain:

cd ~/opendnp3/build
./outstation-tls-demo \
  /path/to/your/working/dir/anylogDNP3ca.cert \
  /path/to/your/working/dir/outstation1.cert \
  /path/to/your/working/dir/outstation1.key

Plain TCP, no TLS: run ./outstation-demo instead, from the same directory.

See also

  • DNP3 — the main DNP3 connector doc; this page is referenced from its outstation-testing section.