Создание клиентов OPC UA с поддержкой безопасности
Одна из ключевых функций OPC UA — поддержка безопасности, что означает криптографически зашифрованный и подписанный протокол, поддержку аутентификации и авторизации пользователей.
Для работы каждый экземпляр приложения (установка программы) должен иметь свой собственный Application Instance Certificate и соответствующий закрытый ключ.
Приложения могут либо генерировать самоподписанные сертификаты самостоятельно, получать их от центра сертификации с помощью OPC UA GDS, либо просто быть сконфигурированы с сертификатами, созданными вручную пользователем.
Поскольку в настоящее время Qt OPC UA не поддерживает генерацию сертификатов или GDS, этот учебник описывает, как создать самоподписанный сертификат OPC UA в командной строке с помощью OpenSSL.
Создание нового сертификата приложения
Для того чтобы сгенерировать корректный сертификат x509v3 со всеми необходимыми расширениями для OPC UA, сначала необходимо настроить файл конфигурации со всей необходимой информацией.
Не забудьте изменить subject и subjectAltName в соответствии с вашим случаем.
Важно вставить ApplicationURI приложения в поле URI файла subjectAltName, а имя хоста вашего ПК или устройства — в поля DNS файла subjectAltName. В качестве альтернативы, вы можете использовать поле IP, если ваше устройство не поддерживает имена хостов и вы работаете со статическими IP-адресами. Будущие версии Qt OPC UA смогут генерировать для вас сертификат с правильной информацией. Пока вы можете создать его с помощью командной строки OpenSSL.
Пример: opcuaviewer.config
[ req ] default_bits = 2048 default_md = sha256 distinguished_name = subject req_extensions = req_ext x509_extensions = req_ext string_mask = utf8only prompt = no [ req_ext ] basicConstraints = critical, CA:FALSE keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment subjectAltName = URI:urn:foo.com:The%20Qt%20Company:QtOpcUaViewer,DNS:foo.com subjectKeyIdentifier = hash authorityKeyIdentifier=keyid:always,issuer:always [ subject ] countryName = DE stateOrProvinceName = Berlin localityName = Berlin organizationName = The Qt Company commonName = QtOpcUaViewer
Используя этот файл конфигурации, OpenSSL может создать соответствующий сертификат для локального использования.
# create a self-signed certificate and private key openssl req -new -x509 -config opcuaviewer.config -newkey rsa:2048 -keyout opcuaviewer.key -nodes -outform der -out opcuaviewer.der # install the certificate and key into the application PKI directory mv opcuaviewer.der /path/to/application/pki/own/certs/opcuaviewer.der mv opcuaviewer.key /path/to/application/pki/own/private/opcuaviewer.pem # secure private key file permissions chmod 600 /path/to/application/pki/own/private/opcuaviewer.pem
Важно обеспечить безопасность прав доступа к файлу закрытого ключа, чтобы доступ к нему имел только приложение UA. Для служб (демонтов) рекомендуется создать отдельные учётные записи непривилегированных пользователей для этого и сделать этого пользователя владельцем ключа. Для интерактивных приложений этот ключ должен быть индивидуальным для пользователя. Для интерактивных приложений также возможно защитить ключ паролем. В этом случае пользователь должен вводить пароль каждый раз, когда приложение запускается и загружает ключ. По этой причине защищённые паролем ключи не являются хорошим решением для автономных приложений, поскольку это потребовало бы хранения пароля в файле конфигурации.
Вы можете вывести данные сертификата с помощью OpenSSL, чтобы проверить содержимое сертификата:
openssl x509 -in opcuaviewer.der -text -noout
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
be:aa:41:79:8a:b0:4f:9a
Signature Algorithm: sha512WithRSAEncryption
Issuer: C = DE, ST = Berlin, L = Berlin, O = The Qt Company, CN = QtOpcUaViewer
Validity
Not Before: Nov 7 14:38:52 2018 GMT
Not After : Dec 7 14:38:52 2018 GMT
Subject: C = DE, ST = Berlin, L = Berlin, O = The Qt Company, CN = QtOpcUaViewer
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
[ skipped ]
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Key Usage: critical
Digital Signature, Non Repudiation, Key Encipherment, Data Encipherment, Certificate Sign
X509v3 Subject Alternative Name:
URI:urn:foo.com:The%20Qt%20Company:QtOpcUaViewer, DNS:foo.com
X509v3 Subject Key Identifier:
B2:E8:5E:34:21:EA:67:CF:61:FC:14:94:18:C1:AD:13:89:83:CA:9B
X509v3 Authority Key Identifier:
keyid:B2:E8:5E:34:21:EA:67:CF:61:FC:14:94:18:C1:AD:13:89:83:CA:9B
DirName:/C=DE/ST=Berlin/L=Berlin/O=The Qt Company/CN=QtOpcUaViewer
serial:BE:AA:41:79:8A:B0:4F:9A
Signature Algorithm: sha512WithRSAEncryption
[ skipped ] Настройка приложения UA
Для работы с безопасностью с помощью созданного в предыдущем шаге сертификата важно
- Настроить правильную идентификацию приложения
m_identity = m_pkiConfig.applicationIdentity();
- Настроить расположение PKI, чтобы SDK мог найти сертификат, закрытый ключ, список доверенных сертификатов и т. д.
void MainWindow::setupPkiConfiguration() { QString pkidir = QCoreApplication::applicationDirPath(); #ifdef Q_OS_WIN pkidir += "../"; #endif pkidir += "/pki"; m_pkiConfig.setClientCertificateFile(pkidir + "/own/certs/opcuaviewer.der"); m_pkiConfig.setPrivateKeyFile(pkidir + "/own/private/opcuaviewer.pem"); m_pkiConfig.setTrustListDirectory(pkidir + "/trusted/certs"); m_pkiConfig.setRevocationListDirectory(pkidir + "/trusted/crl"); m_pkiConfig.setIssuerListDirectory(pkidir + "/issuers/certs"); m_pkiConfig.setIssuerRevocationListDirectory(pkidir + "/issuers/crl"); // create the folders if they don't exist yet createPkiFolders(); }
Структура папок PKI
Qt OPC UA использует следующую структуру папок:
| Папка | Описание |
|---|---|
| own | Место для хранения собственных сертификатов приложения. |
| trusted | Список доверенных сертификатов приложения или доверенных сертификатов центров сертификации. |
| issuer | Список сертификатов центров сертификации, которым не доверяют, но которые необходимы для проверки подписей в сертификатах. |
| rejected | Здесь приложение хранит отклоненные сертификаты, чтобы администратор мог позже им доверять. Важно иметь настроенное максимальное количество файлов здесь. Если это значение достигнуто, сначала должен быть удалён самый старый файл. Без ограничения злоумышленник может заполнить жёсткий диск машины недействительными попытками подключения. |
Каждая из папок own, trusted, и issuers содержит поддиректории, определённые в следующей таблице.
| Поддиректория | Описание |
|---|---|
| certs | Содержит DER-кодированные сертификаты X.509 v3. Файлы должны иметь расширение .der. |
| private | Содержит закрытые ключи. Формат файла может зависеть от бэкэнда. PEM-кодированные файлы должны иметь расширение .pem. PKCS#12-кодированные файлы должны иметь расширение .pfx. Имя корневого файла должно совпадать с соответствующим файлом открытого ключа в каталоге certs. Этот каталог существует только внутри папки own. |
| crl | Содержит DER-кодированные CRL для любых сертификатов центров сертификации, найденных в каталогах certs. Файлы должны иметь расширение .crl. |
Первое подключение
При первом подключении клиенту нужно доверять сертификату сервера.
Клиент должен отобразить предупреждение о сертификате (с деталями сертификата) и предложить возможность сохранить сертификат в его список доверенных сертификатов. Пример см. в Qt OPC UA Viewer Example.
После того, как клиент принял сертификат сервера, вы можете попробовать подключиться снова. Теперь сервер может отклонить сертификат клиента. Это указывается общим кодом ошибки BadSecurityChecksFailed. Сервер обычно хранит отклоненные сертификаты в специальной папке rejected. Администратор может переместить их в список доверенных сертификатов, чтобы доверять клиентам. Это позволяет избежать ручного копирования сертификата клиента на серверную машину.
Как только сервер доверится клиенту, вы сможете подключиться с поддержкой безопасности.
© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-6.2/security.html