DEV Community

Cover image for VPN access to USB SMB Server on OpenWRT
Peeyush Man Singh
Peeyush Man Singh

Posted on

VPN access to USB SMB Server on OpenWRT

Introduction

This post deals with accessing an SMB server on a USB mounted to your home router via Tailscale VPN. The purpose is to have a shared folder on your home network which stores files that can be accessed and be modified by devices on your home network, thus reducing dependency on third party cloud storage services. In contrast to cloud storage services, your files stay on your home network and need not be transferred over to a remote third party server. In addition, if you're not connected to your home network, but still require access to the shared files, it is possible to do so by connecting via a VPN to your home network.

This post is divided into three parts: Mounting a USB drive to a OpenWRT router, installing SMB server for file sharing and installing Tailscale as a VPN service.

The prerequisites are: a router running OpenWRT as its operating system, and a USB port should be available on the router. My current setup is running OpenWRT v22.03.3 on a TP-Link Archer A9 AC1900 v6. The SMB (Server Message Block) server will run on Samba4. Alternatively, the SMB server can be installed and run on a Raspberry Pi or a NAS, however they are out of scope of this article as they require additional hardware. Here, the SMB server runs directly on the router itself and stores files on a USB mounted to the router. Tailscale VPN is chosen as a VPN service as my OpenWRT router sits behind a primary router which does not allow port forwarding. Alternatively, if you're running OpenWRT on a primary router, OpenVPN or WireGuard could be used as a VPN server.

Mounting USB drive to OpenWRT

Make sure to have the USB drive formatted to FAT32 format. Then plug it in to the router and create an ssh connection to the router.

$ ssh root@192.168.1.1
Enter fullscreen mode Exit fullscreen mode

To use a USB device with OpenWRT, it needs to be configured with ext4 file system.

$ opkg update
$ opkg install block-mount \
kmod-fs-ext4 e2fsprogs parted \
kmod-usb-storage kmod-usb-uhci \
kmod-usb2 kmod-usb3 \
kmod-usb-core kmod-usb-storage
$ parted -s /dev/sda -- mklabel gpt mkpart extroot 2048s -2048s
Enter fullscreen mode Exit fullscreen mode

We now configure OpenWRT to use the USB to expand its root file system. OpenWRT will split the internal storage into rootfs and rootfs_data partitions, which are merged together into a single writable overlay file system. rootfs is a read only partition mounted on /rom. rootfs_data is a writable partition mounted on /overlay. And overlay is a hybrid of these two file systems mounted on /, where the objects that appear in this file system do not always appear to belong to the same file system. Mostly, an object accessed in this union will be indistinguishable
from accessing the corresponding object from the original file systems.

We now configure the file system tables to mount rootfs_data in another directory in case you need to access the original root overlay to change extroot settings. extroot works by setting another overlay partition in the external storage device, and during boot this new overlay partition will be mounted over the internal storage's overlay partition. This allows easy fallback in case the external storage device is removed, as your device will still have its own overlay partition and thus will load all configuration from there.

$ DEVICE="$(sed -n -e "/\s\/overlay\s.*$/s///p" /etc/mtab)"
$ uci -q delete fstab.rwm
$ uci set fstab.rwm="mount"
$ uci set fstab.rwm.device="${DEVICE}"
$ uci set fstab.rwm.target="/rwm"
$ uci commit fstab
Enter fullscreen mode Exit fullscreen mode

Check block partitions using the following command.

$ block info
/dev/mtdblock8: UUID="9fd43c61-c3f2c38f-13440ce7-53f0d42d" VERSION="4.0" MOUNT="/rom" TYPE="squashfs"
/dev/mtdblock9: MOUNT="/rwm" TYPE="jffs2"
/dev/sda1: UUID="fdacc9f1-0e0e-45ab-acee-9cb9cc8d7d49" LABEL="extroot" VERSION="1.0" MOUNT="/overlay" TYPE="ext4"
Enter fullscreen mode Exit fullscreen mode

The mtdblock* are the devices in internal flash memory, and /dev/sda1 is the partition on the USB flash drive.
We now create an ext4 file system on the first partition of the USB device – /dev/sda1.

$ DEVICE="/dev/sda1"
$ mkfs.ext4 -L extroot ${DEVICE}
Enter fullscreen mode Exit fullscreen mode

Now, we configure the selected partition as new overlay via fstab.

$ eval $(block info ${DEVICE} | grep -o -e "UUID=\S*")
$ uci -q delete fstab.overlay
$ uci set fstab.overlay="mount"
$ uci set fstab.overlay.uuid="${UUID}"
$ uci set fstab.overlay.target="/overlay"
$ uci commit fstab
Enter fullscreen mode Exit fullscreen mode

We now transfer the content of the current overlay to the external drive and reboot the device to apply changes.

$ mount ${DEVICE} /mnt
$ tar -C /overlay -cvf - . | tar -C /mnt -xf -
$ reboot
Enter fullscreen mode Exit fullscreen mode

To test if it worked as expected, after the reboot, login to your Luci web portal and navigate to System -> Mount Points. This should show the USB partition mounted as overlay. And if you navigate to System -> Software, it should show you the additional free space of the overlay partition from the USB drive.

File sharing with Samba4

Install the following dependencies to start a Samba4 server.

$ opkg update
$ opkg install kmod-usb-extras block-mount \
ntfs-3g samba4-server luci-app-samba4
Enter fullscreen mode Exit fullscreen mode

Create a share/ folder. This will be the folder that will be shared on the network. Also, change permissions of the folder so that any user can read and write to the folder.

$ mkdir /overlay/share
$ chmod a+rwX /overlay/share
Enter fullscreen mode Exit fullscreen mode

Now login to Luci web portal and navigate to Services -> Network share and configure as follows.

Interface: lan
Workgroup: WORKGROUP
Enable macOS compatible shares: Check (Optional)
Enter fullscreen mode Exit fullscreen mode

Note: Never expose SMB to the Internet. SMB servers should only be accessed over a VPN.

On the Shared directories section, add a directory with the following configurations.

Name: share
Path: /overlay/share
Browsable: True
Allow guests: True
Enter fullscreen mode Exit fullscreen mode

Save and apply changes. Now we need to add new SMB users. Open /etc/passwd on the router.

$ vi /etc/passwd
Enter fullscreen mode Exit fullscreen mode

Append at the end of file the following line.

newuser:*:1000:65534:newuser:/var:/bin/false
Enter fullscreen mode Exit fullscreen mode

Replace the two newuser placeholders with a username of your choice.

Create password for your newuser.

$ smbpasswd -a newuser
Enter fullscreen mode Exit fullscreen mode

Then restart the Samba4 service.

$ service samba4 restart
Enter fullscreen mode Exit fullscreen mode

Again, login to Luci web portal and navigate to Services -> Network share. On the Shared directories section, on the Allowed Users field, enter the username you selected earlier, uncheck Allow guests, then save and apply.

SMB server is now up and running. You can test this by connecting through another device on the same network. The URL should be smb://192.168.1.1/share (for Windows \\192.168.1.1\share). Then authenticate with the earlier defined username and password.

Install Tailscale on OpenWRT

Install the following dependencies for Tailscale.

$ opkg update
$ okpg install tailscale iptables-nft
Enter fullscreen mode Exit fullscreen mode

Now log in to Tailscale using the following command. Copy the login URL into a browser and use SSO to log in to Tailscale. Then register this router as one of your devices. Also, download and install Tailscale app on a second device, as Tailscale requires at least two devices to be registered to communicate.

$ tailscale up
Enter fullscreen mode Exit fullscreen mode

We need to advertise our local routes for other devices to be able to connect to our local network. You can define the IPv4 address space to be advertised to your devices. Additionally, we can also use this router as an exit node for VPN traffic. If you want split tunneling of your traffic and only require access to the local area network, you can leave out the exit node flag.

$ tailscale up \
--advertise-routes=192.168.0.0/16 \
--advertise-exit-node --accept-routes \
--netfilter-mode=off
Enter fullscreen mode Exit fullscreen mode

Additionally, you need to enable Subnet route and exit node to be allowed on the Tailscale web portal. For this, navigate to the Tailscale web portal. Select Edit route settings on OpenWRT, and enable Subnet routes and Exit node options. Also, you can disable key expiry for OpenWRT router on the web portal so that you need not login time and again via the router.

To use OpenWRT router as an exit node, further configurations should be changed in OpenWRT. Log in to Luci web portal and navigate to Network -> Firewall -> General Settings -> Add and set the following configurations:

General:
    Name: Tailscale
    Input: Accept
    Output: Accept
    Forward: Accept
    Masquerading: True
    MSS clamping: True
    Covered Networks: Unspecified
    Allow forward to destination zones: Lan, Wan
    Allow forward from source zones: Lan, Wan
Advanced:
    Covered devices: tailscale0
Enter fullscreen mode Exit fullscreen mode

Navigate to Network -> Firewall -> NAT Rules -> Add and set the following configurations:

General:
    Name: Tailscale 
    Protocol: Any 
    Outbound zone: Any zone 
    Source address: Any 
    Destination address: Any 
    Action: MASQUERADE
Advanced:
    Outbound device: tailscale0
Enter fullscreen mode Exit fullscreen mode

Tailscale is now configured. Now you should be able to connect to the SMB server via the Tailscale VPN. Tailscale is available as a graphical user app for Windows, Mac, Android, and iOS. To connect to Tailscale from Ubuntu, use the following commands.

$ sudo apt update
$ sudo apt install tailscale
$ #Connect to tailscale and use exit node
$ sudo tailscale up --accept-routes --exit-node=openwrt
$ #Connect to tailscale with split tunneling
$ sudo tailscale up --accept-routes
$ #Disconnect tailscale
$ sudo tailscale down
Enter fullscreen mode Exit fullscreen mode

To start Tailscale automatically on router startup, the Tailscale up command needs to be configured in /etc/init.d.

$ cat > /etc/init.d/tailscalevpn<< EOF
#!/bin/sh /etc/rc.common
# Script to toggle tailscale up and down

START=80

start() {

    tailscale up --advertise-routes=192.168.0.0/16 --advertise-exit-node --accept-routes --netfilter-mode=off

}

stop() {

    tailscale down

}
EOF
Enter fullscreen mode Exit fullscreen mode

The first line of a init.d script must be #!/bin/sh /etc/rc.common. START=80 determines at which point in the init sequence this script gets executed. This means that the file will be symlinked as /etc/rc.d/S80tailscalevpn. It will then start after the init scripts with START=79 and below, but before START=81 and above. The start() command will be run when it is called with 'start' as its parameter (/etc/init.d/tailscalevpn start). Likewise, the stop() command will be run when it is called with 'stop' as its parameter (/etc/init.d/tailscalevpn stop).

Make sure the file is executable.

$ chmod +x /etc/init.d/tailscalevpn
Enter fullscreen mode Exit fullscreen mode

Enable your script. In order to automatically start the init script on boot, it must be enabled. This will create one or more symlinks in /etc/rc.d/ which automatically execute at boot time and shutdown time. This makes the application behave as a system service, by starting when the device boots and stopping at shutdown, as configured in the init.d script. If you need to disable the script, use the disable command.

$ /etc/init.d/tailscalevpn enable
Enter fullscreen mode Exit fullscreen mode

Your script should now have a symlink in /etc/rc.d. At boot time, the init.d daemon just starts executing scripts it finds in /etc/rc.d according to their file names. In this case, our filename will be S80tailscalevpn as described above and will start at the 80th position.

In order to confirm that your script is enabled in init.d, run the following command. If the output of the script is on, it should be enabled.

$ /etc/init.d/tailscalevpn enabled && echo on
on
Enter fullscreen mode Exit fullscreen mode

That is how you can use a USB on a OpenWRT router as a file sharing SMB server and access it via a VPN. Note that SMB is not optimal for streaming media over VPN. It is good for document access over a VPN. However, streaming within the LAN itself is performant. For streaming over VPN, other services such as Plex server should be considered. Apart from SMB, NFS (Network File Share) can also be used to share files on the LAN.

Happy Hacking!

Top comments (3)

Collapse
 
ayushbhusal profile image
Ayush-B

While this article provides a comprehensive guide on setting up an SMB server on a USB mounted to an OpenWRT router and accessing it via Tailscale VPN, it would have been helpful to include performance considerations and potential bottlenecks when running an SMB server directly on the router. Addressing these concerns would help readers evaluate whether this solution is suitable for their specific needs, particularly if they have high data throughput requirements or if their router has limited processing power. Furthermore, exploring alternative file-sharing protocols or services that could be employed in conjunction with, or as alternatives to, SMB could provide readers with a broader range of options to choose from. Nonetheless, the tutorial is informative and well-structured, and it will undoubtedly benefit those looking to set up a private file-sharing solution within their home network.

Collapse
 
pssingh21 profile image
Peeyush Man Singh • Edited

Hi,

as mentioned, NFS is a viable alternative to SMB for network file share. The performance is dependent upon router hardware, internet bandwidth and number of clients using the network simultaneously. For my aforementioned hardware setup, I have an average of about 63% memory usage for a total memory size of 120MB and 5 connected devices. Note that I am also using the external USB as a Swap memory in addition to the internal memory, which will be used in case of high RAM usage. But also note that swapping data can be slow if it needs to be done frequently as the swap-device cannot be accessed with the high datarates as of the RAM.

Collapse
 
ayushbhusal profile image
Info Comment hidden by post author - thread only accessible via permalink
Ayush-B

Exceptional article! This comprehensive and meticulously detailed guide on configuring an SMB server on a USB mounted to an OpenWRT router, and accessing it via Tailscale VPN, is a testament to your profound expertise in the subject. The lucid step-by-step instructions facilitate an effortless understanding and execution of the process, encompassing every essential aspect from USB drive mounting to the fine-tuning of Samba4 and Tailscale configurations.

Moreover, your insights on automating Tailscale during startup and addressing the potential limitations of SMB for media streaming over VPN demonstrate your commitment to providing a holistic and practical solution. This tutorial is truly a valuable resource for individuals seeking a secure, private, and reliable file-sharing alternative within their home network. Your contribution to the community is greatly appreciated, and I look forward to more of your enlightening content in the future!

Some comments have been hidden by the post's author - find out more