How To Provide SMB/CIFS Network Shares To Specific Clients

Samba is an open source implementation of the server message block (SMB) and common internet file system (CIFS) protocols, it allows us to access Windows file share resources from Linux.

With Samba we can export specific directories within a file system over the network to other Windows or Linux clients, allowing us to share various files over the network between different operating systems.

It is important to configure this properly and secure it as much as possible so that only the required clients and users have access to the SMB/CIFS share, otherwise it may be possible for anyone to mount and access the data.

To do this we are going to use the /etc/samba/smb.conf file on the SMB/CIFS server and lock down shares to only be accessible by specific IP addresses and user accounts.


Red Hat Certified Engineer RHCE Video Course
Studying for your RHCE certification? Checkout our RHCE video course over at Udemy which is 20% off when you use the code ROOTUSER.


Example Environment

Here is a list of our servers that we will be testing with, both are running CentOS 7.

  • Samba Client: 192.168.0.100 – This Linux client will mount a directory from the SMB/CIFS server.
  • Samba Server: 192.168.0.200 – This Linux server will serve a directory over SMB/CIFS to the client.

Samba Server Configuration

The server that has the data to share will act as the SMB server and needs the samba package installed.

yum install samba -y

Once installed we can enable our Samba server to automatically start the required SMB service on boot, we’ll also start the service up now as it’s not running by default after installation. We also do this with the NMB service, which is responsible for NetBIOS and is part of the samba package.

systemctl enable smb nmb
systemctl start smb nmb

For further information on basic service management with systemctl, see our guide here.

Once the smb service has started successfully, we can confirm that it is correctly listening on TCP ports 139 and 445.

[root@centos7 ~]# netstat -antup | grep smb
tcp        0      0 0.0.0.0:139             0.0.0.0:*               LISTEN      3536/smbd
tcp        0      0 0.0.0.0:445             0.0.0.0:*               LISTEN      3536/smbd
tcp6       0      0 :::139                  :::*                    LISTEN      3536/smbd
tcp6       0      0 :::445                  :::*                    LISTEN      3536/smbd

Next the firewall must be configured in order to correctly allow SMB traffic through, this can be done as shown below with firewalld. This change will allow TCP ports 135/445 SMB/CIFS traffic into the server from any source IP address. The firewall configuration must also be reloaded as we have put a permanent rule in place which will not apply to the running configuration.

firewall-cmd --permanent --add-service=samba
firewall-cmd --reload

In this example we’re going to mount a user’s home directory over SMB, so we need to make the following change to SELinux to allow this. Note that the -P makes this a permanent change which will persist over system reboot.

setsebool -P samba_enable_home_dirs on

Next we’re going to create a user whose home directory will be shared. We’re specifying the /sbin/nologin shell here as we don’t want this particular user to be able to directly log into the server via console or SSH, this account is going to be used for SMB access only.

useradd rootusers -s /sbin/nologin

This creates a standard Linux user, however we need to set an SMB password on the account.

[root@server ~]# smbpasswd -a rootusers
New SMB password:
Retype new SMB password:
Added user rootusers.

The Samba file shares are configured with the /etc/samba/smb.conf file, this file lists the directories that are available to be accessed over SMB/CIFS, as well as defines any specific source IP addresses that should be allowed to connect in.

hosts allow = 127. 192.168.0.100

This will allow only our client at 192.168.0.100 to connect, as well as localhost 127.0.0.0/8. Hostnames can also be used instead of IP addresses, as long as they resolve to the intended IP address with DNS for instance. Alternatively we can also deny specific hosts by specifying ‘hosts deny’ in the configuration.

Note that the firewall is currently set to allow any IP address in on the SMB ports, here it is the application that is responsible for allowing or denying IP addresses which is what this RHCE objective is all about. In the real world we would also use the firewall to only allow in specific source IP addresses.

We can also allow access to a specific user rather than just a specific host, this method thereby requires authentication in the way of the users password. In this case the rootusers account is allowed access via SMB, all other users will be denied.

valid users = rootusers

We can run the ‘testparm’ command after making our changes to the configuration file to check the syntax, this should advise if there are any mistakes or errors in the configuration prior to restarting the service.

[root@server ~]# testparm
Load smb config files from /etc/samba/smb.conf
rlimit_max: increasing rlimit_max (1024) to minimum Windows limit (16384)
Loaded services file OK.
Server role: ROLE_STANDALONE

Press enter to see a dump of your service definitions

# Global parameters
[global]
        workgroup = MYGROUP
        server string = Samba Server Version %v
        security = USER
        log file = /var/log/samba/log.%m
        max log size = 50
        idmap config * : backend = tdb
        hosts allow = 192.168.0.100
        cups options = raw

After any changes to the /etc/samba/smb.conf file we need to restart the smb service to apply the changes.

systemctl restart smb nmb

Samba Client Configuration

Now that the server is ready to accept SMB connections, we need to prepare the client.

First install the samba-client package and cifs-utils which is used for mounting SMB shares.

yum install samba-client cifs-utils -y

Next modify the firewall by allowing the samba-client service.

firewall-cmd --permanent --add-service=samba-client
firewall-cmd --reload

You can confirm that browsing is working by using smbclient to on the client to connect to the server. In this example we’re connecting to the SMB server at 192.168.0.200 with the rootusers account that we have created there.

[root@client ~]# smbclient -L 192.168.0.200 -U rootusers
Enter rootusers's password:
Domain=[MYGROUP] OS=[Windows 6.1] Server=[Samba 4.2.10]

        Sharename       Type      Comment
        ---------       ----      -------
        IPC$            IPC       IPC Service (Samba Server Version 4.2.10)
        rootusers       Disk      Home Directories
        Send_To_OneNote_2013:1 Printer   Send To OneNote 2013
        Microsoft_Print_to_PDF:4 Printer   Microsoft Print to PDF
        Fax:3           Printer   Fax
        Microsoft_XPS_Document_Writer:2 Printer   Microsoft XPS Document Writer

Among other things, we can see the rootusers share listed as a home directory, as highlighted above.

Mounting the Samba Share

Now that we have prepared the samba share and client, only our client from IP address 192.168.0.100 should be able to mount it, let’s test. The client systems will also need the cifs-utils package installed to be able to mount SMB/CIFS mount points.

[root@client ~]# mount //192.168.0.200/rootusers /mnt -o username=rootusers
Password for rootusers@//192.168.0.200/rootusers:  ********

Now that this has mounted, we can check and confirm that it is listed in the output of df for instance.

[root@client ~]# df -h
Filesystem                Size  Used Avail Use% Mounted on
/dev/sda3                  18G  4.5G   14G  25% /
/dev/sda1                 297M  144M  154M  49% /boot
//192.168.0.200/rootusers   18G  3.7G   15G  21% /mnt

As shown above we can see that //192.168.0.200/rootusers has successfully mounted to the /mnt directory. If we want to mount this automatically during system boot, we can modify the /etc/fstab file as shown below.

//192.168.0.200/rootusers /mnt cifs username=rootusers,password=password 0 0

Once this has been added to the /etc/fstab file, you can run ‘mount -a’ to attempt to mount it. Note that by default the file permissions of the /etc/fstab file allow any user to read the file, so you may not want to store the user password directly within the file.

Instead of specifying the username and password in /etc/fstab, we can use the credentials parameter to point to a file on disk that contains these credentials as shown below.

//192.168.0.200/rootusers /mnt cifs credentials=/root/credentials 0 0

While this file still stores the credentials in plaintext and makes no effort at encrypting them, we can set the permissions to 600 so that only the root user can read the file, denying access to any other users.

[root@client ~]# chmod 600 /root/credentials
[root@client ~]# ls -la /root/credentials
-rw-------. 1 root root 37 May 22 16:12 /root/credentials
[root@client ~]# cat credentials
username=rootusers
password=password

Again test that mounting with these changes works correctly.

At this point you can test by modifying the /etc/samba/smb.conf file on the SMB server to set the ‘host allow’ IP address to something else, then reload the smb service and try to connect again. The connection should fail as the IP address of the client is no longer allowed in, confirming that our configuration is only allowing specific clients in.

Create a custom share

So far we have only successfully mounted a home directory over SMB, now we’ll cover how to create an arbitrary directory and mount that as well.

First we’ll create a directory that we will share over SMB.

[root@server ~]# mkdir /testing
[root@server ~]# chmod 777 /testing

Next we’ll start by modifying the /etc/samba/smb.conf file on the SMB server, adding in the below configuration file for the custom directory we wish to share.

[testing]
comment = This is a file share for the /testing directory.
browseable = yes
path = /testing
valid users = rootusers
writable = yes

This allows our rootusers user account that we created earlier access to the /testing directory.

Finally we modify the SELinux context of this directory. If the syntax of this command is difficult to remember, simply refer to the ‘semanage-fcontext’ manual page for examples.

[root@server ~]# semanage fcontext -a -t samba_share_t "/testing(/.*)?"
[root@server ~]# restorecon -v /testing/
restorecon reset /testing context unconfined_u:object_r:default_t:s0->unconfined_u:object_r:samba_share_t:s0

Next we can check that this is accessible, and then mount it.

[root@client ~]# smbclient -L 192.168.0.200 -U rootusers
Enter rootusers's password:
Domain=[MYGROUP] OS=[Windows 6.1] Server=[Samba 4.2.10]

        Sharename       Type      Comment
        ---------       ----      -------
        testing         Disk      This is a file share for the /root/testing directory.

[root@client ~]# mount //192.168.0.200/testing /mnt -o username=rootusers

At this point we can create a test file from the client as shown below.

[root@client ~]# echo Testing > /mnt/test123

We can check that this file exists on the server, as we can see the expected contents are in this file on the SMB server confirming that we can write content from the client here.

[root@server ~]# cat /testing/test123
Testing

Samba Troubleshooting

Having problems? Try these resources.

Documentation

There is documentation available locally on your system which can be accessed during the RHCE exam. Check out the /usr/share/doc/samba-/ directory.

The manual pages also have helpful information.

man samba
man 5 smb.conf

smbstatus command

You can run the smbstatus command on the server to list currently connected clients and gather further information.

[root@server ~]# smbstatus

Samba version 4.2.10
PID     Username      Group         Machine            Protocol Version
------------------------------------------------------------------------------
13929     rootusers     rootusers     192.168.0.100 (ipv4:192.168.0.100:41380) NT1

Service      pid     machine       Connected at
-------------------------------------------------------
IPC$         13929   192.168.0.100  Sat May 21 23:20:53 2016
rootusers    13929   192.168.0.100  Sat May 21 23:20:53 2016

No locked files

testparm command

As demonstrated earlier, run the testparm command on the Samba server to check the syntax of the /etc/samba/smb.conf file.

Reset smb.conf file

If you think you’ve broken everything beyond repair, simply move or delete the /etc/samba/smb.conf file and then reinstall Samba which will create a fresh new file with default settings.

yum reinstall samba

SELinux

To share a directory over SMB, the context should be set to samba_share_t.

Alternatively you could set samba_export_all_ro which allows read-only access to any directory that you may wish to share over SMB, even if they do not have the samba_share_t context set. The samba_export_all_rw boolean works the same except it allows read/write.

[root@server ~]# setsebool -P samba_export_all_ro off
[root@server ~]# setsebool -P samba_export_all_rw off

The -P makes these changes persist over a system restart.

Summary

As shown we can mount directories from a Samba server to a client running Linux. This functionality allows us to connect to Windows SMB/CIFS based file shares from a Linux system, or alternatively allows a Linux server to offer a share that Windows systems can access.


This post is part of our Red Hat Certified Engineer (RHCE) exam study guide series. For more RHCE related posts and information check out our full RHCE study guide.

  1. setsetbool -P samba_enable_home_dirs on
    should be:
    setsebool -P samba_enable_home_dirs on

  2. I have problem with guest share, when i try to mount the share folder i get an error error(13): Permission denied.But if i use Nautilus and try to browse to the samba share it work fine,
    Any help appreciated

    smb.conf configuration

    [public]
    comment = public
    path = /public
    browseable = yes
    writeable = yes
    guest ok = yes
    —————————————–
    permission of the public folder
    drwxrwxrwx. 3 root root 18 Jan 1 03:49 public
    —————————————–

    mount //ldap/public /mnt -o username=guest,password=
    mount error(13): Permission denied
    Refer to the mount.cifs(8) manual page (e.g. man mount.cifs)

  3. The geek aid,you need to include the line

    guest map bad user = ok in the global section, that should sort u out

  4. Hi Jarrod,thanks for the valuable site.
    please help out me on this where I missed?
    Samba server:
    [multi]
    path = /paas
    writable = yes
    browseable = yes
    valid users = brian bina
    write list = brian
    fstab entry in client :
    //192.168.10.2/paas /mnt/multi cifs credentials=/root/bina,multiuse,sec=ntlmssp 0 0
    I’m able to mount /pass under /mnt/multi but having permission issues on cifscreds.brian has rwx and bina has rx permission on /paas (with setfacl) .I have created bob local user on the client. When I tried to add cifscreds for bob : I did : su – bob
    bob@ ,,,cifscreds add 192.168.10.2 -u brian entered brian password and #cd /mnt/multi then #touch ll.It says permission deny even though brian is getting rwx permission.Also this user is in write list in smb.conf file. Same thing is with bina user which I think is right but why I’m getting permission issue with brian?

    note: /paas is getting public_content_rw_t selinux type . Thanks

  5. Is there a way to prevent a system from updating to a newer release when installing from the repositories? I’m trying to run my labs on RHEL 7.0 as I believe that’s the version specified on Redhat’s website. However, certain packages want to update the system when installed through yum, such as samba and nfs-utils.

    Updating:
    centos-release x86_64 7-5.1804.el7.centos packages 24 k
    dracut x86_64 033-535.el7 packages 325 k
    initscripts x86_64 9.49.41-1.el7 packages 437 k
    samba x86_64 4.7.1-6.el7 packages 661 k

  6. Thanks for the guide. When mounting, the output is:
    mount error(2): No such file or directory
    SELinux and obviously paths seem to be OK. Any idea what that could be?

Leave a Comment

NOTE - You can use these HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>