Как работает аутентификация по сертификатам в OPC UA

  • Михаил
  • 8 мин. на прочтение
  • 9
  • 26 Apr 2026
  • 26 Apr 2026

Давайте подробно разберём, как работает аутентификация по сертификатам в OPC UA, и как правильно настроить её для вашего симулятора iotechsys/opc-ua-sim и C#-клиента.


📊 Схема рукопожатия (Handshake)


┌─────────────────┐                          	┌──────────────────────┐
│   КЛИЕНТ        │                          	│   СЕРВЕР  	       │
│                 │                          	│                 	   │
│ 1. Hello        │───────────────────────────▶	│                 	   │
│                 │                          	│                 	   │
│                 │◀────────────────────────── 	│ 2. Acknowledge  	   │
│                 │                          	│    + Endpoints  	   │
│                 │                          	│                 	   │
│ 3. OpenSecureChannel                       	│                 	   │
│    (Client Certificate)                    	│                 	   │
│    ───────────────────────────────────────▶  	│                 	   │
│                 │                          	│                 	   │
│                 │                          	│ 4. Проверка:    	   │
│                 │                          	│    • Валиден ли 	   │
│                 │                          	│    • В доверенных?   │
│                 │                          	│                 	   │
│                 │◀───────────────────────────	│ 5. Ответ:       	   │
│                 │    (Server Certificate)  	│    OK / Error   	   │
│                 │                          	│                 	   │
│ 6. CreateSession                           	│                 	   │
│    (UserIdentity = Certificate)            	│                 	   │
│    ───────────────────────────────────────▶  	│                 	   │
│                 │                          	│                 	   │
│                 │◀───────────────────────────	│ 7. Session Created   │
│                 │                          	│                 	   │
└─────────────────┘                          	└──────────────────────┘

 

🔑 Ключевые моменты

 

Этап

Что происходит

Где хранится

1. Сертификат клиента

Клиент имеет .pfx файл с приватным ключом

На машине клиента

2. Отправка публичного ключа

При подключении клиент отправляет только публичную часть (.cer) серверу

По сети (шифруется)

3. Проверка доверия

Сервер ищет этот .cer в папке TrustedPeers

На сервере: %ProgramData%\OPC Foundation\CertificateStores\TrustedPeers\

4. Шифрование канала

Если сертификат доверен — сервер шифрует ответ публичным ключом клиента

Используется асимметричное шифрование

5. Расшифровка

Только клиент с приватным ключом может расшифровать ответ

Приватный ключ никогда не покидает клиента

⚠️ Важно: Сервер никогда не получает ваш приватный ключ. Он использует только публичный ключ для шифрования.

Пошаговая настройка для iotechsys/opc-ua-sim

Шаг 1: Создайте сертификат клиента (если нет)

Вариант А: Через PowerShell (Windows)

 

# Создаём самоподписанный сертификат
$cert = New-SelfSignedCertificate `
    -DnsName "OPC Client" `
    -FriendlyName "AuditingReader" `
    -CertStoreLocation "cert:\CurrentUser\My" `
    -KeyExportPolicy Exportable `
    -KeySpec KeyExchange `
    -KeyLength 2048 `
    -NotAfter (Get-Date).AddYears(1)

# Экспортируем в PFX (с паролем)
$password = ConvertTo-SecureString -String "cert_password" -Force -AsPlainText
Export-PfxCertificate `
    -Cert $cert `
    -FilePath "C:\certs\client.pfx" `
    -Password $password

# Экспортируем публичную часть для сервера
Export-Certificate `
    -Cert $cert `
    -FilePath "C:\certs\client.cer" `
    -Type CERT

Вариант Б: Через OpenSSL (Linux/Mac/WSL)

 

# Создаём приватный ключ
openssl genrsa -out client.key 2048

# Создаём запрос на сертификат (CSR)
openssl req -new -key client.key -out client.csr -subj "/CN=AuditingReader/O=MyCompany/C=RU"

# Создаём самоподписанный сертификат
openssl x509 -req -in client.csr -signkey client.key -out client.crt -days 365

# Объединяем в PFX
openssl pkcs12 -export -out client.pfx -inkey client.key -in client.crt -password pass:cert_password

# Извлекаем публичную часть для сервера
openssl x509 -in client.crt -outform DER -out client.cer

Шаг 2: Настройте клиент (C#)

В SecurityConfig укажите:

public const AuthMethod AuthenticationMethod = AuthMethod.Certificate;
public const string ClientCertificatePath = @"C:\certs\client.pfx";
public const string ClientCertificatePassword = "cert_password";
public const bool UseSecurity = true;  // Требуем шифрование
💡 Убедитесь, что путь к .pfx доступен приложению после публикации.

Шаг 3: Добавьте сертификат в доверенные на сервере

Для симулятора в Docker:

  1. Скопируйте client.cer в контейнер:
# Копируем файл в контейнер
docker cp C:\certs\client.cer opc-ua-sim:/tmp/client.cer

# Заходим в контейнер
docker exec -it opc-ua-sim bash

# Создаём папку доверенных (если нет)
mkdir -p /data/certs/TrustedPeers

# Копируем сертификат
cp /tmp/client.cer /data/certs/TrustedPeers/client.cer

# Выходим
exit
  1. ИЛИ через монтирование тома (проще):
# Создайте папку на хосте
mkdir -p C:\opc-certs\TrustedPeers

# Скопируйте client.cer туда
copy C:\certs\client.cer C:\opc-certs\TrustedPeers\

# Перезапустите контейнер с монтированием
docker stop opc-ua-sim && docker rm opc-ua-sim

docker run -d \
  --name opc-ua-sim \
  -p 4840:49947 \
  -v C:\opc-certs:/app/certs \
  -e TRUSTED_CERTS_DIR=/app/certs/TrustedPeers \
  iotechsys/opc-ua-sim:1.2 \
  -l /example-scripts/simulation.lua

 

📌 Точные пути зависят от версии образа. Проверьте документацию или логи: docker logs opc-ua-sim

Шаг 4: Проверка подключения

Запустите клиент:

D:\OpcUaClient.exe

Ожидаемый вывод при успехе:

🔐 Auth: Certificate
✅ Сертификат: CN=AuditingReader
📡 Попытка подключения #1 к opc.tcp://10.10.11.18:4840...
✅ ПОДКЛЮЧЕНО! (AutoReconnectSession)
🔐 Policy: http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256
🔐 Mode: SignAndEncrypt
📜 Режим: Certificate (CN=AuditingReader)

❌ Частые ошибки и решения

 

Ошибка

Причина

Решение

BadSecurityChecksFailed

Сертификат клиента не в TrustedPeers на сервере

Скопируйте client.cer в папку доверенных сертификатов сервера

BadCertificateInvalid

Сертификат просрочен или невалиден

Пересоздайте сертификат с новым сроком (-NotAfter)

BadCertificateUntrusted

Сертификат сервера не доверен клиентом

Включите AutoAcceptUntrusted = true для тестов или добавьте сервер в TrustedPeers клиента

Не найден приватный ключ

.pfx создан без флага Exportable

Пересоздайте с -KeyExportPolicy Exportable (PowerShell) или -export (OpenSSL)

Access denied to .pfx

Нет прав на чтение файла

Запустите от имени администратора или дайте права на файл


🔍 Как отладить, если не подключается

1. Включите логирование в клиенте

Добавьте в CreateClientConfig:

TraceConfiguration = new TraceConfiguration
{
    TraceMasks = 511,  // Все уровни
    LogFilePath = "logs/opc-client.log"
};
Utils.SetTraceOutput(config.TraceConfiguration);

2. Проверьте сертификаты на клиенте

# Просмотр информации о .pfx
certutil -dump C:\certs\client.pfx

# Проверка наличия приватного ключа
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2("C:\certs\client.pfx", "cert_password")
Write-Host "HasPrivateKey: $($cert.HasPrivateKey)"
Write-Host "Subject: $($cert.Subject)"
Write-Host "Valid to: $($cert.NotAfter)"

3. Проверьте, видит ли сервер сертификат

# Зайдите в контейнер
docker exec -it opc-ua-sim bash

# Посмотрите папку доверенных
ls -la /app/certs/TrustedPeers/  # или другой путь из документации

# Проверьте логи сервера
tail -f /var/log/opc-ua-sim.log  # путь может отличаться

🔄 Что происходит при переподключении

  1. Клиент теряет соединение (сеть, перезапуск сервера).
  2. Цикл while(true) в Main ловит исключение.
  3. Клиент повторно использует тот же .pfx — приватный ключ не меняется.
  4. Сервер уже доверяет публичному ключу (он в TrustedPeers).
  5. Сессия восстанавливается без ручного вмешательства.
✅ Это главное преимущество сертификатов: не нужно хранить пароли, а переподключение работает "из коробки".

📋 Чеклист для продакшена

  • Сертификат клиента имеет срок действия ≥ 1 года
  • Приватный ключ защищён паролем и хранится в безопасном месте
  • Публичный ключ добавлен в TrustedPeers на каждом сервере, к которому подключается клиент
  • На клиенте AutoAcceptUntrusted = false (строгая проверка)
  • Включено логирование TraceMasks для отладки инцидентов
  • Реализована ротация сертификатов до истечения срока