Fechar o túnel ssh sem raiz e sem matar todas as outras conexões ssh

5

Eu tenho um túnel ssh escutando em uma porta local, digamos 8888, aberto a partir de uma máquina remota com ssh -R 8888:localhost:80 myuser@myhost . Eu preciso escrever um script para "myuser" em "myhost" que irá fechar este túnel.

O script será executado por "myuser" em "myhost". Não será executado pela raiz nem poderá sudo.

Uma abordagem é encontrar o PID do processo escutando 8888 usando lsof ou netstat e, em seguida, eliminar o processo. No entanto, lsof e netstat se recusam a me dar o PID sem ir sudo. Com netstat eu só recebo - ao invés de "PID / Program name" sem sudo.

Existe uma maneira de descobrir o PID do processo escutando em uma determinada porta sem os privilégios de raiz? O processo de escuta nesta porta está sendo executado sob o mesmo usuário que estamos. Ou existe alguma outra maneira de fechar o túnel ssh do lado de fora?

Note que usar a sequência de escape ssh para redefinir a conexão não é uma solução, pois não no túnel. Nosso script precisa ser executado separadamente do túnel no mesmo host pelo mesmo usuário.

Observe também que apenas executar killall sshd não é uma solução, já que ele matará todas as outras conexões ssh e não apenas essa.

Esta questão não é uma duplicata de muitas questões similares, porque todas as suas respostas aceitas que eu encontrei requerem privilégios de root, ou apenas mata todas as conexões ssh.

O host "myhost" está executando o Ubuntu 12.04.5.

Editar: Resumo da discussão conforme solicitado por @Jakuje:

  • @Patrick sugeriu uma abordagem para usar setuid ou para modificar /etc/sudoers para permitir que o usuário execute o script com privilégios de raiz sem ter sudo completo. Embora, para setuid , precisássemos escrever um binário em vez do script. No entanto, permitir que o usuário execute o script com privilégios de root pode ser um risco de segurança em potencial. E ainda esta solução não cobre o caso de o usuário não ter acesso root, então ele não pode modificar /etc/sudoers . Se o @Patrick escrever isso como uma resposta, eu definitivamente o recomprarei, mas não o marcarei como aceito ainda.

  • @EricRenouf descobriu que o sshd envia o socket para o usuário, então o usuário não pode usar /proc/*/fd para encontrar o processo que tem o socket. Provavelmente é por isso que nem o lsof nem o netstat mostram isso.

Mais ideias:

Como @EricRenouf descobriu que provavelmente não há maneira de obter o sshd PID pelo número de porta do soquete aberto nem o inode. Mas estou curioso para saber se não há outro truque como encontrar esse sshd PID ou como dizê-lo para fechar a conexão. Talvez de alguma forma diretamente com sshd.

Por exemplo, se eu ativar o modo de depuração sshd sshd -d , ele registraria qual processo sshd abriu um encapsulamento para qual porta em /var/log/auth.log , que pode ser lida pelo usuário. Então o script poderia analisar o log e encontrar o PID lá. Mas executar um modo de depuração sshd não é uma boa ideia. Na verdade, existe um patch simples para o sshd ser aberto encapsula mesmo sem o modo de depuração. Mas não tenho certeza se rodar um sshd corrigido seria uma boa idéia também.

Existe algum outro truque?

    
por martin.macko.47 24.05.2017 / 15:27

1 resposta

2

Comece configurando uma chave SSH personalizada para conectar-se a "myhost". Em seguida, edite seu arquivo .ssh / authorized_keys em "myhost" para que o PID pai do shell seja gravado em um arquivo:

command="echo $PPID > tunnel.pid; bash" ssh-rsa AAA...

Você pode querer ajustar algumas outras configurações de segurança e / ou escrever um script personalizado para apenas escrever o PID e travar. O princípio é o mesmo em ambos os sentidos.

Depois que você tiver o PID do processo que mantém a sessão SSH aberta, é só uma questão de script ...

kill 'cat tunnel.pid'

... para finalizar o processo, fechando assim a sessão SSH.

Observe que você pode usar o sinalizador -i no comando ssh para especificar uma chave privada a ser usada na conexão.

Editar: Matar o processo shell não fechará o túnel se houver conexões ativas, então nós matamos o processo SSH pai.

Editar: Embora minha primeira inclinação com qualquer conexão SSH automatizada seja usar chaves SSH, o mesmo processo poderia ser emulado com:

ssh -R 8888:localhost:80 myuser@myhost 'echo $PPID > tunnel.pid; for ((;;)); do sleep 1; done'

Você também pode substituir um script que verifica alguns outros critérios para decidir quando terminar. Essa é provavelmente uma maneira mais limpa de lidar com isso.

    
por 25.05.2017 / 17:37