Core Concepts

Before diving into commands, understand what each technology does and why it exists.

What is Active Directory (AD)?

Active Directory is Microsoft's directory service that runs on Windows Server. It acts as a central authority that stores all user accounts, passwords, and groups in one place, authenticates users when they log in (via Kerberos), controls what resources each user can access, and manages computers joined to the domain. The Windows Server running AD is called a Domain Controller (DC). Every machine in the domain trusts the DC for authentication.

What is Samba?

Samba is an open-source implementation of the SMB (Server Message Block) protocol โ€” the same protocol Windows uses for file sharing. Samba allows Linux machines to share folders that Windows and Linux clients can access like network drives, join an Active Directory domain as a recognised member, and authenticate users against AD so domain users can access Linux shares.

What is Winbind?

Winbind is a component of Samba that acts as a bridge between Linux and Windows AD. It translates Windows user/group identities (SIDs) into Linux user IDs (UIDs/GIDs), allows Linux to resolve AD usernames and groups (like getent passwd), and handles authentication requests against the DC. Without Winbind, Linux would not know what to do with Windows domain users trying to access its file shares.

What is Kerberos?

Kerberos is the authentication protocol used by AD. When a user logs in, the DC issues a ticket. Other machines in the domain accept this ticket as proof of identity โ€” no password is sent over the network.

โš ๏ธ Clock sync matters

Kerberos tickets have timestamps. A clock difference of more than 5 minutes between a machine and the DC causes Kerberos to reject authentication entirely.

ID Mapping (idmap) โ€” Why it matters

Windows identifies users by SIDs (Security Identifiers) like S-1-5-21-...-1001. Linux uses numeric UIDs/GIDs. Winbind must map between these. The smb.conf idmap config controls this:

BackendBehaviour
tdb (use as default *)Simple key-value store for ID mappings. Consistent and reliable for single-domain labs. Use this as the default backend.
autorid (avoid as default)Dynamically assigns IDs per domain. Can produce different GIDs for the same group depending on lookup method โ€” causes NT_STATUS_ACCESS_DENIED even when group membership is correct.
rid (domain-specific)Derives Linux UID from the Windows RID (last number of SID). Predictable and stable.
rangeThe pool of Linux UIDs/GIDs this backend can assign. Must not overlap between backends.
โš ๏ธ Use tdb, not autorid โ€” and watch the spelling

Use tdb (not autorid) as the default * backend for single-domain labs. autorid can assign different GIDs for the same group depending on lookup method, causing permission errors even when group membership is correct. Also: it's tdb not tbd โ€” an easy typo that causes silent failures.

SMB Share Permissions โ€” Syntax Explained

In smb.conf, permissions are written in octal notation. Octal digits: 4 = Read, 2 = Write, 1 = Execute. So 6 = rw, 7 = rwx.

SettingMeaning
create mask = 0660Permissions for new files. Owner rw, group rw, others none.
directory mask = 0770Permissions for new directories. Owner rwx, group rwx, others none.
chmod 2770The leading 2 is setgid โ€” new files/dirs inherit the group automatically.
valid users = @"SDWIN\\Finance"@ means group. SDWIN\\Finance is the AD domain\group. Only this group can connect.

Part 1 โ€” Windows Client & DC Setup

This section covers connecting a Windows computer to the domain and setting up AD groups. Your DC should already be installed with Active Directory Domain Services (AD DS). If you haven't set up your Active Directory yet, see the setup guide here.

Connecting a Windows Computer to the Domain

Do this on any Windows client machine you want to join to SDWIN.LOCAL.

Step 1 โ€” Set DNS to point to the DC

Control Panel โ†’ Network and Sharing Center โ†’ Change adapter settings โ†’ Right-click NIC โ†’ Properties โ†’ IPv4 โ†’ Properties, then set:

IP Address:       192.168.122.x   # unique IP for this machine
Subnet Mask:      255.255.255.0
Default Gateway:  192.168.122.1
Preferred DNS:    192.168.122.100  # your DC
Alternate DNS:    8.8.8.8          # fallback
โš ๏ธ DNS must point to the DC

AD uses DNS to locate domain services (Kerberos, LDAP). Without this, joining the domain will fail.

adapter-settings adapter-properties ipv4-settings adapter-config

Step 2 โ€” Join the Domain

Right-click This PC โ†’ Properties โ†’ Rename this PC (advanced) โ†’ Change โ†’ select Member of Domain โ†’ type SDWIN.LOCAL โ†’ enter Administrator credentials when prompted โ†’ restart.

โœ… After restart

Log in with domain credentials: SDWIN\username or username@SDWIN.LOCAL.

Rename this pc change tab Domain join

Creating AD Groups and Users

On the Domain Controller, open Server Manager โ†’ Tools โ†’ Active Directory Users and Computers.

Step 1 โ€” Create Groups

  1. Right-click the container โ†’ New โ†’ Group
  2. Group name: Finance | Group scope: Global | Group type: Security
  3. Repeat for HR and IT

Step 2 โ€” Create Users

  1. Right-click the container โ†’ New โ†’ User
  2. Fill in First name, Last name, User logon name (e.g. finance1)
  3. Set a password; uncheck User must change password at next logon for lab use

Step 3 โ€” Add Users to Groups

  1. Double-click the Finance group โ†’ Members tab โ†’ Add
  2. Type the username (e.g. finance1) โ†’ Check Names โ†’ OK

Verify from CMD on any domain machine:

net user finance1 /domain

Configure DNS Forwarder on DC

So your DC (and all domain machines using it as DNS) can resolve internet addresses:

  1. Open DNS Manager on Windows Server
  2. Right-click your server name โ†’ Properties โ†’ Forwarders tab
  3. Add 8.8.8.8 and 1.1.1.1 โ†’ OK
โœ… This allows the DC to forward non-local DNS queries

(like google.com) to public DNS resolvers.

Part 2 โ€” Ubuntu Server: Network & Hostname

Configure Static IP with Netplan

Edit the netplan configuration file (check the filename with ls /etc/netplan/):

sudo nano /etc/netplan/01-netcfg.yaml
network:
  version: 2
  ethernets:
    enp1s0:           # use your actual NIC name (ip a)
      dhcp4: no
      addresses:
        - 192.168.122.181/24
      gateway4: 192.168.122.1
      nameservers:
        addresses:
          - 192.168.122.100  # DC as primary DNS
          - 8.8.8.8          # fallback
        search:
          - SDWIN.LOCAL
โš ๏ธ Use spaces, never tabs in YAML

Indentation errors cause "invalid YAML" on netplan apply. The nameservers block sits at the same indent level as addresses โ€” both under the NIC name.

sudo netplan apply
ping 192.168.122.100    # verify DC is reachable
nslookup SDWIN.LOCAL    # verify DNS resolves the domain

Set Hostname

sudo hostnamectl set-hostname SD-Ubuntu.SDWIN.LOCAL

Update /etc/hosts so the FQDN is listed first:

sudo nano /etc/hosts
127.0.0.1   localhost
127.0.1.1   SD-Ubuntu.SDWIN.LOCAL SD-Ubuntu
192.168.122.181   SD-Ubuntu.SDWIN.LOCAL SD-Ubuntu
::1         ip6-localhost ip6-loopback
fe00::0     ip6-localnet
ff00::0     ip6-mcastprefix
ff02::1     ip6-allnodes
ff02::2     ip6-allrouters
โš ๏ธ FQDN must come before the short hostname

Samba warns and DNS update fails if this ordering is wrong.

hostname    # should return: SD-Ubuntu.SDWIN.LOCAL
hostname -f # should return: SD-Ubuntu.SDWIN.LOCAL

Configure Kerberos

sudo nano /etc/krb5.conf
[libdefaults]
    default_realm = SDWIN.LOCAL
    dns_lookup_realm = false
    dns_lookup_kdc = true
โš ๏ธ Kerberos requires clocks within 5 minutes of the DC

If time is off: sudo apt install ntpdate -y && sudo ntpdate 192.168.122.100

Part 3 โ€” Ubuntu Server: Samba File Server

Install Packages

sudo apt update
sudo apt install samba winbind libpam-winbind libnss-winbind -y
PackagePurpose
sambaThe file sharing server โ€” implements the SMB protocol
winbindBridges Linux and AD โ€” resolves domain users/groups, handles auth
libpam-winbindAllows PAM (login system) to authenticate via winbind
libnss-winbindAllows NSS (name service) to look up AD users with getent

Configure /etc/samba/smb.conf

First back up the original:

sudo cp /etc/samba/smb.conf /etc/samba/smb.conf.bak

Edit the [global] section only โ€” do not delete the rest of the file:

sudo nano /etc/samba/smb.conf
[global]
    workgroup = SDWIN                       # NetBIOS name (no .LOCAL)
    realm = SDWIN.LOCAL                     # Full Kerberos realm (uppercase)
    security = ADS                          # Use Active Directory for auth
    winbind use default domain = yes         # Allow 'username' not 'SDWIN\username'
    winbind offline logon = no               # Don't cache credentials offline
    log file = /var/log/samba/log.%m
    logging = file
    max log size = 1000
    panic action = /usr/share/samba/panic-action %d
    template shell = /bin/bash               # Shell for AD users on Linux
    template homedir = /home/%U              # Home dir template for AD users
    idmap config * : backend = tdb          # Simple consistent mapping (not autorid)
    idmap config * : range = 0-999999       # ID pool for non-SDWIN objects
    idmap config SDWIN : backend = rid      # Derive UID from Windows RID
    idmap config SDWIN : range = 1000000-1999999  # Must not overlap * range
โš ๏ธ security = ADS is essential

This is what makes Ubuntu a domain member. Without it (e.g. security = USER), Samba runs standalone and net ads join will fail saying "not configured as member server".

Verify the config:

testparm
โœ… testparm should show: Server role: ROLE_DOMAIN_MEMBER

If it shows ROLE_STANDALONE, security = ADS is missing or wrong.

Join Ubuntu to the AD Domain

sudo net ads join -U Administrator

Enter the Administrator password. Successful output ends with:

Joined 'SD-UBUNTU' to dns domain 'SDWIN.LOCAL'

Verify the join:

sudo net ads testjoin
โš ๏ธ Common join failures

If join fails with "This operation is only allowed for the PDC": security = ADS is missing.

If it fails with Kerberos errors: fix time sync first (sudo ntpdate 192.168.122.100).

Configure NSSwitch

Tell Linux to use winbind when looking up users and groups:

sudo nano /etc/nsswitch.conf
# Before:
passwd: files systemd
group:  files systemd

# After:
passwd: files systemd winbind
group:  files systemd winbind
โœ… Without this change

getent passwd and getent group will not return AD users/groups even if winbind is working.

Start and Enable Services

sudo systemctl restart smbd nmbd winbind
sudo systemctl enable  smbd nmbd winbind

Verify AD users are now visible:

wbinfo -u                          # list all AD users
wbinfo -g                          # list all AD groups
wbinfo -i finance1                 # look up a specific user
getent passwd 'SDWIN\\finance1'    # resolve user via NSS

Create Shared Folders

sudo mkdir -p /srv/shares/finance
sudo mkdir -p /srv/shares/hr
sudo mkdir -p /srv/shares/it

Add share definitions to smb.conf after the [global] section:

[Finance]
    path = /srv/shares/finance
    browseable = yes
    read only = no
    valid users = @"SDWIN\\Finance"   # @ = group; only Finance members
    create mask = 0660               # new files: owner rw, group rw, others none
    directory mask = 0770            # new dirs: owner rwx, group rwx, others none

[HR]
    path = /srv/shares/hr
    browseable = yes
    read only = no
    valid users = @"SDWIN\\HR"
    create mask = 0660
    directory mask = 0770

[IT]
    path = /srv/shares/it
    browseable = yes
    read only = no
    valid users = @"SDWIN\\IT"
    create mask = 0660
    directory mask = 0770

Set Folder Ownership and Permissions

# First find the correct GID for each AD group:
wbinfo --sid-to-gid $(wbinfo --name-to-sid 'SDWIN\Finance')
wbinfo --sid-to-gid $(wbinfo --name-to-sid 'SDWIN\HR')
wbinfo --sid-to-gid $(wbinfo --name-to-sid 'SDWIN\IT')

# Use the GID numbers returned above (example: 1001110, 1001111, 1001112)
sudo chown root:1001110 /srv/shares/finance
sudo chown root:1001111 /srv/shares/hr
sudo chown root:1001112 /srv/shares/it

sudo chmod 2770 /srv/shares/finance
sudo chmod 2770 /srv/shares/hr
sudo chmod 2770 /srv/shares/it

ls -la /srv/shares/    # verify ownership
โš ๏ธ The leading 2 in 2770 is setgid

It ensures any new file created inside the share inherits the group (Finance/HR/IT) automatically, so group permissions stay consistent.

sudo systemctl restart smbd nmbd winbind
testparm

Part 4 โ€” Kali Linux: Join Domain

Kali uses Samba/Winbind only (not realmd/sssd) for AD integration. This is appropriate for penetration testing environments.

Install Packages

sudo apt update
sudo apt install samba winbind libpam-winbind libnss-winbind krb5-user -y

When prompted for Kerberos realm, enter: SDWIN.LOCAL

Configure smb.conf on Kali

sudo nano /etc/samba/smb.conf
[global]
    workgroup = SDWIN
    realm = SDWIN.LOCAL
    security = ADS
    winbind use default domain = yes
    winbind offline logon = no
    template shell = /bin/bash
    template homedir = /home/%U
    idmap config * : backend = tdb
    idmap config * : range = 0-999999
    idmap config SDWIN : backend = rid
    idmap config SDWIN : range = 1000000-1999999
testparm  # should show ROLE_DOMAIN_MEMBER

Configure Kerberos on Kali

sudo nano /etc/krb5.conf
[libdefaults]
    default_realm = SDWIN.LOCAL
    dns_lookup_realm = false
    dns_lookup_kdc = true

Set DNS and Hostname on Kali

sudo nano /etc/resolv.conf
nameserver 192.168.122.100
search SDWIN.LOCAL
sudo hostnamectl set-hostname kali.SDWIN.LOCAL
sudo nano /etc/hosts
# Add: 192.168.122.x  kali.SDWIN.LOCAL  kali

Join Kali to the Domain

sudo net ads join -U Administrator
sudo net ads testjoin

Configure NSSwitch:

sudo nano /etc/nsswitch.conf
passwd: files systemd winbind
group:  files systemd winbind
sudo systemctl restart winbind
wbinfo -u   # verify AD users visible
wbinfo -g   # verify AD groups visible

Access Samba Shares from Kali (Without Joining Domain)

If you only want to test shares without joining, use smbclient directly:

# List all shares on the file server
smbclient -L //192.168.122.181 -U 'SDWIN\\finance1'

# Connect to Finance share
smbclient //192.168.122.181/Finance -U 'SDWIN\\finance1'

# Test a denied user โ€” should return NT_STATUS_ACCESS_DENIED
smbclient //192.168.122.181/Finance -U 'SDWIN\\hruser1'

Commands inside the smbclient prompt:

ls              # list files
put file.txt    # upload file
get file.txt    # download file
mkdir testdir   # create directory
exit            # quit

Query AD users from Kali using rpcclient (no domain join needed):

rpcclient -U 'SDWIN\\Administrator' 192.168.122.100

# Inside rpcclient prompt:
enumdomusers    # list all AD users
enumdomgroups   # list all AD groups

Part 5 โ€” Testing File Share Access

From Windows Client

Open File Explorer and navigate to:

\\192.168.122.181\Finance

Log in with a Finance group member (e.g. SDWIN\finance1). Access should be granted. Try with a user not in Finance โ€” access should be denied.

From Ubuntu (smbclient)

smbclient //192.168.122.181/Finance -U 'SDWIN\\finance1'

Verify AD Resolution on Ubuntu File Server

wbinfo -u                                  # list all AD users
wbinfo -g                                  # list all AD groups
wbinfo --user-groups finance1              # groups finance1 belongs to
wbinfo -i finance1                         # resolve user details
getent group  'SDWIN\\Finance'             # check Finance group members
getent passwd 'SDWIN\\finance1'            # resolve user to Linux UID
โš ๏ธ wbinfo -u returns "Error looking up domain users"

Winbind cannot reach the DC. Check: sudo systemctl status winbind and ping 192.168.122.100.

Part 6 โ€” Complete Teardown & Cleanup

Use this section to undo everything and start fresh. Follow in order.

Step 1 โ€” Remove Ubuntu from the AD Domain

sudo net ads leave -U Administrator
โš ๏ธ Never delete secrets.ldb when cleaning up

It holds the domain join credentials and winbind needs it to connect to the DC. If deleted, winbind will fail to start and you must rejoin with net ads join.

Step 2 โ€” Remove Samba Shares and Data

sudo rm -rf /srv/shares/finance
sudo rm -rf /srv/shares/hr
sudo rm -rf /srv/shares/it

Step 3 โ€” Restore Original smb.conf

sudo cp /etc/samba/smb.conf.bak /etc/samba/smb.conf

# Or wipe it entirely and reinstall samba for a clean default:
sudo apt purge samba winbind libpam-winbind libnss-winbind -y
sudo apt autoremove -y
sudo rm -rf /etc/samba /var/lib/samba /var/cache/samba

Step 4 โ€” Clear Samba Cache

sudo net cache flush

# Safe cache cleanup โ€” NEVER delete secrets.ldb:
sudo rm -f /var/lib/samba/winbindd_idmap.tdb
sudo rm -f /var/lib/samba/winbindd_cache.tdb

Step 5 โ€” Revert NSSwitch

Edit /etc/nsswitch.conf and remove winbind:

passwd: files systemd
group:  files systemd

Step 6 โ€” Revert Hostname (optional)

sudo hostnamectl set-hostname ubuntu-server
sudo nano /etc/hosts   # remove the SDWIN.LOCAL lines

Step 7 โ€” Stop and Disable Services

sudo systemctl stop    smbd nmbd winbind
sudo systemctl disable smbd nmbd winbind

Reinstall Fresh (to redo from scratch)

sudo apt update
sudo apt install samba winbind libpam-winbind libnss-winbind -y
# Now follow Part 3 again from the beginning

Troubleshooting Reference

Error / SymptomFix
ROLE_STANDALONE in testparm security = ADS is missing or set to USER in [global]
Only allowed for PDC of domain security = ADS missing. Ubuntu thinks it's a DC, not a member.
NT_STATUS_ACCESS_DENIED despite correct group GID mismatch from old autorid mappings. Run wbinfo --sid-to-gid $(wbinfo --name-to-sid 'SDWIN\\Finance') to get correct GID and use it directly with chown.
wbinfo -u: Error looking up domain users Winbind can't reach DC. Check: systemctl status winbind, ping 192.168.122.100
net ads join: Kerberos error Clock difference > 5 min. Run: sudo ntpdate 192.168.122.100
net ads join: Join not valid Domain left or machine account deleted in AD. Rejoin with net ads join.
idmap tdb vs autorid confusion Use tdb not autorid as the * backend. autorid causes GID inconsistency. Also check spelling: tdb not tbd.
winbind.service: exit-code failure Run: sudo winbindd -F -S to see the actual error message
DNS update failed on join /etc/hosts FQDN not listed first, or hostname not set to FQDN
Unidentified Network on Windows No gateway set on Windows NIC, or VM on wrong virtual network