Encaminhar porta local ou arquivo de soquete para arquivo de soquete remoto

24

Pergunta rápida - Eu corro duas caixas Linux, uma na minha própria área de trabalho e a outra no meu VPS. Por motivos de segurança no final do VPS, optei por conexões de soquete ao MySQL ( /var/run/mysqld/mysql.sock). Eu sei que posso fazer um túnel assim: ssh -L 3307:127.0.0.1:3306 [email protected]se eu configurar o servidor sql remoto para escutar em alguma porta, mas o que eu quero saber é que posso fazer algo assim: ssh -L /path/to/myremotesqlserver.sock:/var/run/mysqld/mysql.sockencapsulando assim dois soquetes, em oposição a duas portas?

Uma solução perfeitamente aceitável também seria encaminhar uma porta local para o arquivo de soquete remoto, mas sempre que possível, estou tentando não ter servidores tcp em execução na caixa remota.

(e sim, eu sei que o tcp seria mais fácil).


fonte
Se o motivo pelo qual você não deseja usar o TCP na caixa mySQL é devido a questões de segurança (por exemplo, ataques remotos, etc.), é claro que você pode protegê-lo ou, se isso não for bom o suficiente, faça com que o mySQL ouça apenas 127.0.0.1 para suas conexões TCP, você pode fazer o túnel facilmente através do SSH. Caso contrário, eu apoio a solução socat abaixo.
Mattias Ahnberg
lwn.net/Articles/609321 OpenSSH 6.7 trará encaminhamento de soquete
Hubbitus
@Hubbitus, esse recurso está disponível agora, se sim, você pode fornecer uma resposta de exemplo?
CMCDragonkai
Esse comentário estava no formato de resposta, mas foi convertido em comentário por alguém. E agora vejo que você já sugere uma resposta abaixo.
Hubbitus

Respostas:

35

Encaminhar um soquete local sob demanda

  • Configurar autenticação de chave pública SSH
  • Instale socatnas duas extremidades
  • crie um diretório localmente para seus soquetes, inacessível a outros usuários.
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'

então

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

roubado do encaminhamento de soquetes de domínio unix com ssh e socat

ijk
fonte
Isso é incrível e deve ser a resposta aceita.
John Smith Opcional
32

Durante o tempo em que a pergunta foi feita, era realmente impossível, mas é possível hoje em dia.

Você pode: UNIX => TCP e UNIX => encaminhamento UNIX.

Por exemplo:

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

É possível desde o OpenSSH 6.7.

Igor Chubin
fonte
1
Eu consegui encaminhar minha socket local à tomada servidor remoto usando acima e cliente run janela de encaixe remotamente (isso poderia ser feito por ssh diretamente, mas onde está a diversão nisso :)ssh -L /home/user/docker.sock:/var/run/docker.sock dockerhost -N
sdkks
11

eu não fiz isso, mas eu tentaria com socat . talvez algo como:

ssh [email protected] -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

novamente, eu nunca fiz nada assim.

Javier
fonte
Vou tentar e informar como vai. Eu tenho usado a implementação baseada em TCP.
Não posso fazê-lo funcionar no momento, mas +1 de qualquer maneira para a ideia, eu gosto. Avisarei se eu resolver.
O +1 parece um utilitário útil.
Warner
5

Não é necessário mais socat desde o ssh 6.7. Você pode encaminhar soquetes de domínio unix diretamente como:

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

Mais informações: https://medium.com/@dperny/forwarding-the-docker-socket-over-ssh-e6567cfab160

CMCDragonkai
fonte
Eu também achei isso útil para conectar a um soquete local como um usuário diferente. Isso permite executar programas clientes em um processo do servidor que desconecta determinados IDs de usuário (conexões provenientes de seus próprios executores de tarefas).
Warbo 12/07/19
Encaminhando um soquete para a mesma máquina, mas com um diretório diferente controlado por um usuário diferente, usando sshd para autenticar o acesso? Qual é o seu caso?
CMCDragonkai
Permissões / acesso ao diretório não são um problema. Em vez disso, um daemon específico descarta qualquer tentativa de conexão feita por usuários em um determinado grupo (supostamente para impedir que os novatos fiquem confusos). O uso do ssh permite que esses usuários se conectem (via soquete com túnel) como se fossem um usuário que não pertencem a esse grupo e, portanto, não sejam desconectados.
Warbo 13/07/19
Interessante, engraçado como você quer dizer o nix-daemon, também estou lidando com questões relacionadas a isso. Eu estou querendo saber por que o nix-daemon está cortando conexões com usuários em um determinado grupo? Isso é uma coisa de configuração de segurança? Ou relacionado a: nixos.org/nix/manual/#idm140737318362784 ?
CMCDragonkai
De acordo com a mensagem de confirmação , é para evitar o uso "acidental". Eu trouxe aqui
#
2

Outra modificação da resposta @mpontes '/ @ javier que

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'

Limpador

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
'

PROS

  1. Funciona no openssh anterior a 6.7 (como CentOS 7)
  2. Mata o socat na terminação ssh, em vez de ter que re-ssh no servidor remoto
  3. Permite login ssh não público (ao contrário da solução ijk)

Característica

  1. Como a -fopção não é usada, você pode usar uma chave pública e executar em segundo plano via &ou pode fazer logon interativamente e usar Ctrl + Z e usar o mesmo $!para armazenar o pid.

CONS

  1. Não é possível usar facilmente a -fopção ssh, pois você perderá o pid do ssh dessa maneira. Esse método depende da execução em primeiro plano e Ctrl + C para matar.
  2. Muito mais complicado

Explicação

  • socat ...& - execute socat em segundo plano no servidor remoto
  • pid=$! - armazene o pid
  • trap kill\ $pid 0- executar kill $pidna terminação do bash
  • while :; sleep... - sente-se em um loop infinito
  • echo -ne \ \b- Espaço de eco seguido de backspace. Isso falha assim que o ssh é desconectado. Com a sleep 5, isso significa que socatpode executar até 5 segundos após o ssh

Nota: Na verdade testados usando janela de encaixe, a porta 2375, /var/run/docker.socke variável de ambiente DOCKER_HOST='tcp://localhost:2375', mas deve funcionar para todos mysql o mesmo

Atualizar

Usando os controles SSH , você pode usar a -fbandeira do meu jeito, basta adicionar as seguintes bandeiras

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

E você terá

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'

Agora você pode encerrar todas as sessões controladas usando

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

As -oopções podem ser salvas no seu .ssh/configarquivo ou você pode usar -S (mas ainda precisará -o ControlMaster)

Andy
fonte
Estou usando scripts dentro de um contêiner do Docker para implantar código em outros hosts. Sua lógica de conexão é incrível, mas termina quando a sessão do bash termina. Isso impede que eu chame docker run ... connect.shpara configurar o túnel seguido por docker run ... deploy.sh. Eu tentei nohup, &e disownmas eles parecem quebrar socatfechando stdoute provocando a kill. Alguma idéia de ajustes para apoiar este caso (ou seja, ainda perto quando o SSH sobrevive a uma renúncia)?
claytond
ESTÁ BEM. Isso realmente funciona bem (com -fe & disown) em um terminal. Aparentemente, o problema foi criado pelo script "wrapper". Gostaria de receber sugestões, mas estou analisando perguntas e respostas mais apropriadas agora.
claytond
@claytond Não sei exatamente o que você está fazendo, mas sim, todos os outros comandos são encerrados quando o pid 1 de um contêiner termina.O que eu normalmente faria no cenário de script de implantação é usar o comando "deploy" e escrever um ponto de entrada para o meu contêiner imagem que diz "se $ 1 (o comando) == deploay then" execute os comandos ssh e os comandos deploy e, em seguida, termine, o que fechará a conexão ssh. Você também pode docker run ... connect.sh, e docker exec {container name/id} deploy.sh, para que eles joguem juntos.
Andy em
Você está certo. Na verdade, estou usando execum runcontêiner já existente e o pipe SSH não persistia após o exectérmino. Esclarei que isso se devia a uma peculiaridade na maneira como os scripts são executados. Se eu mudei a chamada para seu próprio script e chamei nohup <script.sh> & disown, ela sobreviverá à conclusão do exec.
claytond
1

Elaborando a resposta de Javier, isso funciona para mim:

ssh -f [email protected] -L 9999:localhost:9999 "socat TCP-LISTEN:9999,fork,bind=localhost UNIX-CONNECT:/var/run/mysqld/mysql.sock"

Você precisa forkse conectar várias vezes sem precisar morrer depois de fechar a primeira conexão. Além disso, a maneira como o socat permite que você especifique um endereço ao qual se vincular é através da bindopção, não como um endereço antes da porta.

Depois disso, basta conectar-se localhost:9999normalmente como faria. Então, para desmontar o túnel:

ssh -f [email protected] "killall socat"

(ou algo semelhante, você pode fazer coisas mais elaboradas que envolvem manter o PID da sociedade)

mpontes
fonte
1

Sim, você pode usar o socat.

Primeiro, faça o túnel TCP com SSH. Então use socat assim:

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

Em seguida, dê permissões ao novo soquete criado (pode ser o chmod 777)

user190133
fonte
Isso é possível desde o OpenSSH 6.6.
ysdx
3
chmod 777: não não não não não! Nunca, nunca corra chmod 777. Praticamente nunca é necessário! Nem mesmo para "fins de teste". Se o arquivo é legível, é legível. Se for gravável pelo userou groupque precisar ser gravado, será gravável. Não há absolutamente nenhuma necessidade de dar a todos permissão de gravação e esquecer dechmod lo de volta a algo sadio é exatamente como as multinacionais são invadidas. Apenas não faça isso. Sempre. Eu escrevi uma introdução às permissões do Unix . Por favor, leia!
Martin Tournoij 13/03/16