ssh: Вытаскиваем для себя чужой порт из-за NAT

16d526e28f544abcbda706df72cad813.png
Что делает ssh -R © erik, unix.stackexchange.com

Подключиться к сервису за NAT, имея человека рядом с сервисом, вооруженного ssh, и белый ip у себя.


В ssh есть режим, в котором он открывает порт на сервере и, через туннель от сервера до клиента, перенаправляет соединения в указанный адрес в сети клиента.

То есть нам нужно поднять sshd, попросить человека выполнить

$ ssh -N -R server_port:target:target_port sshd_server


И у нас на машине с sshd откроется порт server_port, который будет туннелироваться в target: target_port в сети этого человека.

ForceCommand echo "no shell access is given"


Если задать эту опцию, то указанная команда будет выполняться заместо любой переданной клиентом (обычно клиент запускает шелл).
Так как scp работает через [встроенную] команду sftp, то копирование файлов тоже будет закрыто.

Туннелирование (форвардинг) при этом все еще работает.

AllowTcpForwarding remote


Разрешает режимы туннелирования tcp:

  • local (опция -L в ssh) — открыть порт на клиенте и перенаправить подключения на заданный клиентом адрес в сети сервера
  • remote (опция -R) — открыть порт на сервере и туннелировать подключения на заданный клиентом адрес в его сети
  • all или yes — разрешает и local, и remote
  • no — запрещает tcp туннели
Match


Как обычно, вышеуказанные опции можно положить в секцию, например, Match User tunnel, и они будут действительны только для соединений, аутентифицирующихся под именем этого пользователя. (ssh… tunnel@sshd_server)

Положить в конец sshd_config и не забыть создать пользователя tunnel
Match User tunnel
    ForceCommand echo "no shell access is given"
    AllowTcpForwarding remote
    # на случай, если у нас глобально установлено иначе:
    X11Forwarding no
    PermitTunnel no


Еще было бы хорошо ограничить порты, которые клиент может занимать на сервере, но без патчей к sshd этого не сделать.
Хочется решать задачу в духе netcat: не трогать системный sshd, не создавать новых пользователей и не запускать демонов.

sshd можно запустить без рута, если сделать отдельный конфиг и отключить несколько опций. (При этом он не сможет принимать пользователей отличных от того, с которым он был запущен). Также нужно указать отдельный HostKey и отдельный PidFile.

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

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

Готовый скрипт: запускалка пользовательского sshd, ограниченного созданием туннелей.

© Habrahabr.ru