Learn through the super-clean Baeldung Pro experience:
>> Membership and Baeldung Pro.
No ads, dark-mode and 6 months free of IntelliJ Idea Ultimate to start with.
Last updated: April 13, 2024
Server Message Block (SMB) is a protocol for sharing resources over a network. It’s fairly widely supported and provides authentication. In particular, the main implementations of SMB are the Common Internet File System (CIFS) and Samba protocols. Both include the main definitions of SMB. In fact, Samba and Linux tools in general have many references to CIFS.
In this tutorial, we explore the Samba implementation of SMB and the mount.cifs command. First, we go over client utilities for the protocol. After that, we move on with a basic Samba server setup. Next, we discuss how to perform a fairly simple Samba mount. Then, we show credentials handling during mounting. Finally, we briefly get into version considerations and explore some SMB-specific mount options.
We tested the code in this tutorial on Debian 12 (Bookworm) with GNU Bash 5.2.15. Unless otherwise specified, it should work in most POSIX-compliant environments.
While there are Samba clients such as smbclient, in Linux, we usually employ the cifs-utils package in combination with mount.
So, let’s first install cifs-utils:
$ apt install cifs-utils
After doing so, we should have access to the mount.cifs command:
$ mount.cifs
Usage: mount.cifs <remotetarget> <dir> -o <options>
Mount the remote target, specified as a UNC name, to a local directory.
[...]
In fact, there are two different versions of the mount command that relate to Samba:
This way, we can enforce the strongest possible security currently available in later SMB versions.
Further, cifs-utils contains an entire toolkit:
Previously, these user-space utilities were part of the samba package. However, since they are mostly client-oriented, they were split off. They work with the in-kernel CIFS filesystem.
Now, let’s create a basic Samba server to test with.
First, we install the samba package:
$ apt install samba
Next, we configure /etc/samba/smb.conf by adding a few lines:
$ cat /etc/samba/smb.conf
[...]
[smbshare]
comment = Custom Samba Share
path = /mnt/samba
public = yes
browseable = yes
writable = yes
Lastly, we restart the smb service:
$ systemctl restart smb
At this point, /mnt/samba/ is exposed as the public, browseable, and writable //<MACHINE_IDENTIFIER>/smbshare/ share. Here, MACHINE_IDENTIFIER can be a mapping like localhost, a custom name such as xost, an IP address, or similar.
Due to the standardization of mount, the basic form of the mount.cifs command just takes a target and path. In case there are mount –options (-o) to pass, we can also add them accordingly.
Let’s see a basic example:
$ mount.cifs //localhost/smbshare/ /mnt/smbshare/
Alternatively, we can use the longer form:
$ mount --types cifs //localhost/smbshare/ /mnt/smbshare/
Either way, we attempt to mount //localhost/smbshare/ at /mnt/smbshare/.
After doing so, we should be able to access /mnt/smbshare/ and freely work with the path and data under it.
Of course, this fairly simple procedure usually isn’t the case for remote systems, which often require credentials.
There are different ways to access a Samba share as a specific user, often required with remote mounts.
To begin with, Samba offers the so-called guest account for unrestricted access. For that, we either add the public: yes or guest ok: yes setting to /etc/samba/smb.conf.
Once we do, we append guest to the –options of the mount command:
$ mount.cifs --options guest //localhost/smbshare/ /mnt/smbshare/
While they don’t require any credentials, guest accounts often only allow us to view just basic information. Further, not all servers enable this option. Even when it’s available, servers rarely enable guest access to all shares.
While we might be able to mount as a guest, a more common method is to use credentials.
For that, we usually get a prompt as part of the mount operation:
$ mount.cifs //localhost/smbshare/ /mnt/smbshare/
Password for baeldung@//localhost/smbshare/:
The mount command automatically assumes we want to use the current user as the remote one as well. After entering the respective password, we log in with the current local username to the remote host.
Since remote user credentials don’t always match local ones, let’s see how to specify another username.
Critically, local system users don’t automatically have a respective Samba equivalent. To create that, we use the smbpasswd command with the [-a]dd user option:
$ smbpasswd -a baeldung
New SMB password:
Retype new SMB password:
Added user baeldung.
Notably, despite its name, the [-a]dd option of smbpasswd only includes Samba entries for users that already exist on the system.
After having a prepared username, we include it as [user]name in the –options to mount:
$ mount.cifs --options user=baeldung //localhost/smbshare/ /mnt/smbshare/
Password for baeldung@//localhost/smbshare/:
Now, the prompt and login user change due to the user= or username= option and the value we supply.
If the user is part of a specific [dom]ain, we can add that as well:
$ mount.cifs --options user=baeldung,domain=DOM1 //localhost/smbshare/ /mnt/smbshare/
This is related to the workgroup setting in the smb.conf file.
Indeed, we can even include a [pass]word in the mount options, although this isn’t secure:
$ mount.cifs --options user=baeldung,pass=1password //localhost/smbshare/ /mnt/smbshare/
Notably, running mount.cifs without any other arguments results in a hint with all options, which begins with the short form of the three most common ones:
$ mount.cifs
[...]
Options:
user=<arg>
pass=<arg>
dom=<arg>
[...]
One of them is [pass]word. Still, including sensitive information in commands isn’t recommended.
To avoid passing credentials on the command line, we can also use a credentials file.
For that, we first create a file and restrict its permissions:
$ touch .smbcreds
$ chmod 600 .smbcreds
After that, we populate the file with the respective credential information in the correct format:
$ vi .smbcreds
[...]
username=baeldung
password=1password
domain=WORKGROUP
Critically, no leading spaces are allowed at any point here.
Finally, we can specify the file after the credentials option:
$ mount.cifs --options credentials=/mnt/.smbcreds //localhost/smbshare/ /mnt/smbshare/
Thus, we automate the login process without exposing any sensitive information.
Over the years, Samba has evolved through several versions:
Naturally, the latest one is often the most secure, but not always compatible with older versions.
Further, we indicate the desired version via the vers option:
$ mount.cifs --options vers=3.0 //localhost/smbshare/ /mnt/smbshare/
Now, let’s try with a lower version:
$ mount.cifs --options vers=1.0 //localhost/smbshare/ /mnt/smbshare/
mount error(95): Operation not supported
Evidently, the server we’re trying to connect to doesn’t support the 1.0 version of SMB. Version compatibility is one of the top reasons for connection issues.
Further, the CIFS dialect is gradually getting dropped in favor of the SMB specification.
In addition to the filesystem-agnostic mount options, there are some more Samba-oriented settings we can use.
Several options relate to session establishment.
While there are two possible default ports that the command tries (445 and 139), we can also specify a custom one via port=. In addition, although not mandatory due to the possible resolution mechanisms of the target, we can also indicate the ip= address of the destination.
Two settings dictate the NetBIOS name:
This way, we can have finer control.
Since CIFS wasn’t initially targeting Linux and UNIX environments, extensions to the protocol implementation became a standard part of many versions. This trend continued and POSIX extensions for SMB were specifically designed for more security.
Let’s explore some options that behave differently according to the extensions.
First, we look at the situation when the extensions aren’t supported:
Now, let’s see how the behavior differs when extensions are supported:
Notably, the default perm performs permission checks on the client in addition to those on the server
When it comes to inherent security, the sec option has several possible values:
Further, noacl disables POSIX access control list (ACL) operations.
Since inodes are system-specific, control over them can be important when it comes to remote mounts like Samba.
For instance, directio prevents inode data caching to gain a small performance benefit. The default behavior is to read ahead and write behind inodes.
Another example is the serverino option, which prevents the client from generating inode numbers. The default is noserverino, which enables clients to generate their own inode numbers.
Due to the different platforms that support CIFS, character mapping differences can cause issues in certain cases. In addition, there are reserved characters that may confuse filesystem object processing:
Of these, the \ backslash is fairly hard to handle due to its role as a special escape character.
Still, the mapchars option can help by remapping the other six characters to Unicode sequences. The default behavior is nomapchars, which doesn’t perform any translation.
Two mount options distinguish between ways of handling server crashes:
The desired behavior mainly depends on the network stability and share criticality.
When transmitting data via CIFS, the default read size is usually 16Kb, while the default write is 57344b, i.e., fourteen pages of 4096b.
However, we can theoretically change these parameters via rsize and wsize. In practice, wsize is limited to its default value, so we can only lower it. On the other hand, rsize depends on a compile-time parameter of the CIFS module. Usually, we can go down to 2048b and up to 127Kb without issues but may need server support for more.
In this article, we explored the Samba implementation of the SMB protocol along with many options to mount Samba shares.
In conclusion, although SMB is usually more common in Microsoft Windows environments, Linux provides a complete toolkit for handling the protocol and many of its intricacies.