Octoprint publishing

Материал из Ender 3 Wiki
Перейти к навигации Перейти к поиску

Публикация octoprint

Печать идёт очень долго, но находиться рядом с принтером не всегда возможно, эта инструкция для тех кто хочет иметь возможность удалённого управления принтером.

Для удалённого управления можно использовать два варианта.

  1. Подключить принтер к компьютеру по usb, а к компьютеру подключаться удалённо по RDP или TeamViewer-у или аналогам.
  2. Подключить принтер к специальному принт-серверу 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