Samsung Galaxy display running CyanogenMod

How to Enable SSH Service on CyanogenMod

The CyanogenMod project has been shut down. Click here for more information. This page is of historical interest only.

SSH on CyanogenMod

I had installed CyanogenMod on my Samsung Galaxy, and wanted a better way of accessing it. I installed SSHDroid and was reasonably pleased, but it had its quirks and limitations. Then I learned that there is an SSH daemon and it's pretty easy to set up and enable.

I followed a different path, though, as almost everything I want to do needs root access. Mostly this is using scp to copy picture files out of /storage/sdcard1/DCIM/Camera/ and then deleting them through ssh. That directory is owned by user root and group sdcard_r and it's mode 770. The other thing I commonly do is compare things like the networking commands on Android to those on Linux.

So, the shell account you get from the adb shell can't do what I want.

Preparing

Make sure you have installed the android-tools package on your Linux machine. If it's packaged under a different name, ask YUM which package you would have to add to get the adb program:
yum provides /usr/bin/adb

Go into the settings menu on your phone, select Developer Options, and find Root access. Tap it and change it to Apps and ADB.

Now you should be able to run adb shell from your Linux notebook or desktop and get a shell on your USB-connected device. Within that session, become root with su.

Escape
Vol-Up + E
Vol-Up
Back

If this isn't possible, you can do the following work from an Android terminal emulator. The trickiest part is editing a pair of configuration files, but just use vim after verifying how to input a Escape character. For the terminal emulator I use it's done by pressing and holding Vol-Up and then pressing E. Also try Vol-Up by itself, and the Back button at the bottom.

CyanogenMod menu, Settings -- Developer options
Special keys in Android terminal emulator, part 1
Special keys in Android terminal emulator, part 2

Finally, you need an SSH key pair, see this page for details on using ssh-keygen if you haven't done this yet. The result will be key files in ~/.ssh,, public keys in id_rsa.pub and id_dsa.pub, private keys in id_rsa and id_dsa. The file authorized_keys will contain all your public keys.

Use /data/ssh/ instead of /system/etc/ssh/

The standard place for SSH server configuration is the directory /system/etc/ssh/. However, the next time you flash a new /system, which might be within the next week, you would lose your settings.

We will put our system configuration and host keys in /data/ssh/ instead, and we will make sure to start the SSH daemon so it expects that.

Set Up Server Configuration Directory

The default PATH environment variable puts /system/bin before /system/xbin, and the bin directory is largely filled with symbolic links to toolbox. The resulting ls command is a little odd. So, verify that some things are in place this way:

# /system/xbin/ls -laR /data/ssh 

You should see that directory /data/ssh exists, is owned by root, and is mode 700 or 750.

It should contain a directory /data/ssh/empty/ with no contents and mode 700.

These should already be there. If they seem to be missing check your typing. If you really need to, re-create them if they are missing for some reason.

Set Up Authorized User Public Keys

Create a user SSH directory and make it owned by user shell temporarily. Don't overlook the "." in the file name!
/data/ssh is for system configuration,
/data/.ssh is for user configuration.

# mkdir /data/.ssh
# chmod 700 /data/.ssh
# chown sheel:shell /data/.ssh 

We are using the account shell as it is used when connecting with adb. Now switch to your Linux machine and run this one command:

Linux$ adb push ~/.ssh/authorized_keys /data/.ssh/ 

Switch back to your root session on the phone and change the ownership and permissions:

# cd /data/.ssh
# chown shell:shell *
# chmod 600 * 

Configure the SSH Server

An SSH configuration already exists on the phone, but we will make a few changes and put the modified version in /data/ssh/sshd_config so it is not overwritten when we do the next system flash.

# cd /data/ssh
# cp /system/etc/ssh/sshd_config .
# chmod 600 sshd_config
# vim sshd_config 

We only need to make a few changes. You will find that most of the file is comments, and much of what you are doing is uncommenting settings already in the file. Depending on the version of OpenSSH, some may have already been the default behavior anyway.

1. Change:
#PermitRootLogin yes
to:
PermitRootLogin yes

2. Change:
#PubkeyAuthentication yes
to:
PubkeyAuthentication yes

3. Change:
#PasswordAuthentication yes
to:
PasswordAuthentication yes

4. Change:
#PermitEmptyPasswords no
to:
PermitEmptyPasswords no

5. Change:
#ChallengeResponseAuthentication yes
to:
ChallengeResponseAuthentication no

6. Change:
Subsystem sftp /usr/libexec/sftp-server
to:
Subsystem sftp internal-sftp

Check your work:

# diff /system/etc/ssh/sshd_config /data/ssh/sshd_config 

Start the SSH Server at Boot Time

There is a script on the system to start sshd, but we need to change where it looks for its configuration.

The boot logic on Android says that if the directory /data/local/userinit.d exists, then run each of the scripts found there at boot time. We will name our script 99sshd:

# mkdir /data/local/userinit.d
# cd /data/local/userinit.d
# cp /system/bin/start-ssh 99sshd
# chmod 755 99sshd
# vim 99sshd 

Change the two instances of /system/etc/ssh/sshd_config to /data/ssh/sshd_config.

Check your work. This shows the output you should see. You won't see the colored highlighting, I added it here to draw your attention to what you need to check.

# diff /system/bin/start-ssh /data/local/userinit.d/99sshd
38c38
<     /system/bin/logwrapper /system/bin/sshd -f /system/etc/ssh/sshd_config -D -d
---
>     /system/bin/logwrapper /system/bin/sshd -f /data/ssh/sshd_config -D -d
41c41
<     /system/bin/sshd -f /system/etc/ssh/sshd_config -D
---
>     /system/bin/sshd -f /data/ssh/sshd_config -D 

Test It!

Run /data/local/userinit.d/99sshd and log in over SSH as root from another system. Warning: If you had been using another SSH server such as SSHDroid, your SSH client will have saved those old server public keys. The native Android SSH service will generate its own host key pairs the first time it starts. Your SSH client will not see the expected server public key, it will display a warning message and then abort the attempt to connect. You need to edit your ~/.ssh/known_hosts and remove the existing line for your Android device.

When you succeed, reboot the Android device and verify that the SSH service was automatically started.

Scanning mine with Nmap I see this:

# nmap -sS -sV -O 192.168.1.102

Starting Nmap 6.47 ( http://nmap.org ) at 2015-07-01 17:21 EDT
Nmap scan report for 192.168.1.102
Host is up (0.23s latency).
Not shown: 999 closed ports
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 6.4 (protocol 2.0)
MAC Address: 00:37:6D:A9:B9:35 (Murata Manufacturing Co.)
Device type: general purpose
Running: Linux 3.X
OS CPE: cpe:/o:linux:linux_kernel:3
OS details: Linux 3.2 - 3.10
Network Distance: 1 hop

OS and Service detection performed. Please report any incorrect results at http://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 66.26 seconds 

Be Careful, and Enjoy!

Be very careful doing everything as root. You have no need to worry about someone guessing a 1024-bit (or longer) RSA key, unless you somehow generated your key pair in a flawed environment. Your primary concern is self-inflicted damage from your own root activity.