# Clients absichern

> Anleitung: Den Client absichern: Endpunkt wählen, Serverzertifikate prüfen, das eigene Zertifikat schützen, Benutzer anmelden, Checkliste für den Betrieb.

**Beispielanwendungen:**

- Client.Authentication ([C#](https://github.com/Traeger-GmbH/opcuanet-samples/tree/master/cs/Basic/Client.Authentication), [VB.NET](https://github.com/Traeger-GmbH/opcuanet-samples/tree/master/vb/Basic/Client.Authentication)): Meldet sich mit Benutzername und Passwort am Server an und liest und schreibt einen Node.
- Server.Authentication ([C#](https://github.com/Traeger-GmbH/opcuanet-samples/tree/master/cs/Basic/Server.Authentication), [VB.NET](https://github.com/Traeger-GmbH/opcuanet-samples/tree/master/vb/Basic/Server.Authentication)): Lässt nur Benutzer zu, die mit Benutzername und Passwort angemeldet sind, und prüft sie über eine Zugriffsliste.

Diese Seite bündelt alle Einstellungen, mit denen ein Client seine Verbindungen zu einem Server absichert. Die Standardwerte des OPC UA .NET SDK sind auf einen einfachen Einstieg ausgelegt und für den Produktivbetrieb nicht geeignet. Welche Einstellungen Sie dafür ändern sollten, fasst der Abschnitt [Härtung für den Produktivbetrieb](https://www.traeger.de/docs/development/opcua/security/client#hartung-fur-den-produktivbetrieb) zusammen. Die Grundlagen beschreiben die Seiten [Zertifikate verstehen](https://www.traeger.de/docs/development/opcua/security/certificates) und [Benutzer und Rollen](https://www.traeger.de/docs/development/opcua/security/users-roles).

## Standardwerte im Überblick

Beteiligte Typen: `OpcClient`, `OpcClientSecurity`, `OpcCertificateStores`, `OpcCertificateSettings`, `OpcTransport`

| Einstellung | Standardwert | Empfehlung für den Produktivbetrieb |
|---|---|---|
| `Security.EndpointPolicy` | `null`: Der Client wählt den Endpunkt mit dem niedrigsten Level, in der Regel einen Endpunkt mit dem Modus `None` | Policy mit `SignAndEncrypt` und `Basic256Sha256`, `Aes128_Sha256_RsaOaep` oder `Aes256_Sha256_RsaPss` festlegen |
| `Security.UseOnlySecureEndpoints` | `false` | `true`, falls keine `EndpointPolicy` festgelegt ist |
| `Security.AutoUpgradeEndpointPolicy` | `false` | `true` zusammen mit einer `EndpointPolicy` |
| `Security.AutoAcceptUntrustedCertificates` | `true`: Der Client nimmt unbekannte Serverzertifikate an | `false`; Serverzertifikate vorab in den `TrustedPeerStore` aufnehmen |
| `Security.VerifyServersCertificateDomains` | `false` | `true` |
| `Security.CertificateValidationRules` | `Default`: Der Client nimmt mit SHA-1 signierte Zertifikate an, die rückwärtskompatible Prüfung ist aktiv | `RejectSHA1Signed` und `DisableBackwardsCompatibleValidation` |
| `CertificateStores.AutoCreateCertificate` | `true`: Fehlt ein Zertifikat, erzeugt der Client ein neues (bis Version 2.58 auch, wenn das vorhandene ungültig ist) | `false` und ein verwaltetes Zertifikat verwenden |
| Automatisch erzeugtes Zertifikat | selbstsigniert, Schlüssellänge 2048 Bit, gültig für 600 Monate | Zertifikat einer eigenen Zertifizierungsstelle mit einer Laufzeit nach Ihrer Richtlinie |
| `Security.UserIdentity` | `null`: anonyme Anmeldung | Benutzername-Passwort-Paar oder Zertifikat |
| `Transport` | `MaxMessageSize` 10 MB, `MaxByteStringLength` 5 MB, `MaxStringLength` und `MaxArrayLength` je 65535 | nur so weit erhöhen, wie die Anwendung es braucht |

> **Unsichere Standardwerte**
> Mit den Standardwerten verbindet sich der Client in der Regel unverschlüsselt und nimmt das Zertifikat jedes ihm unbekannten Servers an. Damit kann sich ein Angreifer im Netzwerk als Server ausgeben (engl. man in the middle), die übertragenen Daten mitlesen und verändern und an ihn übertragene Anmeldedaten erhalten. Ändern Sie diese Einstellungen vor dem Produktivbetrieb.

## Endpunkt sicher wählen

Beteiligte Typen: `OpcClient`, `OpcClientSecurity`, `OpcSecurityPolicy`, `OpcSecurityMode`, `OpcSecurityAlgorithm`, `OpcDiscoveryClient`, `OpcEndpointDescription`

Standardmäßig wählt der Client aus den angebotenen Serverendpunkten den mit der **einfachsten Sicherheitskonfiguration**, also den Endpunkt mit dem niedrigsten Level. Laut OPC Foundation ist das Level der Policy eines Endpunkts ein relatives Maß für die Sicherheitsmechanismen, die der Endpunkt verwendet. Per Definition ist damit ein Endpunkt mit einem höheren Level sicherer als ein Endpunkt mit einem niedrigeren Level. In der Regel wählt der Client so einen Endpunkt mit dem Modus `None`. Wenn der Server keinen solchen anbietet, wählt er einen Endpunkt mit `Sign` oder `SignAndEncrypt`.

**Nur verschlüsselte Endpunkte berücksichtigen**: Wenn der Client ausschließlich verschlüsselte Endpunkte berücksichtigen soll, setzen Sie die Eigenschaft `UseOnlySecureEndpoints` auf `true`. Der Client wählt dann nur Endpunkte mit dem Modus `SignAndEncrypt` (Enumeration `OpcSecurityMode`):

```csharp
client.Security.UseOnlySecureEndpoints = true;

```

```vbnet
client.Security.UseOnlySecureEndpoints = True

```

**Endpunkt mit dem höchsten Level wählen**: Wenn der Client den Endpunkt auswählen soll, der das höchste Policy-Level definiert, setzen Sie die Eigenschaft `UseHighLevelEndpoint` auf `true`:

```csharp
client.Security.UseHighLevelEndpoint = true;
```

```vbnet
client.Security.UseHighLevelEndpoint = True
```

**Bestimmte Sicherheitskonfiguration festlegen**: Wenn der Client einen Endpunkt mit einer bestimmten Sicherheitskonfiguration auswählen soll, legen Sie die Eigenschaft `EndpointPolicy` wie im folgenden Beispiel fest. Der Client verwendet dann nur einen Endpunkt mit genau diesem `OpcSecurityMode` und `OpcSecurityAlgorithm`. Wählen Sie einen aktuellen Algorithmus: `Basic128Rsa15` und `Basic256` gelten als veraltet, vorzuziehen sind zum Beispiel `Basic256Sha256`, `Aes128_Sha256_RsaOaep` oder `Aes256_Sha256_RsaPss`. Wenn Sie keinen Algorithmus angeben (`OpcSecurityAlgorithm.Auto`), verwendet der Client für `Sign` und `SignAndEncrypt` den Algorithmus `Basic256Sha256`. Mit einem Server, der nur `Basic256` oder `Basic128Rsa15` anbietet, verbindet er sich dann nicht. Die Eigenschaften `UseOnlySecureEndpoints` und `UseHighLevelEndpoint` berücksichtigt er dabei nicht:

```csharp
client.Security.EndpointPolicy = new OpcSecurityPolicy(
        OpcSecurityMode.SignAndEncrypt,
        OpcSecurityAlgorithm.Basic256Sha256);
```

```vbnet
client.Security.EndpointPolicy = New OpcSecurityPolicy( _
        OpcSecurityMode.SignAndEncrypt, _
        OpcSecurityAlgorithm.Basic256Sha256)
```

**Auf einen sichereren Endpunkt ausweichen**: Wenn der Client auf einen sichereren Endpunkt ausweichen soll, falls der Server die festgelegte Policy nicht anbietet, setzen Sie zusätzlich die Eigenschaft `AutoUpgradeEndpointPolicy` auf `true`. Welchen Endpunkt der Client nach dem Verbindungsaufbau tatsächlich verwendet, liefert die Eigenschaft `UsedEndpoint`:

```csharp
client.Security.EndpointPolicy = new OpcSecurityPolicy(
        OpcSecurityMode.SignAndEncrypt,
        OpcSecurityAlgorithm.Basic256Sha256);
 
// Use the next better endpoint in case the server does not offer the policy.
client.Security.AutoUpgradeEndpointPolicy = true;
 
client.Connect();
Console.WriteLine("Used endpoint: {0}", client.UsedEndpoint);
```

```vbnet
client.Security.EndpointPolicy = New OpcSecurityPolicy( _
        OpcSecurityMode.SignAndEncrypt, _
        OpcSecurityAlgorithm.Basic256Sha256)

'Use the next better endpoint in case the server does not offer the policy.
client.Security.AutoUpgradeEndpointPolicy = True

client.Connect()
Console.WriteLine("Used endpoint: {0}", client.UsedEndpoint)
```

Um die Endpunkte eines Servers zu untersuchen, verwenden Sie die Klasse `OpcDiscoveryClient`. Welche Arten von Benutzeridentitäten ein Endpunkt unterstützt, liefert die Eigenschaft `SupportedTokenTypes` der Endpunktbeschreibung:

```csharp
using (var client = new OpcDiscoveryClient("opc.tcp://localhost:4840/")) {
    var endpoints = client.DiscoverEndpoints();
 
    foreach (var endpoint in endpoints) {
        // Your code to operate on each endpoint.
    }
}

```

```vbnet
Using client As New OpcDiscoveryClient("opc.tcp://localhost:4840/")
    Dim endpoints = client.DiscoverEndpoints()
 
    For Each endpoint in endpoints
        'Your code to operate on each endpoint.
    Next
End Using

```

**Nach dem Verbindungsaufbau prüfen**: Prüfen Sie, ob der Client tatsächlich einen verschlüsselten Endpunkt verwendet. Das ist vor allem dann sinnvoll, wenn keine feste `EndpointPolicy` festgelegt ist:

```csharp
client.Connect();
 
if (client.UsedEndpoint.Policy.Mode != OpcSecurityMode.SignAndEncrypt) {
    client.Disconnect();
    throw new InvalidOperationException("The server offers no encrypted endpoint.");
}
```

```vbnet
client.Connect()

If client.UsedEndpoint.Policy.Mode <> OpcSecurityMode.SignAndEncrypt Then
    client.Disconnect()
    Throw New InvalidOperationException("The server offers no encrypted endpoint.")
End If
```

## Serverzertifikate prüfen und vertrauen

Beteiligte Typen: `OpcClient`, `OpcClientSecurity`, `OpcCertificateValidationFailedEventArgs`, `OpcCertificateValidationRules`, `OpcCertificateJudgementEventArgs`, `OpcCertificateImpeachment`, `OpcCertificateStores`, `OpcCertificateStoreInfo`

Ein Server sendet beim Verbindungsaufbau sein Zertifikat zur Authentifizierung an den Client. Anhand des Serverzertifikats entscheidet der Client, ob er wirklich eine Verbindung zu diesem Server aufbaut und ihm damit vertraut.

**Domänen im Zertifikat prüfen**: Die im Serverzertifikat hinterlegten Domänen prüft der Client zusätzlich, wenn Sie die Eigenschaft `VerifyServersCertificateDomains` aktivieren. Standardmäßig ist sie deaktiviert:

```csharp
client.Security.VerifyServersCertificateDomains = true;

```

```vbnet
client.Security.VerifyServersCertificateDomains = True

```

**Nur vertrauenswürdige Zertifikate akzeptieren**: Wenn der Client nur vertrauenswürdige Zertifikate akzeptieren soll, deaktivieren Sie die standardmäßige Akzeptanz unbekannter Zertifikate. Abgelaufene, gesperrte oder anderweitig ungültige Zertifikate nimmt der Client auch bei aktivierter Akzeptanz nicht automatisch an:

```csharp
client.Security.AutoAcceptUntrustedCertificates = false;

```

```vbnet
client.Security.AutoAcceptUntrustedCertificates = False

```

**Zertifikate selbst prüfen**: Sobald Sie die standardmäßige Akzeptanz unbekannter Zertifikate deaktiviert haben, sollten Sie eine benutzerdefinierte Prüfung der Zertifikate vorsehen:

```csharp
client.CertificateValidationFailed += HandleCertificateValidationFailed;
...
private void HandleCertificateValidationFailed(
        object sender,
        OpcCertificateValidationFailedEventArgs e)
{
    if (e.Certificate.Thumbprint == "...")
        e.Accept = true;
}

```

```vbnet
AddHandler client.CertificateValidationFailed, AddressOf HandleCertificateValidationFailed
...
Private Sub HandleCertificateValidationFailed( _
        ByVal sender As Object, _
        ByVal e As OpcCertificateValidationFailedEventArgs)
    If e.Certificate.Thumbprint = "..." Then
        e.Accept = True
    End If
End Sub

```

**Zertifikat manuell vertrauen**: Wenn der Client ein Serverzertifikat als nicht vertrauenswürdig eingestuft hat, können Sie es manuell als vertrauenswürdig deklarieren. Speichern Sie es dazu im `TrustedPeerStore`:

```csharp
// In context of the event handler the sender is an OpcClient.
var client = (OpcClient)sender;
 
if (!client.CertificateStores.TrustedPeerStore.Contains(e.Certificate))
    client.CertificateStores.TrustedPeerStore.Add(e.Certificate);

```

```vbnet
'In context of the event handler the sender is an OpcClient.
Dim client = CType(sender, OpcClient)
 
If Not client.CertificateStores.TrustedPeerStore.Contains(e.Certificate) Then
    client.CertificateStores.TrustedPeerStore.Add(e.Certificate)
End If

```

**Strengere Regeln zur Prüfung der Zertifikate** legt die Eigenschaft `CertificateValidationRules` fest. Mit `RejectSHA1Signed` lehnt der Client Zertifikate ab, die mit SHA-1 signiert wurden. Mit `DisableBackwardsCompatibleValidation` prüft er nach den aktuell empfohlenen Regeln. Standardmäßig sind beide Regeln deaktiviert:

```csharp
client.Security.CertificateValidationRules
        = OpcCertificateValidationRules.RejectSHA1Signed
        | OpcCertificateValidationRules.DisableBackwardsCompatibleValidation;
```

```vbnet
client.Security.CertificateValidationRules _
        = OpcCertificateValidationRules.RejectSHA1Signed _
        Or OpcCertificateValidationRules.DisableBackwardsCompatibleValidation
```

**Zertifikatswechsel behandeln**: Wenn der Server während einer bestehenden Verbindung ein anderes Zertifikat verwendet als beim Verbindungsaufbau, löst der Client das Ereignis `CertificateJudgement` aus. Ohne Behandlung führt diese Situation zu einer Ausnahme. Über die Eigenschaft `Dismiss` der Ereignisargumente können Sie die Beanstandung zurückweisen:

```csharp
client.CertificateJudgement += HandleCertificateJudgement;
...
private static void HandleCertificateJudgement(
        object sender,
        OpcCertificateJudgementEventArgs e)
{
    // The server uses a different certificate than when the connection was established.
    if (e.Impeachment == OpcCertificateImpeachment.Changed
            && e.ImpeachedCertificate.Thumbprint == "...")
        e.Dismiss = true;
}
```

```vbnet
AddHandler client.CertificateJudgement, AddressOf HandleCertificateJudgement
...
Private Shared Sub HandleCertificateJudgement( _
        ByVal sender As Object, _
        ByVal e As OpcCertificateJudgementEventArgs)
    'The server uses a different certificate than when the connection was established.
    If e.Impeachment = OpcCertificateImpeachment.Changed _
            AndAlso e.ImpeachedCertificate.Thumbprint = "..." Then
        e.Dismiss = True
    End If
End Sub
```

**Nur einen bestimmten Server zulassen**: Wenn der Client unbekannte Zertifikate nicht pauschal annehmen soll, Sie aber auch nicht jedes Zertifikat vorab im `TrustedPeerStore` hinterlegen möchten, kann der Client im Ereignis `CertificateValidationFailed` gezielt das Zertifikat des erwarteten Servers annehmen. Er erkennt es an seinem Fingerabdruck (engl. thumbprint). Die Eigenschaft `Result` nennt den Grund der Beanstandung. Nehmen Sie nur Zertifikate mit dem Ergebnis `Untrusted` an. Ergebnisse wie `Revoked`, `TimeInvalid`, `InvalidDomain` oder `ChainIncomplete` weisen auf ein gesperrtes, abgelaufenes, für einen anderen Rechner ausgestelltes oder nicht vollständig prüfbares Zertifikat hin:

```csharp
client.CertificateValidationFailed += HandleCertificateValidationFailed;
...
private void HandleCertificateValidationFailed(
        object sender,
        OpcCertificateValidationFailedEventArgs e)
{
    // Accept only the expected server, and only if its certificate is merely unknown.
    e.Accept = e.Result == OpcCertificateValidationResult.Untrusted
            && string.Equals(
                    e.Certificate.Thumbprint,
                    expectedThumbprint,
                    StringComparison.OrdinalIgnoreCase);
}
```

```vbnet
AddHandler client.CertificateValidationFailed, AddressOf HandleCertificateValidationFailed
...
Private Sub HandleCertificateValidationFailed( _
        ByVal sender As Object, _
        ByVal e As OpcCertificateValidationFailedEventArgs)
    'Accept only the expected server, and only if its certificate is merely unknown.
    e.Accept = e.Result = OpcCertificateValidationResult.Untrusted _
            AndAlso String.Equals( _
                    e.Certificate.Thumbprint, _
                    expectedThumbprint, _
                    StringComparison.OrdinalIgnoreCase)
End Sub

```

## Eigenes Zertifikat schützen

Beteiligte Typen: `OpcClient`, `OpcCertificateManager`, `OpcCertificateSettings`, `OpcCertificateStores`, `OpcCertificateRequestedEventArgs`

Wie ein Zertifikat geladen, erzeugt und gespeichert wird, beschreibt der Abschnitt [Anwendungszertifikat](https://www.traeger.de/docs/development/opcua/client/configuration#anwendungszertifikat). Für die Sicherheit sind dabei die folgenden Punkte wichtig.

**Eigenschaften des Zertifikats festlegen**: Ein vom SDK erzeugtes Zertifikat ist selbstsigniert, verwendet einen Schlüssel mit 2048 Bit und ist 600 Monate gültig. Schlüssellänge (`KeySize`) und Gültigkeit in Monaten (`Lifetime`) legen Sie über die Klasse `OpcCertificateSettings` fest. Für den Produktivbetrieb empfiehlt sich ein Zertifikat, das die Zertifizierungsstelle (engl. certificate authority) Ihres Unternehmens ausgestellt hat:

```csharp
// The key size is specified in bits, the lifetime in months.
var settings = new OpcCertificateSettings(client.ApplicationName) {
    KeySize = 4096,
    Lifetime = 24
};
 
client.Certificate = OpcCertificateManager.CreateCertificate(settings);
```

```vbnet
'The key size is specified in bits, the lifetime in months.
Dim settings = New OpcCertificateSettings(client.ApplicationName) With { _
    .KeySize = 4096, _
    .Lifetime = 24 _
}

client.Certificate = OpcCertificateManager.CreateCertificate(settings)
```

**Kein Zertifikat stillschweigend ersetzen**: Bis Version 2.58 gilt: Wenn die Eigenschaft `AutoCreateCertificate` aktiv ist und der Client beim Verbindungsaufbau kein gültiges Zertifikat findet, löscht er das bisherige Zertifikat aus dem `ApplicationStore` und erzeugt ein neues, selbstsigniertes Zertifikat. Das geschieht zum Beispiel, wenn das Zertifikat abgelaufen ist. Server, die dem bisherigen Zertifikat vertraut haben, lehnen den Client danach ab.

Ab Version 2.59 ersetzt der Client ein vorhandenes, aber ungültiges Zertifikat nie automatisch. Er löst stattdessen das Ereignis `CertificateRequested` aus. Die Eigenschaft `Reason` der Ereignisdaten nennt den Grund: `Invalid`, `UseNotAllowed`, `Revoked`, `TimeInvalid`, `IssuerUseNotAllowed`, `IssuerRevoked` oder `IssuerTimeInvalid`. Für ein abgelaufenes Zertifikat lautet er zum Beispiel `TimeInvalid`. Die Eigenschaft `AutoCreateCertificate` der Ereignisdaten ist dabei `false`. Wenn der Handler kein anderes Zertifikat bereitstellt, verwendet der Client weiter das vorhandene Zertifikat. Ein Zertifikat, das der Handler über die Eigenschaft `AlternativeCertificate` bereitstellt, verwendet der Client ab Version 2.59 beim Verbindungsaufbau, auch bei späteren Verbindungen. Es muss seinen privaten Schlüssel enthalten.

Stellen Sie über das Ereignis `CertificateRequested` selbst ein Zertifikat bereit und deaktivieren Sie die automatische Erzeugung:

```csharp
client.CertificateStores.AutoCreateCertificate = false;
client.CertificateRequested += HandleCertificateRequested;
...
private void HandleCertificateRequested(
        object sender,
        OpcCertificateRequestedEventArgs e)
{
    e.AlternativeCertificate = OpcCertificateManager.LoadCertificate(
            certificatePath,
            certificatePassword);
}
```

```vbnet
client.CertificateStores.AutoCreateCertificate = False
AddHandler client.CertificateRequested, AddressOf HandleCertificateRequested
...
Private Sub HandleCertificateRequested( _
        ByVal sender As Object, _
        ByVal e As OpcCertificateRequestedEventArgs)
    e.AlternativeCertificate = OpcCertificateManager.LoadCertificate( _
            certificatePath, _
            certificatePassword)
End Sub

```

**Den privaten Schlüssel schützen**: Der `ApplicationStore` enthält das Zertifikat samt privatem Schlüssel. Das SDK legt für die Dateien der Zertifikatspeicher keine Zugriffsrechte fest. Legen Sie die Zertifikatspeicher deshalb in einem Verzeichnis ab, auf das nur das Benutzerkonto der Anwendung zugreifen darf. Wie Sie die Zertifikatspeicher konfigurieren, beschreibt der Abschnitt [Anwendung und Sitzung konfigurieren](https://www.traeger.de/docs/development/opcua/client/configuration#anwendung-und-sitzung-konfigurieren). Laden Sie ein vorhandenes Zertifikat aus einer durch ein Passwort geschützten `.pfx`-Datei.

## Benutzer anmelden

Beteiligte Typen: `OpcClient`, `OpcUserIdentity`, `OpcClientIdentity`, `OpcCertificateIdentity`, `OpcClientSecurity`, `OpcCertificateStores`, `OpcCertificateStoreInfo`

Wenn ein Server zusätzlich zum Clientzertifikat Informationen über die Identität des Benutzers erwartet, legen Sie die Identität über die Eigenschaft `UserIdentity` fest. Zur Auswahl stehen Identitäten mit Benutzername und Passwort oder mit einem Zertifikat. Wenn der Server eine anonyme Benutzeridentität unterstützt, müssen Sie keine spezielle Identität festlegen.

**Benutzeridentität mit Benutzername und Passwort festlegen**:

```csharp
client.Security.UserIdentity = new OpcClientIdentity("userName", "password");

```

```vbnet
client.Security.UserIdentity = New OpcClientIdentity("userName", "password")

```

**Benutzeridentität mit Zertifikat (mit privatem Schlüssel) festlegen**:

```csharp
client.Security.UserIdentity = new OpcCertificateIdentity(new X509Certificate2("Doe.pfx"));

```

```vbnet
client.Security.UserIdentity = New OpcCertificateIdentity(New X509Certificate2("Doe.pfx"))

```

**Anonyme Benutzeridentität festlegen** (standardmäßig bereits so vorkonfiguriert):

```csharp
client.Security.UserIdentity = null;

```

```vbnet
client.Security.UserIdentity = Nothing

```

**Benutzeridentität im laufenden Betrieb wechseln**: Die Methode `ChangeUserIdentity` meldet an der bestehenden Sitzung einen anderen Benutzer an, ohne die Verbindung zu trennen. Mit `null` arbeitet der Client als anonymer Benutzer weiter. Wenn der Server die Identität ablehnt, löst die Methode eine `OpcException` mit dem Status des Servers aus, zum Beispiel `BadUserAccessDenied`. Die Sitzung und die bisherige Identität bleiben dann bestehen. Erst nach einem erfolgreichen Wechsel liefert die Eigenschaft `UserIdentity` die neue Identität. Wenn der Client nicht verbunden ist, löst die Methode eine `OpcException` mit dem Status `BadServerNotConnected` aus:

```csharp
client.ChangeUserIdentity(new OpcClientIdentity("userName", "password"));
```

```vbnet
client.ChangeUserIdentity(New OpcClientIdentity("userName", "password"))
```

**Übertragung des Passworts**: Das Passwort einer Benutzername-Passwort-Identität verschlüsselt der Client mit dem Zertifikat des Servers, sofern der Server für seine Benutzer-Token eine Sicherheitsstrategie angibt. Ein Server, der mit diesem SDK entwickelt ist, tut das auch an Endpunkten mit dem Modus `None`. Bei Servern anderer Hersteller kann das Passwort dort unverschlüsselt übertragen werden. Der Schutz ist zudem nur so viel wert wie die Prüfung des Serverzertifikats: Wenn der Client unbekannte Zertifikate automatisch annimmt, kann ein Angreifer, der sich als Server ausgibt, das Passwort entschlüsseln. Melden Sie Benutzer deshalb nur über Endpunkte mit dem Modus `SignAndEncrypt` an und deaktivieren Sie dafür die Eigenschaft `AutoAcceptUntrustedCertificates`. Hinterlegen Sie Passwörter nicht im Quelltext, sondern lesen Sie sie zur Laufzeit aus einem geschützten Speicher.

## Grenzen der Datenübertragung

Die Grenzen für die Größe von Nachrichten, Zeichenketten und Arrays schützen den Client auch vor übergroßen Antworten eines Servers. Erhöhen Sie sie nur so weit, wie es die Anwendung erfordert (siehe [Grenzen der Datenübertragung](https://www.traeger.de/docs/development/opcua/client/configuration#grenzen-der-datenubertragung)).

## OPC Classic und DCOM

Für Verbindungen zu OPC-Classic-Servern gelten die Sicherheitseinstellungen von DCOM. Wie Sie Anmeldung und Authentifizierungsstufe festlegen, beschreibt der Abschnitt [Entfernte Server und DCOM-Sicherheit](https://www.traeger.de/docs/development/opcua/client/opc-classic#entfernte-server-und-dcom-sicherheit) der Seite OPC Classic.

## Härtung für den Produktivbetrieb

Prüfen Sie vor dem Produktivbetrieb die folgenden Punkte:

1. **Verschlüsselten Endpunkt erzwingen**: `EndpointPolicy` mit `SignAndEncrypt` und einem aktuellen Algorithmus festlegen oder `UseOnlySecureEndpoints` aktivieren und den verwendeten Endpunkt prüfen (siehe [Endpunkt sicher wählen](https://www.traeger.de/docs/development/opcua/security/client#endpunkt-sicher-wahlen)).
2. **Unbekannte Serverzertifikate ablehnen**: `AutoAcceptUntrustedCertificates` deaktivieren, Serverzertifikate in den `TrustedPeerStore` aufnehmen oder gezielt im Ereignis `CertificateValidationFailed` annehmen (siehe [Serverzertifikate prüfen und vertrauen](https://www.traeger.de/docs/development/opcua/security/client#serverzertifikate-prufen-und-vertrauen)).
3. **Zertifikate streng prüfen**: `CertificateValidationRules` auf `RejectSHA1Signed` und `DisableBackwardsCompatibleValidation` stellen und `VerifyServersCertificateDomains` aktivieren.
4. **Eigenes Zertifikat verwalten**: ein Zertifikat mit angemessener Schlüssellänge und Laufzeit verwenden, `AutoCreateCertificate` deaktivieren und die Zertifikatspeicher in einem geschützten Verzeichnis ablegen (siehe [Eigenes Zertifikat schützen](https://www.traeger.de/docs/development/opcua/security/client#eigenes-zertifikat-schutzen)).
5. **Benutzer anmelden**: eine Benutzeridentität verwenden und Passwörter nicht im Quelltext hinterlegen (siehe [Benutzer anmelden](https://www.traeger.de/docs/development/opcua/security/client#benutzer-anmelden)).
6. **Zertifikatswechsel nicht ungeprüft akzeptieren**: das Ereignis `CertificateJudgement` behandeln und `Dismiss` nur nach einer eigenen Prüfung setzen.
7. **Grenzen nicht unnötig erhöhen**: die Grenzen unter `Transport` nur so weit anpassen, wie es die Anwendung erfordert.
8. **Lizenzschlüssel schützen**: den Schlüssel nicht im Klartext in öffentlich zugänglichen Dateien oder Repositories ablegen (siehe [Fahrlässige Veröffentlichung](https://www.traeger.de/docs/development/opcua/license#fahrlassige-veroffentlichung)).

Zusammengefasst sieht ein so konfigurierter Client wie folgt aus:

```csharp
var client = new OpcClient("opc.tcp://192.168.0.10:4840/");
 
// Only an encrypted endpoint with a current algorithm.
client.Security.EndpointPolicy = new OpcSecurityPolicy(
        OpcSecurityMode.SignAndEncrypt,
        OpcSecurityAlgorithm.Basic256Sha256);
client.Security.AutoUpgradeEndpointPolicy = true;
 
// Trust only known server certificates and check them strictly.
client.Security.AutoAcceptUntrustedCertificates = false;
client.Security.VerifyServersCertificateDomains = true;
client.Security.CertificateValidationRules
        = OpcCertificateValidationRules.RejectSHA1Signed
        | OpcCertificateValidationRules.DisableBackwardsCompatibleValidation;
 
// Use a managed certificate instead of a generated one.
client.CertificateStores.AutoCreateCertificate = false;
client.Certificate = OpcCertificateManager.LoadCertificate(certificatePath, certificatePassword);
 
// Log on as a user instead of anonymously.
client.Security.UserIdentity = new OpcClientIdentity(userName, password);
```

```vbnet
Dim client = New OpcClient("opc.tcp://192.168.0.10:4840/")

'Only an encrypted endpoint with a current algorithm.
client.Security.EndpointPolicy = New OpcSecurityPolicy( _
        OpcSecurityMode.SignAndEncrypt, _
        OpcSecurityAlgorithm.Basic256Sha256)
client.Security.AutoUpgradeEndpointPolicy = True

'Trust only known server certificates and check them strictly.
client.Security.AutoAcceptUntrustedCertificates = False
client.Security.VerifyServersCertificateDomains = True
client.Security.CertificateValidationRules _
        = OpcCertificateValidationRules.RejectSHA1Signed _
        Or OpcCertificateValidationRules.DisableBackwardsCompatibleValidation

'Use a managed certificate instead of a generated one.
client.CertificateStores.AutoCreateCertificate = False
client.Certificate = OpcCertificateManager.LoadCertificate(certificatePath, certificatePassword)

'Log on as a user instead of anonymously.
client.Security.UserIdentity = New OpcClientIdentity(userName, password)
```
