6

Since DSM 6.2.2 we have troubles connecting to a Synology NAS as non-admin user via ssh. Before this was possible by simply changing the login shell in /etc/passwd from /sbin/nologin to /bin/sh. This does not seem to work any longer.

I additionally tried to edit /etc/ssh/sshd_conf to explicitly AllowUsers but to no avail. It seems that the client does a successful auth but then some PAM-module(?) shuts down the connection again.

Has anyone ssh working as non-admin under the latest version of DSM?

This is the log output:

2019-05-23T21:55:36+02:00 hostname sshd[13551]: pam_unix(sshd:session): session opened for user test by (uid=0)
2019-05-23T21:55:36+02:00 hostname sshd[13551]: pam_unix(sshd:session): session closed for user test

6 Answers 6

2

I looked for somewhere online to post this, as I just solved this problem, and thought the solution would be useful for others!

(Please remove dashes from urls when obvious.., I don't have reputation to post a lot of links)

This is a solution for the issue of not being able to log on to Synology NAS via ssh unless you're a member of the Administrators group. From reading several posts about this online, this problem is present in DSM 6.2.x

There are plenty of valid reasons a user could be given ssh access. At the same time, not every user needs Administrator access, so it seems Synology Inc. has made a poor decision to force this rule. I haven't found a way to fix this using the stock sshd, so I compiled my own sshd.

I take no responsibility if you spill your coffee, stumble in your chair and fall on your cat, or otherwise sustain damage from this guide. But as of October 2019, everything is tested to work in my lab.

Let's start.

System this was tested on:

 Synology DS418j with DSM 6.2.2-24922 Update 3, Linux hostname 4.4.59+ 
  #24922 aarch64 GNU/Linux synology_rtd1296_ds418j  
 Qubes release 4.0 (R4.0) with an App-VM running Fedora release 30 (Thirty)

Pre-requisites:

  • A synology NAS you can access via ssh with an existing user that's in the administrators group.
  • A linux environment, this could be virtualized. On Mac a system terminal should suffice. To follow my lead verbatim, go for a Fedora 30 install. If you use Ubuntu, at least you need to use apt-get instead of dnf, there might also be other distro specific elements.

Warning, if you're used to use 'make install' when installing linux software. Don't do it when following this guide, unless you know what you're doing and deviates from the guide. If you do so, you might break your system. Further, there's no need to be anything but an ordinary user while working on this guide, from the perspective of the compiling host. Only ocassionally is sudo needed.

Additionally, if you for whatever reason manage to bork your ssh daemon, you can always enable telnet through DSM web UI, and connect to synology cli via telnet to rectify what you did wrong. Also, it's wise to take a note of everything you're doing, and backing up all files you are replacing and all files you are altering prior to doing so. Note, if you are doing this guide, working with a remote synology server, and you're not entirely sure what you're doing, there's a plausible danger that you will lock yourself out of the server. At least, make sure you have an exit, like admin hands on site that could recover access for you.

Synology and DS (Disk Station) will be used interchangeably in the rest of the guide.

Since Synology Inc. seemingly has altered the original sshd binary, adding a sshd binary that will give ssh access to the synology box for users outside the administrators group is what this guide will teach you to do.

Interestingly, it's possible to do something called cross compile, it means you can compile software on one platform that can run on another platform.

The source code for openssh is available, and so is its dependencies. This means we can compile it on a linux system and run it on a synology with an ARM CPU.

First off, get yourself access to a linux machine. If you don't have linux installed, download virtualization software like vmware or virtualbox and install or load a linux virtual machine. It might also work using cygwin as a subsystem in Windows. Refer to respective documentation for this.

Please note that certain elements of this guide might not fit with your unique circumstances, please adjust your journey through this guide accordingly. This guide should give you some pointers to fix the ssh-issue, even if you don't have the exact same setup as me.

First off, find out which processor your DS has.

Find your specific synology model here: https://www.synology.com/en-global/knowledgebase/DSM/tutorial/Compatibility_Peripherals/What_kind_of_CPU_does_my_NAS_have

Also check in a ssh-session on your synology terminal, uname -a should give you some hints.

In my case, both the Synology Support Center link and the output from uname -a shows that I have a Realtek RTD1293 CPU, it's an ARM processor, for more interesting information, check out https://en.wikichip.org/wiki/arm/aarch64

So, we need to get the sources and crosscompile it on the linux laptop, so we can scp the binary to synology and circumvent the login-restriction.

Before you proceed, verify that you can ssh into your synology, if your ssh-fu is strong, you might've set up an entry in your ~/.ssh/config looking like this:

#My synology
Host DS
    Port 22
    Hostname 192.168.10.100
    User localuser
    IdentityFile /home/localuser/.ssh/id_ed25519

Substitute variables for whatever your local situation dictates.

At the very least, you should be able to log in to your synology by running a command like ssh localuser@192.168.10.100. If you have a non-default identity file or a non default port, add those parameters. How to configure passwordless ssh is out of the scope of this guide. Note that synology is also picky about permissions on all files and directories belonging to a user, before allowing ssh login. There are plenty of posts online about this. You may proceed using password login, however, but if you're on a local network and using end consumer devices that are private, it's more convenient to use ssh-keys for login to ssh. You may also use passphrases on your private keys. Also check that when logged in with your existing user you can do sudo whoami. This should prompt you for your sudo password, unless you have configured sudo to not need a password for your user, and you will see 'root' after hitting the enter key.

Now for the fun part!!

On your linux (fedora?) instance, log in, start a terminal and make a project directory and enter it.

mkdir ~/crosscompile ; cd ~/crosscompile

Use a web-browser in your linux instance, and go to https://cdn.openbsd.org/pub/OpenBSD/OpenSSH/portable/, find the latest version at the bottom. Pr. Oct 2019 this is openssh-8.1p1.

Go back to the linux terminal and download it, I'll be using 8.1p1, but please use whatever version is newer, if you see this guide when a new release has been made.

wget https://cdn.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-8.1p1.tar.gz
wget https://cdn.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-8.1p1.tar.gz.asc

The second line gets the PGP signature of the file.

Now, if it isn't already installed, install pgpdump:

sudo dnf install pgpdump

Proceed with

pgpdump openssh-8.1p1.tar.gz.asc

Sample output:

Old: Signature Packet(tag 2)(451 bytes)
    Ver 4 - new
    Sig type - Signature of a binary document(0x00).
    Pub alg - RSA Encrypt or Sign(pub 1)
    Hash alg - SHA512(hash 10)
    Hashed Sub: issuer fingerprint(sub 33)(21 bytes)
     v4 -   Fingerprint - 59 c2 11 8e d2 06 d9 27 e6 67 eb e3 d3 e5 f5 6b 6d 92 0d 30 
    Hashed Sub: signature creation time(sub 2)(4 bytes)
        Time - Wed Oct  9 02:39:36 CEST 2019
    Sub: issuer key ID(sub 16)(8 bytes)
        Key ID - 0xD3E5F56B6D920D30
    Hash left 2 bytes - 1c 52 
    RSA m^d mod n(3195 bits) - ...
        -> PKCS-1

Note the Key ID, 0xD3E5F56B6D920D30 (It might differ for a newer version..) Also take note of the Fingerprint, we'll get back to that.

Now, install gpg2 if it isn't installed;

sudo dnf install gpg2.

Get the pgp-key from the releaser:

wget https://cdn.openbsd.org/pub/OpenBSD/OpenSSH/portable/DJM-GPG-KEY.asc

Import it:

gpg2 --import DJM-GPG-KEY.asc

Get the release key, and import it:

wget https://cdn.openbsd.org/pub/OpenBSD/OpenSSH/RELEASE_KEY.asc
gpg2 --import RELEASE_KEY.asc

Now verify the download:

gpg2 --verify openssh-8.1p1.tar.gz.asc openssh-8.1p1.tar.gz

Result:

gpg: Signature made Wed Oct  9 02:39:36 2019 CEST
gpg:                using RSA key 59C2118ED206D927E667EBE3D3E5F56B6D920D30
gpg: Good signature from "Damien Miller <djm@mindrot.org>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg:          There is no indication that the signature belongs to the owner.
Primary key fingerprint: 59C2 118E D206 D927 E667  EBE3 D3E5 F56B 6D92 0D30

Note that the fingerprint matches what pgpdump told us from the pgp signature. All looks good. If you are worried about the key not being trusted by a signature, you'll need to either edit the trust of the key yourself, or get somebody to do it. If you have a very critical installation, contacting Damien Miller and have him read up the fingerprint is an option. You should probably compensate him for that!

Anyway, to ensure that the download is as safe as posible, you should verify with several sources, so let's try.

A quick search reveals what's apparently Miller's blog. And this post gives some more details:

http://blog.djm.net.au/2013/12/pgp-keys-rotated.html

Now copy that whole key blob to a file on disk, then do a pgpdump filename on it.

This should give you an output like this:

pgpdump keyblob | grep 0D30  | grep fin
Key fingerprint = 59C2 118E D206 D927 E667  EBE3 D3E5 F56B 6D92 0D30

If you are curious, copy the entire output of the command to a text-editor and search for '0xD3E5F56B6D920D30' as referred earlier in the guide. You will then see the release-key is a subkey of Miller's personal key.

Ok, at this point, we asume the openssh download is sound.

Unpack openssh:

tar xvzf openssh-8.1p1.tar.gz

You must determine which Tool Chain you need: https://originhelp.synology.com/developer-guide/compile_applications/download_dsm_tool_chain.html

In my case, I downloaded the one I needed with this command:

wget https://sourceforge.net/projects/dsgpl/files/DSM%206.2.2%20Tool%20Chains/Realtek%20RTD129x%20Linux%204.4.59/rtd1296-gcc494_glibc220_armv8-GPL.txz/download -O rtd1296-gcc494_glibc220_armv8-GPL.txz

Afaik, there's no way to verify the download. I uploaded it to virustotal, and there was no engines found.

Extract the Tool Chain:

sudo tar Jxvf rtd1296-gcc494_glibc220_armv8-GPL.txz -C /usr/local

Aditionally we need zlib and openssl.

  wget https://zlib.net/zlib-1.2.11.tar.gz
  wget https://zlib.net/zlib-1.2.11.tar.gz.asc

(Also here, check for newer version)

pgpdump zlib-1.2.11.tar.gz.asc | grep ID

gives Key ID - 0x783FCD8E58BCAFBA

Fetch and import it:

wget http://pgp.key-server.io/download/0x783FCD8E58BCAFBA
gpg2 --import 0x783FCD8E58BCAFBA

Verify the download:

gpg2 --verify zlib-1.2.11.tar.gz.asc zlib-1.2.11.tar.gz

This should give a good signature from Mark Adler

At this point, you might use the fingerprint or DSA Key, to try to find references other places on the web, if you need further verification.

Extract zlib: tar xvzf zlib-1.2.11.tar.gz

We need also openssl:

  wget https://www.openssl.org/source/openssl-1.1.1d.tar.gz
  wget https://www.openssl.org/source/openssl-1.1.1d.tar.gz.sha256
  wget https://www.openssl.org/source/openssl-1.1.1d.tar.gz.asc

sha256sum openssl-1.1.1d.tar.gz gives 1e3a91bc1f9dfce01af26026f856e064eab4c8ee0a8f457b5ae30b40b8b711f2  
cat openssl-1.1.1d.tar.gz.sha256 gives 1e3a91bc1f9dfce01af26026f856e064eab4c8ee0a8f457b5ae30b40b8b711f2

We have now verified the integrity of the file. Let's check the signature as well.

pgpdump openssl-1.1.1d.tar.gz.asc  | grep -E "Fin|ID"

Results:

 v4 -   Fingerprint - 86 57 ab b2 60 f0 56 b1 e5 19 08 39 d9 c4 d2 6d 0e 60 44 91 
Sub: issuer key ID(sub 16)(8 bytes)
    Key ID - 0xD9C4D26D0E604491

Let's get the key and import it to the keyring:

 wget http://pgp.key-server.io/download/0xD9C4D26D0E604491
 gpg2 --import 0xD9C4D26D0E604491 

Result:

gpg: key D9C4D26D0E604491: public key "Matt Caswell <matt@openssl.org>" imported

We now verify the download:

gpg2 --verify openssl-1.1.1d.tar.gz.asc openssl-1.1.1d.tar.gz

gpg: Signature made Tue Sep 10 15:13:14 2019 CEST
gpg:                using RSA key 8657ABB260F056B1E5190839D9C4D26D0E604491
gpg: Good signature from "Matt Caswell <matt@openssl.org>" [unknown]
gpg:                 aka "Matt Caswell <frodo@baggins.org>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg:          There is no indication that the signature belongs to the owner.
Primary key fingerprint: 8657 ABB2 60F0 56B1 E519  0839 D9C4 D26D 0E60 4491

Fingerprint match,and a reference can also be found here to the same fingerprint: https://wiki.freebsd.org/OpenSSL/Base/Update111

We must assume at this point that all sw we downloaded is verified and ok, now let's build the ARM sshd binary!

cd zlib-1.2.11

Let's configure zlib:

CC=/usr/local/aarch64-unknown-linux-gnueabi/bin/aarch64-unknown-linux-gnueabi-gcc LD=/usr/local/aarch64-unknown-linux-gnueabi/bin/aarch64-unknown-linux-gnueabi-ld CFLAGS+=-I/usr/local/aarch64-unknown-linux-gnueabi/aarch64-unknown-linux-gnueabi/sysroot/usr/include LDFLAGS+=-L/usr/local/aarch64-unknown-linux-gnueabi/aarch64-unknown-linux-gnueabi/lib ./configure 

Then make it:

make

Let's verify:

ls -l libz* 

should now show something like this:

-rw-rw-r-- 1 user user 155378 Oct 20 04:45 libz.a
lrwxrwxrwx 1 user user     14 Oct 20 04:45 libz.so -> libz.so.1.2.11
lrwxrwxrwx 1 user user     14 Oct 20 04:45 libz.so.1 -> libz.so.1.2.11
-rwxrwxr-x 1 user user 133664 Oct 20 04:45 libz.so.1.2.11

Fine Synology user! Let's compile openssl!

Let's extract it and change to the working directory:

cd .. && tar xvzf openssl-1.1.1d.tar.gz && cd openssl-1.1.1d

Then we configure it:

CFLAGS+=-I/usr/local/aarch64-unknown-linux-gnueabi/aarch64-unknown-linux-gnueabi/sysroot/usr/include LDFLAGS+=-L/usr/local/aarch64-unknown-linux-gnueabi/aarch64-unknown-linux-gnueabi/lib ./Configure  linux-generic64 shared  -DL_ENDIAN --prefix=/home/user0/opensslArm --openssldir=/home/user/opensslArm  CC=/usr/local/aarch64-unknown-linux-gnueabi/bin/aarch64-unknown-linux-gnueabi-gcc RANLIB=/usr/local/aarch64-unknown-linux-gnueabi/bin/aarch64-unknown-linux-gnueabi-ranlib AR=/usr/local/aarch64-unknown-linux-gnueabi/bin/aarch64-unknown-linux-gnueabi-ar LD=/usr/local/aarch64-unknown-linux-gnueabi/bin/aarch64-unknown-linux-gnueabi-ld MAKEDEPPROG=/usr/local/aarch64-unknown-linux-gnueabi/bin/aarch64-unknown-linux-gnueabi-gcc PROCESSOR=ARM 

Now let's make it:

make

This takes a while, so be patient.

Let's verify it:

ls lib*so* 

Should give

libcrypto.so  libcrypto.so.1.1  libssl.so  libssl.so.1.1

Congratulations, you are coming closer and closer to making this happen for real!

Let's compile openssh!

First we must configure it:

./configure --host=arm-linux --with-libs --with-zlib=/home/user/crosscompile/zlib-1.2.11 --with-ssl-dir=/home/user/crosscompile/openssl/openssl-1.1.1d --disable-etc-default-login CC=/usr/local/aarch64-unknown-linux-gnueabi/bin/aarch64-unknown-linux-gnueabi-gcc AR=/usr/local/aarch64-unknown-linux-gnueabi/bin/aarch64-unknown-linux-gnueabi-ar

Now, make it:

make

Several executable binaries are now created in ~/crosscompile/openssh-8.1p1

Let's see if we can log in with an ordinary user via ssh to DS, using the new sshd binary we've created. By now you should have a passwordless login to DS with an existing user belonging in the administrator group.

Let's copy the new sshd and libcrypto to the DS:

scp ~/crosscompile/openssh-8.1p1/sshd DS:~/newsshd
scp ~/crosscompile/openssl-1.1.1d/libcrypto.so.1.1 DS:~

Then let's ssh to DS in an ordinary manner:

ssh DS

Then let's make a copy of sshd_config:

sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config_new

Edit the new config file:

vim /etc/ssh/sshd_config_new

Change 'UsePAM yes' to '#UsePAM yes'

Uncomment HostKey /etc/ssh/ssh_host_ed25519_key

Save and exit.

Change ownership of the new sshd:

sudo chown root:root newsshd

We now need to make a slight edition to a couple of files. First back up the files we are going to edit:

sudo cp /etc/passwd /etc/passwd.org && sudo cp /etc/group /etc/group.org

Insert this line at the bottom of /etc/passwd :

sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin

Likewise, insert this line to the bottom of /etc/group :

/etc/group:sshd:*:27:

If you do not do the changes above, you'll get 'Privilege separation user sshd does not exist' when running the sshd binary you just transferred.

Now, let's do a connection test!

On DS:

sudo LD_LIBRARY_PATH="/absolutepathtohomedir:$LD_LIBRARY_PATH" /absolutepathtohomedir/newsshd -p 444 -f /etc/ssh/sshd_config_new -h /etc/ssh/ssh_host_ed25519_key -d

This will start the new sshd binary in debug mode.

You can now connect to this ordinarily from your linux instance with

ssh -p 444 user@DS

FINALLY - THE GREAT REPLACEMENT.

Make sure to take a note of everything that you do, and keep a note of it somewhere, along with the files you have. Synology Inc. is known for sometimes replacing edits and files when doing updates. If this happens, you need to enable telnet via DSM and login via telnet on local network to restore the settings. Possibly, you could set up a cronjob to monitor the system, and revert automatically any changes that comes along with an update. Depending on your setup, you may not need to update DSM very often, if you're already on a very secure and segmented network.

The relevant binaries we've compiled for ARM architecture residing in ~/crosscompile/openssh-8.1p1 :

  • ./ssh-agent (authentication agent)
  • ./sftp-server (SFTP server subsystem)
  • ./ssh (OpenSSH SSH client (remote login program))
  • ./ssh-keyscan (gather ssh public keys)
  • ./ssh-keygen (authentication key generation, management and conversion)
  • ./sftp (secure file transfer program)
  • ./ssh-keysign (disabled by default)
  • ./ssh-add (adds RSA or DSA identities to the authentication agent )
  • ./scp (secure copy (remote file copy program))
  • ./ssh-pkcs11-helper (ssh-agent (helper program for PKCS#11 support)
  • ./sshd (OpenSSH SSH daemon)

You must decide which of these you need. If you're only going to use sshd and scp, then it might be sufficient to replace these binaries.

First off, edit the original /etc/ssh/sshd_config file, comment 'UsePAM yes' to '#UsePAM yes', then uncomment 'HostKey /etc/ssh/ssh_host_ed25519_key'.

You should really just use ed25519 keys, if you use other types of keys, uncomment accordingly.

Let's make sure openssl support is available.

On my DS, this doesn't overwrite anything, your mileage my vary. Check if the target exist already. I've done it this way, as it's a simple method to get this working. Possibly the shared object file could be put in a custom path and added to the search path for shared object files.

sudo mv ~/libcrypto.so.1.1 /usr/lib/

Find the location of the files you want to replace:

which sshd ; which scp

Result:

/bin/sshd
/bin/scp

Back up these two files.

sudo cp /bin/sshd /bin/sshd.DS.orginal
sudo cp /bin/scp /bin/scp.DS.orginal

Exit to the linux instance and copy over the newly created scp file:

scp scp DS:~

Ssh to DS, and move the scp file and set correct ownership:

sudo mv ~/scp /bin
sudo chown root:root /bin/scp

Since /bin/sshd is active, it can't be overwritten, so we need to kill it. But before this we need to have launched our newly created sshd so we have an alternate path to the DS.

Start a new terminal on your linux instance , and ssh to DS in the normal way:

ssh DS

Then, spawn an instance of your new sshd server:

sudo /absolutepathtohomedir/newsshd -p 777 -f /etc/ssh/sshd_config_new -h /etc/ssh/ssh_host_ed25519_key

Exit the ssh-session, and try to log in to a session controlled by the newly spawned ssh binary:

ssh -p 777 user@DS

Now, kill the original ssh-server on port 22.

sudo su

then edit ssh configuration

vim /etc/init/sshd.conf

Comment out the respawn lines, so they look like below:

#respawn
#respawn limit 5 10

Then:

netstat -ap | grep ssh

Find the process id to the right

The line should look like:

tcp        0      0 0.0.0.0:ssh             0.0.0.0:*               LISTEN      9508/sshd

Stop ssh-shell

synoservice --hard-stop ssh-shell

Kill the sshd process.

kill -9 9508

Check if the process is gone, and nothing is listening on port 22:

netstat -tpa | grep 22

Possibly you need to shut down other instances of sshd, if you've experimented with various ports during this guide.

If all fails, you could disable ssh via DSM.

Finally:

cp /fullhomepath/newsshd /bin/sshd && chown root:root /bin/sshd

Reverse the respawn comments done earlier to /etc/init/sshd.conf

Create this symlink as the new sshd complains the local sshd_config file does not exist

ln -s /etc/ssh/sshd_config /usr/local/etc/sshd_config

Re-enable sshd:

synoservice --hard-enable ssh-shell

Now, verify that the copied files match those compiled:

On DS:

sha256sum /bin/sshd /bin/scp

On linux instance:

sha256sum ~/crosscompile/openssh-8.1p1/sshd ~/crosscompile/openssh-8.1p1/scp

Hashes for respective binaries should match between systems.

We can also check the version of the new, vs the old files:

 ash-4.3# /bin/sshd.DS.orginal --version ; /bin/scp.DS.orginal --version

 unknown option -- - OpenSSH_7.4p1, OpenSSL 1.0.2r-fips  26 Feb 2019 usage: sshd [-46DdeiqTt] [-C connection_spec] [-c
     host_cert_file]
                 [-E log_file] [-f config_file] [-g login_grace_time]
                 [-h host_key_file] [-o option] [-p port] [-u len] unknown 

option -- - usage: scp [-12346BCpqrv] [-c cipher] [-F ssh_config] [-i
         identity_file]
                    [-l limit] [-o ssh_option] [-P port] [-S program]
                    [[user@]host1:]file1 ... [[user@]host2:]file2

ash-4.3# /bin/sshd --version ; /bin/scp --version

unknown option -- -
OpenSSH_8.1p1, OpenSSL 1.1.1d  10 Sep 2019
usage: sshd [-46DdeiqTt] [-C connection_spec] [-c host_cert_file]
            [-E log_file] [-f config_file] [-g login_grace_time]
            [-h host_key_file] [-o option] [-p port] [-u len]
unknown option -- -
usage: scp [-346BCpqrTv] [-c cipher] [-F ssh_config] [-i identity_file]
            [-J destination] [-l limit] [-o ssh_option] [-P port]
            [-S program] source ... target

You could now try to connect normally to the Synology again:

ssh DS

You will now be greeted with something like "WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!"

This is expected. Rectify it manually by editing /home/user/.ssh/known_hosts, it should be sufficient to remove old keys and reconnect, then accept the new key.

Finally, to check if something gets altered by a reboot, optionally reboot the DS.

To ensure that the custom lines in /etc/passwd and /etc/group stick, use the script below, save it to /usr/local/bin/pwdgroupfixer.sh, remember to make it executable by chmod +x.

Make an entry in roots crontab:

*/5 *   *   *   *   root    /bin/sh /usr/local/bin/pwdgroupfixer.sh

Note that synology is particular about the formatting of its crontab. Use tabs instead of spaces, it's a good tip to use an existing entry and copy it to a new line and modify it.

Finally restart crontab service:

sudo synoservice -restart crond

#!/bin/sh
#pwdgroupfixer.sh

#Entries to support sshd

PASSWORDFILE=/etc/passwd
USERLINE="sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin"

GROUPFILE=/etc/group
GROUPLINE="/etc/group:sshd:*:27:"


itemcheck(){
  FILE=$1
  ITEM=$2
DATE=`/bin/date +%Y-%m-%d`
TEMPFILE=/tmp/$DATE
/bin/echo '0' > $TEMPFILE

FOUND=0
/bin/sed '/^[ \t\r\n]*$/d' $FILE | while read LINE; do
    if [[ ${LINE:0:1} != "#" ]]; then
         if [ "$LINE" == "$ITEM" ];
         then
            let FOUND++
            /bin/echo $FOUND > $TEMPFILE
         fi
     fi
  done

FOUND=`/bin/cat $TEMPFILE`

if [ "$FOUND" -eq "0" ]; then
    /bin/cp $FILE $FILE.`/bin/date +%Y-%m-%d`
    /bin/echo $ITEM >> $FILE
fi

}

itemcheck $PASSWORDFILE "$USERLINE"
itemcheck $GROUPFILE $GROUPLINE

#end pwdgroupfixer.sh
8
  • Thanks for your efforts and for sharing them. However, wouldn't it have been much easier to make use of Entware instead of compiling yourself? Oct 21, 2019 at 10:34
  • I read somewhere there was community efforts to get unofficial packages to synology, never looked very much into it. Entware I had actually never heard of before. Will have to read more about that. I might be a bit paranoid, can Entware be trusted? Is their security sound? Of course it will be a whole lot simpler to use some package system that can be easily installed and that can be used to give the user access to a whole lot of packages. Anyway, with the manual method I described, the normal user can now ssh to DS, but your comment is surely worth considering for many users, including me. Oct 21, 2019 at 15:02
  • Afaik Entware is an effort to bring OpenWRT's Opkg Package Manager to other embedded devices. OpenWRT has quite a good track record, no? I've been using it for a couple of years if I want to bring other or more up to date packages to Synology. Oct 21, 2019 at 18:13
  • 1
    For the "normal" user I would also suggest to not replace the default OpenSSH binaries but to simply spin up a second SSH-server on a different port via task manager. That way it is probably more likely to survive firmware updates etc. and one doesn't mess with the Synology internal workings. Might be an option for the less savvy users. Oct 21, 2019 at 18:13
  • 1
    Thanks for the efforts @NordicViking! I wrote a blog post on how to enable ssh for non-root users that explains the easy way (as suggested by @TylerDurden)
    – Laurenz
    Nov 29, 2020 at 13:30
1

On DiskStations that feature Docker I found it easiest to use an OpenSSH-container. I went for linuxserver/openssh-server. That way I can mount only the relevant data into to the container and I don't have to mess with Synology's configs.

1

I have tried the following approach, which involves neither installing additional software nor giving elevated privileges to users who shouldn't get them. However, I have not yet confirmed that this solution actually works; I suspect I might need to restart the NAS a second time at the end of the procedure. I'll update here as I learn more. If somebody tries it all the way up to the second restart, please leave a comment!

I realized that I could play Synology's game and reduce the "administrators" user group to just a group that gives you SSH privilege.

I created a second group and gave it all the same privileges as the default "administrators" group. Let's say you name this group "realadmin". All the users that are actually supposed to have admin rights, should be added to this group (just to be safe, keep them in the original "administrators" as well). After creating this group and adding all users that should have admin rights, ssh into the NAS with an admin account and sudo vi /etc/sudoers. Replace %administrators by %realadmin (make very sure you type this right, perhaps copy-paste from the DSM admin panel for certainty) and save and close by typing wq!. Restart the NAS for this change to take effect (you lose your sudo access until you have restarted the NAS). Finally, remove all permissions from the "administrators" group except for those that you are likely to use with SSH, such as rsync. Update the description to reflect that "administrators" is now basically the SSH user group. Add all users that you want to give SSH access; they should now gain no administrative rights from being "administrators". Be sure to set the shell back to /bin/sh for each of these users in /etc/passwd and create a .ssh/authorized_keys file in their home directories with the public keys with which they should be able to authenticate.

I took the above steps and then tried SSH-ing into the NAS with a non-real-admin account which I had added to the "administrators" group. Still, I got permission denied (publickey). I'm not sure what's missing at this point. Maybe I need to restart the NAS again in order for the addition of the user to "administrators" to take effect. I briefly tried adding the same user to "realadmin" as well, but the user still couldn't use SSH, at least not without restarting the NAS. I have not restarted the NAS a second time yet, because I have processes running that I don't want to interrupt too often and because I figured out a different, quick-and-dirty workaround that solves my particular problem for now.

I originally described this (theoretical) solution on the Synology community forum, with some additional discussion, on this page: https://community.synology.com/enu/forum/1/post/125859?page=2 (16th reply, most recent at the time of writing).

1
  • Interesting approach. By now I just reverted to using Docker for this task. Aug 30, 2021 at 8:44
0

From version 6.2.0 of Synology DSM, ssh access is restricted to members of the administrators group.

To get around this limitation, we will install a dockerized ssh inside the Synology NAS.

Steps:

  • Change the Synology SSH to a port different than 22 (such as 2222): Control Panel > Terminal & SNMP

  • Install Docker from Packages Center

  • Enable user home folders: Control Panel > Users > Advanced

  • Create a fake sshd user and disable it (docker will need it): Control Panel > Users

Then we must ssh as administrator to the Synology NAS and create several scripts as root

Create the cronjob script :

mkdir -p /etc/docker-ssh
cat <<EOF > /etc/docker-ssh/cronjob
#!/bin/sh
set -e
# fix passwd entries to add /bin/bash as shell and only keep /homes/
awk -F ':' < /etc/passwd '
  /^root/ {print}
  /homes/ {print \$1 ":" \$2 ":" \$3 ":" \$4 ":" \$5 ":" \$6 ":/bin/bash"}
' > /etc/docker-ssh/passwd
chmod 644 /etc/docker-ssh/passwd
# fix homes root permissions
chmod 755 /var/services/homes
find /var/services/homes/ -mindepth 1 -maxdepth 1 -type d \
  | xargs --no-run-if-empty chmod 700
EOF

chmod +x /etc/docker-ssh/cronjob

Register the cronjob script to run every hour :

echo "@hourly root [ -x /etc/docker-ssh/cronjob ] && /etc/docker-ssh/cronjob" > /etc/cron.d/docker-ssh

Create a fake sshd_config used by the dockerized ssh

cat <<EOF > /etc/docker-ssh/sshd_config
Port 22
Protocol 2
HostKey /etc/ssh/ssh_host_rsa_key
SyslogFacility AUTH
LogLevel VERBOSE
LoginGraceTime 120
PermitRootLogin no
StrictModes yes
PubkeyAuthentication yes
AuthorizedKeysFile %h/.ssh/authorized_keys
IgnoreRhosts yes
HostbasedAuthentication no
PermitEmptyPasswords no
ChallengeResponseAuthentication no
PasswordAuthentication no
PrintMotd no
TCPKeepAlive yes
AcceptEnv LANG LC_*
Subsystem sftp /usr/lib/openssh/sftp-server
EOF

Finally, create the main script to run the dockerized sshd container :

cat <<EOF > /etc/docker-ssh/run.sh
#!/bin/sh
set -eu

# Find openssh-server images here: https://hub.docker.com/r/linuxserver/openssh-server/tags
SSHD_DOCKER_IMAGE=ghcr.io/linuxserver/openssh-server:version-8.4_p1-r3
SSHD_OPTIONS=(-D -e) # run in foreground + log to stdout

# initialize the dummy etc/passwd file (it should be refreshed by cronjob after container boot)
for file in /etc/ssh/ssh_host_rsa_key /etc/ssh/sshd_config /etc/group; do
  ln -sf \${file} /etc/docker-ssh/\${file##*/}
done
# run the cronjob manually once to be sure that all our files exist.
/etc/docker-ssh/cronjob

# stop container if already running
docker rm -f ssh-server >/dev/null 2>&1 || :

# run the container again
exec docker run \
  --detach \
  --restart=unless-stopped \
  --name=ssh-server \
  --hostname=$(hostname) \
  --volume /etc/docker-ssh/ssh_host_rsa_key:/etc/ssh/ssh_host_rsa_key:ro \
  --volume /etc/docker-ssh/sshd_config:/etc/ssh/sshd_config:ro \
  --volume /etc/docker-ssh/passwd:/etc/passwd:ro \
  --volume /etc/docker-ssh/group:/etc/group:ro \
  --volume /var/services/homes:/var/services/homes \
  --publish 0.0.0.0:22:22 \
  --entrypoint=/usr/sbin/sshd \
  "\${SSHD_DOCKER_IMAGE}" "\${SSHD_OPTIONS[@]}"
EOF

chmod +x /etc/docker-ssh/run.sh

Finally, run the script:

/etc/docker-ssh/run.sh

Once the sshd container is running, users should be able to ssh to their homes as before.

Since interactive authentication is disabled, users should create in advance the .ssh/authorized_keys file with these permissions:

chmod u+rwx,g-rwx,o-rwx $HOME/.ssh folder
chmod u+r-wx,g-rwx,o-rwx $HOME/.ssh/authorized_keys

To uninstall, simply:

docker rm -f openssh-server
rm -rf /etc/docker-ssh /etc/cron.d/docker-ssh
0

I am in no way a NAS expert, but enabling user's access to git_repos sets shell in /etc/passwd to /var/packages/Git/target/bin/git-shell on DSM 6.2.4-25556 Update 5 (so it fits into DSM 6.2.x category). Changing that to /bin/sh grants SSH access.

-1

you have to edit /etc/passwd the usual way, then proceed to edit /etc/ssh/sshd_config by changing the value of

ChallengeResponseAutentication

form no to yes.

Then restart the ssh daemon by killall -1 sshd

1
  • 1
    Nope, doesn't work. Same behaviour as before. Thanks anyway. May 23, 2019 at 19:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.