TLS – Sichere Client-Server-Kommunikation mit Hilfe von Zertifikaten oder PSK (Pre-Shared Key)

Dieses Beispiel zeigt, wie eine sichere Datenkommunikation mit Hilfe von TLS (Transport Layer Security) in einer TwinCAT IEC 61850 Client- und Server-Applikation realisiert werden kann. Das TLS-Protokoll erlaubt nur die Verschlüsselung der Client-Server-Kommunikation. Die GOOSE-Publisher/Subscriber-Daten können auf diese Weise nicht verschlüsselt werden. Wenn sie eine ältere Version des TwinCAT IEC 61850 Telecontrol Configurators verwenden, dann wird dort die TLS-Funktionalität möglicherweise noch nicht unterstützt. Um dieses Beispielprojekt fehlerfrei übersetzen und testen zu können benötigen Sie eine neuere Version des TF6510 IEC 61850 Telecontrol.

Systemvoraussetzung

TF6510 IEC 61850 Telecontrol v3.1.96.7 oder neuer

Download TwinCAT XAE Project (*.zip): Sample30.zip

Allgemeine Information zu diesem Beispielprojekt

Das TLS-Beispiel besteht aus zwei separaten TwinCAT IEC 61850 Projekten. Nach dem Auspacken des Zip-Archives finden Sie im Unterordner \ClientWithTLS\Sample30 ein TwinCAT IEC 61850 Client-Projekt und im Unterordner \ServerWithTLS\Sample30 ein TwinCAT IEC 61850 Server-Projekt.

Das hier beschriebene: Client – Basis Beispielprojekt und hier beschriebene: Server – Basis Beispielprojekt dienten als Grundlage für das TLS-Beispielprojekt.

Dieses Beispiel zeigt hauptsächlich zwei Möglichkeiten der TLS-Datenverschlüsselung:

  1. TLS mit Zertifikaten (z. B.: eigene, selbstsignierte Zertifikate).
  2. TLS mit PSK (Pre-Shared Key).

Jedes TwinCAT IEC 61850 Client-/Server-Projekt kann auf relativ einfache Weise um die TLS-Funktionalität erweitert werden. Damit die Verschlüsselung/Entschlüsselung der Daten auf beiden Seiten funktioniert, muss dies auch logischerweise auf beiden Seiten, beim Client und beim Server erfolgen. Diese Erweiterung besteht hauptsächlich aus der Konfiguration der privaten Schlüssel (Private-Keys), Passwörter, Zertifikate oder der PSK-Schlüssel. Bei der Konfiguration der privaten Schlüssel und Zertifikate werden z.B. dem Server- bzw. Client-Funktionsbaustein die Dateipfade zu den Ordnern mitgeteilt, in denen die privaten Schlüsseldateien und Zertifikate abgelegt wurden. Die benötigten TLS-Konfigurationsparameter werden dabei vorher in einer dafür vorgesehenen Funktionsbausteininstanz vom Typ: FB_SocketTlsSettingsClass gespeichert. Die Übergabe dieser Information an die IEC 61850 Client/Server-Funktionsbausteine erfolgt über eine definierte Schnittstelle vom Typ I_SocketTlsSettingsClass, welche der FB_SocketTlsSettingsClass-Funktionsbaustein implementiert. Die IEC 61850 Server- und Client-Funktionsbausteine greifen während der Verbindungsherstellung über diese Schnittstelle auf die gespeicherte TLS-Konfiguration und damit auch auf die privaten Schlüssel-, Zertifikatdateien zu. Beim Erfolg wird eine sichere Kommunikationsverbindung hergestellt.

Format der Private-Keys und Zertifikate

Die Zertifikatdateien müssen im PEM-Format (Privacy-Enhanced Mail) vorliegen. Damit der Client oder Server auf die Schlüssel- und Zertifikatdateien problemlos zugreifen kann, wird für die Dateien als Ablageort z.B. folgender Ordner auf dem Windows-Zielsystem empfohlen: \TwinCAT\3.1\Target\Certificates\IEC61850.

Bei den privaten Schlüsseldateien und Zertifikatdateien handelt es sich um Textdateien. Eine private Schlüsseldatei beginnt mit der Zeile:
„-----BEGIN PRIVATE KEY-----“.
Danach folgt der Schlüssel und endet mit der Zeile:
„-----END PRIVATE KEY-----".
Beispiel:

-----BEGIN PRIVATE KEY-----
MIIEzAIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDIx4bVTxEHDhuKWl0XJAkLZfqj
NvMkD26sv/VViprpeMCbU/fSun+2oJO1iczd7Ut66SQBBePxsFEQhfAhO0TaGDDrfF9WP7WbkGb7
...
V0um2x+kKJ8hsD9vfORBf7KnwJi0QitwG41PoGDUi6RD8IUybKbLc5a/hx1C5hR0TBnXuxpguzed
pq0NPKFQk7d0ArahQPrYmUySyfagDTALBgNVHQ8xBAMCAJA=
-----END PRIVATE KEY-----

Die Zertifikatdateien beginnen mit der Zeile:
-----BEGIN CERTIFICATE-----“.
Danach folgen die Zertifikatdaten und enden mit der Zeile:
-----END CERTIFICATE-----“.
Beispiel:

-----BEGIN CERTIFICATE-----
MIIDyDCCArCgAwIBAgIQRGxL9tvn64FPEmnMEI8FLjANBgkqhkiG9w0BAQsFADBl
MWMwYQYDVQQDDFpSb290IENBLE9VPVR3aW5DQVQsTz1CZWNraG9mZiBBdXRvbWF0
...
6D2L4WEjrzIMR07EWJC4JKvDqxiQMAHsUkpy4vS817ZBsuL0/M8EbG9sTdEGxZp
9+GR0Np4ku7TkdJ5
-----END CERTIFICATE-----

TLS-Beispielkonfiguration mit dem FB_IEDTLSecurity-Funktionsbaustein

Um die TLS-Konfiguration mit Hilfe des Funktionsbausteins FB_SocketTlsSettingsClass noch weiter vereinfachen zu können, wurde im „ClientWithTLS\Sample30“- und auch im „ServerWithTLS\Sample30“-Projekt, um den FB_SocketTlsSettingsClass-Funktionsbaustein ein weiterer Hilfs-Funktionsbaustein „FB_IEDTLSecurity“ implementiert.

Der „FB_IEDTLSecurity“ Funktionsbaustein besitzt nur noch eine Methode: „Enable“. Mit Hilfe der „Enable“-Methodenparameter kann die TLS-Konfiguration aktiviert/deaktiviert und die Art der TLS-Verschlüsselung in unserem Beispiel festgelegt werden.

METHOD FINAL Enable : I_SocketTlsSettingsClass
VAR_INPUT
    bEnable : BOOL;
    bPSK    : BOOL;
END_VAR

bEnable: Aktiviert/deaktiviert die TLS-Konfiguration. Bei „TRUE“ werden alle notwendigen TLS-Konfigurationseinstellungen in der lokalen Instanz „fbTls“ des FB_SocketTlsSettingsClass-Funktionsbausteins gespeichert. Die TLS-Konfiguration soll in diesem Fall aktiviert werden. Der Wert „FALSE“ deaktiviert die TLS-Konfiguration.

bPSK: Konfiguriert die Art der Verschlüsselung. Bei „TRUE“ wird eine sichere TLS-Verbindung durch Verwendung eines PSK (Pre-Shared Key) hergestellt. Bei „FALSE“ wird eine sichere TLS-Verbindung durch Austausch der Zertifikate hergestellt.

Rückgabeparameter: Wenn ein gültiger Schnittstellenzeiger auf die TLS-Konfigurationseinstellungen zurückgeliefert wird (Rückgabewert <> 0), dann soll eine sichere TLS-Client-Server-Verbindung hergestellt werden. Beim Rückgabewert Null soll eine herkömmliche Verbindung (ohne TLS) hergestellt werden.

Server TLS-Beispielkonfiguration

Die Implementierung der „FB_IEDTLSecurity.Enable“-Methode unterscheidet sich im Client und Server Projekten. Im Serverprojekt werden die Pfade der Zertifikate und der privaten Schlüssel des Servers und im Client-Projekt, die des Clients konfiguriert. Beim Root CA-Zertifikat handelt es sich auf beiden Seiten um das gleiche Zertifikat. Das Root CA-Zertifikat muss auf beiden Systemen vorhanden sein.

VAR
    key       : ARRAY[0..14] OF BYTE:=[16#1B,16#D0,16#6F,16#D2,16#56,16#16,16#7D,16#C1,16#E8,16#C7,16#48,16#2A,16#8E,16#F5,16#FF];
    sIdentity : STRING(TCPADS_TLS_PSK_IDENTITY_SIZE)    :='MyIdentity';
    sCaPath   : STRING(TCPADS_TLS_CERTIFICATE_PATH_SIZE):='C:\TwinCAT\3.1\Target\Certificates\IEC61850\rootCA.pem';
    sCertPath : STRING(TCPADS_TLS_CERTIFICATE_PATH_SIZE):='C:\TwinCAT\3.1\Target\Certificates\IEC61850\127.0.0.1.pem';
    sKeyPath  : STRING(TCPADS_TLS_CERTIFICATE_PATH_SIZE):='C:\TwinCAT\3.1\Target\Certificates\IEC61850\127.0.0.1.key';
    sKeyPwd   : STRING(TCPADS_TLS_KEY_PASSWORD_SIZE)    :='ServerPass';
    sCrlPath  : STRING(TCPADS_TLS_CERTIFICATE_PATH_SIZE):='';
    flags     : ST_TlsListenFlags :=DEFAULT_TLSLISTENFLAGS;
END_VAR
IF bEnable THEN
    Enable:=fbTls.Reset();
    IF bPSK THEN
        fbTls.AddPsk(key:=key, sIdentity:=sIdentity);
    ELSE
        fbTls.AddCa(sCaPath:=sCaPath);
        fbTls.AddCert(sCertPath:=sCertPath, sKeyPath:=sKeyPath, sKeyPwd:=sKeyPwd);
        IF sCrlPath <> '' THEN
            fbTls.AddCrl(sCrlPath:=sCrlPath);
        END_IF
        fbTls.SetListenFlags(flags:=flags);
    END_IF
END_IF

Client TLS-Beispielkonfiguration

VAR
    key       : ARRAY[0..14] OF BYTE:=[16#1B,16#D0,16#6F,16#D2,16#56,16#16,16#7D,16#C1,16#E8,16#C7,16#48,16#2A,16#8E,16#F5,16#FF];
    sIdentity : STRING(TCPADS_TLS_PSK_IDENTITY_SIZE)    :='MyIdentity';
    sCaPath   : STRING(TCPADS_TLS_CERTIFICATE_PATH_SIZE):='C:\TwinCAT\3.1\Target\Certificates\IEC61850\rootCA.pem';
    sCertPath : STRING(TCPADS_TLS_CERTIFICATE_PATH_SIZE):='C:\TwinCAT\3.1\Target\Certificates\IEC61850\client.pem';
    sKeyPath  : STRING(TCPADS_TLS_CERTIFICATE_PATH_SIZE):='C:\TwinCAT\3.1\Target\Certificates\IEC61850\client.key';
    sKeyPwd   : STRING(TCPADS_TLS_KEY_PASSWORD_SIZE)    :='ClientPass';
    sCrlPath  : STRING(TCPADS_TLS_CERTIFICATE_PATH_SIZE):='';
    flags     : ST_TlsConnectFlags :=DEFAULT_TLSCONNECTFLAGS;
END_VAR
IF bEnable THEN
    Enable:=fbTls.Reset();
    IF bPSK THEN
        fbTls.AddPsk(key:=key, sIdentity:=sIdentity);
    ELSE
        fbTls.AddCa(sCaPath:=sCaPath);
        fbTls.AddCert(sCertPath:=sCertPath, sKeyPath:=sKeyPath, sKeyPwd:=sKeyPwd);
        IF sCrlPath <> '' THEN
            fbTls.AddCrl(sCrlPath:=sCrlPath);
        END_IF
        fbTls.SetConnectFlags(flags:=flags);
    END_IF
END_IF

Initialisierung der TLS-Konfiguration im IEC 61850 Server oder Client

Der „FB_IEDTLSecurity“-Funktionsbaustein wird in der globalen Variablenliste „TcTelecontrol“ instanziiert. Die Übergabe der TLS-Konfigurationseinstellungen an den IEC 61850 Server oder Client erfolgt durch das Setzen der „ipTLS“-Eigenschaft in den Server- oder Client-Protokolleinstellungen. Durch die Zuweisung eines gültigen Schnittstellenzeigers der „ipTLS“-Eigenschaft, werden die TLS-Konfigurationseinstellungen und damit die TLS-Verschlüsselung aktiviert. Durch die Zuweisung einer Null der „ipTLS“-Eigenschaft, wird die TLS-Konfiguration und die Verschlüsselung deaktiviert. In diesem Beispiel nutzen wir den Rückgabewert der „Enable“-Methode, um die TLS-Verschlüsselung zu aktivieren (Rückgabewert <> Null) oder zu deaktivieren (Rückgabewert = Null). Der Rückgabewert der „Enable“-Methode ist immer Null, wenn der „bEnable“-Methodenparameter „FALSE“ ist.

Setzen der Server TLS-Konfiguration

Der Server in diesem Beispiel besitzt die IP-Adresse: „127.0.0.1“. Diese Adresse muss eventuell angepasst werden.

VAR_GLOBAL

    fbIEDTLSecurity: FB_IEDTLSecurity;
    fbIEDServer: FB_iec61850ServerClass := (ipIED:=fbIED, settings:=(bEnable:=TRUE, sLocalHost:='127.0.0.1', ipTLS:=fbIEDTLSecurity.Enable(bEnable:=TRUE, bPSK:=TRUE)));

END_VAR

Setzen der Client TLS-Konfiguration

Der Client in diesem Beispiel verbindet sich mit einem Server mit der IP-Adresse: „127.0.0.1“. Auch diese Adresse muss eventuell angepasst werden.

VAR_GLOBAL

    fbIEDTLSecurity: FB_IEDTLSecurity;
    fbIEDClient: FB_IEDClient := (fbConnection:=(ipIED:=fbIED, settings:=(sRemoteHost:='127.0.0.1', ipTLS:=fbIEDTLSecurity.Enable(bEnable:=TRUE, bPSK:=TRUE))));

END_VAR

Besonderheiten des Server-Zertifikats

Bei der TLS-Datenverschlüsselung mit Zertifikaten wird der Host-Name oder die IP-Adresse des Servers entweder als „CommonName“- oder als „Subject Alternative Name“-Parameter im Zertifikat konfiguriert. D.h. wenn Sie in diesem Beispiel die IP-Adressen angepasst haben und die TLS-Verschlüsselung mit Zertifikaten testen wollen dann müssen Sie auch den „CommonName“ oder den „Subject Alternative Name“ in Ihrem Zertifikat entsprechend setzen. Zum Testen können selbstsignierte Zertifikate verwendet werden. Solche Zertifikate können z. B. unter Windows mit einem Power Shell-Skript erstellt werden. Unter Windows kann der „CommonName“ oder der „Subject Alternative Name“ relativ einfach überprüft werden.

Beispielzertifikat mit „CommonName“='192.168.10.160':

TLS – Sichere Client-Server-Kommunikation mit Hilfe von Zertifikaten oder PSK (Pre-Shared Key) 1:

Beispielzertifikat mit „Subject Alternative Name“ = '127.0.0.1':

TLS – Sichere Client-Server-Kommunikation mit Hilfe von Zertifikaten oder PSK (Pre-Shared Key) 2:

Sicherer ISO TP0 Port

Es wird empfohlen, bei aktiven TLS-Kommunikation die von IANA festgelegte (Secure ISO TP0) Portnummer zu verwenden (Standardwert: 3782). Über die Eigenschaft „FB_SocketTlsSettingsClass.nSecurePort“ kann diese Portnummer (für den Server und Client) auf einen anderen Wert umkonfiguriert werden. In unserer Implementierung wird diese Portnummer automatisch verwendet, sobald die TLS-Konfiguration durch das Setzen der „ipTLS“-Eigenschaft im IEC 61850 Client- oder Server-Funktionsbaustein aktiviert wurde. Wenn keine TLS-Konfiguration aktiv ist dann wird beim Server die Portnummer: „fbIEDServer.settings.nLocalPort“ und beim Client die Portnummer: „fbIEDClient.fbConnection.settings.nRemotePort“ verwendet (Standardwert: 102).

Test der sicheren TLS-Verbindung mit PSK

In beiden, Client/Server-Beispielprojekten ist standardmäßig TLS mit PSK (Pre-Shared Key) konfiguriert und aktiviert. Für TLS mit PSK werden keine Zertifikate benötigt. Für einen einfachen Funktionstest müssen nur die IP-Adressen in beiden Projekten angepasst werden.

Test der sicheren TLS-Verbindung mit Zertifikaten

Falls Sie TLS mit Zertifikaten testen möchten, dann kopieren Sie zuerst die Zertifikate und private Schlüssel auf das Server- und Client-Zielsystem.

Server-Zielsystem:

Client-Zielsystem:

Bei den oberen Dateinamen handelt es sich nur um Beispielnamen. Sie können die Pfade und Dateinamen in der „Enable“-Methode des „FB_IEDTLSecurity“-Funktionsbausteins anpassen. Um die TLS-Konfiguration mit Zertifikaten zu aktivieren, muss der „bPSK“-Parameter in der „FB_IEDTLSecurity.Enable“-Methode auf „FALSE“ gesetzt werden.

TLS mit Zertifikat im Server-Projekt aktivieren:

VAR_GLOBAL

fbIEDServer: FB_iec61850ServerClass := (ipIED:=fbIED, settings:=(bEnable:=TRUE, sLocalHost:='192.168.10.141', ipTLS:=fbIEDTLSecurity.Enable(bEnable:=TRUE, bPSK:=FALSE)));

END_VAR

TLS mit Zertifikat im Client-Projekt aktivieren:

VAR_GLOBAL

fbIEDClient: FB_IEDClient := (fbConnection:=(ipIED:=fbIED, settings:=(sRemoteHost:='192.168.10.141', ipTLS:=fbIEDTLSecurity.Enable(bEnable:=TRUE, bPSK:=FALSE))));

END_VAR