Como criar um usuário SSH restrito para encaminhamento de porta?

106

ændrük sugeriu uma conexão reversa para obter uma conexão SSH fácil com outra pessoa (para ajuda remota). Para que isso funcione, é necessário um usuário adicional para aceitar a conexão. Esse usuário precisa poder encaminhar sua porta através do servidor (o servidor atua como proxy).

Como crio um usuário restrito que não pode fazer nada além do descrito acima?

O novo usuário não deve ser capaz de:

  • executar comandos shell
  • acessar arquivos ou fazer upload de arquivos para o servidor
  • use o servidor como proxy (por exemplo, webproxy)
  • acessar serviços locais que, de outra forma, não estavam acessíveis ao público devido a um firewall
  • mate o servidor

Resumindo, como crio um usuário SSH restrito que só pode se conectar ao servidor SSH sem privilégios, para que eu possa conectar-me através dessa conexão ao computador dele?

Lekensteyn
fonte

Respostas:

166

TL; DR - vá para o final da resposta, "Aplicando as restrições"

A adição de um usuário restrito consiste em duas partes: 1. Criando o usuário 2. Configurando o daemon SSH (sshd)

Configurando o sshd

O melhor lugar para conhecer as possibilidades do SSH é lendo as páginas de manual relacionadas:

Onde o cliente SSH pode executar ações?

Antes de restringir algo, você precisa conhecer os recursos do SSH. Cuspir nas páginas do manual produz:

  • Execução de comandos do shell
  • Upload de arquivo através do sftp
  • Encaminhamento de porta
    • O cliente encaminha uma porta (des) usada para o servidor
    • O servidor encaminha sua porta para o cliente
    • O servidor encaminha uma porta de outro host para o cliente (proxy-ish)
  • Encaminhamento X11 (encaminhamento de exibição)
  • Encaminhamento de agente de autenticação
  • Encaminhamento de um dispositivo de túnel

Na seção Autenticação da página de manual do sshd (8) :

Se o cliente se autenticar com êxito, será exibida uma caixa de diálogo para preparar a sessão. Nesse momento, o cliente pode solicitar coisas como alocar uma pseudo-tty, encaminhar conexões X11, encaminhar conexões TCP ou encaminhar a conexão do agente de autenticação pelo canal seguro.

Depois disso, o cliente solicita um shell ou a execução de um comando . Os lados entram no modo de sessão. Nesse modo, qualquer um dos lados pode enviar dados a qualquer momento, e esses dados são encaminhados de / para o shell ou comando no lado do servidor e o terminal do usuário no lado do cliente.

Opções para restringir recursos SSH

Os arquivos e suas opções que alteram o comportamento são:

  • ~/.ssh/authorized_keys - contém chaves que podem se conectar e que podem receber opções:
    • command="command"- O comando fornecido pelo usuário (se houver) é ignorado. Observe que o cliente pode especificar o encaminhamento de TCP e / ou X11, a menos que seja explicitamente proibido . Observe que esta opção se aplica à execução de shell, comando ou subsistema.
    • no-agent-forwarding - Proíbe o encaminhamento do agente de autenticação quando essa chave é usada para autenticação.
    • no-port-forwarding - Proíbe o encaminhamento de TCP quando essa chave é usada para autenticação
    • no-X11-forwarding - "Proíbe o encaminhamento do X11 quando essa chave é usada para autenticação."
    • permitopen="host:port" - Limite o encaminhamento de porta 'ssh -L' local para que ele possa se conectar apenas ao host e à porta especificados.
  • ~/.ssh/environment- Este arquivo é lido no ambiente no login (se existir). O processamento do ambiente é desativado por padrão e é controlado pela opção PermitUserEnvironment
  • ~/.ssh/rc - Contém rotinas de inicialização a serem executadas antes que o diretório inicial do usuário se torne acessível.
  • /etc/ssh/sshd_config - o arquivo de configuração em todo o sistema
    • AllowAgentForwarding - Especifica se o encaminhamento ssh-agent (1) é permitido.
    • AllowTcpForwarding
    • ForceCommand - "Força a execução do comando especificado pelo ForceCommand, ignorando qualquer comando fornecido pelo cliente e ~ / .ssh / rc, se presente. O comando é chamado usando o shell de login do usuário com a opção -c."
    • GatewayPorts - "Especifica se os hosts remotos têm permissão para se conectar às portas encaminhadas para o cliente. Por padrão, o sshd (8) vincula os encaminhamentos de portas remotas ao endereço de loopback. Isso impede que outros hosts remotos se conectem às portas encaminhadas. GatewayPorts pode ser usado para especificar esse sshd deve permitir o encaminhamento de portas remotas para se vincular a endereços sem loopback, permitindo que outros hosts se conectem. "
    • PermitOpen:

      Especifica os destinos para os quais o encaminhamento de porta TCP é permitido. A especificação de encaminhamento deve ser uma das seguintes formas:

      PermitOpen host:port
      PermitOpen IPv4_addr:port
      PermitOpen [IPv6_addr]:port
      

      Vários encaminhamentos podem ser especificados, separando-os com espaço em branco. Um argumento de 'any' pode ser usado para remover todas as restrições e permitir solicitações de encaminhamento. Por padrão, todas as solicitações de encaminhamento de porta são permitidas.

    • PermitTunnel- Especifica se o encaminhamento do dispositivo tun (4) é permitido. O padrão é 'não'
    • X11Forwarding- Especifica se o encaminhamento X11 é permitido. O padrão é 'não'

Aplicando as restrições

A modificação do arquivo de configuração em todo o sistema /etc/ssh/sshd_configpermite que a configuração seja aplicada mesmo se a autenticação baseada em senha for aplicada ou se as restrições ~/.ssh/authorized_keysforem removidas acidentalmente. Se você modificou os padrões globais, descomente as opções adequadamente.

Match User limited-user
   #AllowTcpForwarding yes
   #X11Forwarding no
   #PermitTunnel no
   #GatewayPorts no
   AllowAgentForwarding no
   PermitOpen localhost:62222
   ForceCommand echo 'This account can only be used for [reason]'

Agora adicione um usuário:

sudo useradd -m limited-user

A opção ForceCommandpode ser omitida se o shell estiver definido como um não-shell como /bin/false(ou /bin/true), pois /bin/false -c [command]não fará nada.

Agora, o cliente pode conectar-se apenas à porta 62222 no endereço de loopback do servidor pelo SSH (ele não escutará no endereço IP público)

Desabilitar AllowTcpForwardingtambém proibiria o uso de -R, derrotando assim o uso de uma conta restrita para encaminhar uma única porta. PermitOpen localhost:62222pressupõe que a porta 62222 no servidor nunca esteja em uso porque o cliente pode se conectar e ouvir com satisfação também.

Se o encaminhamento de TCP for permitido na configuração do sistema e a autenticação baseada em senha desabilitada, você também poderá usar as configurações por chave. Edite ~/.ssh/authorized_keyse adicione as próximas opções antes de ssh-(com um espaço entre as opções e ssh-):

command="echo 'This account can only be used for [reason]'",no-agent-forwarding,no-X11-forwarding,permitopen="localhost:62222"

Verificar

Para garantir que funcione conforme o esperado, alguns casos de teste precisam ser executados. Nos comandos abaixo, hostdeve ser substituído pelo login real, se não estiver definido ~/.ssh/config. Por trás do comando, é mostrado um comando que deve ser executado no cliente ou no servidor (conforme especificado).

# connection closed:
ssh host
# connection closed (/bin/date is not executed):
ssh host /bin/date
# administratively prohibited (2x):
ssh host -N -D 62222 # client: curl -I --socks5 localhost:62222 example.com
ssh host -N -L 8080:example.com:80 # client: curl -I localhost:8080
sftp host
# should be possible because the client should forward his SSH server
ssh host -N -R 8080:example.com:80 # server: curl -I localhost:8080
# This works, it forwards the client SSH to the server
ssh host -N -R 62222:localhost:22
# unfortunately, the client can listen on that port too. Not a big issue
ssh host -N -L 1234:localhost:62222

Conclusão

Lista de verificação: O usuário SSH não deve:

  • executar comandos shell - concluídos
  • acessar arquivos ou fazer upload de arquivos para o servidor - pronto
  • use o servidor como proxy (por exemplo, webproxy) - pronto
  • acessar serviços locais que, de outra forma, não estavam acessíveis ao público devido a um firewall - parcialmente , o cliente não pode acessar outras portas além da 62222, mas pode ouvir e conectar-se à porta 62222 no servidor
  • matar o servidor - concluído (observe que essas verificações são limitadas ao servidor SSH. Se você tiver outro serviço vulnerável na máquina, isso poderá permitir que um possível invasor execute comandos, mate o servidor etc.)
Lekensteyn
fonte
3
Para que isso funcione, a conta adicionada por useradddeve ser desbloqueada. Isso pode ser feito substituindo a senha /etc/shadowpor asteric ( *) ou definindo uma senha usando sudo passwd limited-user.
Lekensteyn
2
O SFTP funciona porque o servidor SSH executa o sftp-servercomando. Com ForceCommand, este comando não será mais executado.
Lekensteyn
2
Também útil é a from=opção authorized_keys. Permite limitar o uso da chave a fontes com um endereço IP ou nome de host específico. Exemplo from="1.1.1.1"ou from="10.0.0.?,*.example.com". Consulte a seção "AUTHORIZED_KEYS FILE FORMAT" na página de manual ( linux.die.net/man/8/sshd ) para obter todas as opções de chaves autorizadas.
quer
2
"AllowTcpForwarding local" proíbe o encaminhamento remoto. (Eu não sei se ele existia quando esta resposta foi escrito.)
Simon Sapin
1
Observe que isso é interrompido por conexões ssh persistentes; portanto, você não deve ter algo parecido Host * ControlMaster autono seu ~/.ssh/configarquivo ao se conectar ssh -N. Se você precisar, usessh -N -o ControlMaster=no
nh2 10/04
3

Tenho certeza de que existem muitas soluções para isso e muito mais robustas do que a que estou propondo. No entanto, isso pode ser suficiente para suas necessidades. Para fazer isso, suponho que o usuário tenha a capacidade de fazer autenticação baseada em chave ssh (putty ou qualquer ssh unix deve suportar isso).

  • Adicione um usuário como faria normalmente ('adduser' ou qualquer outra ferramenta)

  • Crie os usuários .ssh dir e .ssh / allowed_keys

your_user $ sudo -Hu ssh_forwarder /bin/bash

ssh_forwarder $ cd ~
ssh_forwarder $ mkdir .ssh
ssh_forwarder $ ( umask 066 && cat > .ssh/authorized_keys ) <<EOF
no-agent-forwarding,no-X11-forwarding,command="read a; exit" ssh-rsa AAAB3NzaC1y....2cD/VN3NtHw== smoser@brickies
EOF
  • Desative o acesso por senha a esta conta.
your_user $ sudo usermod --lock ssh_forwarder

Agora, a única maneira de o usuário entrar no seu sistema é através do acesso à chave ssh adequada, e o ssh executará "/ bin / bash -c 'leia a'" para eles, não importa o que eles tentem executar. 'read a' simplesmente lerá até uma nova linha e, em seguida, o shell será encerrado, portanto, o usuário precisará pressionar 'enter' para interromper a conexão.

Existem muitas outras coisas que você pode fazer em 'command ='. Veja man authorized_keyse procure por 'comando' para mais informações.

Se você não gostar do fato de que pressionar Enter mata a conexão, use algo como o seguinte para a entrada 'command =':

command="f=./.fifo.$$ && mkfifo $f && trap \"rm -f $f\" EXIT && read a <$f && echo $a; exit;"

Isso apenas cria um fifo temporário no diretório inicial dos usuários e tenta ler a partir dele. Nada será gravado nesse arquivo; portanto, isso será interrompido indefinidamente. Além disso, se você deseja encerrar forçosamente essa conexão, poderá fazer algo como:

 your_user$ echo GOODBYE | sudo tee ~ssh_forwarder/.fifo.*

Isso deve usar pouquíssimos recursos e nada deve dar errado nesse script que não terminaria com o encerramento do shell.

sleep 1h; echo You have been here too long. Good bye.

Eu não vi fora da mão como você pode permitir que o usuário para a frente remoto ( ssh -R), mas limit ( ssh -L). Talvez o 'openopen' possa ser usado. O Google não foi muito útil. Parece que algo como 'no-port-forwarding, allowremoteopen = 10001' seria útil para permitir ssh -R 6901:localhost:6901.

Esta é uma solução. Definitivamente, ele pode ser aprimorado e qualquer abertura de portas remotas deve ser examinada. Se meu objetivo fosse permitir que minha avó se conectasse à minha LAN, para que eu pudesse usar o vnc para visualizar sua tela, e o acesso a essas chaves fosse limitado a ela, eu me sentiria razoavelmente seguro. Se fosse para uma empresa, seria necessária uma investigação mais aprofundada. Uma coisa a ter em atenção é ssh -Nnão solicitar um shell, portanto o código 'command =' não é executado.

Outros mecanismos possivelmente mais seguros podem incluir a criação de um shell personalizado para o usuário e até o bloqueio com aparência.

smoser
fonte
3
Parece muito hackish, nem é necessário ter um shell porque nenhum comando precisa ser executado. Veja a página de manualssh para a -Nopção. Deve haver uma maneira mais limpa de fazer isso.
precisa saber é o seguinte
Isso é verdade. Espero ver uma solução mais limpa também. Eu acho que as chaves_estabelecidas em conjunto com o encaminhamento sem porta seria uma solução muito boa se houvesse uma opção 'allowremoteopen'.
Smoser
Eu fiz algumas pesquisas (veja acima). Como ssh -Nnão executa um comando, não há problema em command="something"fechar a sessão.
Lekensteyn
Estou esquecendo de algo? Parecia que chsh ssh_forwarder -s /bin/false é tudo o que preciso.
typelogic