Налаштування webssh з обмеженням мережевих підключень
Перед тим, як почати
Наведений варіант налаштування хоч і має деякий умовний ступінь захисту від сторонніх, проте він не передбачає публічного використання, включаючи звичайних користувачів, він розглядається як запасний канал управління для домашнього сервера і тільки для нього у випадку, якщо штатні та надійні канали немає можливості використовувати, наприклад, якщо доступний лише браузер у телефоні.
Хоча, для телефону є інші варіанти, той же Termux, і телефон не може повною мірою бути довіреним пристроєм, проте приклад є приклад.
Незважаючи на те, що сам wssh-клієнт може використовувати one-time-password, основним захистом повинен бути nginx з auth_basic та зв’язкою логін-пароль для location /webssh/ які я раджу генерувати нові після використання старих. Так як вони можуть бути використані для авторизації з обладнання, до якого немає повної довіри.
Так, звісно ж, робити у жодному разі не треба.
Але якщо дуже хочеться щось включити/вимкнути/перезапустити, то можна.
Почнемо
Завдання мати можливість використовувати ssh в умовах недоступності повноцінного і захищеного робочого середовища (ноут, openvpn, ssh), а веб-інтерфейс управління, або з існуючих, або самописний все одно не дає всіх можливостей інтерактивної консолі.
Вибрано найбільш компактну та підтримувану реалізацію клієнта на python.
Згідно з документацією, блок-схема зв’язків працює наступним чином.
1 2 3 4 5 6 7 |
[xterm.js] [python client] [any ssh server]
+---------+ http +--------+ ssh +-----------+
| browser | <==========> | webssh | <=======> | ssh server|
+---------+ websocket +--------+ ssh +-----------+
|
У цьому випадку клієнт wssh може підключитися до будь-якого сервера, включаючи локальний, використовуючи під час підключення будь-який логін. Але ціль обмежити роботу ssh тільки з локальним сервером, при цьому авторизуючись користувачем з обмеженими можливостями доступу до зовнішньої мережі.
Блок-схема реалізації
1 2 3 4 5 6 7 8 9 10 | user:webssh
iptables:127.0.0.1<>127.0.0.1 only
sshd_config:AllowUsers webssh@127.0.0.1
+--------------------------------------+
| |
+---------+ http | +--------+ ssh +-----------+ |
| browser | <==========> | | webssh | <=======> | ssh server| |
+---------+ websocket | +--------+ ssh +-----------+ |
| |
+--------------------------------------+
|
До ділу
Встановлюємо пакети
1 2 3 | apt install python-setuptools python-pip apt install libpython2.7-dev gcc libffi-dev python-wheel make build-essential pip install webssh |
Додаємо користувача, вводимо достатній пароль.
1 2 | groupadd --gid 29132 webssh adduser --home /home/webssh --shell /bin/bash --ingroup webssh --uid 29132 webssh |
Додаємо два правила в скрипт управління iptables або вам видніше куди.
1 2 3 4 5 6 | # ~~~~~~~~~~~~~~~~~~~~~~~ webssh allow only localhost connections ~~~~~~~~~~~~~~~~~~~~~ # connect to sshd on localhost | connect from nginx to wssh client $I -A OUTPUT -s 127.0.0.1/32 -d 127.0.0.1/32 -m state --state NEW,RELATED,ESTABLISHED -m owner --uid-owner webssh -j ACCEPT $I -A OUTPUT -m state --state NEW,RELATED,ESTABLISHED -m owner --uid-owner webssh -j DROP # $I -A OUTPUT -m state --state NEW,RELATED,ESTABLISHED -m owner --uid-owner webssh -j ACCEPT # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ / webssh ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
У директиву AllowUsers до sshd_config додаємо дозвіл для підключення користувача webssh тільки з локальної системи.
Якщо у вас не була описана ця директива, то доповніть її відповідним чином, інакше втратите зв’язок із сервером!
Наприклад:
1 2 | AllowUsers root@192.168.1.* user@192.168.1.102 another@192.168.1.201 webssh@127.0.0.1
|
nginx <> wssh
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | location /webssh/ { rewrite /webssh/(.*) /$1 break; client_body_buffer_size 4k; client_max_body_size 512k; keepalive_timeout 240s; keepalive_requests 100; send_timeout 30s; # Час активності неактивної консолі, підключення буде скинуто за відсутності активності. client_body_timeout 30s; more_set_headers "X-Frame-Options: SAMEORIGIN"; more_set_headers "X-Content-Type-Options: nosniff"; more_set_headers "X-XSS-Protection: \"1; mode=block\""; more_set_headers "Strict-Transport-Security: \"max-age=31536000; includeSubdomains; preload\" always"; auth_basic "ACCESS"; auth_basic_user_file /etc/nginx/auth/domain-webssh.pwd; # deny all; proxy_intercept_errors off; proxy_pass http://127.0.0.1:2222; # webssh proxy_http_version 1.1; proxy_read_timeout 120; proxy_set_header Upgrade $http_upgrade; # http://nginx.org/ru/docs/http/websocket.html 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; proxy_set_header X-Forwarded-For $remote_addr; proxy_redirect off; proxy_set_header Proxy ""; } |
wssh backend
Кому як зручніше запускати демона, тут я використовую власні скрипти/вочдоги, чернетка:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | #!/bin/bash # wssh run script # crontab # */5 * * * * /usr/local/bin/run-webssh.sh > /dev/null 2>&1 # rc.local # /usr/local/bin/run-webssh.sh > /dev/null 2>&1 EC="9" ps aux | grep -Ev "grep|su" | grep -Eo "/usr/local/bin/wssh" ; EC="$?" [[ "$EC" != "0" ]] && { WSPROC="`ps ax | grep "wssh" | grep -v "grep" | awk '{print $1}' | tr '\n' ' '`" kill -9 $WSPROC su - webssh -c "cd /home/webssh/ ; /usr/bin/python /usr/local/bin/wssh --address=127.0.0.1 --logging=info --log-file-prefix=webssh.log --port=2222 --encoding=utf-8 >/dev/null 2>&1" exit 0 } exit 0 |
Таким чином, python-клієнт wssh (який є backend сервером для nginx), запущений від користувача webssh, якому заборонені будь-які з’єднання, крім 127.0.0.1.
Цей wssh-клієнт може підключитися до серверного ssh-демона використовуючи логін webssh та заданий пароль, для доступу до сторінки може повинен використовуватися інший логін та інший пароль, заданий у auth_basic_user_file /etc/nginx/auth/domain-webssh.pwd.
Елегантно?
Елегантно.
Звичайно, поверх цього можна спорудити додаткові засоби та механізми як для обмеження, так і для розширення повноважень користувача у системі.
На закуску
Переписуємо стилі шрифтів
nano /usr/local/lib/python2.7/dist-packages/webssh/templates/index.html
1 2 3 4 5 6 7 8 9 | @font-face {font-family: "LiberationMono";font-style:normal;font-weight:normal; src: url("/webssh/static/css/fonts/LiberationMono-Regular.eot"); src: url("/webssh/static/css/fonts/LiberationMono-Regular.eot?#iefix") format("embedded-opentype"), url("/webssh/static/css/fonts/LiberationMono-Regular.woff2") format("woff2"), url("/webssh/static/css/fonts/LiberationMono-Regular.woff") format("woff"), url("/webssh/static/css/fonts/LiberationMono-Regular.ttf") format("truetype"), url("/webssh/static/css/fonts/LiberationMono-Regular.otf") format("opentype"), url("/webssh/static/css/fonts/LiberationMono-Regular.svg") format("svg");font-display:swap;} body {font-family:'LiberationMono', monospace !important;} |
Копіюємо набір шрифтів у ls -la /usr/local/lib/python2.7/dist-packages/webssh/static/css/fonts/
1 2 3 4 5 6 7 8 9 10 | total 364 drwxr-sr-x 2 root staff 4096 Sep 27 13:10 . drwxr-sr-x 3 root staff 4096 Sep 26 23:02 .. -rw-r--r-- 1 root staff 0 Sep 26 22:30 .gitignore -rw-r--r-- 1 root staff 49031 May 1 22:39 LiberationMono-Regular.eot -rw-r--r-- 1 root staff 97288 May 1 23:57 LiberationMono-Regular.otf -rw-r--r-- 1 root staff 81738 May 1 23:57 LiberationMono-Regular.svg -rw-r--r-- 1 root staff 55212 May 1 22:05 LiberationMono-Regular.ttf -rw-r--r-- 1 root staff 40428 May 1 22:39 LiberationMono-Regular.woff -rw-r--r-- 1 root staff 33992 May 1 22:39 LiberationMono-Regular.woff2 |
Оригінальний пост на SecOps.it Blog • Налаштування webssh з обмеженням мережевих підключень