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

87
O

undrü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 pelo servidor (o servidor atua como proxy).

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

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

  • executar comandos do shell
  • acessa arquivos ou faz upload de arquivos para o servidor
  • use o servidor como proxy (por exemplo, webproxy)
  • acesse serviços locais que, de outra forma, não seriam acessíveis publicamente devido a um firewall
  • mate o servidor

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

    
por Lekensteyn 10.06.2011 / 22:04

2 respostas

138

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

Adicionar 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 se conhecer as possibilidades do SSH é lendo as páginas de manual relacionadas:

  • ssh (1)
  • ssh_config (5)
  • sshd (8)
  • sshd_config (5)

Onde o cliente SSH pode executar ações?

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

  • Execução de comandos do shell
  • Upload de arquivo por meio do sftp
  • Encaminhamento de porta
    • O cliente encaminha uma porta (in) 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 do agente de autenticação
  • Encaminhamento de um dispositivo de túnel

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

  

Se o cliente se autenticar com sucesso, uma caixa de diálogo para preparar   a sessão é inserida. Neste momento, o cliente pode solicitar coisas como    alocando uma pseudo-tty, encaminhando conexões X11, encaminhando TCP   conexões ou encaminhando a conexão do agente de autenticação   canal seguro.

     

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

Opções para restringir recursos do SSH

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

  • ~/.ssh/authorized_keys - contém chaves que podem se conectar, as quais podem receber opções:
    • command="command" - O comando fornecido pelo usuário (se houver) é ignorado. Observe que o cliente pode especificar o encaminhamento TCP e / ou X11, a menos que seja explicitamente proibido . Observe que essa 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 - Proibe o encaminhamento de TCP quando essa chave é usada para autenticação
    • no-X11-forwarding - "Proibe o encaminhamento do X11 quando esta chave é usada para autenticação."
    • permitopen="host:port" - Limita o encaminhamento de porta 'ssh -L' local de tal forma que só pode se conectar 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 pessoal do usuário se torne acessível.
  • /etc/ssh/sshd_config - o arquivo de configuração do sistema
    • AllowAgentForwarding - Especifica se o encaminhamento de 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 é invocado 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 encaminhamentos de porta remotos ao endereço de loopback. Isso evita que outros hosts remotos se conectem a portas encaminhadas. usado para especificar que o sshd deve permitir que encaminhamentos de porta remota sejam vinculados a endereços que não sejam de loopback, permitindo que outros hosts se conectem. "
    • %código%:
        

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

      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 todos   restrições e permitir quaisquer solicitações de encaminhamento. Por padrão, todos   solicitações de encaminhamento de porta são permitidas.

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

Aplicando as restrições

Modificando o arquivo de configuração de todo o sistema X11Forwarding permite que a configuração seja aplicada mesmo se a autenticação baseada em senha for aplicada ou se as restrições em /etc/ssh/sshd_config forem acidentalmente removidas. Se você modificou os padrões globais, você deve descomentar as opções de acordo.

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 ~/.ssh/authorized_keys pode ser omitida se o shell estiver definido como não-shell, como ForceCommand (ou /bin/false ), pois /bin/true não fará nada.

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

Desativar /bin/false -c [command] também não permite o uso de AllowTcpForwarding , invalidando, assim, o uso de uma conta restrita para encaminhar uma única porta. -R assume que a porta 62222 no servidor nunca está em uso porque o cliente pode se conectar facilmente a ela e escutá-la também.

Se o encaminhamento de TCP for permitido na configuração de todo o sistema e na autenticação com base na senha desativada, também é possível usar configurações por chave. Edite PermitOpen localhost:62222 e adicione as próximas opções antes do ~/.ssh/authorized_keys (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 ter certeza de que funciona como esperado, alguns casos de teste precisam ser executados. Nos comandos abaixo, ssh- deve ser substituído pelo login real, se não estiver definido em host . 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 do SSH não deve poder:

  • executar comandos do shell - concluído
  • acessa arquivos ou envia arquivos para o servidor - concluído
  • use o servidor como proxy (por exemplo, webproxy) - concluído
  • acessam serviços locais que não eram acessíveis publicamente devido a um firewall - parcialmente , o cliente não pode acessar outras portas que não o 62222, mas pode ouvir e conectar à porta 62222 no servidor
  • mate 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 pode permitir que um possível invasor execute comandos, mate o servidor etc.)
O
por Lekensteyn 22.06.2011 / 11:11
2

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, eu estou supondo que o usuário é capaz 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 / authorized_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
  • Desativar o acesso por senha a essa conta.
your_user $ sudo usermod --lock ssh_forwarder

Agora, a única maneira que o usuário pode entrar no seu sistema é através do acesso à chave ssh apropriada, e o ssh irá executar o "/ bin / bash -c 'ler um'" para eles, não importa o que eles tentem executar . 'read a' irá simplesmente ler até uma nova linha, e então o shell irá sair, então o usuário apenas terá que digitar 'enter' para matar a conexão.

Existem muitas outras coisas que você poderia fazer em 'command ='. Veja man authorized_keys e procure por 'command' para mais informações.

Se você não gosta do fato de que clicar em enter mata a conexão, você pode usar 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 cria um fifo temporário no diretório inicial dos usuários e, em seguida, tenta ler a partir dele. Nada será gravado nesse arquivo, portanto, isso será interrompido indefinidamente. Além disso, se você quiser encerrar a conexão com força, poderá fazer algo como:

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

Isso deve usar muito poucos recursos, e nada deve dar errado nesse script que não terminaria na terminação do shell.

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

Não percebi como você poderia permitir que o usuário fosse encaminhado remotamente ( ssh -R ), mas limite ( ssh -L ). Talvez 'permitopen' pudesse ser usado. Googling não foi muito útil. Parece que algo como 'no-port-forwarding, permitremoteopen = 10001' seria útil para permitir ssh -R 6901:localhost:6901 .

Esta é uma solução . Pode definitivamente ser melhorado, 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 ver a tela dela, e o acesso a essas chaves fosse limitado a ela, eu pessoalmente me sentiria razoavelmente seguro. Se isso fosse para uma empresa, seria necessária uma investigação mais minuciosa. Uma coisa a ter em conta é que ssh -N não solicita um shell, portanto, o código 'command =' não é executado.

Outros mecanismos, possivelmente mais seguros, podem incluir a criação de um shell customizado para o usuário e até mesmo bloquear isso com o apparmour.

    
por smoser 21.06.2011 / 15:09