Octoprint publishing
Содержание
Публикация octoprint
Печать идёт очень долго, но находиться рядом с принтером не всегда возможно, эта инструкция для тех кто хочет иметь возможность удалённого управления принтером.
Для удалённого управления можно использовать два варианта.
- Подключить принтер к компьютеру по usb, а к компьютеру подключаться удалённо по RDP или TeamViewer-у или аналогам.
- Подключить принтер к специальному принт-серверу OctoPrint https://octoprint.org
Рассмотрим второй вариант.
Наиболее простой способ установить Octoprint, скачать официальный образ для миникомпьютера raspberry pi, причём желательно raspberry pi 3.
Также подойдёт китайский аналог orange pi 4х ядерный с 1Гб оперативной памяти. (фактически для работы octoprint требуется порядка 150Мб оперативной памяти, но для компиляции модулей python требуется больше), но устанавливать linux и octoprint придётся самостоятельно.
О том как правильно удалённо управлять принтером используя 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 fail2ban
Сгенерируем самоподписанный сертифекат
этот этап можно пропустить если у вас уже есть другой сертификат.
sudo mkdir /etc/nginx/ssl
sudo openssl req -x509 -nodes -days 7300 -newkey rsa:2048 -keyout /etc/nginx/ssl/nginx.key -out /etc/nginx/ssl/nginx.crt
все поля можно заполнять произвольными значениями кроме вопроса
Common Name (e.g. server FQDN or YOUR name) []: my.ender3.club
тут лучше всего указать dns адрес по которому будет доступен ваш принтер в интернете, если у вас такого адреса нет то его нужно придумать (например my.ender3.club).
В последствии самоподписанный сертификат можно импортировать в "корневые доверенные центры сертификации" а dns имя прописать в файле c:\windows\system32\drivers\etc\hosts.
например
my.ender3.club 111.222.111.222
Таким образом вы сможете подключаться к принтеру и будете защищены от подмены сертификата, несмотря на то что сертификат самоподписанный.
Кроме того это единственный способ как заставить работать cura с самоподписанным сертификатом.
настроим nginx
Создадим файл с логином и паролем, логин и пароль должны быть достаточно сложными, поскольку это основная защита от атакующего.
sudo htpasswd -c /etc/nginx/.htpasswd secretoctoprintuser
создадим директорию
sudo mkdir /etc/nginx/snippets
в ней создадим файл sudo nano /etc/nginx/snippets/self-signed.conf в котором укажем путь до сертификата
ssl_certificate /etc/nginx/ssl/nginx.crt; ssl_certificate_key /etc/nginx/ssl/nginx.key;
поскольку на arm архитектуре очень часто нет аппаратной поддержки шифрования aes настроим ssl на алгоритм chacha20 который в 3 раза быстрее aes.
sudo nano /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";
Небольшое отступление. Для работы ssl этой настройки достаточно, но для повышения безопасности сервера лучше всего с генерировать дополнительный ключ командой sudo openssl dhparam -out /etc/nginx/dhparam.pem 2048 но это займёт достаточно много времени а после этого раскомментировать строку "ssl_dhparam /etc/nginx/dhparam.pem;" в файле /etc/nginx/snippets/ssl-params.conf , а затем перезапустить nginx командой sudo systemctl restart nginx сейчас этого можно не делать, но после того как всё настроите не забудьте сделать этот шаг.
создадим файл с настройками проксирования для octoprint sudo nano /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;
отредактируем файл sudo nano /etc/nginx/sites-enabled/default
отключим порт 80
#listen 80 default_server; #listen [::]:80 default_server;
включим порт 443, для этого раскомментируем строку 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, который настроим ниже.
теперь nginx настроен можно перезапускать
systemctl restart nginx
настроим mjpeg_streamer
для запуска сервиса будем использовать вот такой скрипт sudo nano /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
скрипт запуска имеет зависимость от устройства video0 для того чтобы это работало необходимо чтобы udev сообщил systemd когда это устройство появится
для этого создадим файл sudo nano /etc/udev/rules.d/99-v4lsystemd.rules с таким содержимым
KERNEL=="video*", SUBSYSTEM=="video4linux", SUBSYSTEMS=="usb", TAG+="systemd"
для того чтобы mjpg_streamer работал с устройством /dev/video0
нужно выполнить
systemctl enable mjpg_streamer\@video0.service
systemctl start mjpg_streamer\@video0.service
настроим octoprint
так чтобы слушал только локальный ip, после этой операции доступ к octoprint будет только через nginx
в файле конфигурации octoprint, у меня это
nano /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
fail2ban
для того чтобы защититься от подбора пароля настроим fail2ban
sudo nano /etc/fail2ban/jail.d/nginx-http-auth.conf
[nginx-http-auth] enabled = true
sudo systemctl restart fail2ban
firewall
если вы публикуете octoprint на роутере, то достаточно пробросить только один порт например внешний порт роутера 9090 пробросить на внутренний порт octoprint 443 (этот порт слушает nginx), настраивать firewall на самом octoprint необязательно.
Но если у вас сервер octoprint имеет белый ip адрес, т.е непосредственно подключен к сети internet то дополнительно необходимо настроить firewall на самом octoprint сервере.
наиболее удобный для этого shorewall
apt install shorewall
о том как он настраивается лучше всего почитать в документации или в статье https://www.opennet.ru/base/net/shorewall.txt.html