Skip to main content

Android: Adding scp/sftp support to dropbear and mounting with sshfs

I have recently received an android smartphone, and one of the first things I did with it was to root it :). This allows power-usres to get the most out of their hardware.

The next thing on my list was to set up a SSH server and to be able to transfer files between my Linux system and my phone (by the way, I'm running Android 4.1 and it seems USB mass storage support has been removed. MTP/PTP modes have either horrible transfer speed or are poorly supported in Ubuntu).

With the above in mind, the plan was to:
  • Enable tethering on the phone
  • Run a SSH server to support issuing remote commands and file transfer (FTP might have been an alternative, but I'm a SSH adept).
Browsing the market I found SSHDroid which does all that it advertised. Problem is - the free version conflicts with my add-blocking apps and requests that they are disabled to run.

For me, this is a big nuisance, so I kept looking. I found Dropbear SSH Server 2, which is completely free, but doesn't support scp/sftp.

So, I wanted scp/sftp support, so I started to work on a solution.

If, after starting Dropbear server you try to transfer a file via scp you get this error (pris is the name of my phone and is mapped to an IP address via the /etc/hosts file):
adrianp@frost:~$ scp test.log root@pris:/storage/sdcard0/
Welcome to DropBear SSH Server II!
root@pris's password:
sh: scp: not found
lost connection
adrianp@frost:~$
then, you are in the same situation I was...

For scp/sftp to work, the process needs to have access to the scp/sftp-server binaries on your android system. But it seems dropbear doesn't come with those binaries. But searching around the system, the binaries are available in the SSHDroid package.

So, I was doing the following steps to make those binaries available to the whole system (needs a rooted system with busybox installed):

root@android:/data/local # scp
sh: scp: not found
127|root@android:/data/local # find / -name scp 2>/dev/null

/data/data/berserker.android.apps.sshdroid/dropbear/scp
1|root@android:/data/local # /data/data/berserker.android.apps.sshdroid/dropbear/scp
usage: scp [-1246BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file]
           [-l limit] [-o ssh_option] [-P port] [-S program]
           [[user@]host1:]file1 [...] [[user@]host2:]file2

1|root@android:/data/local # ls -l /system/xbin/                              
-rwxr-xr-x root     shell       59760 2012-09-28 12:15 dexdump
-rwsr-sr-x root     root        91992 2012-12-21 10:02 su
root@android:/data/local # echo $PATH                                         
/sbin:/system/sbin:/system/bin:/system/xbin
root@android:/data/local # mount -o remount,rw /system
root@android:/data/local # ln -s /data/data/berserker.android.apps.sshdroid/dropbear/scp /system/xbin/scp

root@android:/data/local # ln -s /data/data/berserker.android.apps.sshdroid/dropbear/ssh /system/xbin/ssh
root@android:/data/local # ln -s /data/data/berserker.android.apps.sshdroid/dropbear/sftp-server /system/xbin/sftp-server
root@android:/data/local # mount -o remount,ro /system
At this point, you can use scp to transfer files from your computer to your Android device. However, you can't mount it with sshfs yet.

The problem when mounting it is that sshfs tries to use the sftp server, and by default it tries to call it from /usr/libexec/sftp-server. This path does not exist on your android device, and you will need to instruct sftp to use /system/xbin/sftp-server instead. You can do this with the following command:

sudo sshfs -o sftp_server=/system/xbin/sftp-server  root@pris:/storage /media/pris
Of course, in order to mount the device as a regular user and to be able to transfer files, you will need to prepare your mount point and your fstab entry:

adrianp@frost:~/temp$ sudo mkdir -p /media/pris
adrianp@frost:~/temp$ sudo chown root:fuse /media/pris
adrianp@frost:~/temp$ sudo chmod g+w /media/pris
adrianp@frost:~/temp$ cat /etc/fstab | grep pris
sshfs#root@pris:/storage /media/pris fuse user,fsname=sshfs#root@pris:/storage,noauto,sftp_server=/system/xbin/sftp-server 0 0
You will now be able to mount the device via the command line (or in Nautilus). It will ask for your ssh password, and then it will display the files as if they were local. In terms of performance, I get about 4.6MB/s reads and 4.1MB/s write speed (over USB).  Compared to ~240kB/s read/write in MTP mode, I would say I get quite a performance boost!

Remember, in order to follow the steps above you will need:
  • a rooted android device
  • busybox installed
  • SSHDroid installed (it will remain installed even if you don't start the ssh service. You can possibly uninstall it if you replace the "ln -s" commands with "cp" instead)
  • Dropbear II (and started)
  • either a wifi connection between your PC and android device, or USB tethering (it's what I'm using)
Enjoy!

Comments

László said…
You're the man, thanks so much! I can finally scp back and forth and use sshfs with my phone!
Adrian Popa said…
Glad it helped.
I'm currently running a variant of the above instructions with the change that I moved sftp-server to /usr/libexec instead of /system/xbin. This allows me to skip specifying sftp-server in the mount command.

The problem is the system deletes /usr/libexec on reboot, so I need to recreate it...
George Profenza said…
This is great! I've just this now and it works like a charm.

Multumesc :)
Adrian Popa said…
I have mostly abandoned mounting over ssh and I'm currently using FTP for more performance. Over USB tethering I can now get about 10MB/s transfer rates (compared to 4.5MB/s with ssh).

I am using ES Explorer's FTP server (if you create a shortcut on the desktop you can enable it without turning on Wifi).
Lehin' said…
Great post. I had to add `,allow_other` option to fstab, and my `ssh` binary was in the `/data/dropbear` folder, but otherwise worked perfectly.

Popular posts from this blog

Home Assistant + Android TV = fun

Here's a quick setup guide for controlling your Android TV from within Home Assistant. I've used it to control a genuine Android TV (Philips 7304) and an Odroid N2 running Android TV. For this to work you need ADB access. It can usually be enabled from within Developer Settings. The great part is - you don't need root access! The most important things are described in the androidtv component for Home Assistant: https://www.home-assistant.io/integrations/androidtv/ Make sure you go through the adb setup. My configuration is simple (inside configuration.yaml): media_player:   - platform: androidtv     name: TV Bedroom ATV     host: 192.168.1.61     device_class: androidtv Once Home Assistant restarts, your TV might require you to accept the connection (adb authentication). This happens only once (or until you reset your ATV to factory settings). Once running the integration will show you the current ATV state (on or off) and allows you to turn it on or off.

SmokePing + InfluxDB export + docker + slaves + Grafana = fun

I've been working for a while on this project - with the purpose of getting SmokePing measurements from different hosts (slaves) into InfluxDB so that we can better graph them with Grafana. The slaves run multiple Smokeping instances inside Docker so that they have separate networking (measure through different uplinks, independently). This will not be a comprehensive configuration guide, but a quick "how to" to handle setup and basic troubleshooting. It assumes you already know how to set up and operate a regular Smokeping install with or without slaves and that you are fluent in Smokeping configuration syntax, know your way around Docker and aren't a stranger from InfluxDB and Grafana (sorry, there's a lot of information to take in). 1. Getting Smokeping with InfluxDB support - you can get it either from the official page (most changes have been merged) - https://github.com/oetiker/SmokePing (PR discussion here: https://github.com/oetiker/SmokePing/issues/

Installing Home Assistant Supervised on an old 32bit HP laptop

 I've received a challenge from my former boss: an old HP laptop that was born in 2005:  an HP-Compaq NC6220 ( https://www.pocket-lint.com/laptops/reviews/hp/68181-hp-compaq-nc6220-notebook-laptop/ ). The specs are abysmal: So, i386, 1.7GHz single-core CPU (remember those?), 1G of DDR2 RAM (2x512M) and a 40GB ATA (not SATA!) drive. But hey, at least it has a serial port!  The challenge is to install HomeAssistant ( https://www.home-assistant.io/ ) on it so that he can monitor some Zigbee temperature sensors and relays (via a gateway). The first hurdle was to remove the BIOS password - following this nice guide: https://www.youtube.com/watch?v=ZaGKyb0ntSg Next-up - install HASSOS. Unfortunately, it doesn't support i386, but only x86_64... So, I went the Home Assistant Supervised route, and installed Debian 11 i386 edition from a netinstall USB ( https://cdimage.debian.org/debian-cd/current/i386/iso-cd/debian-11.6.0-i386-netinst.iso ).   Once Debian was up and running (didn't