Подключение к удаленному серверу через Python WebSSH

Обычно вы подключаетесь к серверу SSH с помощью приложения командной строки в терминале или эмулятора терминала, который включает в себя клиент SSH. Но есть и другие способы. Например, некоторые инструменты, такие как Python’s WebSSH, позволяют подключаться по SSH и запускать терминал прямо в браузере.

Скачивайте книги ТОЛЬКО на русском языке у нас в телеграм канале: PythonBooksRU

Это может быть полезно в ряде ситуаций. Например, при проведении живых презентаций, когда сложно демонстрировать обычное окно терминала. Это также может быть полезно в образовательных учреждениях при предоставлении доступа к командной строке новичкам, поскольку это избавляет их от необходимости устанавливать программное обеспечение на свои устройства (особенно на Windows, где возможности по умолчанию имеют свои недостатки). И, наконец, WebSSH очень портативен и не имеет никаких зависимостей, кроме Python, для начала работы. Другие веб-терминальные стеки могут быть гораздо сложнее и ориентированы на Linux.

Следуя этому руководству, вы настроите WebSSH и подключитесь по SSH в браузере. Затем вы защитите его SSL-сертификатом и запустите его за обратным прокси-сервером Nginx для производственного развертывания.

Необходимые условия

  • Среда Windows, Mac или Linux с запущенной службой SSH. Может быть полезно запустить WebSSH локально, но если у вас нет службы SSH, запущенной на локальной машине, вы можете использовать удаленный сервер Linux, следуя руководству по первоначальной настройке сервера для Ubuntu 22.04.
  • Язык программирования Python с менеджером пакетов pip.
  • Чтобы включить HTTPS в браузере, вам понадобятся SSL-сертификаты и собственное доменное имя. Если у вас нет собственного доменного имени, вы можете использовать IP-адрес для первых двух шагов этого руководства.

Шаг 1 – Установка WebSSH

Если вы уже установили Python и pip, вы можете устанавливать пакеты Python из PyPI, репозитория программного обеспечения Python. WebSSH предназначен для установки и запуска непосредственно из командной строки, поэтому вам не потребуется настраивать виртуальную среду. Виртуальные среды более полезны при работе над собственными проектами, а не при установке общесистемных инструментов.

Для установки пакета WebSSH используйте pip install:

sudo pip3 install webssh
Output
…
Successfully built webssh
Installing collected packages: tornado, pycparser, cffi, pynacl, paramiko, webssh
Successfully installed cffi-1.15.1 paramiko-2.11.0 pycparser-2.21 pynacl-1.5.0 tornado-6.2 webssh-1.6.0

Установка через sudo приведет к глобальной установке команды wssh. Вы можете убедиться в этом, используя which wssh:

which wssh
Output
/usr/local/bin/wssh

Итак, вы установили WebSSH. В следующем шаге вы запустите его и подключитесь к нему. Однако сначала вам нужно добавить правило брандмауэра. По умолчанию WebSSH работает на порту 8888. Если вы используете ufw в качестве брандмауэра, разрешите этот порт через команду allow ufw:

sudo ufw allow 8888

Мы позже вернемся к этому правилу брандмауэра.

Шаг 2 – Запуск и подключение к WebSSH

Если вы используете WebSSH на локальной машине, вы можете запустить wssh самостоятельно без дополнительных аргументов для запуска. Если вы запускаете WebSSH на удаленном сервере, вам нужно добавить флаг --fbidhttp=False, чтобы разрешить удаленные соединения по обычному HTTP. Подключение по незащищенной сети небезопасно, но подойдет для демонстрации. К тому же, мы обеспечим безопасность WebSSH позже в этом учебнике.

$ wssh --fbidhttp=False

Теперь вы можете подключиться к WebSSH и войти в систему. Перейдите по адресу your_domain:8888 в браузере (используйте localhost вместо your_domain (вашего домена), если вы работаете локально). Вы должны увидеть страницу входа в WebSSH:

Укажите свои учетные данные SSH. Если вы следовали руководству по первоначальной настройке сервера, вам нужно использовать аутентификацию на основе ключа, а не пароля. Это означает, что вам нужно указать только Hostname сервера, к которому вы подключаетесь, ваше имя пользователя (Username) для сервера и ваш SSH-ключ, который должен находиться в директории .ssh/ в вашем локальном домашнем каталоге (обычно под именем id_rsa).

Примечание: Как вы уже догадались по необходимости вручную указывать имя хоста, WebSSH также может использоваться для подключения к любым серверам, не обязательно к тому, на котором он запущен. В данном руководстве он запускается на том же сервере, к которому вы подключаетесь.

Нажмите кнопку Connect, и перед вами появится приветственное приглашение терминала по умолчанию:

В этот момент вы можете использовать свой терминал как обычно, точно так же, как если бы вы подключились по SSH. Несколько пользователей могут одновременно подключаться через один и тот же экземпляр WebSSH.

Если вы используете WebSSH на локальной машине исключительно для потоковой передачи или захвата видео, это может быть все, что вам нужно. Вы можете ввести Ctrl+C в терминале, из которого вы запустили WebSSH (не в терминале WebSSH), чтобы остановить сервер WebSSH после завершения работы.

Если вы работаете на удаленном сервере, вы не захотите использовать WebSSH в производственной среде через незащищенное HTTP-соединение. Хотя вы все равно будете защищены механизмом аутентификации службы SSH, использование SSH-соединения через HTTP представляет значительный риск для безопасности и, скорее всего, позволит злоумышленникам украсть ваши учетные данные SSH. В следующих шагах мы защитим WebSSH так, чтобы он был не менее безопасен, чем обычное SSH-соединение.

Шаг 3 (необязательный) – Защита WebSSH с помощью SSL-сертификата

Чтобы выполнить этот шаг, вы уже должны были получить собственное доменное имя и SSL-сертификаты. Один из способов сделать это – использовать LetsEncrypt в автономном режиме.

Когда LetsEncrypt получает сертификаты, по умолчанию он сохраняет их в /etc/letsencrypt/live/your_domain. Проверьте, есть ли они у вас:

$ sudo ls /etc/letsencrypt/live/your_domain
Output
README  cert.pem  chain.pem  fullchain.pem  privkey.pem

Чтобы запустить WebSSH с поддержкой HTTPS, вам нужно указать путь к сертификату и путь к ключу. Это fullchain.pem и privkey.pem. По умолчанию WebSSH предоставляет доступ к HTTPS через порт 4433, поэтому откройте этот порт в брандмауэре:

$ sudo ufw allow 4433

Затем запустите WebSSH с путями к вашему сертификату и ключу (замените your_domain на название вашего домена):

$ sudo wssh --certfile='/etc/letsencrypt/live/your_domain/fullchain.pem' --keyfile='/etc/letsencrypt/live/your_domain/privkey.pem'

В браузере перейдите по адресу https://your_domain:4433, и вы увидите тот же интерфейс, что и в предыдущем шаге, но теперь с поддержкой HTTPS. Теперь этого достаточно для безопасной релизной конфигурации.

Однако вы все еще запускаете приложение wssh непосредственно из терминала, а доступ к нему в браузере осуществляется через нестандартный порт. В последних двух шагах этого руководства вы устраните оба этих ограничения.

Шаг 4 (необязательный) – Запуск WebSSH через Nginx

Использование веб-сервера Nginx в проекте может повысить производительность и значительно упростить защиту сайта. Дальше мы установим Nginx и настроим его на обратное проксирование запросов к WebSSH, то есть он будет обрабатывать запросы от пользователей к WebSSH и обратно.

Обновите список пакетов, затем установите Nginx с помощью apt:

$ sudo apt update nginx
$ sudo apt install nginx

Если вы используете брандмауэр ufw, вам следует внести некоторые изменения в конфигурацию на этом этапе, чтобы обеспечить доступ к стандартным портам HTTP/HTTPS, 80 и 443. ufw имеет стоковую конфигурацию под названием “Nginx Full”, которая обеспечивает доступ к обоим этим портам:

$ sudo ufw allow “Nginx Full”

Nginx позволяет добавлять конфигурации для каждого сайта в отдельные файлы в подкаталоге sites-available/. Используя nano или ваш любимый текстовый редактор, создайте новую конфигурацию Nginx по адресу /etc/nginx/sites-available/webssh:

$ sudo nano /etc/nginx/sites-available/webssh

Вставьте следующие данные в новый файл конфигурации, обязательно заменив your_domain на имя вашего домена.

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name your_domain www.your_domain
    root /var/www/html;

    access_log /var/log/nginx/webssh.access.log;
    error_log /var/log/nginx/webssh.error.log;

    location / {
        proxy_pass http://127.0.0.1:8888;
        proxy_http_version 1.1;
        proxy_read_timeout 300;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Real-PORT $remote_port;
    }

    listen 443 ssl;
    # RSA certificate
    ssl_certificate /etc/letsencrypt/live/your_domain/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/your_domain/privkey.pem;

    # Redirect non-https traffic to https
    if ($scheme != "https") {
        return 301 https://$host$request_uri;
    }
}

Вы можете рассматривать эту конфигурацию как состоящую из трех основных блоков. Первый блок, идущий перед строкой location/, содержит шаблонную конфигурацию Nginx для обслуживания веб-сайта на стандартном HTTP-порту 80. Блок location/ содержит конфигурацию для проксирования входящих соединений на WebSSH, который работает на внутреннем порту 8888, при сохранении SSL. Конфигурация в конце файла, после блока location/, настраивает ваши пары ключей LetsEncrypt SSL и перенаправляет HTTP-соединения на HTTPS.

Сохраните и закройте файл. Если вы используете nano, нажмите Ctrl+X, затем, когда появится запрос, Y, а затем Enter.

Далее вам нужно активировать эту новую конфигурацию. В Nginx принято создавать символические ссылки (как ярлыки) из файлов в sites-available/ в другую папку под названием sites-enabled/, когда вы решаете включить или отключить их. Используя полные пути для ясности, создайте такую ссылку:

$ sudo ln -s /etc/nginx/sites-available/webssh /etc/nginx/sites-enabled/webssh

По умолчанию Nginx включает другой конфигурационный файл по адресу /etc/nginx/sites-available/default, связанный с /etc/nginx/sites-enabled/default, который также обслуживает индексную страницу по умолчанию. Давайте избавимся от этого, удалив конфиг из /sites-enabled, поскольку оно конфликтует с вашей новой конфигурацией WebSSH:

$ sudo rm /etc/nginx/sites-enabled/default

Примечание: Конфигурация Nginx в этом руководстве предназначена для обслуживания одного приложения, WebSSH. Вы можете расширить эту конфигурацию Nginx для обслуживания нескольких приложений на одном сервере, следуя Nginx documentation.

Затем запустите nginx -t для проверки конфигурации перед перезапуском Nginx:

$ sudo nginx -t
Outputnginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Теперь вы можете перезапустить службу Nginx, чтобы новая конфигурация вступила в силу:

$ sudo systemctl restart nginx

Наконец, вы можете удалить правила брандмауэра, созданные ранее для прямого доступа к WebSSH, поскольку теперь весь трафик будет обрабатываться Nginx через стандартные порты HTTP/HTTPS:

$ sudo ufw delete allow 8888
$ sudo ufw delete allow 4433

Перезапустите webssh в командной строке:

$ wssh

В этот раз вам не нужно указывать пути к сертификату и ключу, так как этим занимается Nginx. Затем перейдите на ваш домен в браузере.

Обратите внимание, что WebSSH теперь обслуживается по HTTPS через Nginx без необходимости указывать порт. На данном этапе вы автоматизировали все, кроме запуска самого wssh. Вы сделаете это в последнем шаге.

Шаг 5 (необязательный) – Создание службы Systemd для WebSSH

Развертывание серверных приложений, которые не запускаются автоматически в фоновом режиме, может быть поначалу неинтуитивным, поскольку вам придется каждый раз запускать их непосредственно из командной строки. Решением этой проблемы является создание собственной фоновой службы.

Для этого необходимо создать файл модулей, который будет использоваться системой init вашего сервера. Почти во всех современных дистрибутивах Linux система init называется Systemd, и вы можете взаимодействовать с ней с помощью команды systemctl.

Если WebSSH все еще запущен в вашем терминале, нажмите Ctrl+C, чтобы остановить его. Затем, используя nano или ваш любимый текстовый редактор, откройте новый файл /etc/systemd/system/webssh.service:

$ sudo nano /etc/systemd/system/webssh.service

Ваш файл устройства должен содержать, как минимум, разделы [Unit], [Service] и [Install]:

[Unit]
Description=WebSSH terminal interface
After=network.target

[Service]
User=www-data
Group=www-data
ExecStart=wssh

[Install]
WantedBy=multi-user.target

Этот файл можно разбить следующим образом:

  • Раздел [Unit] содержит текстовое описание вашей новой службы, а также параметр After, который указывает, когда она должна быть запущена при старте системы, в данном случае после того, как сетевые интерфейсы вашего сервера заработают.
  • Раздел [Service] указывает, какая команда должна быть запущена, а также какой пользователь должен ее выполнять. В данном случае www-data – это пользователь Nginx по умолчанию на сервере Ubuntu, а wssh – это сама команда.
  • Раздел [Install] содержит только строку WantedBy=multi-user.target, которая работает вместе с партером After в разделе [Unit] для обеспечения запуска службы, когда сервер уже готов принимать логины пользователей.

Сохраните и закройте файл. Теперь вы можете запустить (start) новую службу WebSSH и включить (enable) ее автоматический запуск при загрузке:

$ sudo systemctl start webssh
$ sudo systemctl enable webssh

Используйте systemctl status webssh, чтобы убедиться в успешном запуске. Вы должны получить вывод, аналогичный тому, что был при первом запуске команды в терминале.

$ sudo systemctl status webssh
Output
● webssh.service - WebSSH terminal interface
     Loaded: loaded (/etc/systemd/system/webssh.service; enabled; vendor preset: enabled)
     Active: active (running) since Thu 2022-08-11 22:08:25 UTC; 2s ago
   Main PID: 15678 (wssh)
      Tasks: 1 (limit: 1119)
     Memory: 20.2M
        CPU: 300ms
     CGroup: /system.slice/webssh.service
             └─15678 /usr/bin/python3 /usr/local/bin/wssh

Aug 11 22:08:25 webssh22 systemd[1]: Started WebSSH terminal interface.
Aug 11 22:08:26 webssh22 wssh[15678]: [I 220811 22:08:26 settings:125] WarningPolicy
Aug 11 22:08:26 webssh22 wssh[15678]: [I 220811 22:08:26 main:38] Listening on :8888 (http)

Теперь вы можете перезагрузить https://your_domain в своем браузере, и у вас снова должен появиться интерфейс WebSSH. С этого момента WebSSH и Nginx будут автоматически перезапускаться вместе с вашим сервером и работать в фоновом режиме.

Заключение

В этом руководстве вы установили WebSSH – портативное решение для предоставления интерфейса командной строки в браузере. Вы улучшили безопасность и надежность, добавив SSL, затем добавив обратный прокси Nginx, и, наконец, создав системную службу для WebSSH. Это хорошая модель для развертывания небольших серверных веб-приложений в целом, и особенно важная для SSH, который полагается на пары ключей для обеспечения безопасности.

Перевод статьи Alex Garnett «How to Connect to a Terminal from Your Browser Using Python WebSSH».