Назад | Перейти на главную страницу

Невозможно войти через SSH в какие-либо учетные записи с использованием оболочки / bin / bash на Synology NAS

Я пытаюсь установить bash в качестве оболочки по умолчанию на ARM Linux, работающем на встроенном устройстве (Synology DS212 + NAS). Но что-то действительно не так, и я не могу понять, что именно.

Симптомы:

1) Корень имеет / bin / bash в качестве оболочки по умолчанию и может нормально входить в систему через 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 имеет / bin / bash в качестве оболочки по умолчанию и получает сообщение «Permission denied» при попытке входа через 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) изменение оболочки joeuser обратно на / 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
$ 


Что еще более странно, я могу войти в систему как joeuser, используя /bin/bash с помощью последовательной консоли (!). Также su - joeuser как root работает нормально, поэтому сам двоичный файл bash работает нормально.

В отчаянии я изменил uid пользователя joeuser на 0 в / etc / passwd, но это тоже не сработало, так что, похоже, это не связано с разрешениями.

Похоже, что bash выполняет дополнительную проверку, которая не нравится sshd, и блокирует соединения для пользователей без полномочий root. Может быть, какая-то проверка работоспособности - или эмуляция терминала - запускает SIGCHLD, но только при вызове через ssh.

Я уже просмотрел каждый элемент sshd_config, а также перевел SSHD в режим отладки, но не нашел ничего странного. Вот мой /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


А вот результат /usr/syno/sbin/sshd -d, показывая неудачную попытку пользователя joeuser войти в систему с / bin / bash в качестве оболочки:

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


Здесь у вас есть полный вывод sshd -dd вместе с ssh -vv.

Баш:

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

Бинарный файл bash был скомпилирован из исходного кода. Я также пробовал использовать предварительно скомпилированный двоичный файл из Распространение программного обеспечения, но имел ту же проблему. Я проверил отсутствие общих библиотек, используя objdump -x, но они все там.

Есть идеи, что могло быть причиной этого "В доступе отказано, попробуйте еще раз.«? Я почти ныряю в исходный код bash, чтобы исследовать, но стараюсь не гоняться часами за чем-то, что может быть глупо.

РЕДАКТИРОВАТЬ: добавление дополнительной информации о bash и системе

$ 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

Для справки в будущем: после слишком многих часов исследования и отладки этой проблемы я наконец обнаружил основную причину.

Версия OpenSSH, используемая Synology, является настраиваемой версией, которая не вести себя как исходный код. В нем есть множество хаков и специальных настроек - например, дополнительная проверка перед принятием входа в систему, чтобы увидеть, включена ли служба SSH в веб-интерфейсе, или удаление специальных символов (;, |, ') из команд rsync или .. . ждать его... избегать использования обычными пользователями оболочки, отличной от / bin / sh или / bin / ash. Да, жестко запрограммирован в двоичном формате.

Вот фрагмент кода из OpenSSH 5.8p1, распространяемый Synology в их исходном коде. (DSM4.1 - ветка 2636), файл 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 */
...
}


Как вы понимаете, IsAllowShell(pw) был виноват:

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;
}


Неудивительно, почему у меня было такое странное поведение. Только оболочки / bin / sh и / bin / ash будут приняты для пользователей, отличных от корень или админ. И это независимо от uid (я тестировал также Joeuser uid = 0, и это не сработало. Теперь понятно почему).

После определения причины исправить было легко: просто удалите вызов IsAllowShell (). Мне потребовалось время, чтобы получить правильную конфигурацию для кросс-компиляции openssh и всех его зависимостей, но в конце концов это сработало.

Если кому-то интересно сделать то же самое (или попытаться перекрестно скомпилировать другие модули ядра или двоичные файлы для Synology), вот моя версия Makefile. Он был протестирован с Исходный код OpenSSH-5.8p1, и хорошо работает с моделями под управлением процессора Marvell Kirkwood mv6281 / mv6282 (например, DS212 +). Я использовал хост под управлением Ubuntu 12.10 x64.

Итог: плохая практика, ужасный код и отличный пример того, что не делать. Я понимаю, что иногда OEM-производителям необходимо разработать специальные настройки, но им следует дважды подумать, прежде чем копать слишком глубоко. Это не только приводит к невозможности поддержки кода для них, но также создает всевозможные непредвиденные проблемы в будущем. К счастью, GPL существует, чтобы сохранять их честность и открытость.

Чтобы обойти эту проблему, и поскольку я установил bash через ipkg, и я не могу быть уверен, что / opt всегда будет доступен (правильно смонтирован), я просто поместил следующее в свой .profile

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

в то время как / etc / passwd содержит / bin / ash в качестве оболочки.

попробуйте / etc / ssh / sshd_config
поиск AllowUsers

если он там, попробуйте добавить туда пользователя joeuser, просто имя пользователя

также он может быть заблокирован в pam ... не помню, какой это файл ...

Посмотрим. Он изолирован от одной оболочки, плюс вы просматриваете отладочную информацию sshd, так что это не проблемы с доступом для записи в ~ joeuser / .ssh. Это то, что привлекает большинство людей.

Вы пытались создать дополнительного обычного пользователя (то есть не joeuser), чтобы убедиться, что у него такая же проблема? Это изолировало бы его от конфигурации пользователя по сравнению с общесистемной конфигурацией.

Если это общесистемная проблема, следующее, на что я обращаю внимание, - это общие файлы конфигурации, такие как / etc / profile, которые получают все. Может быть условный блок, который не запускается, если имя пользователя - root. (не эффективный идентификатор пользователя, поскольку вы уже тестировали его)

Проверьте dmesg на наличие отчетов об ошибках сегментации, если вы еще этого не сделали, на случай, если происходит что-то еще более странное.

Их модифицированная версия openssh ищет /bin/sh оболочка ?

Тогда простое решение:

ln -fs / bin / bash / bin / sh

Попробуйте переустановить Bash и посмотрите, поможет ли это.

Если кто-то наткнется на это, потому что они сделали ту же ошибку, что и я:

да: $ sudo usermod -s /bin/bash your_username

нет: $ sudo usermod -s bash your_username

Второй приведет к отказу в разрешении при ssh'ing in.