Expertus metuit
Безопасный ssh-туннель
2016-12-12 12:38
Теги: linux, kb

Ранее я уже писал несколько раз об организации ssh-туннелей: SOCKS-прокси через SSH, Туннель через SSH-сервер. В этой статье я расскажу, как максимально безопасно организовать SOCKS-прокси через ssh-туннель.

Обычно, когда делают SOCKS-прокси-туннель, просто добавляют к команде соединения через ssh аргумент типа -D localhost:8008. Потенциально это не очень безопасно по нескольким причинам:

  • вместо авторизации по ключу используется интерактивная авторизация по паролю;
  • на сервере может быть включен X-Forwarding, дыра;
  • авторизация происходит под обычным пользователем в интерактивной сессии.

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

Авторизация по паролю также чревата последствиями. Например, если вы хотите разрешить нескольким разным людям подключения с туннелем, вам придётся создать несколько аккаунтов на сервере с разными паролями. Авторизация через ключи решает эту и ещё несколько других проблем.

Также для авторизации для прокси-туннеля можно использовать отдельный ключ с простым паролем, это удобно.

Дальше детальная пошаговая инструкция для настройки.

Начальные условия:

  • linux-сервер с установленным openssh-server сравнительно актуальной версии;
  • root-доступ к этому серверу;
  • локальный компьютер с linux/macos и терминалом.

Создаём специального системного пользователя для туннеля

На сервере.

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

$ sudo adduser --gecos "" --shell /bin/sh --disabled-password tunnel
Adding user `tunnel' ...
Adding new group `tunnel' (1001) ...
Adding new user `tunnel' (1001) with group `tunnel' ...
Creating home directory `/home/tunnel' ...
Copying files from `/etc/skel' ...

Создаём отдельный ssh-ключ для туннеля

На клиентской машине.

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

$ ssh-keygen -f ~/.ssh/id_rsa-TUNNEL
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /Users/sigsergv/.ssh/id_rsa-TUNNEL.
Your public key has been saved in /Users/sigsergv/.ssh/id_rsa-TUNNEL.pub.
The key fingerprint is:
SHA256:8tX6AUhejsdaQqwA4vDkUbg/oMN3wtAIgB0aScfKKk8 sigsergv@local
The key's randomart image is:
+---[RSA 2048]----+
|O+*=.            |
|*B++   .         |
|+.*..   + .      |
| =o. . = * .     |
|o.oo  o S B .    |
|=.E+o. o * o     |
|.+. o.  o . .    |
|  .        . .   |
|            .    |
+----[SHA256]-----+
$ cat ~/.ssh/id_rsa-TUNNEL.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDeMwFpgO2sXU5E2FRNJZV8GD9Gtpih+ELn2rBT401IfnRFLktX6GbD9nQsbcNYvZYJXcTf
c+asMzW5WmviiOwqCBszEAvW9iPDDUrZjo1QhFGKE0w05OOdjSX/NMc0Nc95A+5BjOZzHVw3Lefzj9nhxMMVyBCtH64zoczcmrQWSwL
qS9QbHfH1rD3gRxB/Xm1myObRAS713pAfTNsKuIMJzLisRRlS2cajKuaUvfdKQaNFCEIC+hNV9SdpPfmpwHVTIvRm/OgS85vfA5Jd8
jTxbP/2C9bamV0YqkHWtV/+sQuzgsPrFvtmzt0a2sUKmHphSxUEcxT39q4VH1NyMjI3 sigsergv@local

Теперь в файле ~/.ssh/id_rsa-TUNNEL.pub лежит публичный ключ, который мы используем на следующем этапе.

Настраиваем ssh-авторизацию

На сервере.

Сначала базовые шаги:

$ sudo mkdir /home/tunnel/.ssh
$ sudo touch /home/tunnel/.ssh/authorized_keys
$ sudo chown -R tunnel:tunnel /home/tunnel/.ssh

Теперь нужно отредактировать файл /home/tunnel/.ssh/authorized_keys и прописать туда публичный ssh-ключ с некоторыми дополнительными параметрами. Допустим, публичный ключ лежит в файле ~/.ssh/id_rsa-TUNNEL.pub на локальной машине и имеет вид типа ssh-rsa AAAAB....

Когда добавляется просто ключ в файл authorized_keys, его содержимое выглядит так (это одна строчка, я её для читабельности сократил, в жизни она длиннее):

ssh-rsa AAAAB3Nza...MjI3 sigsergv@local

Опции добавляются перед ключом, в данном случае — перед символами ssh-rsa, для нашей конфигурации опции будут такие (их значение я объясню чуть позже, также помним, что это всё одна строка, я её разбил на две для читабельности):

command="/bin/echo 'SSH tunnel session has been started, press CTRL+C to terminate'; /bin/sleep infinity",
no-X11-forwarding,no-user-rc,no-agent-forwarding,no-pty AAAAB3Nza...MjI3 sigsergv@local

Опции разделяются запятыми, вот они все с объяснениями (вообще все описаны в man sshd).

command="/bin/echo 'SSH tunnel session has been started, press CTRL+C to terminate'; /bin/sleep infinity"
Здесь мы задаём команду, которая будет выполняться вместо bash/zsh/итп, в данном случае мы выводим сообщение клиенту, что запущен туннель и дальше запускаем программу, которая просто ничего не делает и из которой можно выйти через Ctrl+C (/bin/sleep infinity).
no-X11-forwarding
Отключаем X11-forwarding, это нужно сделать обязательно, иначе клиент сможет запустить, например, xterm
no-user-rc
Отключаем выполнение файла ~/.ssh/rc.
no-agent-forwarding
Отключаем перенаправление ssh-agent.
no-pty
Отключаем аллокацию tty.

Как подключаться к такому туннелю

На клиентской машине.

Всё как обычно:

$ ssh -i ~/.ssh/id_rsa-TUNNEL -D 127.0.0.1:8000 tunnel@example.com
PTY allocation request failed on channel 1
SSH tunnel session has been started, press CTRL+C to terminate

Туннель (и локальный SOCKS-proxy по адресу 127.0.0.1:8000) будет работать, пока вы не нажмёте Ctrl+C

Чтобы ещё упростить себе жизнь, можно добавить параметры подключения в файл ~/.ssh/config:

Host tunnel-example
    IdentityFile ~/.ssh/id_rsa-TUNNEL
    Hostname example.com
    DynamicForward 127.0.0.1:8000
    RequestTTY no
    Compression yes
    User tunnel

Теперь для создания туннеля-прокси достаточно набрать команду ssh tunnel-example.

Комментарии

Текст комментария (разметка: *курсив*, **полужирная**, [ссылка](http://example.com) или <http://example.com> ещё)
Имя (обязательно, 50 символов или меньше)
Email, на который получать ответы (не будет опубликован)
Веб-сайт
© 2006—2016 Sergey Stolyarov | Работает на Pyrone