Coder Social home page Coder Social logo

android_external_sshfs's Introduction

android_external_sshfs

sftp (secure file transfer program) client that uses FUSE to mount files and directories served by any SSH server to an android client, secure enough to mount over the internet

Overview

The code is mostly from the FUSE project's sshfs implementation, found here. It's been adapted to compile into the cyanogenmod android rom.

This project will allow you to securely mount a folder served up by an ssh server to your android device from anywhere with a network connection.

A typical use case for this would be that you have a phone with 8GB of non-expandable storage and you want access to your 100GB music collection while you're on the go (either via cell or Wi-Fi data access). This project allows all the apps on your phone to see your entire music/movie/book/document/whatever collection as if your files were on your device (if your data connection permits it).

This project provides (for free) the functionality promised by the currently broken and ~$2.75 app in the play store called SSHFSAndroid.

How to build and install

This module will build a single binary executable file: 'sshfs' that will be installed into /system/xbin on your device, if you follow the instructions provided.

During the installation, some glib-2.0 libraries will also be built and installed on your phone.

This was only tested under cyanogenmod cm-10.2. It'll probably work fine in other roms so long as they have FUSE support.

However, it should be noted that there have been reports with this not working properly in CM12+ (Lollipop). If, after you build this, the sshfs directory structure disappears after opening a file, rest assured that the developer is working to find the source of the problem.

It should also be noted that this has only been tested with SuperSu. You may come across unknown issues when using a different SU app.

These steps assume:

  1. You have a working cyanogenmod or cm-based rom's build environment with the rom's source tree located in ~/android/system (see here for instructions on how to get this, and consult your rom's forum thread or auther regarding its source if you have a cm-based rom)
  2. Your device's currently-installed rom is built from this tree
  3. You have successfully built the entire rom image, which makes sure all required libraries are built, and also ensures you have a working source tree
  4. Your device is ready to be connected via adb to your machine containing this build environment, either through wifi or USB (the adb commands in the instructions below are for connecting via USB. Tweak at your leasure)

Note: These instructions will differ if you are building in a system other than a Linux distro. Mac and Windows users will need to either run a Virtual Machine for the build environment (recommended) or consult a CyanogenMod build guide that is specific to their operating system (and their operating system's release version, most likely).

To build and install onto your device, issue the following commands in your build environment:

git clone https://github.com/greyltc/android_external_sshfs.git ~/android/system/external/sshfs
git clone https://github.com/greyltc/android_external_glib.git -b cm-10.2 ~/android/system/external/glib
adb root
adb remount
cd ~/android/system/
source build/envsetup.sh
lunch

Running the lunch command will prompt you to choose a device. Choose the device that your source tree supports (presumably the one you are building for).
!!! Your phone should be plugged in at this point !!!

cd ~/android/system/external/glib
mmp -B
cd ~/android/system/external/sshfs
mmp -B

After a successful compile, you should see something like this at the end of your terminal's output:

Pushing: system/xbin/sshfs
5061 KB/s (125476 bytes in 0.024s)

If you see that, you know the binary was built and pushed successfully to your device. If you don't see that, make sure you have a proper build environment. Usually these commands will show errors pointing to missing files. If it fails to find a file in "~/android/system/vendor/..." and you have already successfully built your rom with your source tree, you most likely chose the wrong device when you ran "lunch" or you never ran it at all.

How to use

In a shell on your android device type sshfs -h, you'll see:

usage: sshfs [user@]host:[dir] mountpoint [options]

general options:
    -o opt,[opt...]        mount options
    -h   --help            print help
    -V   --version         print version

SSHFS options:
    -p PORT                equivalent to '-o port=PORT'
    -C                     equivalent to '-o compression=yes'
    -F ssh_configfile      specifies alternative ssh configuration file
    -1                     equivalent to '-o ssh_protocol=1'
    -o reconnect           reconnect to server
    -o delay_connect       delay connection to server
    -o sshfs_sync          synchronous writes
    -o no_readahead        synchronous reads (no speculative readahead)
    -o sshfs_debug         print some debugging information
    -o cache=BOOL          enable caching {yes,no} (default: yes)
    -o cache_timeout=N     sets timeout for caches in seconds (default: 20)
    -o cache_X_timeout=N   sets timeout for {stat,dir,link} cache
    -o workaround=LIST     colon separated list of workarounds
             none             no workarounds enabled
             all              all workarounds enabled
             [no]rename       fix renaming to existing file (default: off)
             [no]nodelaysrv   set nodelay tcp flag in sshd (default: off)
             [no]truncate     fix truncate for old servers (default: off)
             [no]buflimit     fix buffer fillup bug in server (default: on)
    -o idmap=TYPE          user/group ID mapping, possible types are:
             none             no translation of the ID space (default)
             user             only translate UID of connecting user
             file             translate UIDs/GIDs contained in uidfile/gidfile
    -o uidfile=FILE        file containing username:remote_uid mappings
    -o gidfile=FILE        file containing groupname:remote_gid mappings
    -o nomap=TYPE          with idmap=file, how to handle missing mappings
             ignore           don't do any re-mapping
             error            return an error (default)
    -o ssh_command=CMD     execute CMD instead of 'ssh'
    -o ssh_protocol=N      ssh protocol to use (default: 2)
    -o sftp_server=SERV    path to sftp server or subsystem (default: sftp)
    -o directport=PORT     directly connect to PORT bypassing ssh
    -o slave               communicate over stdin and stdout bypassing network
    -o transform_symlinks  transform absolute symlinks to relative
    -o follow_symlinks     follow symlinks on the server
    -o no_check_root       don't check for existence of 'dir' on server
    -o password_stdin      read password from stdin (only for pam_mount!)
    -o SSHOPT=VAL          ssh options (see man ssh_config)

The following example assumes:

  1. You already have an ssh server running somewhere on a machine with hostname (or IP) SERVER that you can log into as USER
  2. You have created an empty directory on your device to mount to at the following location: /data/media/0/sshfsmount
  3. You have turned off namespace separation in your SU app, if the option exists. If you are running certain android versions and you have SuperSu (which is recommended for 4.0+), you can turn this off in SuperSu's settings. Be aware that if namespace separation is on, you will not be able to access the files outside of the app you use to initiate the connection, because namespace separation forces fuse-mounted directories to be on a per-app basis. If you change this setting, it is recommended to reboot your device before testing sshfs.

Mounting

Make sure /data/media/0/sshfsmount exists and is an empty directory.
In a shell on your android device type:

su
sshfs USER@SERVER: /data/media/0/sshfsmount -o allow_other -o ro -o follow_symlinks -o StrictHostKeyChecking=no -o reconnect -o TCPKeepAlive=no

Replace USER with your ssh login name and SERVER with the server hostname or IP address (note the colon after SERVER is intentional). You will be asked for your ssh password for USER.

  • -o ro means you'll mount the files as read only (recommended to prevent file damage because this project is experimental)
  • -o allow_other sets the permissions of the mounted files so that you can access them
  • -o follow_symlinks enables symlinks in your ssh share to work properly
  • -o StrictHostKeyChecking=no bypasses a prompt for a security measure used to prevent MITM attacks
  • -o reconnect allows for reconnection after interruption in network service
  • -o TCPKeepAlive=no prevents interruptions in network connectivity from bringing down the connection

When the sshfs command completes successfully you'll be dumped back to the command line with no indication that it worked. You can verify that the mount completed properly by issuing ls /data/media/0/sshfsmount you should see the directory structure of your ssh home directory.

To mount a directory on the ssh server other than your home directory, add it after the colon USER@SERVER:/some/path/to/mount

Unmounting/cleanup

Any failed attempts at mounting will likely leave the mount point directory "dirty". This prevents the success of any future mount attempts. The "dirty" mountpoint can be "cleaned" by unmounting it with the following command. It's good practice to execute this command any time something goes wrong to ensure that future attempts at mounting are not foiled by a "dirty" mount point directory.

su
umount /data/media/0/sshfsmount

Passwordless login

It's a real drag to have to enter your password every time you want to connect to your server. Especially if you're trying to automate the process. Follow these steps to setup public key authentication to log into your server without typing in a password on your device.

In a shell on your android device type:

su
ssh-keygen

Press enter at the prompts here to generate a key with no passphrase. Your public key should now be in /data/.ssh/id_rsa.pub Now copy this key to your ssh server like this:

su
cat /data/.ssh/id_rsa.pub | ssh USER@SERVER "mkdir -p ~/.ssh; cat >> ~/.ssh/authorized_keys"

Replace USER with your ssh login name and SERVER with the server hostname or IP address
You'll have to enter your password here one last time.
To actually use paswordless login, you must add -o IdentityFile=/data/.ssh/id_rsa from now on so that your sshfs command becomes something like:

su
sshfs USER@SERVER: /data/media/0/sshfsmount -o allow_other -o ro -o follow_symlinks -o StrictHostKeyChecking=no -o reconnect -o TCPKeepAlive=no -o  IdentityFile=/data/.ssh/id_rsa

You'll no longer be prompted for a password when using sshfs. Perfect for automated mounting and unmounting. Note that you must do this for each server you with to set up passwordless login to.

Other usage ideas

After you setup passwordless login (as described above) you can:

  • Use the GScript Lite app to add a buttons to your homescreen that mount and unmount your files
  • The Tasker (paid) app becomes almost essential to maintain connectivity during network state changes. Setup Tasker tasks that execute the mount command when wifi and cellular connections go up and the unmount command when they go down. My testing shows this makes the mount bulletproof.

Limitations

  • Media files mounted this way will NOT be picked up automatically by an automated media scanner (media scanning over a network connection is a bad idea anyway).
  • Mounting to any arbitrary directory on your device has not been fully tested and may not always work. Mounting to /data/media/0/sshfsmount as in the example above works reliably for me, as does mounting to /data/local/sshfsmount. YMMV for mounting to other directories.
  • Error message reporting doesn't work. If the sshfs command encounters any errors it will return 1 and exit silently so you're flying blind if things aren't working. sshfs prints its error messages to stderr which apparently android sends to /dev/null. I've found that -o sshfs_debug -o debug can cause crashes themselves (especially with paswordless login) so you best not use those either. Just don't make any mistakes and everything will be fine :^)
  • Connections are not maintained when the device's IP address changes (the underlying SSH connection breaks in this case). For example when the user switches from cellular to Wi-Fi the mountpoint will become disconnected. This could potentially be solved by something like mosh: http://mosh.mit.edu/ A readily available workaround is to use the paid Tasker app to manage tne mount point as the network state changes (see above).

android_external_sshfs's People

Contributors

drakonas avatar greyltc avatar l3iggs avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

android_external_sshfs's Issues

[question] Is there anything in the code that would actually prevent this running on AOSP? (nexus 6, Android 5.0.1)

Hi, I have been porting a lot of unix-y programs to my phone recently, and I'm wondering if this uses any features that would actually require a custom ROM, or if it was just developed primarily for cyanogen.

I really don't want to bother with flashing to cyanogen; I'd like to use it on my almost-stock android device. Cyanogen has a lot of stuff I don't need and/or want. I can build depended libraries, probably.

I've already compiled openSSL and gnuTLS, for example. I also think I am prepared to build glibc for it. Anything short of the kernel, basically.

Unable to build sshfs

Hi John,

first of all: Thanks for porting sshfs to Android.

I'm not very experienced in building Android/CM so this entire issue could easily be my fault but maybe you have a clue for me how I could make it happen after all...

I prepared

~/android/system

as described in the README.
I did have some issues during the build concerning mpdecision, thermald and camera.default.so. But when I excluded those from the make I succeeded in building the image.

Afterwards, I cloned your repositories, however I used the cm-10.2 branches as my CM tree is 10.2:

$ git clone -b cm-10.2 https://github.com/l3iggs/android_external_glib.git ~/android/system/external/sshfs
$ git clone -b cm-10.2 https://github.com/l3iggs/android_external_glib.git ~/android/system/external/glib

after

cd ~/android/system/external/sshfs
adb root
adb remount
mmp -B

the build fails pretty quickly, complaining:

PRODUCT_COPY_FILES device/htc/pyramid/keylayout/AVRCP.kl:system/usr/keylayout/AVRCP.kl ignored.
No private recovery resources for TARGET_DEVICE pyramid
make: *** No rule to make target '/home/user1/android/system/out/target/product/pyramid/obj/SHARED_LIBRARIES/libglib-2.0_intermediates/export_includes', needed by '/home/user1/android/system/out/target/product/pyramid/obj/EXECUTABLES/sshfs_intermediates/import_includes'.  Stop.
make: Leaving directory '/home/user1/android/system'

I then attempted to build the glib first but failed doing so:
First, it complained about missing LOCAL_MODULE_TAGS. Once I had added those into each of the .mk files, I received the following error message:

external/glib/glib/gbitlock.c: In function 'g_futex_wait':
external/glib/glib/gbitlock.c:84:12: error: 'SYS_futex' undeclared (first use in this function)
external/glib/glib/gbitlock.c:84:12: note: each undeclared identifier is reported only once for each function it appears in
external/glib/glib/gbitlock.c: In function 'g_futex_wake':
external/glib/glib/gbitlock.c:101:12: error: 'SYS_futex' undeclared (first use in this function)

which I couldn't resolve.

I would be grateful for any pointers.

SSHFS Seg Faults on Lollipop for Moto X 2013 (ghost)

SSHFS properly mounts the folder, but if you try to open anything but a folder, the SSH server successfully opens and closes the file, but the SSHFS client reads a few bits of the file, and then immediately ends in a memory violation sig 11 seg fault.

Command used to connect:
sshfs [email protected]:/ /system/sshfs -o ro -o allow_other -o follow_symlinks -o StrictHostKeyChecking=no -o reconnect -o TCPKeepAlive=no

Full catlog from before issue occurs to after issue occurs
Clipped catlog from where problem started and ended
Filtered catlog by 'ssh'

Note: I might have been using Enforcing SELinux mode at the time of the catlog saves, but the same issue happens in Permissive SELinux mode.

2nd Note: See my first issue that explains related problems, and more details on my setup: #4

sshfs crashes when accessing a file

SSHFS Process crashes when accessing a file.

Tested on:

  1. Nexus 5 - 4.4 KitKat (KRT16M) - Google Factory Image
  2. Emulator - Nexus 4 - Android 4.4 - API Level 19 - armeabi-v7a

Test:
root@hammerhead:/ # sshfs user@host: /sdcard/sshfs/
The authenticity of host 'host (192.168.xxx.xxx)' can't be established.
ECDSA key fingerprint is ...
Are you sure you want to continue connecting (yes/no)? yes
user@host's password:

root@hammerhead:/ # ps | grep ssh
root 10301 1 2628 1332 c027636c b6dc56d8 S ssh
root 10305 1 5412 228 ffffffff b6e09908 S sshfs

root@hammerhead:/ # ls /sdcard/sshfs/Downloads/test.file <
/sdcard/sshfs/Downloads/test.file

root@hammerhead:/ # cat /sdcard/sshfs/Downloads/test.file
tmp-mksh: cat: /sdcard/sshfs/Downloads/test.file: Transport endpoint is not connected

root@hammerhead:/ # dmesg
...
<7>[ 1171.776191] SELinux: initialized (dev fuse, type fuse), uses genfs_contexts
<3>[ 1229.253004] init: untracked pid 10305 exited
<3>[ 1229.259947] init: untracked pid 10301 exited
...

Error: No private recovery resources for TARGET_DEVICE

Hello,
I'm trying to find a working sshfs solution, and I found this lib.

I'm trying to compile it for CM 12, (not sure if it is supposed to work). I think I got the requirements, CyanogenMod dev environment.

I get this error:

No private recovery resources for TARGET_DEVICE
make: *** No rule to make target '/home/blum/android/system/out/target/product/falcon/obj/SHARED_LIBRARIES/libglib-2.0_intermediates/export_includes', needed by '/home/blum/android/system/out/target/product/falcon/obj/EXECUTABLES/sshfs_intermediates/import_includes'.  Stop.
make: Leaving directory '/home/blum/android/system'

The build environment is 64bit Arch Linux.
Have no idea how to proceed.. Can you help me with some advice what should I try?

Package as an apk

Can this be packaged as an APK? I'm running CM11 M9, and would love to use this to connect to a media server.

SSHFS mounts for root, but is totally inaccessible outside of the rooted Terminal Emulator in Lollipop+

I am rewriting this issue report because I have found more details on what the problem is.

I successfully built sshfs for CM12.1-based rom. (had to rename "#include <syscall.h>" to "#include <sys/syscall.h>" in external/glib/glib/gbitlock.c to build properly for Lollipop)

Now, I used official CM12.1 source tree, but my rom is Resurrection Remix 5.1.1r2 for Moto X 2013. I'm not sure how sincere you are when you say "the source tree needs to be what your rom is built from", because my familiarity of how building things for Android differs from building for Linux is about 5%. lol. Based on my experience with Linux, I thought it'd be fine to use CM12.1 since my rom is based on it, and there is no clear guide on setting up a Resurrection Remix source tree (if that is even what you're asking for).

Anyways, it built successfully and even mounts the SSHFS properly, except there is one bug that makes the whole thing pointless... When in the root shell in Terminal Emulator, the files on my SSH server are properly read and up-to-date. The problem is that any app trying to access this folder, whether it has root access or not, sees the folder and its contents as if the mount never occurred.

Example of reproduction on Resurrection Remix (and I assume other Lollipop or CM12 based roms):

First, I created /system/sshfs with 0777 permissions.

I mounted sshfs using the exact line in your README.md to /system/sshfs.

ls -l /system/sshfs shows the files AND folders, all with 0660 permissions. Same with the /system/sshfs folder itself.

Now, if I goto /system in Root Explorer (root or non-root mode), /system/sshfs is shown to have 0777 permissions. When I go into the folder, it is empty. I can create a file there... but it does not show up in rooted Terminal Emulator, which still acts like the folder is fuse-mounted. Then, I exit to normal user mode in Terminal emulator, and presto, the folder with the file I created shows up.

If I "su -" in Terminal Emulator again, the files from my SSHFS mount are back.

It seems to me that SE Linux changes or SE context introduction in 4.4 is causing sshfs to fuse mount inside of a sandbox of some sort... which makes it inaccessible outside of the same environment that mounted it.

If you can correct any mistake I made kindly, in case it was user error on my part, please... please do so... I have wrung out my knockers trying to get working SSHFS off and on for the past year, ever since SSHFSAndroid stopped updating (which is around the time I bought it... :/ ).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.