FreeBSD CIFS/SMB File Server

http://www.bmtsolutions.us/wiki/freebsd:cifs:server

This guide covers setting FreeBSD up as a CIFS/SMB File Server via Samba with ZFS storage.

This guide covers FreeBSD 10 and Samba 4.1.7 for previous version see:

Please refer to my FreeBSD Installation Guide if you need help installing FreeBSD.

Update FreeBSD

You may wish to make sure FreeBSD and the ports collection are up to date. To do so, use the below commands. However, please make sure you understand the risks if you are running these commands on an existing system with ports installed.

freebsd-update fetch
freebsd-update install
 
portsnap fetch update

Kerberos

This only applies to an ADS Setup. As far as I know Kerberos has no function or use for a simple non-ADS Samba setup.

*NOTE:* I believe Samba 4.1 uses a built-in Kerberos implementation but I haven’t fully verified that. The krb5.conf settings might not have any impact on Samba4 at all anymore..

As long as your FQDN is set correctly in rc.conf then Kerberos should be able to find your domain controllers without needing anything configured in the krb5.conf file. Or so, that has been my recent experience.

However, here is an example krb5.conf file you could use. This is based off the krb5.conf man page.

krb5.conf
[libdefaults]
    default_realm = EXAMPLE.COM
 
[domain_realm]
    .example.com = EXAMPLE.COM
 
[realms]
    EXAMPLE.COM = {
        kdc = kdc.example.com
        default_domain = example.com
    }
 
[logging]
    kdc = FILE:/var/heimdal/kdc.log
    kdc = SYSLOG:INFO
    default = SYSLOG:INFO:USER

Install Samba

This part is pretty easy.

cd /usr/ports/net/samba41
make config
make install clean

The options you select at the configuration page will depend on your environment and needs.

  • ADS/LDAP – If you are not integrating into an Active Directory environment you can uncheck ADS and LDAP
  • CUPS – If you do not intend to share printers then you can uncheck CUPS.
+------------------------------ samba41-4.1.7 ---------------------------------+
¦ +--------------------------------------------------------------------------+ ¦
¦ ¦ [x] ACL_SUPPORT    File system ACL support                               ¦ ¦
¦ ¦ [x] ADS            Active Directory support                              ¦ ¦
¦ ¦ [x] AIO_SUPPORT    Asyncronous IO support                                ¦ ¦
¦ ¦ [ ] CUPS           CUPS printing system support                          ¦ ¦
¦ ¦ [ ] DEBUG          With debug information in the binaries                ¦ ¦
¦ ¦ [ ] DEVELOPER      With development support                              ¦ ¦
¦ ¦ [ ] DNSUPDATE      Dynamic DNS update(require ADS)                       ¦ ¦
¦ ¦ [ ] EXP_MODULES    Experimental modules                                  ¦ ¦
¦ ¦ [ ] FAM_SUPPORT    File Alteration Monitor support                       ¦ ¦
¦ ¦ [x] LDAP           LDAP support                                          ¦ ¦
¦ ¦ [x] MANPAGES       Build and/or install manual pages                     ¦ ¦
¦ ¦ [ ] PAM_SMBPASS    PAM authentication via passdb backends                ¦ ¦
¦ ¦ [x] PTHREADPOOL    Pthread pool                                          ¦ ¦
¦ ¦ [ ] QUOTAS         Disk quota support                                    ¦ ¦
¦ ¦ [x] SYSLOG         Syslog support                                        ¦ ¦
¦ ¦ [x] UTMP           UTMP accounting support                               ¦ ¦
¦ ¦----------------------------------- DNS ----------------------------------¦ ¦
¦ ¦ (*) NSUPDATE       Use internal DNS with NSUPDATE utility                ¦ ¦
¦ ¦ ( ) BIND98         Use bind98 as a DNS server frontend                   ¦ ¦
¦ ¦ ( ) BIND99         Use bind99 as a DNS server frontend                   ¦ ¦
¦ ¦--------------------------------- ZEROCONF -------------------------------¦ ¦
¦ ¦ (*) AVAHI          Zeroconf support via Avahi                            ¦ ¦
¦ ¦ ( ) MDNSRESPONDER  Zeroconf support via mDNSResponder                    ¦ ¦
¦ +--------------------------------------------------------------------------+ ¦
+------------------------------------------------------------------------------+

Configure Samba

My goal with the smb4.conf file is to keep it as absolutely simple as possible. So I omit anything where the default values from Samba work and only include lines that were needed to get this working in my environment. It’s always recommended to review the samba documentation and other guides for settings that might apply to your environment. Near the bottom of this guide there should be the complete output of testparm -v that you can also reference.

Non-ADS Config

This section will cover configuration as a simple File Server with basic security for a home or very small office setup.

ADS Config

This section covers configuration as a Member File Server within an Active Directory domain.

Basic Settings

/usr/local/etc/smb4.conf
[global]
    workgroup = EXAMPLE
    realm = EXAMPLE.COM
    security = ADS
 
[testshare]
    path = /
    read only = no

No, really. That’s all you actually need. But read below for more options you may want.

TDB Backend for idmap

The TDB Backend is the default option when no backend is specified.

However, you can specify it and provide a uid/gid mapping range if you want by adding the following to the global section. The range setting tells Samba what range of ID’s to use for UID/GID mapping and you may adjust it as you see fit.

idmap config *:backend = tdb
idmap config *:range = 70001-80000

You can read more about the tdb backend with the below link.

https://www.samba.org/samba/docs/man/manpages-3/idmap_tdb.8.html

RID Backend for idmap

You can use the RID idmap backend with Samba to calculate the UID/GID values based off the Active Directory RID value. This protects your Samba installation from loosing the mappings due to a damaged tdb database and allows all Samba installations to use the same UID/GID values. You can read more about the RID backend on Samba’s website with the link below.

https://www.samba.org/samba/docs/man/manpages-3/idmap_rid.8.html

From what I understand. The SID is unique per Domain and the RID is only unique inside a given Domain. A users or groups complete SID is composed of the domain SID with the user/group RID as the last four or more numbers. RIDs are never re-used and so the “next RID” value will always grow to a larger and larger number over time. This is an easy way to get static SID to Linux UID/GID mappings that are the same across all Samba servers.

You need to also configure a “fall back” backend, such as TDB for anything that doesn’t have an RID value. Such as some of the domain “BUILTIN” accounts and groups like “Everyone” or “Administrators”.

A UID/GID is built by taking the RID and adding the low range number. So, if a RID is 1250 and your rid mapping is 500-100000 then the UID/GID would come out as 1750. You want to make sure your high range number is large enough to accommodate any UID/GID that would be calculated in this fashion. For example, if your mapping was 500-1000 and the same RID of 1250 would calculate to a GID/RID of 1750 but since your high range number is 1000 it wouldn’t be able to do the mapping and it would be ignored in same fashion (I haven’t tested it – just what I understand from the documentation)

The idmap range should be configured the same for any given domain on ALL samba servers otherwise you won’t have matching UID/GID values which is the whole point for doing it in the first place.

Below is a hopefully safe example of using idmap_rid for a mid sized domain.

idmap config *:backend = tdb
idmap config *:range = 2000-5000
 
idmap config EXAMPLE: default = yes
idmap config EXAMPLE: backend = rid
idmap config EXAMPLE: range = 6000-100000

Reference

AD Backend for idmap

The AD backend is slightly similar to the RID backend in that it provides protection against lost/damanged TDB database and keeps GID/UID mapping the same across all Samba installtions. It differs just in how it accomplishes that. With the AD backend the samba idmapper will pull the UID/GID values directly out of the Active Directory database. This means, a UID and GID value must be present in AD (via the RFC2307/SFU schema extensions) for each user.

You can read more about the AD backend on Samba’s website with the link below.

https://www.samba.org/samba/docs/man/manpages-3/idmap_ad.8.html

If I get some more time I will try and document this more, however the above link describes it pretty well. The trick here is getting the RFC2703 schema extensions added to a Windows Active Directory but there are several examples on the web for most Windows server versions. Just google it.

Reference

NTFS ACLs on ZFS

These are the settings I have been using successfully in my (Windows AD) environment to correctly store NTFS permissions in a sensible way. I’m using 100% ZFS and not all of these settings will apply to UFS. As with most Samba settings you can add these on a per-share basis but I normally add them to the [global] section.

read only = no
inherit permissions = No
inherit acls = No
inherit owner = No
force unknown acl user = No
store dos attributes = yes
map read only = no
 
vfs objects  = zfsacl
nfs4:mode    = special
nfs4:acedup  = merge
nfs4:chown   = yes

You also need to set two ZFS settings on any pools/datasets you intend to store ACLs on.

zfs set aclmode=passthrough dataset/pool
zfs set aclinherit=passthrough dataset/pool

“Previous Versions” on ZFS

You can take ZFS snapshots for a Samba share and have those snapshots show up under the “Previous Versions” tab on a Windows computer. It’s an amazingly great first-level backup method. You can automate the snapshots to run on a regular interval or each time you connect to the samba share. Image you damange or accidently delete a file and the “restore” process is to just right-click on a folder, select the previous versions tab and get the most recent files.

The short and quick example to enable ZFS ACLs and Previous Version ShadowCopies is below.

[someshare]
    path = /somepool
    vfs objects  = shadow_copy2, zfsacl
    shadow: snapdir = .zfs/snapshot
    shadow: sort = desc
    shadow: localtime = no
    shadow: format = %Y-%m-%dT%H:%M:%S
    nfs4:mode    = special
    nfs4:acedup  = merge
    nfs4:chown   = yes

Then, create snapshots with

zfs snapshot somepool@`date -u +%Y-%m-%dT%H:%M:%S`

You can read more about the vfs_shadow_copy2 module here

notes

Some ideas for managing “rolling snapshots” that work with “Previous Versions”

snapshots can be given special properties when created, like..

zfs snapshot -o "zfsnap:ttl=1m" pool@date

With this you could set a TTL for a snapshot without putting it in the snapshot name itself. You could set all sorts of properties. Also, custom properties on the dataset will get added to snapshots. So you could set “zfsnap:ttl=1m” on the main dataset and all snapshots would inherit that property. This way the configuration of your rolling snapshot systems could be stored fully inside the ZFS properties.

Also, these custom properties can be changed anytime. So you can change the TTL or even add more custom properties to a snapshot.

Samba Auditing

Placeholder..

Short version: This logs all delete/move/writes

vfs objects  = full_audit
full_audit:prefix = %u|%I
full_audit:success = chflags chmod chmod_acl chown mkdir rename rmdir unlink write pwrite pwrite_send pwrite_recv
full_audit:failure = none
full_audit:facility = LOCAL7
full_audit:priority = ALERT

Samba has support for logging access, renames, deletes, etc.

nsswitch

Winbind needs to be added to the /etc/nsswitch.conf file. Here’s an example below.

/etc/nsswitch.conf
#
# nsswitch.conf(5) - name service switch configuration file
# $FreeBSD: release/10.0.0/etc/nsswitch.conf 224765 2011-08-10 20:52:02Z dougb $
#
group: files winbind
#group: compat
#group_compat: nis
hosts: files dns
networks: files
passwd: files winbind
#passwd: compat
#passwd_compat: nis
shells: files
services: compat
services_compat: nis
protocols: files
rpc: files

All done. No restart of nsswitch should be needed.

Join ADS Domain

To see that everything looks okay. Try running the below command. It should (at this point) print out valid info on your domain.

net ads info

To join this Samba server to the domain use the below command. Adjust the username if needed.

net ads join -U Administrator

You can follow up with the following command to make sure everything went okay.

net ads testjoin

Start Samba Server

At this point it probably makes sense to fire up the samba server itself and try to connect to it.

First, we want to enable the server.

echo 'samba_server_enable="YES"' >> /etc/rc.conf

Now lets start the server.

service samba_server start

Advanced? Settings

Here is a handful of additional Samba settings you might want to use.

admin users

admin users = “@domain admins”

load printers

disable spoolss

domain master

local master

csc policy

interfaces

log file

netbios name

max log size

default yes

read only

Performance

Placeholder

AIO

Samba AIO needs the AIO module loaded. Here’s how to do that and configure the system to load it on boot.

kldload aio
echo 'aio_load="YES"' >> /boot/loader.conf

Notes

Troubleshooting

getent passwd/group does not show domain users

Try asking getent for a specific user. Try both with the domain and without. If you have changed the winbind domain separator then you should adjust the below to match.

getent passwd DOMAIN\\username
 
getent passwd username

If the 1st line works and not the second then you might want to read about the setting *winbind use default domain = yes

If both lines work but when typing getent passwd without a username domain users are not displayed then you may want to read about the settings *winbind enum users = yes* and also *winbind enum groups = yes*

Unable to connect to CUPS server localhost:631 – Bad file descriptor

You may also see failed to retrieve printer list: NT_STATUS_UNSUCCESSFUL

To disable printers in Samba add the following to the global section.

load printers = No
printing = bsd
printcap name = /dev/null
disable spoolss = Yes

DNS update failed: NT_STATUS_INVALID_PARAMETER

If you get this.. It might be.. That the netbois name in smb4.conf should match your system hostname..

Kinit failed: KDC has no support for encryption type

I get this error still. If you find an answer I’d love to know it. Please email me!

More…

Reference