Как работает аутентификация по сертификатам в OPC UA
Давайте подробно разберём, как работает аутентификация по сертификатам в 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. Сертификат клиента | Клиент имеет | На машине клиента |
2. Отправка публичного ключа | При подключении клиент отправляет только публичную часть (.cer) серверу | По сети (шифруется) |
3. Проверка доверия | Сервер ищет этот .cer в папке | На сервере: |
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:
- Скопируйте
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- ИЛИ через монтирование тома (проще):
# Создайте папку на хосте
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)❌ Частые ошибки и решения
Ошибка | Причина | Решение |
|---|---|---|
| Сертификат клиента не в | Скопируйте |
| Сертификат просрочен или невалиден | Пересоздайте сертификат с новым сроком ( |
| Сертификат сервера не доверен клиентом | Включите |
|
| Пересоздайте с |
| Нет прав на чтение файла | Запустите от имени администратора или дайте права на файл |
🔍 Как отладить, если не подключается
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 # путь может отличаться🔄 Что происходит при переподключении
- Клиент теряет соединение (сеть, перезапуск сервера).
- Цикл
while(true)вMainловит исключение. - Клиент повторно использует тот же
.pfx— приватный ключ не меняется. - Сервер уже доверяет публичному ключу (он в
TrustedPeers). - Сессия восстанавливается без ручного вмешательства.
✅ Это главное преимущество сертификатов: не нужно хранить пароли, а переподключение работает "из коробки".📋 Чеклист для продакшена
- Сертификат клиента имеет срок действия ≥ 1 года
- Приватный ключ защищён паролем и хранится в безопасном месте
- Публичный ключ добавлен в
TrustedPeersна каждом сервере, к которому подключается клиент - На клиенте
AutoAcceptUntrusted = false(строгая проверка) - Включено логирование
TraceMasksдля отладки инцидентов - Реализована ротация сертификатов до истечения срока
Только полноправные пользователи могут оставлять комментарии. Аутентифицируйтесь пожалуйста, используя сервисы.