Accessing remote filesystems with Fuse + SSHFS
Today I needed to share files between linux server instances. Setting up a traditional NFS share is not an option since NFS V3 requires opening too many ports on the firewall. NFS v4 needs less ports but without Kerberos, there is no security. Since I already have ssh access opened, I decided to use Fuse which allow mounting filesystem in userspace + SSHFS which provides the Fuse driver to mount the remote filesystem thru an SSH tunnel. Here is how I set it up on my Amazon Linux instance.
Installing the tools
First, install Fuse if it’s not already installed.
$ sudo yum -y install fuse fuse-devel glib2-devel
Loaded plugins: fastestmirror, priorities, security, update-motd
Loading mirror speeds from cached hostfile
* amzn-main: packages.eu-west-1.amazonaws.com
* amzn-updates: packages.eu-west-1.amazonaws.com
Setting up Install Process
Resolving Dependencies
--> Running transaction check
---> Package fuse.x86_64 0:2.8.6-1.10.amzn1 will be installed
---> Package fuse-devel.x86_64 0:2.8.6-1.10.amzn1 will be installed
--> Processing Dependency: fuse-libs = 2.8.6-1.10.amzn1 for package: fuse-devel-2.8.6-1.10.amzn1.x86_64
--> Processing Dependency: libfuse.so.2()(64bit) for package: fuse-devel-2.8.6-1.10.amzn1.x86_64
--> Processing Dependency: libulockmgr.so.1()(64bit) for package: fuse-devel-2.8.6-1.10.amzn1.x86_64
---> Package glib2-devel.x86_64 0:2.22.5-6.9.amzn1 will be installed
--> Running transaction check
---> Package fuse-libs.x86_64 0:2.8.6-1.10.amzn1 will be installed
--> Finished Dependency Resolution
Dependencies Resolved
================================================================================
Package Arch Version Repository Size
================================================================================
Installing:
fuse x86_64 2.8.6-1.10.amzn1 amzn-updates 76 k
fuse-devel x86_64 2.8.6-1.10.amzn1 amzn-updates 33 k
glib2-devel x86_64 2.22.5-6.9.amzn1 amzn-main 1.5 M
Installing for dependencies:
fuse-libs x86_64 2.8.6-1.10.amzn1 amzn-updates 84 k
Transaction Summary
================================================================================
Install 4 Package(s)
Total download size: 1.7 M
Installed size: 13 M
Downloading Packages:
(1/4): fuse-2.8.6-1.10.amzn1.x86_64.rpm | 76 kB 00:00
(2/4): fuse-devel-2.8.6-1.10.amzn1.x86_64.rpm | 33 kB 00:00
(3/4): fuse-libs-2.8.6-1.10.amzn1.x86_64.rpm | 84 kB 00:00
(4/4): glib2-devel-2.22.5-6.9.amzn1.x86_64.rpm | 1.5 MB 00:00
--------------------------------------------------------------------------------
Total 6.0 MB/s | 1.7 MB 00:00
Running rpm_check_debug
Running Transaction Test
Transaction Test Succeeded
Running Transaction
Installing : fuse-libs-2.8.6-1.10.amzn1.x86_64 1/4
Installing : fuse-devel-2.8.6-1.10.amzn1.x86_64 2/4
Installing : fuse-2.8.6-1.10.amzn1.x86_64 3/4
Installing : glib2-devel-2.22.5-6.9.amzn1.x86_64 4/4
Installed:
fuse.x86_64 0:2.8.6-1.10.amzn1 fuse-devel.x86_64 0:2.8.6-1.10.amzn1
glib2-devel.x86_64 0:2.22.5-6.9.amzn1
Dependency Installed:
fuse-libs.x86_64 0:2.8.6-1.10.amzn1
Complete!
Then download, compile and install SSHFS.
$ wget http://downloads.sourceforge.net/project/fuse/sshfs-fuse/2.3/sshfs-fuse-2.3.tar.gz
--2011-12-30 10:16:06-- http://downloads.sourceforge.net/project/fuse/sshfs-fuse/2.3/sshfs-fuse-2.3.tar.gz
Resolving downloads.sourceforge.net... 216.34.181.59
Connecting to downloads.sourceforge.net|216.34.181.59|:80... connected.
HTTP request sent, awaiting response... 302 Found
Location: http://heanet.dl.sourceforge.net/project/fuse/sshfs-fuse/2.3/sshfs-fuse-2.3.tar.gz [following]
--2011-12-30 10:16:06-- http://heanet.dl.sourceforge.net/project/fuse/sshfs-fuse/2.3/sshfs-fuse-2.3.tar.gz
Resolving heanet.dl.sourceforge.net... 193.1.193.66, 2001:770:18:aa40::c101:c142
Connecting to heanet.dl.sourceforge.net|193.1.193.66|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 129222 (126K) [application/x-gzip]
Saving to: `sshfs-fuse-2.3.tar.gz'
100%[======================================>] 129,222 --.-K/s in 0.05s
2011-12-30 10:16:06 (2.51 MB/s) - `sshfs-fuse-2.3.tar.gz' saved [129222/129222]
$ tar zxf sshfs-fuse-2.3.tar.gz
$ cd sshfs-fuse-2.3
$ ./configure
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking for gcc... gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables...
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking for style of include used by make... GNU
checking dependency style of gcc... gcc3
checking whether gcc and cc understand -c and -o together... yes
checking for library containing dlsym... -ldl
checking OpenSSH version... 5.3 >= 4.4, disabling NODELAY workaround
checking for pkg-config... /usr/bin/pkg-config
checking pkg-config is at least version 0.9.0... yes
checking for SSHFS... yes
checking for fuse_opt_parse... yes
configure: creating ./config.status
config.status: creating Makefile
config.status: creating config.h
config.status: config.h is unchanged
config.status: executing depfiles commands
$ make
make all-am
make[1]: Entering directory `/tmp/sshfs-fuse-2.3'
gcc -DHAVE_CONFIG_H -I. -D_REENTRANT -DFUSE_USE_VERSION=26 -DLIBDIR=\"/usr/local/lib\" -D_FILE_OFFSET_BITS=64 -pthread -I/usr/include/fuse -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -g -O2 -Wall -W -MT sshfs-sshfs.o -MD -MP -MF .deps/sshfs-sshfs.Tpo -c -o sshfs-sshfs.o `test -f 'sshfs.c' || echo './'`sshfs.c
mv -f .deps/sshfs-sshfs.Tpo .deps/sshfs-sshfs.Po
gcc -DHAVE_CONFIG_H -I. -D_REENTRANT -DFUSE_USE_VERSION=26 -DLIBDIR=\"/usr/local/lib\" -D_FILE_OFFSET_BITS=64 -pthread -I/usr/include/fuse -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -g -O2 -Wall -W -MT sshfs-cache.o -MD -MP -MF .deps/sshfs-cache.Tpo -c -o sshfs-cache.o `test -f 'cache.c' || echo './'`cache.c
mv -f .deps/sshfs-cache.Tpo .deps/sshfs-cache.Po
gcc -D_FILE_OFFSET_BITS=64 -pthread -I/usr/include/fuse -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -g -O2 -Wall -W -o sshfs sshfs-sshfs.o sshfs-cache.o -pthread -L/lib64 -lfuse -ldl -lgthread-2.0 -lrt -lglib-2.0
make[1]: Leaving directory `/tmp/sshfs-fuse-2.3'
$ sudo make install
make[1]: Entering directory `/tmp/sshfs-fuse-2.3'
test -z "/usr/local/bin" || /bin/mkdir -p "/usr/local/bin"
/usr/bin/install -c sshfs '/usr/local/bin'
test -z "/usr/local/share/man/man1" || /bin/mkdir -p "/usr/local/share/man/man1"
/usr/bin/install -c -m 644 sshfs.1 '/usr/local/share/man/man1'
make[1]: Leaving directory `/tmp/sshfs-fuse-2.3'
Using sshfs
Before attempting to mount the filesystem we will setup ssh public key authentication to avoid typing password every time.
SSH public key authentication
Some ssh basic for the new comers…
Generate an ssh public key if you don’t already have one.
$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/srv/cloud/one/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /srv/cloud/one/.ssh/id_rsa.
Your public key has been saved in /srv/cloud/one/.ssh/id_rsa.pub.
The key fingerprint is:
d4:fc:84:51:a3:ca:8d:18:e0:5e:bf:b6:bf:79:d7:c6 oneadmin@ip-10-58-75-89
The key's randomart image is:
+--[ RSA 2048]----+
| . ..o |
| . . o + . |
| . o . = . |
| . . * + o |
| . . S . . |
| . |
| o o |
| . . .. . E|
| ..+o . . |
+-----------------+
Now open the content of the ~/.ssh/id_rsa.pub file in the ~/.one/authorized_keys file on the remote host and test the connection.
$ ssh ec2-46-137-64-48.eu-west-1.compute.amazonaws.com hostname
The authenticity of host 'ec2-46-137-64-48.eu-west-1.compute.amazonaws.com (10.226.6.214)' can't be established.
RSA key fingerprint is b6:3e:8c:57:40:45:aa:de:98:f7:1b:37:0f:31:e1:b3.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'ec2-46-137-64-48.eu-west-1.compute.amazonaws.com,10.226.6.214' (RSA) to the list of known hosts.
ip-10-226-6-214
The first time you connect to a host with ssh, you need to accept the remote host key as the key to identify the remote host as a known host. Should this key change, ssh will report a warning as it may be a man in the middle attack attempt.
Mounting the remote filesystem
The command syntax to mount the remote filesystem thru an SSH tunnel will be in the form sshfs <public_instance_name>:<remote_directory> <local_mount_directory> but remember to create a mount point for the remote filesystem first.
$ mkdir /tmp/remote_fs
$ /usr/local/bin/sshfs ec2-46-137-64-48.eu-west-1.compute.amazonaws.com:/ /tmp/remote_fs
$ df -h
Filesystem Size Used Avail Use% Mounted on
/dev/xvda1 7.9G 1.3G 6.6G 16% /
tmpfs 299M 0 299M 0% /dev/shm
ec2-46-137-64-48.eu-west-1.compute.amazonaws.com:
7.9G 4.9G 2.9G 63% /tmp/remote_fs
$ ls /tmp/remote_fs/
AMI boot etc lib local media opt root sbin srv tmp var
bin dev home lib64 lost+found mnt proc s3fs selinux sys usr
It works. You can know access the remote filesystem using this mountpoint!
Unmounting the filesystem
Unmounting the filesystem is really easy. Just run the fusermount command with the -u argument.
$ fusermount -u /tmp/oneremote
$ df -h
Filesystem Size Used Avail Use% Mounted on
/dev/xvda1 7.9G 1.3G 6.6G 16% /
tmpfs 299M 0 299M 0% /dev/shm
blog comments powered by Disqus