Создание SSH-туннеля. Часть первая

26.12.2019

Теги: CLILinuxSSHUbuntuWindowsВиртуализацияКомандаКонфигурацияНастройкаСервер

SSH туннель — это туннель, создаваемый посредством SSH соединения и используемый для шифрования туннелированных данных. Используется для того, чтобы обезопасить передачу данных в интернете. Особенность состоит в том, что незашифрованный трафик какого-либо протокола шифруется на одном конце SSH соединения и расшифровывается на другом.

Строго говоря, SSH-туннели не являются полноценными туннелями и это название следует рассматривать как сложившееся в профессиональной среде устойчивое наименование. Официальное название технологии — SSH Port Forwarding — это опциональная возможность протокола SSH, которая позволяет передать TCP-пакет с одной стороны SSH-соединения на другую и произвести в процессе передачи трансляцию IP-заголовка по заранее определенному правилу.

Понять, как работает SSH туннель очень просто: если представить его в виде point-to-point соединения. Так же как и в PPP, любой пакет, попавший в один конец соединения, будет передан и получен на другом конце туннеля. Дальше, в зависимости от адреса получателя, заданного в IP заголовке, пакет будет либо обработан принимающей стороной туннеля (если пакет предназначается непосредственно ей), либо смаршрутизирован дальше в сеть (если адресатом является другой узел сети).

За TCP Port Forwarding отвечает опция AllowTcpForwarding в файле конфигурации SSH-сервера. По умолчанию она имеет значение yes, так что дополнительные настройки не нужны.

Проброс локального соединения на удаленную машину

Синтаксис команды:

$ ssh -L [ЛокальныйАдрес:]ЛокальныйПорт:АдресНазначения:ПортНазначения Пользователь@УдаленныйСервер
         \_____________  _____________/ \_____________  _____________/              \______  _____/
                       \/                             \/                                   \/
                   точка входа                пункт назначения                        точка выхода

После этого все соединения на ЛокальныйАдрес:ЛокальныйПорт будут перебрасываться удаленному серверу, который будет соединяться с АдресНазначения:ПортНазначения от своего имени.

Проброс удаленного соединения на локальную машину

Для совершения обратного действия нужно выполнить команду с ключом -R:

$ ssh -R [УдаленныйАдрес:]УдаленныйПорт:АдресНазначения:ПортНазначения Пользователь@УдаленныйСервер
         \_____________  _____________/ \_____________  _____________/
                       \/                             \/               точка выхода — хост, где
                   точка входа                пункт назначения         выполняется эта команда      

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

Для OpenSSH точка входа всегда совпадает с локальным интерфейсом 127.0.0.1, поэтому его можно опустить, сразу начиная команду с порта точки входа.

Примеры проброса соединения

У меня физический компьютер с двумя виртуальными машинами. На физической машине — Windows 10 и установлены web-сервер Apache и сервер БД MySQL. На виртуальной машине ssh-server — Ubuntu 18.04 и установлен SSH-сервер. На виртуальной машине web-server — Ubuntu 18.04 и установлен web-сервер Apache и сервер БД MySQL.

  • Физическая машина TKMCOMP, ОС Windows 10, ip-адрес 192.168.110.2
  • Виртуальная машина ssh-server, ОС Ubuntu 18.04, ip-адрес 192.168.110.8
  • Виртуальная машина web-server, ОС Ubuntu 18.04, ip-адрес 192.168.110.12

Все машины находятся в одной локальной сети — для удобства проведения экспериментов с построением туннелей. Хотя с практической точки зрения нужен компьютер с белым ip-адресом и с установленным ssh-сервером — который будет посредником между двумя компьютерами с серыми ip-адресами.

На виртуальной машине web-server работает web-сервер Apache — если на физическом компьютере открыть в браузере страницу http://192.168.110.12, то увидим дефолтную страницу Apache:

На физической машине TKMCOMP тоже работает web-сервер Apache — если открыть в браузере страницу http://127.0.0.1, то увидим вывод php-функции phpinfo():

На виртуальной машине ssh-server необходимо открыть порт для ssh-соединений. У меня это — 2222:

$ sudo ufw allow 2222/tcp
Правило добавлено
Правило добавлено (v6)
$ sudo ufw status verbose
Состояние: активен
Журналирование: on (low)
По умолчанию: deny (входящие), allow (исходящие), disabled (маршрутизированные)

В                          Действие    Из
----------------------------------------------------
2222/tcp                   ALLOW IN    Anywhere
2222/tcp (v6)              ALLOW IN    Anywhere (v6)

Проброс локального соединения на удаленную машину

Открываем на физической машине PowerShell и выполняем команду:

> ssh -p 2222 -L 127.0.0.1:8080:192.168.110.12:80 evgeniy@192.168.110.8
  • точка входа в туннель — физическая машина TKMCOMP, интерфейс localhost
  • точка выхода из туннеля — виртуальная машина ssh-server, интерфейс localhost
  • пункт назначения tcp-пакетов — виртуальная машина web-server

Теперь у нас есть туннель от 192.168.110.2 до 192.168.110.8: пакеты от физической машины попадают в туннель и будут получены виртуальной машиной ssh-server. А поскольку пункт назначения 192.168.110.12 — пакеты будут направлены дальше в сеть, к виртуальной машине web-server.

На физической машине открываем в браузере страницу http://127.0.0.1:8080 — и видим дефолтную страницу Apache:

Проброс удаленного соединения на локальную машину

Открываем на физической машине PowerShell и выполняем команду:

> ssh -p 2222 -R 127.0.0.1:8080:127.0.0.1:80 evgeniy@192.168.110.8
  • точка входа в туннель — виртуальная машина ssh-server, интерфейс localhost
  • точка выхода из туннеля — физическая машина TKMCOMP, интерфейс localhost
  • пункт назначения tcp-пакетов — физическая машина TKMCOMP (пакеты предназначены ей)

Теперь у нас есть туннель от 192.168.110.8 до 192.168.110.2: пакеты от виртуальной машины ssh-server попадут в туннель и будут получены физической машиной. Откроем на виртуальной машине ssh-server браузер и наберем в адресной строке http://192.168.110.8:8080 или http://127.0.01:8080. Мы видим вывод функции phpinfo() от web-сервера физической машины:

Однако, если мы откроем браузер на виртуальной машине web-server и наберем в адресной строке http://192.168.110.8:8080 — то ничего не увидим:

Пакеты от виртуальной машины web-server придут на сетевой интерфейс enp0s3 (192.168.110.8) виртуальной машины ssh-server. А перенаправляются в туннель только те пакеты, которые пришли на интерфейс обратной петли loopback (127.0.0.1). Чтобы это исправить, нужно изменить настройки ssh-сервера — отредактировать файл конфигурации /etc/ssh/sshd_config:

GatewayPorts yes
$ sudo systemctl restart ssh

Но это очень радикальный путь, лучше использовать опцию -g в команде создания туннеля. Она действует аналогично GatewayPorts, но уменьшает риск забыть об этой настройке ssh-сервера, когда в ней уже не будет необходимости.

Обновляем страницу http://192.168.110.8:8080 на виртуальной машине web-server:

Поиск: CLI • Linux • SSH • Ubuntu • Windows • Команда • Туннель • Сервер • Клиент • Порт • Конфигурация • Настройка

Каталог оборудования
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Производители
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Функциональные группы
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.