Переслать локальный порт или файл сокета в файл удаленного сокета

24

Быстрый вопрос - я использую два linux-бокса, один мой рабочий стол, а другой мой VPS. По соображениям безопасности на стороне VPS я выбрал сокет-соединения с MySQL ( /var/run/mysqld/mysql.sock). Я знаю, что могу туннелировать так: ssh -L 3307:127.0.0.1:3306 user@site.comесли я настрою удаленный сервер SQL для прослушивания какого-либо порта, но я хочу знать, могу ли я сделать что-то вроде: ssh -L /path/to/myremotesqlserver.sock:/var/run/mysqld/mysql.sockтуннелирование двух сокетов, а не двух портов?

Совершенно приемлемым решением также является перенаправление локального порта в файл удаленного сокета, но, где это возможно, я стараюсь не запускать tcp-серверы на удаленном компьютере.

(и да, я знаю, что tcp будет проще).


источник
Если причина, по которой вы не хотите использовать TCP на блоке mySQL, связана с проблемами безопасности (например, удаленными атаками и т. Д.), Вы можете использовать любой брандмауэр, а если этого недостаточно, заставить mySQL слушать только 127.0.0.1. для его соединений TCP вы можете легко туннелировать через SSH. Если нет, то я поддерживаю решение socat ниже.
Маттиас Анберг
lwn.net/Articles/609321 OpenSSH 6.7 принесет переадресацию сокетов
Hubbitus
@ Hubbitus доступна ли эта функция сейчас, если да, можете ли вы дать пример ответа?
CMCDragonkai
Этот комментарий был в форме ответа, но кем-то преобразован в комментарий. И теперь я вижу, вы уже предлагаете ответ ниже.
Hubbitus

Ответы:

35

Переадресация локального сокета по требованию

  • Настройка аутентификации с помощью открытого ключа SSH
  • Установить socatна обоих концах
  • создать каталог локально для ваших сокетов, недоступный для других пользователей.
export SOCKET_DIR=~/.remote-sockets
mkdir -p $SOCKET_DIR
socat "UNIX-LISTEN:$SOCKET_DIR/mysqld.sock,reuseaddr,fork" \
EXEC:'ssh user@server socat STDIO UNIX-CONNECT\:/var/run/mysqld/mysqld.sock'

тогда

mysql -S $SOCKET_DIR/mysqld.sock -u mysqluser -p

украдено из переадресации доменных сокетов unix с помощью ssh и socat

IJK
источник
Это потрясающе и должно быть принятым ответом.
Джон Смит Необязательный
32

Хотя в то время, когда задавался вопрос, это было действительно невозможно, но в настоящее время это возможно.

Вы можете сделать следующее: UNIX => TCP и UNIX => UNIX forwarding.

Например:

ssh \
  -R/var/run/mysql.sock:/var/run/mysql.sock \
  -R127.0.0.1:3306:/var/run/mysql.sock \
  somehost

Это возможно начиная с OpenSSH 6.7.

Игорь Чубин
источник
1
Мне удалось перенаправить мой локальный сокет на сокет удаленного сервера, используя вышеописанное, и запустить клиент Docker удаленно (это может сделать ssh напрямую, но где в этом удовольствие?)ssh -L /home/user/docker.sock:/var/run/docker.sock dockerhost -N
sdkks
11

я этого не делал, но я бы попробовал с сокатом . может быть что-то вроде:

ssh xxx@yyy.zzz -L 9999:localhost:9999 "socat TCP-LISTEN:localhost:9999 UNIX-CONNECT:/var/run/mysqld/mysql.sock"
socat UNIX-LISTEN:/path/to/local/socket TCP:localhost:9999

опять же, я никогда не делал ничего подобного.

Хавьер
источник
Я попробую и дам вам знать, как это происходит. Я использую реализацию на основе tcp.
Я не могу заставить его работать в данный момент, но все равно +1 за идею, мне это нравится. Я дам вам знать, если я это исправлю.
+1 выглядит как полезная утилита.
Warner
5

Больше не требуется socat, так как ssh 6.7. Вы можете пересылать доменные сокеты Unix напрямую, например:

ssh -nNT -L $(pwd)/docker.sock:/var/run/docker.sock user@someremote

Дополнительная информация: https://medium.com/@dperny/forwarding-the-docker-socket-over-ssh-e6567cfab160

CMCDragonkai
источник
Я также нашел это полезным для подключения к локальному сокету от имени другого пользователя. Это позволило мне запускать клиентские программы для серверного процесса, который отключает определенные идентификаторы пользователей (соединения, поступающие от собственных исполнителей заданий).
Варбо
Переадресация сокета на тот же компьютер, но в другой каталог, управляемый другим пользователем, используя sshd для аутентификации доступа? Какой у вас вариант использования?
CMCDragonkai
Разрешения / доступ к каталогам не являются проблемой. Скорее, конкретный демон отбрасывает любые попытки подключения, предпринятые пользователями в определенной группе (предположительно, для предотвращения путаницы новичков). Использование ssh позволяет этим пользователям подключаться (через туннельный сокет), как если бы они были пользователями, не входящими в эту группу, и, следовательно, не отключаться.
Варбо
Интересно, забавно, как вы имеете в виду nix-демона, я также занимаюсь вопросами, касающимися этого. Мне интересно, почему nix-daemon сбрасывает соединения с пользователями в определенной группе? Это конфигурация безопасности? Или связано с: nixos.org/nix/manual/#idm140737318362784 ?
CMCDragonkai
Согласно сообщению commit, это предотвращает «случайное» использование. Я поднял это здесь
Варбо
2

Еще одна модификация ответа @mpontes '/ @ javier,

ssh user@remoteserver -L 9999:localhost:9999 'socat TCP-LISTEN:9999,fork,bind=localhost UNIX-CONNECT:/var/run/mysqld/mysql.sock& pid=$!; trap "kill $pid" 0; while echo -ne " \b"; do sleep 5; done'

Очиститель

ssh user@remoteserver -L 9999:localhost:9999 '
  socat TCP-LISTEN:9999,fork,bind=localhost UNIX-CONNECT:/var/run/mysqld/mysql.sock&
  pid=$!
  trap "kill $pid" 0
  while echo -ne " \b"; do
    sleep 5
  done
'

ПРОФИ

  1. Работает на openssh ранее 6.7 (например, CentOS 7)
  2. Убивает socat при ssh-завершении, вместо того, чтобы заново подключаться к удаленному серверу
  3. Разрешает непубличный вход по ssh (в отличие от решения ijk)

Характерная черта

  1. Поскольку эта -fопция не используется, вы можете либо использовать открытый ключ и запускать его в фоновом режиме, &либо войти в систему в интерактивном режиме и использовать Ctrl + Z и использовать то же самое $!для хранения pid.

МИНУСЫ

  1. Не легко использовать -fопцию ssh, так как вы потеряете pid ssh таким образом. Этот метод основан на запуске на переднем плане и Ctrl + C, чтобы убить.
  2. Гораздо сложнее

объяснение

  • socat ...& запустить socat в фоновом режиме на удаленном сервере
  • pid=$! - хранить пид
  • trap kill\ $pid 0- запустить kill $pidпо окончании bash
  • while :; sleep... - сидеть в бесконечной петле
  • echo -ne \ \b- Эхо-пробел с последующим возвратом. Это терпит неудачу, как только ssh отключен. С sleep 5, это означает, что socatможет работать до 5 секунд после SSH

Примечание: На самом деле протестированы с использованием докер, порт 2375, /var/run/docker.sockи переменную окружения DOCKER_HOST='tcp://localhost:2375', но должны работать для всех MySQL то же самое

Обновить

Используя SSH Controls , вы можете использовать -fфлаг, используя мой способ, просто добавьте следующие флаги

-f -o ControlPath=~/.ssh/%C -o ControlMaster=auto

И вы получите

ssh -f -o ControlPath=~/.ssh/%C -o ControlMaster=auto user@remoteserver -L 9999:localhost:9999 'set -m; socat TCP-LISTEN:9999,fork,bind=localhost UNIX-CONNECT:/var/run/mysqld/mysql.sock& pid=$!; trap "kill $pid" 0; while echo -ne " \b"; do sleep 5; done'

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

ssh -o ControlPath=~/.ssh/%C -O exit remoteserver

Эти -oпараметры могут быть сохранены в вашем .ssh/configфайле, или вы можете использовать вместо -S (но все равно нужно -o ControlMaster)

Энди
источник
Я использую скрипты внутри контейнера Docker для развертывания кода на других хостах. Ваша логика подключения удивительна, но заканчивается, когда заканчивается сеанс bash. Это препятствует тому, чтобы я звонил, docker run ... connect.shчтобы настроить туннель, сопровождаемый docker run ... deploy.sh. Я попробовал nohup, &и , disownно они , кажется, сломать socat, закрывая stdoutи запуская kill. Любые идеи для твиков, чтобы поддержать этот случай (то есть все еще близки, когда SSH делает, но переживают отречение)?
Клейтонд
ХОРОШО. Это на самом деле работает нормально (с / -fи & disown) в терминале. Видимо проблема создана скриптом «обертка». Я бы приветствовал вклад, но сейчас смотрю на более подходящие вопросы и ответы.
Клейтонд
@claytond Не знаю точно, что вы делаете, но да, все другие команды завершаются, когда pid 1 контейнера заканчивается. Что я обычно делал бы в сценарии развертывания, это использовать команду "deploy" и написать точку входа для моего контейнера. Изображение, которое скажет «если $ 1 (команда) == deploay then», запустите команды ssh и команды deploy, а затем end, что закроет соединение ssh. Можно и так docker run ... connect.sh, и docker exec {container name/id} deploy.shони играют вместе.
Энди
Вы правы. Я на самом деле использую execуже runконтейнер, а канал SSH не сохранился после execзавершения. Я пояснил, что это было связано со странностью способа выполнения сценариев. Если я переместил вызов в свой собственный сценарий и вызвал nohup <script.sh> & disownего, он выживет после завершения exec.
Клейтонд
1

Развивая ответ Хавьера, это работает для меня:

ssh -f xxx@yyy.zzz -L 9999:localhost:9999 "socat TCP-LISTEN:9999,fork,bind=localhost UNIX-CONNECT:/var/run/mysqld/mysql.sock"

Вам нужно fork, чтобы иметь возможность подключаться несколько раз, не умирая, как только вы закроете первое соединение. Кроме того, socat позволяет вам указать адрес для привязки, используя bindопцию, а не как адрес перед портом.

После этого просто подключитесь localhost:9999как обычно. Затем снести туннель:

ssh -f xxx@yyy.zzz "killall socat"

(или что-то подобное, вы можете сделать более сложные вещи, которые включают в себя сохранение PID socat)

mpontes
источник
1

Да, вы можете использовать socat.

Сначала сделайте TCP-туннель с SSH. Затем используйте socat следующим образом:

socat unix-listen: /var/run/mysqld/mysqld.sock,fork,unlink-early tcp: 127.0.0.1: 3306

Затем дайте разрешения на новый созданный сокет (может быть chmod 777)

user190133
источник
Это возможно начиная с OpenSSH 6.6.
ysdx
3
chmod 777: нет-нет-нет-нет-нет! Никогда не бегай chmod 777. Это практически никогда не требуется! Даже для "тестирования". Если файл доступен для чтения, значит, он доступен для чтения. Если он может быть записан тем userили иным пользователем group, то он доступен для записи. Абсолютно нет нужды давать всем права на запись, а забывать о chmodчем-то вменяемом - это то, как транснациональные корпорации взламываются. Просто не делай этого. Когда-либо. Я написал введение в разрешения Unix . Пожалуйста, прочитайте это!
Мартин Турной.