суббота, 14 мая 2011 г.

Переброс портов и интерфейса графических программ с помощью SSH

У вас есть учетная запись user1 на сервере example.net с IP-адресом 8.9.10.11, на котором запущен демон SSH. Вы находитесь в локальной сети, имеющей подключение к Интернету. Ваш IP-адрес в локальной сети 192.168.0.2. Все адреса взяты для примера, везде подставляйте свои значения.

Примеры задач, которые вам может понадобиться выполнить с использованием главного преимущества SSH - высокой степени защиты соединения:
  • (1) На вашем сервере установлен MySQL и соединения для пользователя root разрешены только с локальной машины (т.е. с самого сервера), вы же хотите подключиться к нему со своей домашней машины (к примеру, из MySQL Administrator или MySQL Workbench).
  • (2) В вашей локальной сети есть веб-сервис, недоступный извне, а вы хотите скачать с него файл прямо на сервер.
  • (3) Вы хотите запускать на сервере GUI-приложения (программы с графическим интерфейсом) таким образом, чтобы они отображались на вашем компьютере как обычные окна.
Сначала рассмотрим первые 2 случая, они предполагают переброс TCP-портов. Чтобы упростить понимание, немного поговорим о том, как происходят соединения TCP с точки зрения обывателя:
  1. Программа-сервер занимает определенный порт и ждет пока кто-нибудь подключится. Порт на этой машине считается занятым и другие программы уже не могут его использовать. В качестве аналогии, представьте себе розетку на стене, в которую, тем не менее, можно подключать очень много вилок.
  2. Программа-клиент соединяется с программой-сервером путем подключения к определенному адресу и порту в сети. Программа-клиент как раз втыкает свою вилку в розетку программы-сервера.
В данном случае переброс портов работает как "удлинитель", позволяя переносить розетку со стены, скажем, в другую комнату.

Теперь перейдем к практике. На практике нужно знать, что создавать "розетки" с номером порта 1024 и меньше (в том числе с помощью "удлинителя") могут только привилегированные пользователи. На "вилки" это ограничение не распространяется. И второй нюанс: "вилка удлинителя" включается в "розетку" программы-сервера только в тот момент, когда в "розетку удлинителя" включается "вилка" программы-клиента (это несколько отличается от работы обычного удлинителя). Короче говоря, вся цепочка соединений полностью создается только при появлении клиента. На самом деле, для вас это не будет иметь особой разницы в большинстве случаев, поэтому не забивайте голову.

Разберем задачу (1) в наших терминах:
  • На сервере example.net есть "розетка" на стандартном для MySQL порту 3306, причем доступна она только с самого сервера, т.е. висит на его адресе 127.0.0.1.
  • Нужно провести "удлинитель" к нам на домашний компьютер, опять же, сделав "розетку удлинителя" доступной только с локальной машины.
Для этого мы подключаемся к серверу по SSH используя следующую команду:
$ ssh user1@example.net -L localhost:3307:127.0.0.1:3306
Опция -L означает, что мы создаем локальную "розетку" с помощью "удлинителя" (L = local). Таких параметров вы можете указать несколько, таким образом проложив сразу несколько "удлинителей". Разбираем параметры:
  • localhost - IP-адрес или имя машины, где будет создана "розетка удлинителя". Здесь мы ограничиваем "розетку" подключениями только с локального компьютера. Для доступа к "розетке" со всей локальной сети можно указать здесь 192.168.0.2 (адрес для примера, см. начало статьи). Этот параметр можно не указывать (опустив и двоеточие после него, сразу начав с порта), по-умолчанию и так используется localhost. Для использования других значений придется править настройки SSH на сервере (параметр GatewayPorts, подробности в документации на sshd).
  • 3307 - номер порта, по которому будет создана "розетка удлинителя". Можно использовать здесь и стандартный порт MySQL 3306, но это вызовет проблемы, если у вас запущен и локальный MySQL.
  • 127.0.0.1 - IP-адрес или имя машины, куда будет подключаться "вилка удлинителя". Чтобы для сервера подключения казались локальными, используем 127.0.0.1, или localhost. Опять же, ничто не мешает указать произвольный адрес в сети интернет, в таком случае соединение будет установлено с указанным адресом. Может быть полезно, если нужно исключить прослушку в локальной сети, хотя есть более адекватные способы это сделать.
  • 3306 - номер порта, к которому будет подключена "вилка удлиннителя", здесь указан стандартный порт MySQL.
Пока будет установлено SSH-соединение, мы можем в локальных программах указывать сервер - localhost, порт - 3307 и таким образом соединяться с MySQL на сервере. "Розетка" на локальном компьютере, соединение пойдет через "удлинитель" и попадет в "розетку" на сервере.

Задача (2) является обратной:
  • На машине в локальной сети (для примера возьмем адрес 192.168.0.100) есть "розетка" с номером порта 80 (стандартный порт HTTP), доступная только для данной локальной сети.
  • Нужно провести "удлинитель" так, чтобы "розетка" оказалась на нашем сервере, а соединение происходило с "розеткой" на машине в локальной сети.
Чтобы ее решить, нужно подключиться по SSH со следующими параметрами:
$ ssh user1@example.net -R localhost:8080:192.168.0.100:80
Здесь опция -R означает, что мы создаем "розетку удлиннителя" на удаленном сервере (R = remote). Опять же, ничего не мешает указывать несколько таких опций и комбинировать их с опциями -L. Параметры:
  • localhost - IP или имя удаленной машины, на которой будет создана "розетка удлинителя". Можно не указывать (опустив двоеточие, начав сразу с порта), по-умолчанию и так localhost.
  • 8080 - номер порта для "розетки удлинителя". Повторюсь, порты до 1024 включительно могут использовать только привилегированные пользователи.
  • 192.168.0.100 - IP или имя машины на локальной стороне, в "розетку" которой мы подключим наш "удлинитель"
  • 80 - порт машины на локальной стороне, куда будет подключена "вилка удлинителя"
Пока будет установлено такое соединение, из консоли сервера мы сможем скачать какой-нибудь файл с веб-сервиса в локальной сети:
$ wget http://localhost:8080/some/path/file.zip
В самом простом случае всё заработает и так, в более сложном - вам придется на сервере дописать соответствие адреса веб-сервиса вашему локальному в файл /etc/hosts, но это оставим за пределами данной статьи.

Запоминать команды для переброса портов довольно просто:
  • Параметр (-L или -R) - это место создания "розетки удлинителя":
    L = local = "розетка" на стороне клиента
    R = remote = "розетка" на стороне сервера
  • Первая часть аргумента задает адрес и порт "розетки удлинителя", т.е. той "розетки", которую вы сами создаете с помощью SSH
  • Вторая часть аргумента - адрес и порт "розетки", куда будет подключена "вилка удлинителя", т.е. уже существующей "розетки"
Задача (3) решается уже не перебросом портов, а перебросом соединений с X-сервером. Неприятное предварительное условие - в настройках SSH-сервера должна быть включена опция X11Forwarding (должна иметь значение yes, по-умолчанию no). Далее вы просто соединяетесь с сервером следующей командой (буква X заглавная, это важно):
$ ssh user1@example.net -X
После этого, запуская графические приложения из данной консоли, вы увидите их на своем экране как обычные окна, но работать они будут на удаленном сервере.

На этом всё. Безопасных вам соединений.