No se puede iniciar sesión a través de SSH en ninguna cuenta con / bin / bash shell en Synology NAS

30

Estoy tratando de instalar bash como shell predeterminado en un ARM Linux que se ejecuta en un dispositivo integrado (Synology DS212 + NAS). Pero hay algo realmente mal, y no puedo entender qué es.

Síntomas

1) Root tiene / bin / bash como shell predeterminado, y puede iniciar sesión normalmente a través de SSH:

$ grep root /etc/passwd
root:x:0:0:root:/root:/bin/bash

$ ssh root@NAS
root@NAS's password:
Last login: Sun Dec 16 14:06:56 2012 from desktop
# 


2) joeuser tiene / bin / bash como shell predeterminado y recibe "Permiso denegado" cuando intenta iniciar sesión a través de SSH:

$ grep joeuser /etc/passwd
joeuser:x:1029:100:Joe User:/home/joeuser:/bin/bash

$ ssh joeuser@localhost
joeuser@NAS's password:
Last login: Sun Dec 16 14:07:22 2012 from desktop
Permission denied, please try again.
Connection to localhost closed.


3) cambiar el shell de joeuser de nuevo a / bin / sh:

$ grep joeuser /etc/passwd
joeuser:x:1029:100:Joe User:/home/joeuser:/bin/sh

$ ssh joeuser@localhost
Last login: Sun Dec 16 15:50:52 2012 from localhost
$ 


Para hacer las cosas aún más extrañas, puedo iniciar sesión como joeuser /bin/bashusando la consola serie (!). También a su - joeusercomo root funciona bien, por lo que el binario bash en sí está funcionando bien.

En un acto de desesperación, cambié el uid de joeuser a 0 en / etc / passwd, pero tampoco funcionó, por lo que no parece ser algo relacionado con el permiso.

Parece que bash está haciendo algunas comprobaciones adicionales que no le gustaban a sshd y está bloqueando las conexiones para usuarios no root. Tal vez algún tipo de comprobación de cordura, o emulación de terminal, que está activando el SIGCHLD, pero solo cuando se llama a través de ssh.

Ya revisé todos los elementos en sshd_config, y también puse SSHD en modo de depuración, pero no encontré nada extraño. Aquí está mi /etc/ssh/sshd_config:

LogLevel DEBUG
LoginGraceTime 2m
PermitRootLogin yes
RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile      %h/.ssh/authorized_keys
ChallengeResponseAuthentication no
UsePAM yes
AllowTcpForwarding no
ChrootDirectory none
Subsystem       sftp    internal-sftp -f DAEMON -u 000


Y aquí está la salida de /usr/syno/sbin/sshd -d, que muestra el intento fallido de joeuser tratando de iniciar sesión, con / bin / bash como shell:

debug1: Config token is loglevel
debug1: Config token is logingracetime
debug1: Config token is permitrootlogin
debug1: Config token is rsaauthentication
debug1: Config token is pubkeyauthentication
debug1: Config token is authorizedkeysfile
debug1: Config token is challengeresponseauthentication
debug1: Config token is usepam
debug1: Config token is allowtcpforwarding
debug1: Config token is chrootdirectory
debug1: Config token is subsystem
debug1: HPN Buffer Size: 87380
debug1: sshd version OpenSSH_5.8p1-hpn13v11
debug1: read PEM private key done: type RSA
debug1: private host key: #0 type 1 RSA
debug1: read PEM private key done: type DSA
debug1: private host key: #1 type 2 DSA
debug1: read PEM private key done: type ECDSA
debug1: private host key: #2 type 3 ECDSA
debug1: rexec_argv[0]='/usr/syno/sbin/sshd'
debug1: rexec_argv[1]='-d'
Set /proc/self/oom_adj from 0 to -17
debug1: Bind to port 22 on ::.
debug1: Server TCP RWIN socket size: 87380
debug1: HPN Buffer Size: 87380
Server listening on :: port 22.
debug1: Bind to port 22 on 0.0.0.0.
debug1: Server TCP RWIN socket size: 87380
debug1: HPN Buffer Size: 87380
Server listening on 0.0.0.0 port 22.

debug1: Server will not fork when running in debugging mode.
debug1: rexec start in 6 out 6 newsock 6 pipe -1 sock 9
debug1: inetd sockets after dupping: 4, 4
Connection from 127.0.0.1 port 52212
debug1: HPN Disabled: 0, HPN Buffer Size: 87380
debug1: Client protocol version 2.0; client software version OpenSSH_5.8p1-hpn13v11
SSH: Server;Ltype: Version;Remote: 127.0.0.1-52212;Protocol: 2.0;Client: OpenSSH_5.8p1-hpn13v11
debug1: match: OpenSSH_5.8p1-hpn13v11 pat OpenSSH*
debug1: Enabling compatibility mode for protocol 2.0
debug1: Local version string SSH-2.0-OpenSSH_5.8p1-hpn13v11
debug1: permanently_set_uid: 1024/100
debug1: MYFLAG IS 1
debug1: list_hostkey_types: ssh-rsa,ssh-dss,ecdsa-sha2-nistp256
debug1: SSH2_MSG_KEXINIT sent
debug1: SSH2_MSG_KEXINIT received
debug1: AUTH STATE IS 0
debug1: REQUESTED ENC.NAME is 'aes128-ctr'
debug1: kex: client->server aes128-ctr hmac-md5 none
SSH: Server;Ltype: Kex;Remote: 127.0.0.1-52212;Enc: aes128-ctr;MAC: hmac-md5;Comp: none
debug1: REQUESTED ENC.NAME is 'aes128-ctr'
debug1: kex: server->client aes128-ctr hmac-md5 none
debug1: expecting SSH2_MSG_KEX_ECDH_INIT
debug1: SSH2_MSG_NEWKEYS sent
debug1: expecting SSH2_MSG_NEWKEYS
debug1: SSH2_MSG_NEWKEYS received
debug1: KEX done
debug1: userauth-request for user joeuser service ssh-connection method none
SSH: Server;Ltype: Authname;Remote: 127.0.0.1-52212;Name: joeuser
debug1: attempt 0 failures 0
debug1: Config token is loglevel
debug1: Config token is logingracetime
debug1: Config token is permitrootlogin
debug1: Config token is rsaauthentication
debug1: Config token is pubkeyauthentication
debug1: Config token is authorizedkeysfile
debug1: Config token is challengeresponseauthentication
debug1: Config token is usepam
debug1: Config token is allowtcpforwarding
debug1: Config token is chrootdirectory
debug1: Config token is subsystem
debug1: PAM: initializing for "joeuser"
debug1: PAM: setting PAM_RHOST to "localhost"
debug1: PAM: setting PAM_TTY to "ssh"
debug1: userauth-request for user joeuser service ssh-connection method password
debug1: attempt 1 failures 0
debug1: do_pam_account: called
Accepted password for joeuser from 127.0.0.1 port 52212 ssh2
debug1: monitor_child_preauth: joeuser has been authenticated by privileged process
debug1: PAM: establishing credentials
User child is on pid 9129
debug1: Entering interactive session for SSH2.
debug1: server_init_dispatch_20
debug1: server_input_channel_open: ctype session rchan 0 win 65536 max 16384
debug1: input_session_request
debug1: channel 0: new [server-session]
debug1: session_new: session 0
debug1: session_open: channel 0
debug1: session_open: session 0: link with channel 0
debug1: server_input_channel_open: confirm session
debug1: server_input_global_request: rtype no-more-sessions@openssh.com want_reply 0
debug1: server_input_channel_req: channel 0 request pty-req reply 1
debug1: session_by_channel: session 0 channel 0
debug1: session_input_channel_req: session 0 req pty-req
debug1: Allocating pty.
debug1: session_new: session 0
debug1: session_pty_req: session 0 alloc /dev/pts/1
debug1: server_input_channel_req: channel 0 request shell reply 1
debug1: session_by_channel: session 0 channel 0
debug1: session_input_channel_req: session 0 req shell
debug1: Setting controlling tty using TIOCSCTTY.

debug1: Received SIGCHLD.
debug1: session_by_pid: pid 9130
debug1: session_exit_message: session 0 channel 0 pid 9130
debug1: session_exit_message: release channel 0
debug1: session_by_tty: session 0 tty /dev/pts/1
debug1: session_pty_cleanup: session 0 release /dev/pts/1
Received disconnect from 127.0.0.1: 11: disconnected by user
debug1: do_cleanup
debug1: do_cleanup
debug1: PAM: cleanup
debug1: PAM: closing session
debug1: PAM: deleting credentials


Aquí tiene la salida completa de sshd -dd, junto con ssh -vv .

Golpetazo:

# bash --version
GNU bash, version 3.2.49(1)-release (arm-none-linux-gnueabi)
Copyright (C) 2007 Free Software Foundation, Inc.

El binario bash fue compilado de forma cruzada desde la fuente. También intenté usar un binario precompilado de la distribución de Optware , pero tuve exactamente el mismo problema. Verifiqué si faltaban bibliotecas compartidas objdump -x, pero están todas allí.

¿Alguna idea de lo que podría estar causando este " Permiso denegado, por favor intente nuevamente "? Casi me estoy sumergiendo en el código fuente de bash para investigar, pero trato de evitar horas persiguiendo algo que puede ser una tontería.

EDITAR: agregar más información sobre bash y el sistema

$ ls -la /bin/bash
-rwxr-xr-x    1 root     root        724676 Dec 15 23:57 /bin/bash

$  file /bin/bash
/bin/bash: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.14, stripped

$  uname -a
Linux NAS 2.6.32.12 #2661 Mon Nov 12 23:10:15 CST 2012 armv5tel GNU/Linux synology_88f6282_212+

$ grep bash /etc/shells
/bin/bash
/bin/bash2
Gui Ambros
fuente
2
ls -l /bin/bash
Michael Hampton
¿Está / bin / bash en / etc / shells?
tink
Sí, aparece en / etc / shells. Y permisos 0755, agregados arriba.
Gui Ambros
Lo más probable es que se esté ejecutando algo en su archivo .bashrc. ¿Se puede cat ~ joeuser / .bashrc y hurgar en sus guiones de perfil? También puede intentar ejecutar / bin / bash mientras está conectado como él.
vicfn
Sin ~ joeuser / .ssh y sin scripts de perfil. Es un usuario en blanco que acabo de crear para probar.
Gui Ambros

Respuestas:

39

Para referencia futura: después de demasiadas horas investigando y depurando este problema, finalmente descubrí la causa raíz.

La versión OpenSSH utilizada por Synology es una versión altamente personalizada, que no se comporta como el código original. Tiene muchos hacks y personalizaciones ad-hoc, por ejemplo, verificación adicional antes de aceptar un inicio de sesión para ver si el servicio SSH está habilitado dentro de la interfaz web, o quitar caracteres especiales (;, |, ') de los comandos rsync, o ... espere ... evite que los usuarios habituales usen un shell diferente de / bin / sh o / bin / ash . Sí, codificado dentro del binario.

Aquí está el fragmento de código de OpenSSH 5.8p1, según lo distribuido por Synology en su código fuente (DSM4.1 - rama 2636) , archivo session.c:

void do_child(Session *s, const char *command)
{
...

#ifdef MY_ABC_HERE
   char szValue[8];
   int RunSSH = 0;
   SSH_CMD SSHCmd = REQ_UNKNOWN;

   if (1 == GetKeyValue("/etc/synoinfo.conf", "runssh", szValue, sizeof(szValue))) {
           if (strcasecmp(szValue, "yes") == 0) {
                   RunSSH = 1;
           }
   }

   if (IsSFTPReq(command)){
           SSHCmd = REQ_SFTP;
   } else if (IsRsyncReq(command)){
           SSHCmd = REQ_RSYNC;
   } else if (IsTimebkpRequest(command)){
           SSHCmd = REQ_TIMEBKP;
   } else if (RunSSH && IsAllowShell(pw)){
           SSHCmd = REQ_SHELL;
   } else {
           goto Err;
   }

   if (REQ_RSYNC == SSHCmd) {
           pw = SYNOChgValForRsync(pw);
   }
   if (!SSHCanLogin(SSHCmd, pw)) {
           goto Err;
   }
   goto Pass;

 Err:
   fprintf(stderr, "Permission denied, please try again.\n");
   exit(1);

 Pass:
   #endif /* MY_ABC_HERE */
...
}


Como puedes imaginar, IsAllowShell(pw)el culpable fue:

static int IsAllowShell(const struct passwd *pw)
{
     struct passwd *pUnPrivilege = NULL;
     char *szUserName = NULL;
     if (!pw || !pw->pw_name) {
             return 0;
     }
     szUserName = pw->pw_name;
     if(!strcmp(szUserName, "root") || !strcmp(szUserName, "admin")){
             return 1;
     }
     if (NULL != (pUnPrivilege = getpwnam(szUserName))){
             if (!strcmp(pUnPrivilege->pw_shell, "/bin/sh") || 
                     !strcmp(pUnPrivilege->pw_shell, "/bin/ash")) {
                     return 1;
             }
     }
     return 0;
}


No es de extrañar por qué estaba experimentando un comportamiento tan extraño. Solo se aceptarán shells / bin / sh y / bin / ash para usuarios diferentes a root o admin . Y esto independientemente del uid (había probado también hacer joeuser uid = 0, y no funcionó. Ahora es obvio por qué).

Una vez identificada la causa, la solución fue fácil: simplemente elimine la llamada a IsAllowShell () . Me tomó un tiempo obtener la configuración correcta para compilar cruzados openssh y todas sus dependencias, pero al final funcionó bien.

Si alguien está interesado en hacer lo mismo (o intentar compilar de forma cruzada otros módulos del núcleo o binarios para Synology), esta es mi versión de Makefile . Se probó con la fuente OpenSSH-5.8p1 y funciona bien con modelos que ejecutan Marvell Kirkwood mv6281 / mv6282 CPU (como DS212 +). Usé un host con Ubuntu 12.10 x64.

En pocas palabras: malas prácticas, código terrible y un gran ejemplo de lo que no se debe hacer. Entiendo que a veces los OEM necesitan desarrollar personalizaciones especiales, pero deberían pensarlo dos veces antes de excavar demasiado. No solo esto resulta en un código que no se puede mantener para ellos, sino que también crea todo tipo de problemas imprevistos en el futuro. Afortunadamente, la GPL existe para mantenerlos honestos y abiertos.

Gui Ambros
fuente
44
Trabajo estelar, señor, al investigar este problema y retirar el telón de la etapa Synology. Debo admitir que hasta ahora había pensado bastante bien en mi Diskstation, ya que ha sido muy útil y una vez que bootstrapped ahora incluso ejecuta algunos scripts para mí en el nuevo programador de tareas. Pero has revelado algunos defectos en el diseño miope aquí. Todavía estoy satisfecho con Diskstation, pero tendré en cuenta su publicación. Votó tanto la publicación como la respuesta.
Bernard Dy
Votaron por el esfuerzo. Si no quiero molestarme en hacer conexiones de cereales, solo quiero cambiar el shell predeterminado /bin/sh, ¿hay alguna manera de hacerlo?
Vicary del
Por qué Synology haría esto está totalmente fuera de mí :(
Gerhard Burger
Me cambió el nombre /bin/asha /bin/ash.realy vinculado zshal /bin/ash... hasta ahora todo parece estar bien ... o_o
x1a0
7

Para evitar el problema, y ​​dado que instalé bash a través de ipkg y no puedo estar seguro de que / opt siempre estará disponible (montado correctamente), simplemente coloco lo siguiente en mi .profile

[ -x /opt/bin/bash ] && exec /opt/bin/bash

mientras que / etc / passwd contiene / bin / ash como shell.

Tom Regner
fuente
1

Veamos. Está aislado en un único shell, además de que está viendo la salida de depuración sshd, por lo que no es un problema de permisos de escritura mundial con ~ joeuser / .ssh. Ese es el que atrae a la mayoría de la gente.

¿Has intentado crear un usuario normal adicional (es decir, no joeuser) para asegurarte de que experimente el mismo problema? Eso lo aislaría de la configuración del usuario frente a la configuración de todo el sistema.

Si se trata de un problema de todo el sistema, lo siguiente que echaré un vistazo son los archivos de configuración compartidos como / etc / profile que obtienen todos. Puede haber un bloque condicional que no se active si el nombre de usuario es root. (ID de usuario no efectivo, ya que ya lo probó)

Si aún no lo ha hecho, consulte dmesg para ver los informes de fallas de segmentación, en caso de que ocurra algo aún más extraño.

Andrew B
fuente
Gracias Andrew También revisé dmesg, y absolutamente nada. Crear un nuevo usuario tampoco ayudó, por lo que claramente es un problema de todo el sistema. Y joeuser puede iniciar sesión normalmente si cambio el shell de nuevo a / bin / ash, que descarta cualquier / etc / profile u otro (que también verifiqué, por cierto). Es solo con no root, usando bash, a través de ssh. En este punto, ni siquiera es un problema real (puedo vivir con eso como es ahora), pero me molesta admitir que no pude encontrar la causa de este comportamiento extraño. Es un sistema determinista después de todo; no debe haber algún tipo de explicación ...
Gui Ambros
1

intente / etc / ssh / sshd_config
busque AllowUsers

si está allí, intente agregar joeuser allí, solo nombre de usuario

también puede estar bloqueado en pam ... No recuerdo qué archivo es ...

BiG_NoBoDy
fuente
No es el caso. Si se tratara de un problema con AllowUsers, no me permitiría iniciar sesión con joeuser cuando cambio el shell a / bin / ash. Esto no parece estar relacionado con nada relacionado con la seguridad ni con ninguna otra configuración. Probablemente sea una especie de cómo bash maneja los pseudo terminales a través de ssh, versus ash, csh, etc.
Gui Ambros
1

¿Su versión modificada de openssh busca un /bin/shshell?

Solución fácil entonces:

ln -fs / bin / bash / bin / sh

Ponytech
fuente
Esto cambiaría el shell para todos los usuarios, y no solo para aquellos que necesitaban bash. Además, cualquier nueva actualización eliminaría el enlace simbólico (aunque la reparación de openssh también tiene el mismo problema). De todos modos, esto se resolvió, como se describió anteriormente.
Gui Ambros
OK cierto, pero como soy el único usuario en mi NAS, esta solución funciona para mí. De todos modos, gracias por señalar lo que descubriste.
Ponytech
0

Intente reinstalar Bash y vea si eso ayuda.

Pratap
fuente
No, obtuve bash de dos fuentes diferentes (una de la distribución de Optware, y también compilé 3.2 de la fuente), y el mismo problema. Llegué al extremo de incluso obtener bash 4.2 y aplicar los parches (los 39), y la compilación cruzada. Exactamente el mismo comportamiento. Funciona con root, permiso denegado para otros. Mi última suposición es el binario OpenSSH, que es el mismo instalado por defecto por el firmware de Synology. Esta es la única pieza que aún no toqué. Intentaré descargar la última fuente y compilación cruzada para ver qué sucede.
Gui Ambros
2
Extraño, no estoy seguro, pero esto parece ser un problema de configuración automática. ¿Ldap también se está ejecutando en el servidor? ¿Me puede enviar la salida del registro en tiempo real del archivo seguro y del mensaje en el momento del error de inicio de sesión?
Pratap
2
También inicie sesión como root en el servidor y deje que el shell del usuario sea / bin / bash e intente cambiar al usuario usando su - username. Muéstrame el resultado de esto también.
Pratap
0

En caso de que alguien tropiece con esto porque cometió el mismo error que yo hice:

sí: $ sudo usermod -s /bin/bash your_username

no: $ sudo usermod -s bash your_username

El segundo resultará en un permiso denegado cuando ingrese.

Christy
fuente