Перейти к содержанию

Навигация

CryptodevATECCx08 Auth: различия между версиями

Нет описания правки
Метка: visualeditor
(не показано 9 промежуточных версий 4 участников)
Строка 1: Строка 1:
<languages/>
<translate>
== Использование встроенного чипа ATECCx08 для авторизации на внешних сервисах. == <!--T:1-->


== Использование встроенного чипа ATECCx08 для авторизации на внешних сервисах. ==
<!--T:2-->
 
В контроллеры '''WirenBoard''' встроен чип '''ATECCx08''', назначением которого является генерация ключевых пар, хранение приватных ключей а также операции асимметричного шифрования с использованием эллиптических кривых.
В контроллеры '''WirenBoard''' встроен чип '''ATECCx08''', назначением которого является генерация ключевых пар, хранение приватных ключей а также операции асимметричного шифрования с использованием эллиптических кривых.
Приватный ключ после начальной инициализации хранится в микросхеме и не покидает ее, тем самым исключается его компрометация.
Приватный ключ после начальной инициализации хранится в микросхеме и не покидает ее, тем самым исключается его компрометация.


<!--T:3-->
Используя данную микросхему можно организовать авторизацию контроллера и защиту соединения по SSL на внешних сервисах и быть уверенным, что запрос выполнен с использованием именно этого экземпляра микросхемы.
Используя данную микросхему можно организовать авторизацию контроллера и защиту соединения по SSL на внешних сервисах и быть уверенным, что запрос выполнен с использованием именно этого экземпляра микросхемы.


<!--T:4-->
В данной статье пойдет речь о трех вариантах применения: '''nginx''', '''openssl''', '''mosquitto'''.
В данной статье пойдет речь о трех вариантах применения: '''nginx''', '''openssl''', '''mosquitto'''.


<!--T:5-->
Для доступа к криптоустройству нужна библиотека libateccssl1.1, установим ее командой:
Для доступа к криптоустройству нужна библиотека libateccssl1.1, установим ее командой:


<!--T:6-->
'''apt install libateccssl1.1'''
'''apt install libateccssl1.1'''


<!--T:7-->
Далее нужно отредактировать файл '''/etc/ssl/openssl.cnf''', добавив в нем следующие строчки:
Далее нужно отредактировать файл '''/etc/ssl/openssl.cnf''', добавив в нем следующие строчки:


<!--T:8-->
<pre>
<pre>
openssl_conf = openssl_init
openssl_conf = openssl_init


<!--T:9-->
[openssl_init]
[openssl_init]
engines        = engine_section
engines        = engine_section


<!--T:10-->
[engine_section]
[engine_section]
ateccx08 = ateccx08_section
ateccx08 = ateccx08_section


<!--T:11-->
[ateccx08_section]
[ateccx08_section]
init = 1
init = 1
</pre>
</pre>


<!--T:12-->
Теперь приступим к созданию сертификатов.
Теперь приступим к созданию сертификатов.
Для начала создадим свой центр сертификации (Certification Authority, '''CA'''):
Для начала создадим свой центр сертификации (Certification Authority, '''CA'''):


<!--T:13-->
Для этого сгенерируем ключевую пару:
Для этого сгенерируем ключевую пару:
<pre>openssl genrsa -out ca.key 2048</pre>
<pre>openssl genrsa -out ca.key 2048</pre>


<!--T:14-->
И сертификат нашего '''CA''':
И сертификат нашего '''CA''':


<!--T:15-->
<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>


<!--T:16-->
'''CA''' является основой безопасности в данной схеме, поэтому эти операции выполняем на машине доступ к которой
'''CA''' является основой безопасности в данной схеме, поэтому эти операции выполняем на машине доступ к которой
есть только у владельца '''CA'''.
есть только у владельца '''CA'''.


<!--T:17-->
Далее на конроллере WB создаем запрос на сертификат устройства:
Далее на конроллере WB создаем запрос на сертификат устройства:
<!--T:18-->
Для Wiren Board 7:
<pre>openssl req -new -engine ateccx08 -keyform engine -key ATECCx08:00:02:C0:00 -subj "/CN=wirenboard-AP6V5MDG" -out device_AP6V5MDG.csr</pre>
Для Wiren Board 6:


<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>


<!--T:19-->
В этой команде мы указываем, что запрос подписывается приватным ключом, находящимся в криптоустройстве ateccx08 ключом
В этой команде мы указываем, что запрос подписывается приватным ключом, находящимся в криптоустройстве ateccx08 ключом
с идентификатором '''ATECCx08:00:04:C0:00''' и публичным именем wirenboard-AP6V5MDG. Запрос помещаем в файл device_AP6V5MDG.csr.
с идентификатором '''ATECCx08:00:02:C0:00''' и публичным именем wirenboard-AP6V5MDG. Запрос помещаем в файл device_AP6V5MDG.csr.


<!--T:20-->
Имя можно выбрать любое уникальное, удобно для этой цели спользовать идентификатор устройства, который по умолчанию прописывается
Имя можно выбрать любое уникальное, удобно для этой цели спользовать идентификатор устройства, который по умолчанию прописывается
в файле /etc/hostname:
в файле /etc/hostname:


<!--T:21-->
<pre>
<pre>
cat /etc/hostname
cat /etc/hostname
Строка 56: Строка 84:
</pre>
</pre>


<!--T:22-->
Далее этот запрос подписываем в нашем центре сертификации:
Далее этот запрос подписываем в нашем центре сертификации:
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


<!--T:23-->
В этой команде мы уазываем файл запроса, и файлы CA необходимые для подписи. В итоге получаем сертификат устройства device_AP6V5MDG.crt.
В этой команде мы уазываем файл запроса, и файлы CA необходимые для подписи. В итоге получаем сертификат устройства device_AP6V5MDG.crt.
Файл '''device_AP6V5MDG.crt''' копируем на контроллер WB, он будет необходим для авторизацци.
Файл '''device_AP6V5MDG.crt''' копируем на контроллер WB, он будет необходим для авторизацци.


<!--T:24-->
Давайте посмотрим, что содержится в файлах сертификатов CA и устройства:
Давайте посмотрим, что содержится в файлах сертификатов CA и устройства:


<!--T:25-->
<pre>
<pre>
openssl x509 -text -noout -in device_AP6V5MDG.crt
openssl x509 -text -noout -in device_AP6V5MDG.crt


<!--T:26-->
Certificate:
Certificate:
     Data:
     Data:
Строка 107: Строка 140:
</pre>
</pre>


<!--T:27-->
Видим, что сертификат выписан Центром сертификации с именем "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.
Сертификат подписан цифровой подписью.  
Сертификат подписан цифровой подписью.  


<!--T:28-->
Цифровая подпись гарантирует, что никакая часть сертификата не может быть незаметно изменена. В случае изменения проверка публичным
Цифровая подпись гарантирует, что никакая часть сертификата не может быть незаметно изменена. В случае изменения проверка публичным
ключом '''CA''' даст ошибку.
ключом '''CA''' даст ошибку.


<!--T:29-->
<pre>
<pre>
openssl x509 -text -noout -in ca.crt
openssl x509 -text -noout -in ca.crt


<!--T:30-->
Certificate:
Certificate:
     Data:
     Data:
Строка 157: Строка 194:
                 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
             <!--T:31-->
X509v3 Basic Constraints: critical
                 CA:TRUE
                 CA:TRUE
     Signature Algorithm: sha256WithRSAEncryption
     Signature Algorithm: sha256WithRSAEncryption
Строка 177: Строка 215:
</pre>
</pre>


<!--T:32-->
Видим, что сертификат подписан сам своим-же приватным ключом (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 в команде подписи)


<!--T:33-->
Таким образом цепочка доверия (проверки) выстраивается следующим образом:
Таким образом цепочка доверия (проверки) выстраивается следующим образом:


<!--T:34-->
Сертификат устройства подписан сертификатом CA и может быть им проверен:
Сертификат устройства подписан сертификатом CA и может быть им проверен:
<pre>
<pre>
Строка 188: Строка 229:
</pre>
</pre>


<!--T:35-->
Ну а сам сертификат подписан "собой":
Ну а сам сертификат подписан "собой":
<pre>
<pre>
Строка 195: Строка 237:
'''
'''


== Проверка сертификатов на сервере с помощью nginx . == <!--T:36-->


== Настройка nginx. ==
<!--T:37-->
 
Допустим в интернете есть сервер, который должен обрабатывать запросы только от устройств обладающих сертификатами,
Допустим в интернете есть сервер, который должен обрабатывать запросы только от устройств обладающих сертификатами,
выписанными нашим CA.
выписанными нашим CA.
Для включения такой проверки в конфигурационном файле nginx необходимо в секции http или server прописать следующие строчки:
Для включения такой проверки в конфигурационном файле nginx необходимо в секции http или server прописать следующие строчки:


<!--T:38-->
<pre>
<pre>
   ssl_client_certificate  ca.crt;
   ssl_client_certificate  ca.crt;
Строка 207: Строка 250:
</pre>
</pre>


<!--T:39-->
Теперь nginx будет требовать от клиента сертификат, который должен проходить проверку с помощью ca.crt, иначе сервер
Теперь nginx будет требовать от клиента сертификат, который должен проходить проверку с помощью ca.crt, иначе сервер
вернет клиенту ошибку 400:
вернет клиенту ошибку 400:


<!--T:40-->
<pre>
<pre>
curl https://example.com
curl https://example.com
Строка 222: Строка 267:
</pre>
</pre>


Nginx в такой конфигурации удобно использовать на сервере перед реальным сервисом, которые не поддерживают проверку клиентских сертификатов. Для этого нужно настроить proxy_pass на сам сервис и, например, добавить в заголовки серийный номер контроллера через переменную <code>$ssl_client_s_dn</code> или весь клиентский сертификат целиком.
== Добавление поддержки клиентских сертификатов к произвольным сервисам на контроллере ==
Часто программы на контролелере не поддерживают TLS совсем, либо не поддерживают указание клиентских сертификатов, либо не поддерживают работу с openssl engine.
Можно отправить обращения от таких программ к серверу сквозь локальный прокси, который будет оборачивать трафик в TLS с использованием аппаратных ключей.
Вместе с рецептом из предыдущего пункта, это позволяет реализовать аутентификацию по аппаратному ключу практически для любого клиент-серверного ПО.
<!--T:41-->
Теперь сделаем так, чтобы HTTP запросы с контроллера WB проходили данную проверку.
Теперь сделаем так, чтобы HTTP запросы с контроллера WB проходили данную проверку.
Для простоты будем использовать nginx и на клиентской стороне. Это даст возможность работать
Для простоты будем использовать nginx и на клиентской стороне. Это даст возможность работать
с защищенными серверами клиентам не умеющим делать SSL соединения.
с защищенными серверами клиентам не умеющим делать SSL соединения.


<!--T:42-->
Для начала создадим на неиспользуемом локальном порту http сервер, который будет делать
Для начала создадим на неиспользуемом локальном порту http сервер, который будет делать
всю https "магию" за нас:
всю https "магию" за нас:


<!--T:43-->
<pre>
<pre>
server {
server {
Строка 242: Строка 299:
</pre>
</pre>


<!--T:44-->
Добавим пользователя www-data в группу i2c для доступа к криптоустройству:
Добавим пользователя www-data в группу i2c для доступа к криптоустройству:
<pre>
<pre>
Строка 247: Строка 305:
</pre>
</pre>


<!--T:45-->
Выполним команду '''service nginx restart''' для обновления конфигурации.
Выполним команду '''service nginx restart''' для обновления конфигурации.


<!--T:46-->
Теперь при обращении по http на локальный порт 8080 зашифрованные запросы с аутентификационной
Теперь при обращении по http на локальный порт 8080 зашифрованные запросы с аутентификационной
информацией будут отправлятся на сервер example.com.
информацией будут отправлятся на сервер example.com.


<!--T:47-->
<pre>
<pre>
curl localhost:8080/
curl localhost:8080/
Строка 261: Строка 322:
</pre>
</pre>


== Настройка openvpn ==
== Настройка openvpn == <!--T:48-->


<!--T:49-->
Для начала установим пакет:
Для начала установим пакет:


<!--T:50-->
<pre>
<pre>
apt install openvpn
apt install openvpn
</pre>
</pre>


<!--T:51-->
Cоздадим файл req.cnf - он нам потребуется для создания сертификата сервера.  
Cоздадим файл req.cnf - он нам потребуется для создания сертификата сервера.  
<pre>
<pre>
Строка 277: Строка 341:
</pre>
</pre>


<!--T:52-->
Серверу openvpn также требуется файл с параметрами DH, сделаем его.
Серверу openvpn также требуется файл с параметрами DH, сделаем его.
<pre>
<pre>
Строка 282: Строка 347:
</pre>
</pre>


<!--T:53-->
Создание данного файла может потребовать несколько минут.  
Создание данного файла может потребовать несколько минут.  


<!--T:54-->
Далее сделаем приватный ключ нашего сервера и запрос на сертификат. Предполагаем, для примера, что
Далее сделаем приватный ключ нашего сервера и запрос на сертификат. Предполагаем, для примера, что
сервер имеет имя example.com:
сервер имеет имя example.com:


<!--T:55-->
<pre>  
<pre>  
openssl genrsa -out example.key 2048
openssl genrsa -out example.key 2048


<!--T:56-->
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>


<!--T:57-->
Подписываем запрос в нашем центре сертификации:
Подписываем запрос в нашем центре сертификации:


<!--T:58-->
<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>


<!--T:59-->
Теперь приступим к настройке openvpn сервера на машине example.com.
Теперь приступим к настройке openvpn сервера на машине example.com.


<!--T:60-->
Копируем файлы '''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


<!--T:61-->
<pre>
<pre>
port 1194
port 1194
Строка 328: Строка 402:
</pre>
</pre>


<!--T:62-->
Добавим пользователя openvpn в группу i2c для доступа к криптоустройству:
Добавим пользователя openvpn в группу i2c для доступа к криптоустройству:


<!--T:63-->
<pre>
<pre>
usermod -G www-data
usermod -G www-data
</pre>
</pre>


<!--T:64-->
после этого запускаем сервер командой  
после этого запускаем сервер командой  
service openvpn start.
service openvpn start.


<!--T:65-->
Далее на контроллере создаем файл конфигурации клиента:
Далее на контроллере создаем файл конфигурации клиента:
client.ovpn:
client.ovpn:
<pre>
-------------------------------------------------------------------------
-------------------------------------------------------------------------
client
client
Строка 357: Строка 436:
comp-lzo
comp-lzo
-------------------------------------------------------------------------
-------------------------------------------------------------------------
 
</pre>
Обратите внимание на строчку group i2c. Она необходима для работы с криптоустройством.
Обратите внимание на строчку group i2c. Она необходима для работы с криптоустройством.


<!--T:66-->
После этого запускаем клиента:
После этого запускаем клиента:


<!--T:67-->
<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>


<!--T:68-->
Если все хорошо, то в системе должен появиться интерфейс tun0 с адресом из подсети 10.8.0.0/24:
Если все хорошо, то в системе должен появиться интерфейс tun0 с адресом из подсети 10.8.0.0/24:


<!--T:69-->
<pre>
<pre>
tun0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST>  mtu 1500
tun0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST>  mtu 1500
Строка 379: Строка 462:
</pre>
</pre>


<!--T:70-->
Для проверки работоспособности запускаем ping:
Для проверки работоспособности запускаем ping:


<!--T:71-->
<pre>
<pre>
ping 10.8.0.1
ping 10.8.0.1
Строка 388: Строка 473:
</pre>
</pre>


== Настройка mosquitto ==
== Настройка mosquitto == <!--T:72-->
 
<!--T:73-->
UPD:
 
<!--T:74-->
1) openssl.cnf
 
<!--T:75-->
2)  mosquitto=1.4.15-1+wb7-4


<!--T:76-->
3) libateccssl1.1=0.2.1
<!--T:77-->
4) ca-certificates-contactless
<!--T:78-->
5) usermod -a -G i2c mosquitto
<!--T:79-->
<pre>
root@wirenboard-APIJVTIG:~# cat /etc/mosquitto/conf.d/bridge-hw.conf
connection wb_devices_cloud.wirenboard-APIJVTIG
address contactless.ru:8884
<!--T:80-->
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
<!--T:81-->
notifications true
notification_topic /client/wirenboard-APIJVTIG/bridge_status
<!--T:82-->
topic /devices/#  both 2 "" /client/wirenboard-APIJVTIG
topic /config/#  both 2 "" /client/wirenboard-APIJVTIG
topic /rpc/#  both 2 "" /client/wirenboard-APIJVTIG
</pre>
<!--T:83-->
<pre>
root@wirenboard-APIJVTIG:~# cat fix.sh
#!/bin/bash -x
CERT_IN=/etc/ssl/certs/device_bundle.crt.pem
CERT_OUT=/etc/ssl/device/device_bundle.crt.pem
CERT_BKP=/etc/ssl/device/_device_bundle.crt.pem
<!--T:84-->
prn() {
    cat $CERT_IN|grep "$1" -n|sed -n "$2p"|cut -d':' -f1
}
<!--T:85-->
fix() {
    B1=$(prn "BEGIN CERTIFICATE" 1)
    B2=$(prn "BEGIN CERTIFICATE" 2)
    E1=$(prn "END CERTIFICATE" 1)
    E2=$(prn "END CERTIFICATE" 2)
    <!--T:86-->
if [[ "$E1" -le "$B1" || "$E2" -le "$B2" || "$E1" -ge "$B2" ]]; then
        echo "ERROR in device cert bundle."
        exit 1
    fi
    <!--T:87-->
cat $CERT_IN|sed -n "${B2},${E2}p"
    cat $CERT_IN|sed -n "${B1},${E1}p"
}
<!--T:88-->
mkdir -p /etc/ssl/device
<!--T:89-->
if [ -f "$CERT_IN" ]; then
    echo "backup device bundle certificate..."
    cp "$CERT_IN" "$CERT_BKP"
fi
<!--T:90-->
if [ ! -f "$CERT_OUT" ]; then
    if [ ! -f "$CERT_IN" ]; then
        echo "ERROR: no such file: $CERT_IN"
        exit 1
    fi
    fix > "$CERT_OUT"
    echo "Device bundle certificate fix done."
    rm -f "${CERT_IN}"
else
    echo "Device cert $CERT_OUT already fixed."
fi
</pre>
<!--T:91-->
Генерируем приватный ключ и запрос на сертификат:
Генерируем приватный ключ и запрос на сертификат:


<!--T:92-->
<pre>
<pre>
openssl genrsa -out example.key 2048
openssl genrsa -out example.key 2048
Строка 397: Строка 580:
</pre>
</pre>


<!--T:93-->
Создаем сертификат сервера в CA.
Создаем сертификат сервера в CA.
<pre>
<pre>
Строка 402: Строка 586:
</pre>
</pre>


Копируем файлы '''ca.crt''', '''mosquitto.crt''', '''mosquitto.key''' на сервер и редактируем файл конфигурации:
<!--T:94-->
 
Копируем файлы '''ca.crt''', '''mosquitto.crt''', '''mosquitto.key''' на сервер и редактируем файл конфигурации '''/etc/mosquitto/conf.d/server.conf'''
/etc/mosquitto/conf.d/server.conf


<!--T:95-->
<pre>
<pre>
cafile                      /etc/mosquitto/ssl/ca.crt
cafile                      /etc/mosquitto/ssl/ca.crt
Строка 414: Строка 598:
</pre>
</pre>


<!--T:96-->
Запускаем серис:
Запускаем серис:
<pre>
<pre>
Строка 419: Строка 604:
</pre>
</pre>


<!--T:97-->
Также, если требуется, можно сделать чтобы локальный mosquitto сервер на контроллере
Также, если требуется, можно сделать чтобы локальный mosquitto сервер на контроллере
форвардил некоторые топики на удаленный сервер. Для этого создаем файл бриджа: '''/etc/mosquitto/bridge.conf'''
форвардил некоторые топики на удаленный сервер. Для этого создаем файл бриджа: '''/etc/mosquitto/bridge.conf'''


<!--T:98-->
<pre>
<pre>
connection main
connection main
Строка 427: Строка 614:
address example.com:1883
address example.com:1883


<!--T:99-->
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
Строка 432: Строка 620:
</pre>
</pre>


<!--T:100-->
После перезапуска локального сервиса mosquitto топики /test/.. будут отправлятся на удаленный сервер example.com
После перезапуска локального сервиса mosquitto топики /test/.. будут отправлятся на удаленный сервер example.com
по защищенному ssl каналу.
по защищенному ssl каналу.


<!--T:101-->
Примеры клиентских команд mosquitto.
Примеры клиентских команд mosquitto.
Отправка сообщения "message" в топик "test" на сервере example.com  
Отправка сообщения "message" в топик "test" на сервере example.com  


<!--T:102-->
<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>


<!--T:103-->
Получение сообщений из топика "test" на сервере example.com
Получение сообщений из топика "test" на сервере example.com


<!--T:104-->
<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>
</translate>
wb_editors
154

правки