CryptodevATECCx08 Auth: различия между версиями
(не показано 6 промежуточных версий 4 участников) | |||
Строка 1: | Строка 1: | ||
== Использование встроенного чипа ATECCx08 для авторизации на внешних сервисах. == | |||
В контроллеры '''WirenBoard''' встроен чип '''ATECCx08''', назначением которого является генерация ключевых пар, хранение приватных ключей а также операции асимметричного шифрования с использованием эллиптических кривых. | В контроллеры '''WirenBoard''' встроен чип '''ATECCx08''', назначением которого является генерация ключевых пар, хранение приватных ключей а также операции асимметричного шифрования с использованием эллиптических кривых. | ||
Приватный ключ после начальной инициализации хранится в микросхеме и не покидает ее, тем самым исключается его компрометация. | Приватный ключ после начальной инициализации хранится в микросхеме и не покидает ее, тем самым исключается его компрометация. | ||
Используя данную микросхему можно организовать авторизацию контроллера и защиту соединения по SSL на внешних сервисах и быть уверенным, что запрос выполнен с использованием именно этого экземпляра микросхемы. | Используя данную микросхему можно организовать авторизацию контроллера и защиту соединения по SSL на внешних сервисах и быть уверенным, что запрос выполнен с использованием именно этого экземпляра микросхемы. | ||
В данной статье пойдет речь о трех вариантах применения: '''nginx''', '''openssl''', '''mosquitto'''. | В данной статье пойдет речь о трех вариантах применения: '''nginx''', '''openssl''', '''mosquitto'''. | ||
Для доступа к криптоустройству нужна библиотека libateccssl1.1, установим ее командой: | Для доступа к криптоустройству нужна библиотека libateccssl1.1, установим ее командой: | ||
'''apt install libateccssl1.1''' | '''apt install libateccssl1.1''' | ||
Далее нужно отредактировать файл '''/etc/ssl/openssl.cnf''', добавив в нем следующие строчки: | Далее нужно отредактировать файл '''/etc/ssl/openssl.cnf''', добавив в нем следующие строчки: | ||
<pre> | <pre> | ||
openssl_conf = openssl_init | openssl_conf = openssl_init | ||
[openssl_init] | [openssl_init] | ||
engines = engine_section | engines = engine_section | ||
[engine_section] | [engine_section] | ||
ateccx08 = ateccx08_section | ateccx08 = ateccx08_section | ||
[ateccx08_section] | [ateccx08_section] | ||
init = 1 | init = 1 | ||
</pre> | </pre> | ||
Теперь приступим к созданию сертификатов. | Теперь приступим к созданию сертификатов. | ||
Для начала создадим свой центр сертификации (Certification Authority, '''CA'''): | Для начала создадим свой центр сертификации (Certification Authority, '''CA'''): | ||
Для этого сгенерируем ключевую пару: | Для этого сгенерируем ключевую пару: | ||
<pre>openssl genrsa -out ca.key 2048</pre> | <pre>openssl genrsa -out ca.key 2048</pre> | ||
И сертификат нашего '''CA''': | И сертификат нашего '''CA''': | ||
<pre>openssl req -x509 -new -days 3650 -key ca.key -out ca.crt -subj "/CN=MY CA"</pre> | <pre>openssl req -x509 -new -days 3650 -key ca.key -out ca.crt -subj "/CN=MY CA"</pre> | ||
'''CA''' является основой безопасности в данной схеме, поэтому эти операции выполняем на машине доступ к которой | '''CA''' является основой безопасности в данной схеме, поэтому эти операции выполняем на машине доступ к которой | ||
есть только у владельца '''CA'''. | есть только у владельца '''CA'''. | ||
Далее на конроллере WB создаем запрос на сертификат устройства: | Далее на конроллере WB создаем запрос на сертификат устройства: | ||
<pre>openssl req -new -engine ateccx08 -keyform engine -key ATECCx08:00:04:C0:00 -subj "/CN=wirenboard-AP6V5MDG" -out device_AP6V5MDG.csr</pre> | <pre>openssl req -new -engine ateccx08 -keyform engine -key ATECCx08:00:04:C0:00 -subj "/CN=wirenboard-AP6V5MDG" -out device_AP6V5MDG.csr</pre> | ||
В этой команде мы указываем, что запрос подписывается приватным ключом, находящимся в криптоустройстве ateccx08 ключом | В этой команде мы указываем, что запрос подписывается приватным ключом, находящимся в криптоустройстве ateccx08 ключом | ||
с идентификатором '''ATECCx08:00: | с идентификатором '''ATECCx08:00:04:C0:00''' и публичным именем wirenboard-AP6V5MDG. Запрос помещаем в файл device_AP6V5MDG.csr. | ||
Имя можно выбрать любое уникальное, удобно для этой цели спользовать идентификатор устройства, который по умолчанию прописывается | Имя можно выбрать любое уникальное, удобно для этой цели спользовать идентификатор устройства, который по умолчанию прописывается | ||
в файле /etc/hostname: | в файле /etc/hostname: | ||
<pre> | <pre> | ||
cat /etc/hostname | cat /etc/hostname | ||
Строка 84: | Строка 56: | ||
</pre> | </pre> | ||
Далее этот запрос подписываем в нашем центре сертификации: | Далее этот запрос подписываем в нашем центре сертификации: | ||
openssl x509 -req -in device_AP6V5MDG.csr -CA ca.crt -CAkey ca.key -out device_AP6V5MDG.crt -days 365 -CAcreateserial | openssl x509 -req -in device_AP6V5MDG.csr -CA ca.crt -CAkey ca.key -out device_AP6V5MDG.crt -days 365 -CAcreateserial | ||
В этой команде мы уазываем файл запроса, и файлы CA необходимые для подписи. В итоге получаем сертификат устройства device_AP6V5MDG.crt. | В этой команде мы уазываем файл запроса, и файлы CA необходимые для подписи. В итоге получаем сертификат устройства device_AP6V5MDG.crt. | ||
Файл '''device_AP6V5MDG.crt''' копируем на контроллер WB, он будет необходим для авторизацци. | Файл '''device_AP6V5MDG.crt''' копируем на контроллер WB, он будет необходим для авторизацци. | ||
Давайте посмотрим, что содержится в файлах сертификатов CA и устройства: | Давайте посмотрим, что содержится в файлах сертификатов CA и устройства: | ||
<pre> | <pre> | ||
openssl x509 -text -noout -in device_AP6V5MDG.crt | openssl x509 -text -noout -in device_AP6V5MDG.crt | ||
Certificate: | Certificate: | ||
Data: | Data: | ||
Строка 140: | Строка 107: | ||
</pre> | </pre> | ||
Видим, что сертификат выписан Центром сертификации с именем "MY CA" на 1 год, начная с "Feb 4 14:50:14 2019 GMT" (для этого мы указывали -days 365 в команде подписи), | Видим, что сертификат выписан Центром сертификации с именем "MY CA" на 1 год, начная с "Feb 4 14:50:14 2019 GMT" (для этого мы указывали -days 365 в команде подписи), | ||
устройству с именем '''wirenboard-AP6V5MDG''', имеющим приватный ключ соответствующий публичному Subject Public Key Info. | устройству с именем '''wirenboard-AP6V5MDG''', имеющим приватный ключ соответствующий публичному Subject Public Key Info. | ||
Сертификат подписан цифровой подписью. | Сертификат подписан цифровой подписью. | ||
Цифровая подпись гарантирует, что никакая часть сертификата не может быть незаметно изменена. В случае изменения проверка публичным | Цифровая подпись гарантирует, что никакая часть сертификата не может быть незаметно изменена. В случае изменения проверка публичным | ||
ключом '''CA''' даст ошибку. | ключом '''CA''' даст ошибку. | ||
<pre> | <pre> | ||
openssl x509 -text -noout -in ca.crt | openssl x509 -text -noout -in ca.crt | ||
Certificate: | Certificate: | ||
Data: | Data: | ||
Строка 194: | Строка 157: | ||
keyid:53:4B:6D:7A:1A:1F:F8:BE:3F:59:64:70:2B:31:2F:7A:7F:2A:6B:14 | keyid:53:4B:6D:7A:1A:1F:F8:BE:3F:59:64:70:2B:31:2F:7A:7F:2A:6B:14 | ||
X509v3 Basic Constraints: critical | |||
X509v3 Basic Constraints: critical | |||
CA:TRUE | CA:TRUE | ||
Signature Algorithm: sha256WithRSAEncryption | Signature Algorithm: sha256WithRSAEncryption | ||
Строка 215: | Строка 177: | ||
</pre> | </pre> | ||
Видим, что сертификат подписан сам своим-же приватным ключом (Issuer: CN = MY CA, Subject: CN = MY CA) | Видим, что сертификат подписан сам своим-же приватным ключом (Issuer: CN = MY CA, Subject: CN = MY CA) | ||
и выписан на 10 лет: начная с "Feb 4 14:30:01 2019 GMT" (для этого мы указывали -days 3650 в команде подписи) | и выписан на 10 лет: начная с "Feb 4 14:30:01 2019 GMT" (для этого мы указывали -days 3650 в команде подписи) | ||
Таким образом цепочка доверия (проверки) выстраивается следующим образом: | Таким образом цепочка доверия (проверки) выстраивается следующим образом: | ||
Сертификат устройства подписан сертификатом CA и может быть им проверен: | Сертификат устройства подписан сертификатом CA и может быть им проверен: | ||
<pre> | <pre> | ||
Строка 229: | Строка 188: | ||
</pre> | </pre> | ||
Ну а сам сертификат подписан "собой": | Ну а сам сертификат подписан "собой": | ||
<pre> | <pre> | ||
Строка 237: | Строка 195: | ||
''' | ''' | ||
== Настройка nginx. == | |||
Допустим в интернете есть сервер, который должен обрабатывать запросы только от устройств обладающих сертификатами, | Допустим в интернете есть сервер, который должен обрабатывать запросы только от устройств обладающих сертификатами, | ||
выписанными нашим CA. | выписанными нашим CA. | ||
Для включения такой проверки в конфигурационном файле nginx необходимо в секции http или server прописать следующие строчки: | Для включения такой проверки в конфигурационном файле nginx необходимо в секции http или server прописать следующие строчки: | ||
<pre> | <pre> | ||
ssl_client_certificate ca.crt; | ssl_client_certificate ca.crt; | ||
Строка 250: | Строка 207: | ||
</pre> | </pre> | ||
Теперь nginx будет требовать от клиента сертификат, который должен проходить проверку с помощью ca.crt, иначе сервер | Теперь nginx будет требовать от клиента сертификат, который должен проходить проверку с помощью ca.crt, иначе сервер | ||
вернет клиенту ошибку 400: | вернет клиенту ошибку 400: | ||
<pre> | <pre> | ||
curl https://example.com | curl https://example.com | ||
Строка 267: | Строка 222: | ||
</pre> | </pre> | ||
Теперь сделаем так, чтобы HTTP запросы с контроллера WB проходили данную проверку. | Теперь сделаем так, чтобы HTTP запросы с контроллера WB проходили данную проверку. | ||
Для простоты будем использовать nginx и на клиентской стороне. Это даст возможность работать | Для простоты будем использовать nginx и на клиентской стороне. Это даст возможность работать | ||
с защищенными серверами клиентам не умеющим делать SSL соединения. | с защищенными серверами клиентам не умеющим делать SSL соединения. | ||
Для начала создадим на неиспользуемом локальном порту http сервер, который будет делать | Для начала создадим на неиспользуемом локальном порту http сервер, который будет делать | ||
всю https "магию" за нас: | всю https "магию" за нас: | ||
<pre> | <pre> | ||
server { | server { | ||
Строка 299: | Строка 242: | ||
</pre> | </pre> | ||
Добавим пользователя www-data в группу i2c для доступа к криптоустройству: | Добавим пользователя www-data в группу i2c для доступа к криптоустройству: | ||
<pre> | <pre> | ||
Строка 305: | Строка 247: | ||
</pre> | </pre> | ||
Выполним команду '''service nginx restart''' для обновления конфигурации. | Выполним команду '''service nginx restart''' для обновления конфигурации. | ||
Теперь при обращении по http на локальный порт 8080 зашифрованные запросы с аутентификационной | Теперь при обращении по http на локальный порт 8080 зашифрованные запросы с аутентификационной | ||
информацией будут отправлятся на сервер example.com. | информацией будут отправлятся на сервер example.com. | ||
<pre> | <pre> | ||
curl localhost:8080/ | curl localhost:8080/ | ||
Строка 322: | Строка 261: | ||
</pre> | </pre> | ||
== Настройка openvpn == | == Настройка openvpn == | ||
Для начала установим пакет: | Для начала установим пакет: | ||
<pre> | <pre> | ||
apt install openvpn | apt install openvpn | ||
</pre> | </pre> | ||
Cоздадим файл req.cnf - он нам потребуется для создания сертификата сервера. | Cоздадим файл req.cnf - он нам потребуется для создания сертификата сервера. | ||
<pre> | <pre> | ||
Строка 341: | Строка 277: | ||
</pre> | </pre> | ||
Серверу openvpn также требуется файл с параметрами DH, сделаем его. | Серверу openvpn также требуется файл с параметрами DH, сделаем его. | ||
<pre> | <pre> | ||
Строка 347: | Строка 282: | ||
</pre> | </pre> | ||
Создание данного файла может потребовать несколько минут. | Создание данного файла может потребовать несколько минут. | ||
Далее сделаем приватный ключ нашего сервера и запрос на сертификат. Предполагаем, для примера, что | Далее сделаем приватный ключ нашего сервера и запрос на сертификат. Предполагаем, для примера, что | ||
сервер имеет имя example.com: | сервер имеет имя example.com: | ||
<pre> | <pre> | ||
openssl genrsa -out example.key 2048 | openssl genrsa -out example.key 2048 | ||
openssl req -new -key example.key -subj "/CN=example.com" -out example.csr | openssl req -new -key example.key -subj "/CN=example.com" -out example.csr | ||
</pre> | </pre> | ||
Подписываем запрос в нашем центре сертификации: | Подписываем запрос в нашем центре сертификации: | ||
<pre> | <pre> | ||
openssl x509 -req -in example.csr -CA ca.crt -CAkey ca.key -out example.crt -days 365 -CAcreateserial -extfile req.cnf -extensions v3_req | openssl x509 -req -in example.csr -CA ca.crt -CAkey ca.key -out example.crt -days 365 -CAcreateserial -extfile req.cnf -extensions v3_req | ||
</pre> | </pre> | ||
Теперь приступим к настройке openvpn сервера на машине example.com. | Теперь приступим к настройке openvpn сервера на машине example.com. | ||
Копируем файлы '''ca.crt''', '''example.crt''', '''example.key''' и '''dh2048.pem''' и редактируем файл конфигурации openvpn сервера. | Копируем файлы '''ca.crt''', '''example.crt''', '''example.key''' и '''dh2048.pem''' и редактируем файл конфигурации openvpn сервера. | ||
По умолчанию конфигурационный файл лежит в файле /etc/openvpn/server.conf | По умолчанию конфигурационный файл лежит в файле /etc/openvpn/server.conf | ||
<pre> | <pre> | ||
port 1194 | port 1194 | ||
Строка 402: | Строка 328: | ||
</pre> | </pre> | ||
Добавим пользователя openvpn в группу i2c для доступа к криптоустройству: | Добавим пользователя openvpn в группу i2c для доступа к криптоустройству: | ||
<pre> | <pre> | ||
usermod -G www-data | usermod -G www-data | ||
</pre> | </pre> | ||
после этого запускаем сервер командой | после этого запускаем сервер командой | ||
service openvpn start. | service openvpn start. | ||
Далее на контроллере создаем файл конфигурации клиента: | Далее на контроллере создаем файл конфигурации клиента: | ||
client.ovpn: | client.ovpn: | ||
Строка 439: | Строка 361: | ||
Обратите внимание на строчку group i2c. Она необходима для работы с криптоустройством. | Обратите внимание на строчку group i2c. Она необходима для работы с криптоустройством. | ||
После этого запускаем клиента: | После этого запускаем клиента: | ||
<pre> | <pre> | ||
openvpn --config example.ovpn --ca ca.crt --cert device_AP6V5MDG.crt --key engine:ateccx08:ATECCx08:00:04:C0:00 | openvpn --config example.ovpn --ca ca.crt --cert device_AP6V5MDG.crt --key engine:ateccx08:ATECCx08:00:04:C0:00 | ||
</pre> | </pre> | ||
Если все хорошо, то в системе должен появиться интерфейс tun0 с адресом из подсети 10.8.0.0/24: | Если все хорошо, то в системе должен появиться интерфейс tun0 с адресом из подсети 10.8.0.0/24: | ||
<pre> | <pre> | ||
tun0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST> mtu 1500 | tun0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST> mtu 1500 | ||
Строка 462: | Строка 380: | ||
</pre> | </pre> | ||
Для проверки работоспособности запускаем ping: | Для проверки работоспособности запускаем ping: | ||
<pre> | <pre> | ||
ping 10.8.0.1 | ping 10.8.0.1 | ||
Строка 473: | Строка 389: | ||
</pre> | </pre> | ||
== Настройка mosquitto == | == Настройка mosquitto == | ||
UPD: | UPD: | ||
1) openssl.cnf | 1) openssl.cnf | ||
2) mosquitto=1.4.15-1+wb7-4 | 2) mosquitto=1.4.15-1+wb7-4 | ||
3) libateccssl1.1=0.2.1 | 3) libateccssl1.1=0.2.1 | ||
4) ca-certificates-contactless | 4) ca-certificates-contactless | ||
5) usermod -a -G i2c mosquitto | 5) usermod -a -G i2c mosquitto | ||
<pre> | <pre> | ||
root@wirenboard-APIJVTIG:~# cat /etc/mosquitto/conf.d/bridge-hw.conf | root@wirenboard-APIJVTIG:~# cat /etc/mosquitto/conf.d/bridge-hw.conf | ||
Строка 499: | Строка 408: | ||
address contactless.ru:8884 | address contactless.ru:8884 | ||
bridge_cafile /etc/ssl/certs/WirenBoard_Root_CA.pem | bridge_cafile /etc/ssl/certs/WirenBoard_Root_CA.pem | ||
bridge_certfile /etc/ssl/device/device_bundle.crt.pem | bridge_certfile /etc/ssl/device/device_bundle.crt.pem | ||
Строка 506: | Строка 414: | ||
bridge_insecure true | bridge_insecure true | ||
notifications true | notifications true | ||
notification_topic /client/wirenboard-APIJVTIG/bridge_status | notification_topic /client/wirenboard-APIJVTIG/bridge_status | ||
topic /devices/# both 2 "" /client/wirenboard-APIJVTIG | topic /devices/# both 2 "" /client/wirenboard-APIJVTIG | ||
topic /config/# both 2 "" /client/wirenboard-APIJVTIG | topic /config/# both 2 "" /client/wirenboard-APIJVTIG | ||
Строка 516: | Строка 422: | ||
</pre> | </pre> | ||
Генерируем приватный ключ и запрос на сертификат: | Генерируем приватный ключ и запрос на сертификат: | ||
<pre> | <pre> | ||
openssl genrsa -out example.key 2048 | openssl genrsa -out example.key 2048 | ||
Строка 580: | Строка 432: | ||
</pre> | </pre> | ||
Создаем сертификат сервера в CA. | Создаем сертификат сервера в CA. | ||
<pre> | <pre> | ||
Строка 586: | Строка 437: | ||
</pre> | </pre> | ||
Копируем файлы '''ca.crt''', '''mosquitto.crt''', '''mosquitto.key''' на сервер и редактируем файл конфигурации '''/etc/mosquitto/conf.d/server.conf''' | Копируем файлы '''ca.crt''', '''mosquitto.crt''', '''mosquitto.key''' на сервер и редактируем файл конфигурации '''/etc/mosquitto/conf.d/server.conf''' | ||
<pre> | <pre> | ||
cafile /etc/mosquitto/ssl/ca.crt | cafile /etc/mosquitto/ssl/ca.crt | ||
Строка 598: | Строка 447: | ||
</pre> | </pre> | ||
Запускаем серис: | Запускаем серис: | ||
<pre> | <pre> | ||
Строка 604: | Строка 452: | ||
</pre> | </pre> | ||
Также, если требуется, можно сделать чтобы локальный mosquitto сервер на контроллере | Также, если требуется, можно сделать чтобы локальный mosquitto сервер на контроллере | ||
форвардил некоторые топики на удаленный сервер. Для этого создаем файл бриджа: '''/etc/mosquitto/bridge.conf''' | форвардил некоторые топики на удаленный сервер. Для этого создаем файл бриджа: '''/etc/mosquitto/bridge.conf''' | ||
<pre> | <pre> | ||
connection main | connection main | ||
Строка 614: | Строка 460: | ||
address example.com:1883 | address example.com:1883 | ||
bridge_cafile /etc/mosquitto/certs/ca.crt | bridge_cafile /etc/mosquitto/certs/ca.crt | ||
bridge_certfile /etc/mosquitto/certs/device_AP6V5MDG.crt | bridge_certfile /etc/mosquitto/certs/device_AP6V5MDG.crt | ||
Строка 620: | Строка 465: | ||
</pre> | </pre> | ||
После перезапуска локального сервиса mosquitto топики /test/.. будут отправлятся на удаленный сервер example.com | После перезапуска локального сервиса mosquitto топики /test/.. будут отправлятся на удаленный сервер example.com | ||
по защищенному ssl каналу. | по защищенному ssl каналу. | ||
Примеры клиентских команд mosquitto. | Примеры клиентских команд mosquitto. | ||
Отправка сообщения "message" в топик "test" на сервере example.com | Отправка сообщения "message" в топик "test" на сервере example.com | ||
<pre> | <pre> | ||
mosquitto_pub -h example.com --cert device_AP6V5MDG.crt --key 'engine:ateccx08:ATECCx08:00:04:C0:00' --cafile ca.crt -t "test" -m "message" | mosquitto_pub -h example.com --cert device_AP6V5MDG.crt --key 'engine:ateccx08:ATECCx08:00:04:C0:00' --cafile ca.crt -t "test" -m "message" | ||
</pre> | </pre> | ||
Получение сообщений из топика "test" на сервере example.com | Получение сообщений из топика "test" на сервере example.com | ||
<pre> | <pre> | ||
mosquitto_sub -h example.com --cert device_AP6V5MDG.crt --key 'engine:ateccx08:ATECCx08:00:04:C0:00' -t "test" --cafile ca.crt | mosquitto_sub -h example.com --cert device_AP6V5MDG.crt --key 'engine:ateccx08:ATECCx08:00:04:C0:00' -t "test" --cafile ca.crt | ||
</pre> | </pre> | ||
Версия 22:19, 14 марта 2019
Использование встроенного чипа ATECCx08 для авторизации на внешних сервисах.
В контроллеры WirenBoard встроен чип ATECCx08, назначением которого является генерация ключевых пар, хранение приватных ключей а также операции асимметричного шифрования с использованием эллиптических кривых. Приватный ключ после начальной инициализации хранится в микросхеме и не покидает ее, тем самым исключается его компрометация.
Используя данную микросхему можно организовать авторизацию контроллера и защиту соединения по SSL на внешних сервисах и быть уверенным, что запрос выполнен с использованием именно этого экземпляра микросхемы.
В данной статье пойдет речь о трех вариантах применения: nginx, openssl, mosquitto.
Для доступа к криптоустройству нужна библиотека libateccssl1.1, установим ее командой:
apt install libateccssl1.1
Далее нужно отредактировать файл /etc/ssl/openssl.cnf, добавив в нем следующие строчки:
openssl_conf = openssl_init [openssl_init] engines = engine_section [engine_section] ateccx08 = ateccx08_section [ateccx08_section] init = 1
Теперь приступим к созданию сертификатов. Для начала создадим свой центр сертификации (Certification Authority, CA):
Для этого сгенерируем ключевую пару:
openssl genrsa -out ca.key 2048
И сертификат нашего CA:
openssl req -x509 -new -days 3650 -key ca.key -out ca.crt -subj "/CN=MY CA"
CA является основой безопасности в данной схеме, поэтому эти операции выполняем на машине доступ к которой есть только у владельца CA.
Далее на конроллере WB создаем запрос на сертификат устройства:
openssl req -new -engine ateccx08 -keyform engine -key ATECCx08:00:04:C0:00 -subj "/CN=wirenboard-AP6V5MDG" -out device_AP6V5MDG.csr
В этой команде мы указываем, что запрос подписывается приватным ключом, находящимся в криптоустройстве ateccx08 ключом с идентификатором ATECCx08:00:04:C0:00 и публичным именем wirenboard-AP6V5MDG. Запрос помещаем в файл device_AP6V5MDG.csr.
Имя можно выбрать любое уникальное, удобно для этой цели спользовать идентификатор устройства, который по умолчанию прописывается в файле /etc/hostname:
cat /etc/hostname wirenboard-AP6V5MDG
Далее этот запрос подписываем в нашем центре сертификации: openssl x509 -req -in device_AP6V5MDG.csr -CA ca.crt -CAkey ca.key -out device_AP6V5MDG.crt -days 365 -CAcreateserial
В этой команде мы уазываем файл запроса, и файлы CA необходимые для подписи. В итоге получаем сертификат устройства device_AP6V5MDG.crt. Файл device_AP6V5MDG.crt копируем на контроллер WB, он будет необходим для авторизацци.
Давайте посмотрим, что содержится в файлах сертификатов CA и устройства:
openssl x509 -text -noout -in device_AP6V5MDG.crt Certificate: Data: Version: 1 (0x0) Serial Number: bf:85:29:be:19:67:f5:3e Signature Algorithm: sha256WithRSAEncryption Issuer: CN = MY CA Validity Not Before: Feb 4 14:50:14 2019 GMT Not After : Feb 4 14:50:14 2020 GMT Subject: CN = wirenboard-AP6V5MDG Subject Public Key Info: Public Key Algorithm: id-ecPublicKey Public-Key: (256 bit) pub: 04:66:80:f6:83:ea:4f:88:a5:05:df:8f:2c:62:f3: ad:71:55:87:7f:ae:12:ae:b1:74:4b:68:68:fd:f7: e0:8a:f4:44:87:45:ab:c1:07:3f:54:2a:a9:ea:c6: 71:1d:41:63:67:1b:75:f4:00:42:8d:fd:f6:d5:b6: 52:38:e8:5a:a9 ASN1 OID: prime256v1 NIST CURVE: P-256 Signature Algorithm: sha256WithRSAEncryption be:d1:f8:04:fb:34:a9:84:ff:25:b6:04:04:c0:f1:1d:4a:a4: 04:b8:54:6c:a8:46:61:5f:6c:e7:ab:16:8f:ae:45:46:02:99: c6:d3:90:42:91:20:c7:89:d5:cf:4e:23:3a:33:64:ab:1b:c9: 78:18:82:f4:39:8b:97:ae:6c:ee:a4:13:0c:5a:54:6b:69:c8: 1e:fa:24:3d:48:2c:ea:0e:5c:0d:c3:43:c2:49:ea:b2:f8:5e: d7:0b:b5:4e:67:87:53:84:76:23:aa:10:77:5d:f1:21:9e:b0: 4b:16:99:7c:d4:d3:d6:e7:00:9c:bf:53:a1:4b:f4:2c:fc:0b: 64:10:fb:77:fc:3d:b2:71:cf:be:0b:b1:a2:62:ed:8c:92:e4: 78:73:dc:69:c4:61:10:22:66:11:11:8b:d4:3c:b6:4f:7f:2c: 24:07:61:47:15:2a:56:7e:71:69:59:15:8b:53:c8:e2:b5:ed: 34:a0:78:70:d4:f6:cf:0f:6d:df:45:00:3b:0a:39:a2:fb:e7: 89:f3:d9:88:7f:6b:bd:fa:ca:5e:44:94:74:70:5e:86:0b:93: ca:16:71:42:67:eb:77:bd:15:e3:90:2f:68:fd:bc:61:25:a3: a6:e7:8b:b1:42:bc:c2:36:d4:17:67:b3:77:fb:bd:06:e9:35: 3b:8e:08:48
Видим, что сертификат выписан Центром сертификации с именем "MY CA" на 1 год, начная с "Feb 4 14:50:14 2019 GMT" (для этого мы указывали -days 365 в команде подписи), устройству с именем wirenboard-AP6V5MDG, имеющим приватный ключ соответствующий публичному Subject Public Key Info. Сертификат подписан цифровой подписью.
Цифровая подпись гарантирует, что никакая часть сертификата не может быть незаметно изменена. В случае изменения проверка публичным ключом CA даст ошибку.
openssl x509 -text -noout -in ca.crt Certificate: Data: Version: 3 (0x2) Serial Number: d9:e0:91:e7:d0:27:02:db Signature Algorithm: sha256WithRSAEncryption Issuer: CN = MY CA Validity Not Before: Feb 4 14:30:01 2019 GMT Not After : Feb 1 14:30:01 2029 GMT Subject: CN = MY CA Subject Public Key Info: Public Key Algorithm: rsaEncryption Public-Key: (2048 bit) Modulus: 00:c8:5e:02:b8:55:e5:42:97:f7:c6:53:61:d3:df: 66:bf:05:dd:7a:0c:61:a4:68:36:23:3f:3b:c7:83: ec:47:9b:5a:ed:78:8a:5b:f1:5f:88:3d:36:f2:3e: 7b:84:9e:1b:e5:87:bf:3b:00:33:36:1c:0b:3a:16: 2f:8d:be:0e:a4:9e:25:73:4d:93:8a:47:74:29:65: 0e:4e:ea:44:fd:c4:c0:bf:fa:bc:11:d5:93:43:e2: 65:18:bb:f7:e5:fc:16:8c:f9:11:97:76:2c:bb:cb: c0:94:7e:78:12:20:c9:8a:68:29:c1:e8:af:7e:d7: 63:6e:a3:57:79:c9:b3:a8:8c:a3:2d:3e:15:1a:25: ea:f1:50:fc:ea:93:8f:14:5f:34:61:07:a9:dc:24: b8:11:de:9c:17:13:03:19:0d:0c:a3:e8:10:31:50: 82:5b:cb:0e:26:d5:b1:fe:df:c3:f6:f9:e4:0f:b1: 24:40:f2:8d:95:d5:ea:34:b3:27:a1:87:76:9d:f2: 65:74:d5:40:47:dd:a1:32:46:c3:37:ec:a5:b3:09: 30:73:99:d1:9c:bb:a8:05:61:2a:56:89:32:5e:c0: 5d:1d:b6:a6:b6:74:17:be:74:69:9c:b0:e3:bc:b4: f9:96:6d:aa:60:ae:70:d1:ee:07:e5:2c:5d:0a:af: ce:b3 Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Subject Key Identifier: 53:4B:6D:7A:1A:1F:F8:BE:3F:59:64:70:2B:31:2F:7A:7F:2A:6B:14 X509v3 Authority Key Identifier: keyid:53:4B:6D:7A:1A:1F:F8:BE:3F:59:64:70:2B:31:2F:7A:7F:2A:6B:14 X509v3 Basic Constraints: critical CA:TRUE Signature Algorithm: sha256WithRSAEncryption 30:c2:f3:e0:96:51:7d:13:be:06:1d:40:06:70:b8:36:e9:46: 81:64:0c:f0:e7:69:6f:31:2c:e1:86:df:f8:ad:b2:84:6e:90: 4a:38:48:7d:ae:92:a5:71:40:c8:8e:0f:7e:67:e5:66:e7:70: 4d:52:92:fa:a6:54:45:3b:a6:b9:b3:f4:35:ad:1c:6e:6e:15: 06:81:ef:13:54:80:89:2e:7d:75:06:22:59:89:44:a9:ad:25: 30:6c:02:e1:3b:2e:e2:bc:46:90:d1:a5:00:eb:87:57:60:a4: cf:e0:03:4a:b5:32:c4:dc:c7:e3:34:d4:c8:af:e3:ce:20:8c: c4:7f:f0:b8:72:d7:65:3b:38:be:2b:b1:d0:4e:9e:e2:52:32: 41:fe:22:d2:7c:13:60:fe:4a:13:4b:c5:09:f0:00:89:32:22: 47:4d:2c:a1:21:8e:b2:7d:0f:1a:10:f5:94:ee:fb:18:d3:15: f1:9e:70:89:73:c4:41:71:0e:92:22:9c:18:ef:0b:b1:7c:42: 41:e7:9f:e7:82:d5:db:f3:60:d3:2f:2a:86:e4:0c:c0:4c:0c: 17:12:ec:e4:37:96:dc:2d:01:00:22:ac:b5:33:6b:97:41:d7: 37:e5:75:fa:c9:6b:00:2a:d8:87:0f:9e:f3:aa:c5:23:4e:60: 02:a9:5b:eb
Видим, что сертификат подписан сам своим-же приватным ключом (Issuer: CN = MY CA, Subject: CN = MY CA) и выписан на 10 лет: начная с "Feb 4 14:30:01 2019 GMT" (для этого мы указывали -days 3650 в команде подписи)
Таким образом цепочка доверия (проверки) выстраивается следующим образом:
Сертификат устройства подписан сертификатом CA и может быть им проверен:
openssl verify -CAfile ca.crt device_AP6V5MDG.crt device_AP6V5MDG.crt: OK
Ну а сам сертификат подписан "собой":
openssl verify -CAfile ca.crt ca.crt ca.crt: OK
Настройка nginx.
Допустим в интернете есть сервер, который должен обрабатывать запросы только от устройств обладающих сертификатами, выписанными нашим CA. Для включения такой проверки в конфигурационном файле nginx необходимо в секции http или server прописать следующие строчки:
ssl_client_certificate ca.crt; ssl_verify_client on;
Теперь nginx будет требовать от клиента сертификат, который должен проходить проверку с помощью ca.crt, иначе сервер вернет клиенту ошибку 400:
curl https://example.com <html> <head><title>400 No required SSL certificate was sent</title></head> <body bgcolor="white"> <center><h1>400 Bad Request</h1></center> <center>No required SSL certificate was sent</center> <hr><center>nginx/1.14.0 (Ubuntu)</center> </body> </html>
Теперь сделаем так, чтобы HTTP запросы с контроллера WB проходили данную проверку. Для простоты будем использовать nginx и на клиентской стороне. Это даст возможность работать с защищенными серверами клиентам не умеющим делать SSL соединения.
Для начала создадим на неиспользуемом локальном порту http сервер, который будет делать всю https "магию" за нас:
server { listen 8080; location / { proxy_pass https://example.com; proxy_ssl_name example.com; proxy_ssl_server_name on; proxy_ssl_certificate device_AP6V5MDG.crt; proxy_ssl_certificate_key engine:ateccx08:ATECCx08:00:04:C0:00; } }
Добавим пользователя www-data в группу i2c для доступа к криптоустройству:
usermod -G www-data
Выполним команду service nginx restart для обновления конфигурации.
Теперь при обращении по http на локальный порт 8080 зашифрованные запросы с аутентификационной информацией будут отправлятся на сервер example.com.
curl localhost:8080/ <html> <body> EXAMPLE.COM </body> </html>
Настройка openvpn
Для начала установим пакет:
apt install openvpn
Cоздадим файл req.cnf - он нам потребуется для создания сертификата сервера.
[ v3_req ] basicConstraints = CA:FALSE keyUsage = nonRepudiation, digitalSignature, keyEncipherment extendedKeyUsage = serverAuth, clientAuth
Серверу openvpn также требуется файл с параметрами DH, сделаем его.
openssl dhparam -out dh2048.pem 2048
Создание данного файла может потребовать несколько минут.
Далее сделаем приватный ключ нашего сервера и запрос на сертификат. Предполагаем, для примера, что сервер имеет имя example.com:
openssl genrsa -out example.key 2048 openssl req -new -key example.key -subj "/CN=example.com" -out example.csr
Подписываем запрос в нашем центре сертификации:
openssl x509 -req -in example.csr -CA ca.crt -CAkey ca.key -out example.crt -days 365 -CAcreateserial -extfile req.cnf -extensions v3_req
Теперь приступим к настройке openvpn сервера на машине example.com.
Копируем файлы ca.crt, example.crt, example.key и dh2048.pem и редактируем файл конфигурации openvpn сервера. По умолчанию конфигурационный файл лежит в файле /etc/openvpn/server.conf
port 1194 proto tcp dev tun ca /etc/openvpn/server/ca.crt cert /etc/openvpn/server/example.crt key /etc/openvpn/server/example.key dh /etc/openvpn/server/dh2048.pem topology subnet server 10.8.0.0 255.255.255.0 keepalive 10 60 key-direction 0 cipher AES-128-CBC auth SHA256 comp-lzo user nobody group nogroup persist-key persist-tun status /var/run/openvpn/openvpn-status.log management 127.0.0.1 7500 log-append /var/log/openvpn.log
Добавим пользователя openvpn в группу i2c для доступа к криптоустройству:
usermod -G www-data
после этого запускаем сервер командой service openvpn start.
Далее на контроллере создаем файл конфигурации клиента: client.ovpn:
------------------------------------------------------------------------- client dev tun proto tcp remote example.com 1194 resolv-retry infinite nobind user openvpn '''group i2c''' persist-key persist-tun cipher AES-128-CBC auth SHA256 key-direction 1 keepalive 1 10 remote-cert-tls server comp-lzo -------------------------------------------------------------------------
Обратите внимание на строчку group i2c. Она необходима для работы с криптоустройством.
После этого запускаем клиента:
openvpn --config example.ovpn --ca ca.crt --cert device_AP6V5MDG.crt --key engine:ateccx08:ATECCx08:00:04:C0:00
Если все хорошо, то в системе должен появиться интерфейс tun0 с адресом из подсети 10.8.0.0/24:
tun0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST> mtu 1500 inet 10.8.0.2 netmask 255.255.255.0 destination 10.8.0.2 inet6 fe80::53b0:83f3:b1f5:b817 prefixlen 64 scopeid 0x20<link> unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 100 (UNSPEC) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 6 bytes 288 (288.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
Для проверки работоспособности запускаем ping:
ping 10.8.0.1 PING 10.8.0.1 (10.8.0.1) 56(84) bytes of data. 64 bytes from 10.8.0.1: icmp_seq=1 ttl=64 time=2.23 ms 64 bytes from 10.8.0.1: icmp_seq=2 ttl=64 time=2.83 ms
Настройка mosquitto
UPD:
1) openssl.cnf
2) mosquitto=1.4.15-1+wb7-4
3) libateccssl1.1=0.2.1
4) ca-certificates-contactless
5) usermod -a -G i2c mosquitto
root@wirenboard-APIJVTIG:~# cat /etc/mosquitto/conf.d/bridge-hw.conf connection wb_devices_cloud.wirenboard-APIJVTIG address contactless.ru:8884 bridge_cafile /etc/ssl/certs/WirenBoard_Root_CA.pem bridge_certfile /etc/ssl/device/device_bundle.crt.pem bridge_keyfile engine:ateccx08:ATECCx08:00:04:C0:00 bridge_capath /etc/ssl/certs/ bridge_insecure true notifications true notification_topic /client/wirenboard-APIJVTIG/bridge_status topic /devices/# both 2 "" /client/wirenboard-APIJVTIG topic /config/# both 2 "" /client/wirenboard-APIJVTIG topic /rpc/# both 2 "" /client/wirenboard-APIJVTIG
Генерируем приватный ключ и запрос на сертификат:
openssl genrsa -out example.key 2048 openssl req -new -key example.key -subj "/CN=example.com" -out example.csr
Создаем сертификат сервера в CA.
openssl x509 -req -in example.csr -CA ca.crt -CAkey ca.key -out example.crt -days 365 -CAcreateserial -extfile req.cnf -extensions v3_req
Копируем файлы ca.crt, mosquitto.crt, mosquitto.key на сервер и редактируем файл конфигурации /etc/mosquitto/conf.d/server.conf
cafile /etc/mosquitto/ssl/ca.crt certfile /etc/mosquitto/ssl/mosquitto.crt keyfile /etc/mosquitto/ssl/mosquitto.key require_certificate true use_identity_as_username true
Запускаем серис:
service mosquitto start
Также, если требуется, можно сделать чтобы локальный mosquitto сервер на контроллере форвардил некоторые топики на удаленный сервер. Для этого создаем файл бриджа: /etc/mosquitto/bridge.conf
connection main topic test/# out address example.com:1883 bridge_cafile /etc/mosquitto/certs/ca.crt bridge_certfile /etc/mosquitto/certs/device_AP6V5MDG.crt bridge_keyfile engine:ateccx08:ATECCx08:00:04:C0:00
После перезапуска локального сервиса mosquitto топики /test/.. будут отправлятся на удаленный сервер example.com по защищенному ssl каналу.
Примеры клиентских команд mosquitto. Отправка сообщения "message" в топик "test" на сервере example.com
mosquitto_pub -h example.com --cert device_AP6V5MDG.crt --key 'engine:ateccx08:ATECCx08:00:04:C0:00' --cafile ca.crt -t "test" -m "message"
Получение сообщений из топика "test" на сервере example.com
mosquitto_sub -h example.com --cert device_AP6V5MDG.crt --key 'engine:ateccx08:ATECCx08:00:04:C0:00' -t "test" --cafile ca.crt