Octoprint publishing
Публикация octoprint
Печать идёт очень долго, но находиться рядом с принтером не всегда возможно, эта инструкция для тех кто хочет иметь возможность удалённого управления принтером.
Для удалённого управления можно использовать два варианта.
- Подключить принтер к компьютеру по usb, а к компьютеру подключаться удалённо по RDP или TeamViewer-у или аналогам.
- Подключить принтер к специальному принт-серверу OctoPrint https://octoprint.org
Рассмотрим второй вариант.
О том как правильно удалённо управлять принтером используя OctoPrint есть официальный ответ разработчиков есть тут https://octoprint.org/blog/2018/09/03/safe-remote-access/
Если вкратце то они советуют использовать плагины для OctoPrint, такие как "Polar Cloud", "OctoPrint Anywhere", "Telegram" и другие.
Используя плагины вы перекладываете вопрос по безопасности на сторонних людей, которые, теоретически, разбираются в этом вопросе лучше вас.
Поэтому если у вас нет достаточного понимания в том как работает стек протоколов TCP/IP , что такое firewall и как работает шифрование то вам скорее всего лучше использовать плагины, если вы пользуетесь месседжером Телеграмм то наиболее удобно использовать бота для управления вашим принтером.
Дале инструкция для тех у кого уже есть установленный OctoPrint но по какой либо причине необходимо опубликовать свой принтер на своём оборудовании.
Рассмотрим какие могут быть варианты с точки зрения безопасности
Публикация порта Octoprint на роутере без ssl | Очень низкая безопасность |
Публикация через Nginx с самоподписанным сертификатом | Низкая безопасность |
Публикация через Nginx с самоподписанным сертификатом + Basic авторизация | Достаточно высокая безопасность при соблюдении ряда условий |
Публикация через Nginx с сертификатом LetsEncrypt (либо с любым платным сертификатом) + Basic авторизация | Высокая безопасность |
Стратегия повышения безопасности сводится к тому чтобы отдалить атакующего от ненадёжного приложения, такого как octoprint.
Для этого лучше всего использовать nginx либо любой другой прокси сервер который поддерживает SSL и basic авторизацию, можно и авторизацию по сертификатам, но если вы знаете как это работаете то скорее всего вам эта инструкция не нужна.
Я буду рассматривать вариант "Публикация через Nginx с самоподписанным сертификатом + Basic авторизация" поскольку не у всех есть возможность использовать доменное имя, а какой именно сертификат самоподписанный или любой другой с точки зрения настроек сервера значения не имеет.
В конечном итоге нам нужно сделать так чтобы запрос приходил на наш Nginx, он проверит авторизацию посредством basic авторизации, и если всё верно пропустит до octoprint или mjpg_streamer.
Начнём с установки Nginx и необходимых пакетов, я предполагаю что у вас Debian based образ либо Raspberry либо Armbian.
apt install nginx-light apache2-utils
Сгенерируем самоподписанный сертифекат, этот этап можно пропустить если у вас уже есть другой сертификат.
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/nginx/ssl/nginx.key -out /etc/nginx/ssl/nginx.crt
Создадим файл с логином и паролем, логин и пароль должны быть достаточно сложными, поскольку это основная защита от атакующего.
htpasswd -c /etc/nginx/.htpasswd secretoctoprintuser
настроим nginx
создадим директорию
mkdir /etc/nginx/snippets
в ней создадим файл /etc/nginx/snippets/self-signed.conf в котором укажем путь до сертификата
ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt; ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;
поскольку на arm архитектуре очень часто нет аппаратной поддержки шифрования aes настроим ssl на алгоритм chacha20 который в 3 раза быстрее aes.
/etc/nginx/snippets/ssl-params.conf
ssl_protocols TLSv1.2; ssl_prefer_server_ciphers on; #ssl_dhparam /etc/nginx/dhparam.pem; ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-CHACHA20-POLY1305:RSA-PSK-CHACHA20-POLY1305:DHE-PSK-CHACHA20-POLY1305:ECDHE-PSK-CHACHA20-POLY1305:PSK-CHACHA20-POLY1305:ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384'; ssl_ecdh_curve secp384r1; # Requires nginx >= 1.1.0 ssl_session_timeout 10m; ssl_session_cache shared:SSL:10m; ssl_session_tickets off; # Requires nginx >= 1.5.9 ssl_stapling on; # Requires nginx >= 1.3.7 ssl_stapling_verify on; # Requires nginx => 1.3.7 resolver 8.8.8.8 8.8.4.4 valid=300s; resolver_timeout 5s; # Disable strict transport security for now. You can uncomment the following # line if you understand the implications. # add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"; add_header X-Frame-Options DENY; add_header X-Content-Type-Options nosniff; add_header X-XSS-Protection "1; mode=block";
создадим файл с настройками проксирования для octoprint /etc/nginx/snippets/octoprint.conf
октопринт настроен слушать на локальном ip 127.0.0.1 порт 5000
proxy_pass http://127.0.0.1:5000/; # make sure to add trailing slash here! proxy_set_header Host $http_host; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Scheme $scheme; #proxy_set_header X-Script-Name /octoprint; proxy_http_version 1.1; client_max_body_size 0;
отредактируем файл /etc/nginx/sites-enabled/default
раскомментируем строку listen 443 ssl default_server;
а после строки
# include snippets/snakeoil.conf;
добавим
include snippets/self-signed.conf; include snippets/ssl-params.conf;
заменим location /
таким содержимым
auth_basic "auth:"; auth_basic_user_file /etc/nginx/.htpasswd; location /video { proxy_buffering off; proxy_pass http://127.0.0.1:8080/?action=stream; } location / { include snippets/octoprint.conf; }
здесь мы так же определили location для mjpg_streamer, который настроим ниже.
создадим пользователя и пароль для доступа к серверу
htpasswd -с /etc/nginx/.htpasswd myoctoprintuser
теперь nginx настроен можно перезапускать
systemctl restart nginx
настроим mjpeg_streamer
для запуска сервиса будем использовать вот такой скрипт /usr/lib/systemd/system/mjpg_streamer\@.service
[Unit] Description=A server for streaming Motion-JPEG from a video capture device After=network.target Wants=dev-video0.device After=dev-video0.device [Service] Environment="LD_LIBRARY_PATH=/usr/lib/mjpg-streamer" User=mjpg_streamer #ExecStart=/usr/bin/mjpg_streamer -i '/usr/lib/mjpg-streamer/input_uvc.so -d /dev/%I -r 1280x720 -q 85 -timeout 10 -dv_timings' -o '/usr/lib/mjpg-streamer/output_http.so -l 127.0.0.1 -p 8080 -w /usr/share/mjpg_streamer/www' ExecStart=/usr/bin/mjpg_streamer -i '/usr/lib/mjpg-streamer/input_uvc.so -d /dev/%I -r 640x480 -q 50' -o '/usr/lib/mjpg-streamer/output_http.so -l 127.0.0.1 -p 8080 -w /usr/share/mjpg_streamer/www' [Install] WantedBy=multi-user.target
для того чтобы mjpg_streamer работал с устройством /dev/video0
нужно выполнить
systemctl enable mjpg_streamer\@video0.service
systemctl start mjpg_streamer\@video0.service
настроим octoprint чтобы слушал только локальный ip, после этой операции доступ к octoprint будет только через nginx
в файле конфигурации octoprint, у меня это
/home/octoprint/.octoprint/config.yaml
в секции server:
добавим или заменим два параметра
host: 127.0.0.1 port: 5000
в секции webcam:
изменим два параметра для видео потока
snapshot: http://127.0.0.1:8080/?action=snapshot stream: /video
после этого перезапустим octoprint