Використання утиліт timeout – strace для моніторингу неактивності користувача для розриву

Нещодавно я займався тим, що досліджував які є рішення для реалізації web-ssh проксі-сервера. Суть завдання полягає в тому, щоб дати користувачам з'єднуватися з довільним ssh-сервером за допомогою web-інтерфейсу. Зазвичай, рішення web-ssh призначені для з'єднання з сервером, на якому вони розгорнуті, але в рамках мого завдання мені хотілося, щоб користувач міг вказати IP, порт, ім'я та пароль користувача (або ключ) і з'єднатися з довільним сервером. З ходу знайти такого рішення мені не вдалося.

Взагалі, звичайно, є Guacamole, але для мого завдання використання цієї програми було надто затратним як за ресурсами розробки, так і за функціями та їхньою організацією, тому від Guacamole я відмовився.

Однак, для відкритого пакету shellinabox я виявив рішення на блозі німецькою мовою, яке я і вирішив довести до потрібного рівня. У результаті вийшов симпатичний контейнер Docker, який можна знайти як на GitHub так і на Dockerhub, який вирішує всі необхідні завдання.

  1. ресурси проксі-сервера терміналів використовуються неефективно, оскільки він змушений обслуговувати сесії, що не використовуються;
  2. відкрите у браузері без нагляду вікно з ssh навіює почуття туги та вразливості.

Загалом, я вирішив, що хочу домогтися того, щоб shellinabox розривав з'єднання в тому випадку, якщо користувач кілька хвилин не пише нічого на консоль (stdin) і stdout не надходять дані.

Досить тривалий пошук у Google показав мені, що цілі можна досягти з використанням команди timeout та strace. Команда timeout виявилася для мене новою, її призначення.забезпечити переривання процесу по досягненню деякого таймуту у тому випадку, якщо він сам не завершився.

Команду strace я використовую часто, проте зазвичай застосовую її для того, щоб відстежувати причину, з якої якась служба або команда не працює як очікується. У рамках мого пошуку на тему того, як здійснити моніторинг активності на каналах stdin, stdout процесу я виявив, що strace так само може це забезпечити:

Загалом дані команди були тим, що мені було необхідно для здійснення задуманого. Загальна схема виглядає так:

  1. При відкритті нового з'єднання shellinabox запускає python-скрипт;
  2. Python-скрипт запускає (fork) процес-демон моніторингу активності процесу, який здійснює моніторинг свого PID;
  3. python-скрипт виконує (exec) ssh (заміна себе на ssh).

Для тих, хто хоче відразу подивитися, як же влаштований весь скрипт, відправляю сюди. Для інших далі частинами.

Коротко код можна представити наступним чином.

Код простий та самоочевидний. Вся магія знаходиться всередині функції monitor_daemon:

де нас найбільше цікавить частина:

в якій і відбувається в циклі запуск моніторингу, який після заданого періоду очікування виконує завершення процесу ssh, якщо потрібно.

Ось, власне, і все. Рішення виявилося досить простим, але зажадав деякий час вивчення доступних інструментів.

PS: Я не професійний python-розробник, код субоптимальний. PPS: Якщо у когось виникне бажання покращити код, ласкаво просимо до репозиторію, я із задоволенням прийму PR-и.