Samba
Notes
Samba Installation
Installing the package:
# apt-get install samba ntp winbind dnsutils krb5-user smbclient acl
For a DC continue as below, for a fileserver go to #Creating a samba fileserver
Stop and disabled smbd and nmbd services as they are not needed on a DC and can even create problems if left running
systemctl stop smbd systemctl disable smbd systemctl stop nmbd systemctl disable nmbd systemctl stop winbind systemctl disable winbind
Stop samba and move/delete /etc/samba/smb.conf:
# systemctl stop samba-ad-dc # mv /etc/samba/smb.conf /etc/samba/smb.conf.default
If you have multiple domain controllers in your domain, add on each DC all of them to the resolvconf template:
Ubuntu 18.04 and newer
Since Ubuntu 18.04 systemd has a service called systemd-resolved that listens on port 53 (DNS) which makes samba unable to listen at that port. Could be checked with netstat:
# netstat -tulnp | grep 53 tcp 0 0 0.0.0.0:49152 0.0.0.0:* LISTEN 453/samba tcp 0 0 0.0.0.0:49153 0.0.0.0:* LISTEN 453/samba tcp 0 0 0.0.0.0:49154 0.0.0.0:* LISTEN 453/samba tcp 0 0 0.0.0.0:135 0.0.0.0:* LISTEN 453/samba tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN 280/systemd-resolve tcp6 0 0 :::49152 :::* LISTEN 453/samba tcp6 0 0 :::49153 :::* LISTEN 453/samba tcp6 0 0 :::49154 :::* LISTEN 453/samba tcp6 0 0 :::135 :::* LISTEN 453/samba tcp6 0 0 :::53 :::* LISTEN 467/samba udp 29184 0 127.0.0.53:53 0.0.0.0:* 280/systemd-resolve udp6 0 0 :::53 :::* 467/samba
Delete the /etc/resolv.conf symlink
rm /etc/resolv.conf
Create a new /etc/resolv.conf so the servers still knows where to resolve domains
#vi /etc/resolv.conf search domain.local nameserver dc1.ip.add.ress nameserver dc2.ip.add.ress
Now you can stop and disable systemd-resolve:
systemctl stop systemd-resolved systemctl disable systemd-resolved
Ubuntu 16.04 or older
# vi /etc/resolvconf/resolv.conf.d/tail search example.local nameserver ip.addr.a.dc nameserver ip.addr.b.dc nameserver ip.addr.c.dc
Don't forget to update resolv.conf afterwards
# resolvconf -u
For creating a domain use this command
# samba-tool domain provision --interactive --use-rfc2307
For Realm put your desired realm e.g. example.local or a TLD you control absolutely, for DNS forwarder IP address put your main (Internet facing e.g. firewall) DNS server IP address (whether you have a multiple domain bind setup or just using a DNS service on your router) and for the others you can just press enter. NB every DC should have an appropriate forwarder set
If you get an error about ldb, make sure packages samba-dsdb-modules and samba-vfs-modules are installed, if not install them:
apt-get install samba-dsdb-modules samba-vfs-modules
For joining an existing domain use this command
# samba-tool domain join domain.local DC -Usamba.user --realm=domain.local --server=primary.dc.ip
Note: The user used for the join needs to be in group "Domain Admins", you can add a samba user to this group like this:
samba-tool group addmembers "Domain Admins" samba.user
Now start the samba DC service:
# systemctl start samba-ad-dc
If start failes with Failed to start samba-ad-dc.service: Unit samba-ad-dc.service is masked run this command and then start samba-ad-dc again
systemctl unmask samba-ad-dc systemctl start samba-ad-dc
Enable the service to auto start at boot
systemctl enable samba-ad-dc
Add DNS forwarder to /etc/samba/smb.conf in the [global] section
dns forwarder = <ga.te.way.ip>
Restart samba-ad-dc service
systemctl restart samba-ad-dc
For joining an existing domain when the second DC is ruining on a VM with private IP behind a public IP
For joining an existing domain when the second DC is ruining on a private IP behind a public IP (NAT) replication issues can occur. If the replication is working only in one way (from the second DC to the main DC) the DNS records from the main DC has to be updated.
1. First check on which IP the second DC is answering. If the ping returns the private IP of the DC then a DNS update is needed.
2. List the DNS informations of the second DC
sudo samba-tool dns serverinfo newroco-dc2 -U username
The output should look like this:
dwVersion : 0xece0205 fBootMethod : DNS_BOOT_METHOD_DIRECTORY fAdminConfigured : FALSE fAllowUpdate : TRUE fDsAvailable : TRUE pszServerName : NEWROCO-DC2.newroco.local pszDsContainer : CN=MicrosoftDNS,DC=DomainDnsZones,DC=newroco,DC=local aipServerAddrs : '''['172.16.12.13']''' aipListenAddrs : '''['172.16.12.13']''' ......
3. Update the DNS record for the second DC and set as the default IP the public IP of the host:
samba-tool dns update petitsuix newroco.local newroco-dc2 A 172.16.12.13 144.76.221.153 -U username
4. Check the if the update changed the private IP with the public one.
5. Run again the replication command from both ways and both servers.
SSL Certificate
If you want to use LDAPS you can create a self-signed certificate
openssl req -newkey rsa:2048 -keyout /var/lib/samba/private/tls/samba-key.pem -nodes -x509 -days 3650 -out /var/lib/samba/private/tls/samba-cert.pem
Change permissions for the key
chmod 600 /var/lib/samba/private/tls/samba-key.pem
And add these lines in /etc/samba/smb.conf on [global] section:
tls enabled = yes tls keyfile = /var/lib/samba/private/tls/samba-key.pem tls certfile = /var/lib/samba/private/tls/samba-cert.pem tls cafile =
Restart samba
systemctl restart samba-ad-dc
Note well: when using a self-signed certificate most applications would not trust them by default, you have to add it as a trusted certificate.
Kerberos tickets (needed for RSAT tools and probably other)
Package krb5-user was already installed at the beggining, now lets edit /etc/krb5.conf. Delete the whole content of the file and put this instead:
[libdefaults] default_realm = MYDOMAIN.LOCAL dns_lookup_realm = false dns_lookup_kdc = true
Package was also installed at the beginning, but it's service needs to be stopped and disabled
systemctl stop winbind systemctl disable winbind systemctl restart samba-ad-dc
Now you can test a login with smbclient
smbclient -L localhost -U user.name
Checking the replication
If you end up with multiple DCs it's probably a good thing to check that replication works. On a newly joined DCs test manual replication to see if it works both ways, like this:
samba-tool drs replicate <new-dc> <primary-dc> dc=<domain>,dc=local samba-tool drs replicate <primary-dc> <new-dc> dc=<domain>,dc=local
Next test if automatic replication works
samba-tool drs showrepl
SysVol Replication
If you need to setup SysVol Replication for Group Policies (GPO) follow the tutorial bellow from the official documentation
NOTE: on the PDC start the rsync service with
systemctl start rsync systemctl enable rsync
https://wiki.samba.org/index.php/Rsync_based_SysVol_replication_workaround
Samba & LDAP
Authenticating LDAP user
Standard LDAP config in Samba (& elsewhere) is to require a connection to be authenticated before other access granted. This can often be disabled, but it's better practice (and as easy) to create an account for the service that needs access, and use that for connection. The base string for the authenticating user will be of the form:
cn=<username>,cn=<userbasegroup>,dc=<firstpartofADdomainname>,dc=<secondpartofADdomainname>
Base DN
Will vary on setup, but simple base DN is likely to be of the form:
dc=<firstpartofADdomainname>,dc=<secondpartofADdomainname>
Where AD domain name (realm) was of the form
firstpart.secondpart
. If the domain name has more parts you will need those parts expressed as separate DCs.
Secure LDAP quick workaround
Not recommended in production if LDAP authing outside a firewall.
Samba 4 LDAP is secure by default which makes it hard for some simpler LDAP auth systems. If no other solution or for initial testing purposes, secured LDAP can be disabled by adding the following line to smb.conf main section:
ldap server require strong auth = no
Creating a samba fileserver
To make your samba installation into a fileserver. This assumes you already have a working DC or 2 and this server will be a member server for load balancing/egg separation purposes. In this scenario you should set your DNS forwarders to be any local or routable DCs for the domain you want the fileserver to be part of.
NB if you have a multi-site setup, your DCs resolv.conf should have the site-local DCs. This allows site-specific DNS entries to function correctly.
Ubuntu 16.04 or older
This can be done by editing resolvconf's head file:
#vi /etc/resolvconf/resolv.conf.d/head
nameserver ip.addr.dc.1 nameserver ip.addr.dc.2
Then updating resolv.conf with
# resolvconf -u
Ubuntu 18.04 or newer
Since Ubuntu 18.04 the way you add DNS servers changed. Delete the symlink at /etc/resolv.conf
rm /etc/resolv.conf
And manually create the file
#vi /etc/resolv.conf search domain.local nameserver dc1.ip.addr.ess nameserver dc2.ip.addr.ess
Installation and configuration
Depending on how your base machine was created you may need to add the universe repository:
apt-get install software-properties-common add-apt-repository universe
Then install these additional packages:
# apt-get install libnss-winbind libpam-winbind acl libpam-krb5 krb5-user
And configure nsswitch to be able to use winbind (Note: newer ubuntu versions might have other options for passwd and group, don't delete them, just add winbind):
# vi /etc/nsswitch.conf passwd: compat winbind group: compat winbind
Set up your shares
# vi /etc/samba/smb.conf
Replace current file content with next one:
[global] workgroup = workgroupname server string = yourservername security = ads realm = WORKGROUPNAME.TLD # common to be .LOCAL socket options = TCP_NODELAY IPTOS_LOWDELAY SO_RCVBUF=131072 SO_SNDBUF=131072 use sendfile = true idmap config * : backend = tdb idmap config * : range = 100000-299999 idmap config workgroupname : backend = rid idmap config workgroupname : range = 10000-99999 winbind separator = + winbind enum users = yes winbind enum groups = yes winbind use default domain = yes winbind refresh tickets = yes restrict anonymous = 2 log file = /var/log/samba/log.%m max log size = 50 deadtime = 45 read raw = Yes write raw = Yes server signing = mandatory # Network interfaces = ens3 # change to suit, ens3 is first interface if using a [http://docswiki.newro.co/index.php/Creation_of_a_new_VM VM built as per our approach] bind interfaces only = true log file = /var/log/samba/log.%m log level = 1 max log size = 1000 logging = syslog@0 file panic action = /usr/share/samba/panic-action
Example share definition allowing read/write for all domain users:
[sharename] comment = What this share is writeable = yes write list = @"Domain Users" path = /path/to/data/ force directory mode = 775 force group = Domain Users force create mode = 665 valid users = @"Domain Users" create mode = 665 directory mode = 775
Example read-only share definition
[sharename] comment = What this share is writeable = no read list = @"Domain Users" path = /path/to/readonlydata/
NB if your shared volume is coming from a network source like iscsi it is recommended you don't make your share and the mounted volumes directly match; rather shares should reference directories within the mounted volume i.e. if you have an iscsi mount at
/mnt/myiscsi
your samba share should be at
/mnt/myiscsi/myshare
or a further sub branch. This ensures that is the network source is not available, user data isn't written to (nor fills) your fileserver's / filesystem.
If a share should be accessed by 'Domain Users', give the shares folder necessary permissions for the group and set group ownership to "domain users". Note: after joining the AD domain.
chown :"domain users" /path/to/folder
And then join the domain using a domain user that has appropriate privileges e.g. is a member of the Domain Admins group for that domain:
# net ads join -U user.name
Restart the samba services
# systemctl restart winbind nmbd smbd
NB which domain to join is determined from the configuration files.
Recycle Bin
If you want to add a recycle bin functionality to a share add these lines to share configuration
vfs objects = recycle recycle:repository = .recycle recycle:directory_mode = 775 recycle:keeptree = yes recycle:versions = yes recycle:exclude = *.swp,*.swpx,*~ recycle:touch_mtime = yes
More details about samba recycle bin configuration can be found here: Samba Recycle Bin
If you also want files to automatically be deleted after 7 days add a daily cronjob like this:
#vi /etc/cron.daily/samba-recycle-bin #!/bin/bash find /path/to/share/.recycle/* -mtime +7 -exec rm {} \;
And make it executable:
chmod +x /etc/cron.daily/clean-samba-recycle
Testing
Assuming you got no joining errors at the last step above (DNS update ones can be ignored for now), you can verify your server is seeing domain users correctly by
# getent passwd
This should return the normal contents of /etc/passwd, pause for a moment and then continue with all the domain users. If it doesn't show any domain users try restarting the service.
You can then test the availability of the shares you've created
# smbclient -L your.ip.add.ress -U adomain.username
This should ask for your password and if correctly entered return information of the form
Domain=[EXAMPLE] OS=[Windows 6.1] Server=[Samba 4.3.11-Ubuntu] Sharename Type Comment --------- ---- ------- sharename Disk What this share is IPC$ IPC IPC Service (yourservername) Domain=[EXAMPLE] OS=[Windows 6.1] Server=[Samba 4.3.11-Ubuntu] Server Comment --------- ------- YOURSERVERNAME ANOTHERSERVER ADOMAINMEMBERPC Workgroup Master --------- ------- EXAMPLE ANOTHERSERVER
NB you may get different results depending whether you are testing from a machine in the domain or not - if it works from a machine in the domain but not in one from outside, check your that the relevant share configs have
browseable=yes
and the general section doesn't contain a
restrict anonymous
with a value higher than 0 (which is the default i.e. the line isn't needed unless you want to restrict unauthenticated browsing of share listings)
When working remotely without access to a GUI machine that can access the smb fileserver, a final test (e.g. checking users have correct permissions when they have the share mapper) can be performed by mounting the share from the command line. This requires the cifs-util package which can be installed with
apt-get install cifs-utils
and then running
mount -t cifs //server-ip/sharename /mountpoint -o user=user.name
where user.name is an SMB user. If the mount is successful you can check that user has the permissions you expect it to have in terms of file access/creation/deletion etc..
Adding samba users
#!/bin/bash if [ $# -eq 0 ] ; then printf "Username(format name.surname):" read username printf "Email:" read email printf "Fullname(format Name Surname):" read fullname if samba-tool user list | grep -x -q $username; then echo "********************************************" echo "User $username already exists" echo "********************************************" else samba-tool user create $username --mail-address=$email samba-tool user setexpiry $username --noexpiry pdbedit -u $username -f "$fullname" fi else echo > users-pass.txt while IFS='' read -r line || [[ -n "$line" ]]; do IFS=':' read -a userinfo <<< "$line" if samba-tool user list | grep -x -q ${userinfo[0]}; then echo "********************************************" echo "User ${userinfo[0]} already exists" echo "********************************************" echo "${userinfo[0]}" >> existing-users else pass=`shuf -i 10000-99999 -n 1` samba-tool user create ${userinfo[0]} "ChangeMe"$pass --mail-address=${userinfo[1]} samba-tool user setexpiry ${userinfo[0]} --noexpiry pdbedit -u ${userinfo[0]} -f "${userinfo[2]}" echo "${userinfo[0]} - ${userinfo[1]} - ChangeMe$pass" >> users-pass.txt fi done < "$1" fi
If the script is called with no argument, it asks the information for the user to be added, but it can be called with a file as an argument that contains a user list in the following format:
username1:mail1@example.com:Full Name username2:mail2@example.com:Full Name username3:mail3@example.com:Full Name
The passwords are generated automatically and written into the users-pass.txt file
Adding Service accounts
Tips and Tricks
Get user info
If you want to get information about a samba user (displayName, mail, etc.), i found ldapsearch to show the most details
ldapsearch -xLLL -H ldaps://localhost -D "cn=user.name,cn=users,dc=<domain>,dc=local" -W -b "dc=<domain>,dc=local" '(&(sAMAccountName=<user-to-search-for>))'
If last part ('(&(sAMAccountName=<user-to-search-for>))') is omitted it will show all users.
Setting an email for a user
When creating the user
samba-tool user create <username> --mail-address=<email>
For an existing user
Package ldap-utils is required so install it if not already:
apt-get install ldap-utils
Create a file entrymods.ldif:
dn: cn=<username>,cn=Users,dc=<firstpartofdomain>,dc=<secondpartofdomain> changetype: modify replace: mail mail: <email> -
Set the email with ldapmodify command using a samba user that belongs to "Account Operators" group:
ldapmodify -x -D "cn=<username>,cn=Users,dc=<firstpartofdomain>,dc=<secondpartofdomain>" -W -H ldaps://localhost -f entrymods.ldif
Rename username
Rename the CN (ldb-tools should be installed for ldbrename command)
ldbrename -H ldap://localhost CN=<olduser>,CN=Users,DC=<domain>,DC=local CN=<newuser>,CN=Users,DC=<domain>,DC=local -U <user>
Create a file chuser.ldif:
dn: cn=<newuser>,cn=Users,dc=<domain>,dc=local changetype: modify replace: sAMAccountName sAMAccountName: <newuser> - replace: userPrincipalName userPrincipalName: <newuser>@<domain>.local -
Change sAMAccountName and userPrincipalName (the user used below should belong to "Account Operators" group)
ldapmodify -x -D "cn=<user>,cn=Users,dc=<domain>,dc=local" -W -H ldap://localhost -f chuser.ldif
Reload a samba fileserver config
This should in theory reload a samba fileserver config without breaking users connections
smbcontrol all reload-config
Change password complexity/length
samba-tool domain passwordsettings set --complexity=off samba-tool domain passwordsettings set --min-pwd-length=12
Monitor LDAP ports
If you are about to migrate the AD to new DCs and want to make sure you don't have applications still authenticating against the old DCs you can monitor the LDAP port (or any) with tcpdump
tcpdump -n not host za.bb.ix.ip and port 636
This also works nice with screen
Get username/groupname from UID
# wbinfo --uid-info 3000008 NEWROCO\emilian.mitocariu:*:3000008:100::/home/NEWROCO/emilian.mitocariu:/bin/false
Get UID from username
# wbinfo --user-info emilian.mitocariu NEWROCO\emilian.mitocariu:*:3000008:100::/home/NEWROCO/emilian.mitocariu:/bin/false
Troubleshooting
Randome samba service failure
A DC could fail with service samba-ad-dc still running but some samba related ports (389. 636, 135, 445) are closed. Can be checked with following command. If no output, port is closed.
netstat -tulnp | grep <port>
If this happens and restarting the service doesn't do anything, then stop the service
service samba-ad-dc stop
Look for samba processes that are still running
# ps aux | grep samba root 23176 2.4 59.1 1063172 600936 ? S Oct19 35:47 /usr/sbin/samba -D root 28407 0.0 0.0 11284 1012 pts/1 S+ 06:28 0:00 grep --color=auto samba
And kill them using the PID (second column). Note: second row is just the grep command, no need to kill that one.
kill -9 23176
Start the service
service samba-ad-dc start
Check if everything works.
kerberos_kinit_password <fileserver-name>$@OXARCH.LOCAL failed: Looping detected inside krb5_get_in_tkt
If this error is found in the logs you need to leave the domain, rejoin and possibly restart smbd/winbind services.