Hi people, in this article I'm going to show how to join a GNU/Linux machine, specifically a Debian one, to an Active Directory environment.I know, I know, Active Directory (AD) is a commercial tool from the evil Microsoft, but we need to admit that is the most used tool in the market.
However, not because we are in a Microsoft environment we need to use Windows, even if that's what they would like. So, in this post I'm going to describe how GNU/Linux can be joined to Active Directory. Same principles should be applied when using other directory services, like FreeIPA or a pure LDAP service.
I would like you to note that I'm going to use examples from my lab domain, so you will need to adapt them in order to your environment. This is my data:
-
Domain:
dev.lab
-
Domain Administrator:
Administrator
-
Domain Controller:
dc01.dev.lab
-192.168.122.135
Once we are aware of this, let's go to the topic.
Resolving domain with DNS
First thing on the list is to be able to resolve our domain by using DNS. Therefore, our easier option is to establish as DNS server our Domain Controller (DC), which is the machine were the directory database is stored and the one that provides the services for the directory, like DNS.
There can be several Domain Controllers in an Active Directory environment, but pick one of them as our DNS server is enough. Maybe two in case you want a backup DNS server.
My DC IP is 192.168.122.135
. First, I want check that I have conectivity to
it, with a ping command (in case we want to be extrasure, we can use netcat or
nmap to check we can reach the 53/UDP port, used by DNS):
$ ping -c4 192.168.122.135
PING 192.168.122.135 (192.168.122.135) 56(84) bytes of data.
64 bytes from 192.168.122.135: icmp_seq=1 ttl=128 time=0.645 ms
64 bytes from 192.168.122.135: icmp_seq=2 ttl=128 time=0.600 ms
64 bytes from 192.168.122.135: icmp_seq=3 ttl=128 time=0.563 ms
64 bytes from 192.168.122.135: icmp_seq=4 ttl=128 time=0.659 ms
--- 192.168.122.135 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3061ms
rtt min/avg/max/mdev = 0.563/0.616/0.659/0.037 ms
Once we are sure we can connect, we must add the DC as DNS server. In my case I'm going to add it to the /etc/dhcp/dhclient.conf file so dhclient will include it into /etc/resolv.conf, which is the file used by GNU/Linux (specifically by the libc) to retrieve the DNS servers.
Maybe in your case
dhclient
is not on charge of DNS configuration, so you need to discover which program is. The usual alternatives are NetworkManager and systemd-resolved. You can check our article Who is messing with my DNS? to properly configure your DNS.
The commands to add my DC as DNS server would be the following:
$ echo "prepend domain-name-servers 192.168.122.135;" | sudo tee -a /etc/dhcp/dhclient.conf
prepend domain-name-servers 192.168.122.135;
Besides in order to make easier to find domain machines, I want that when I specified a hostname, it is searched inside my domain. Therefore, I'm going to add my domain as the default to search for in case I introduce a machine name without the domain part:
$ echo 'prepend domain-search "dev.lab";' | sudo tee -a /etc/dhcp/dhclient.conf
prepend domain-search "dev.lab";
And finally we restart the service so the new configuration is applied:
$ sudo systemctl restart ifup@enp1s0.service
Be aware the ifup
service, that spawns dhclient
, is given the network
interface as a parameter, which is enp1s0
in my case, but it may differ in
your machine.
Next, we can try to resolve our domain to be sure our DC was properly included as DNS server:
$ cat /etc/resolv.conf
search dev.lab.
nameserver 192.168.122.135
nameserver 192.168.122.1
$ host dev.lab
dev.lab has address 192.168.122.135
We also check that the domain machine names is resolved even if we don't specify the domain part:
$ host dc01.dev.lab
dc01.dev.lab has address 192.168.122.135
$ host dc01
dc01.dev.lab has address 192.168.122.135
A bit of theory: The connection components
Now we got conectivity with the domain, we need to install all the libraries and tools that implement the different protocols that allow our machine to interact with the Domain Controllers.
However, before install them, I would like to share a bit of theory, so we can understand the different parts that are involved in the Active Directory integration.
Active Directory protocols
DNS
We already mess with this one. DNS (Domain Name System) is a very important protocol used to get the IPs of the domain machines. For our domain, the main DNS authority are the Domain Controllers.
Any tool we use will resolve the DNS names without us to worry about it, but in case we want to explicitly get the IP of a machine, we can use utilities like host, nslookup or dig:
$ host dc01.dev.lab
dc01.dev.lab has address 192.168.122.135
Kerberos
Kerberos is an protocol for remote authentication. It is based in tokens called tickets, that the Domain Controller dispenses when an user authenticates with her username and password. Afterwards, tickets can be presented to other domain machines in order to authenticate the user.
There are two tickets types:
-
TGT (Ticket Granting Ticket): Is the ticket returned to an user when she authenticates with her username and password against the Domain Controller. It can be used to ask for tickets for the services, known as ST, without typing the password again.
.---. _____ / /| | | >----Username and password---> .---. | |_____| | | ' /:::::/ <--------------TGT-----------< | |/ client '---' DC
-
ST (Service Ticket): Is a ticket for an specific service, like SMB (also known as CIFS) or LDAP. The ST is retrieved from the Domain Controller when a TGT is presented.
.---. _____ / /| | | >----------TGT---------> .---. | |_____| | | ' /:::::/ <------ST for CIFS-----< | |/ client '---' ^ v DC | | | | .---. | '-----ST for CIFS------> / /| | .---. | '-------shared folder-----< | | ' | |/ '---' SMB/CIFS server
Tickets are used to avoid users being constantly asked by their passwords, which can be annoying, every time a new connection to a machine is made. Besides, tickets can include security information for the upper protocols like as if they must sign or encrypt the messages. Lastly, tickets can also include information about the users, such as the user groups, in a struct known as PAC (Privilege Attribute Certificate).
Kerberos is protocol that is well integrated with other protocolos as SMB or
LDAP, so is not usual to directly interact with it. However, the Debian
krb5-user
package includes several tools to request and list our current
tickets, as in the following example:
$ klist
Ticket cache: FILE:/tmp/krb5cc_1190600500_fwQbdO
Default principal: Administrator@DEV.LAB
Valid starting Expires Service principal
08/22/2024 20:32:19 08/23/2024 06:32:19 krbtgt/DEV.LAB@DEV.LAB
renew until 08/23/2024 20:32:19
08/22/2024 20:32:20 08/23/2024 06:32:19 cifs/dc01.dev.lab@
renew until 08/23/2024 20:32:19
Ticket server: cifs/dc01.dev.lab@DEV.LAB
In this case we can observe two tickets, the one for krbtgt/DEV.LAB@DEV.LAB
which allow us to know that is a TGT, and the one for cifs/dc01.dev.lab
that
we know is for the SMB/CIFS service which allows an user to access shared
folders in the remote system. Knowing the tickets in our current session can
useful for troubleshooting.
LDAP
LDAP is a commonly used protocol in directory services. It allows to query the directory database so you can retrieve and modify the entities, like users or computers. You may think of LDAP as the SQL of directory services.
In the specific case of Active Directory, LDAP uses Kerberos under the hood to authenticate users when a new connection with the Domain Controller is established.
The open source implementation of LDAP is OpenLDAP, which is included in the
libldap-<version>
package, which is a dependency for many other packages
related with the protocol. In addition, if we want to query the directory
database, we can use tools like ldapsearch
from the ldap-utils
package.
Here is an example of domain computers enumeration:
$ ldapsearch -H ldap://dc01.dev.lab -b 'DC=dev,DC=lab' '(objectClass=computer)' name 2>/dev/null | grep name:
name: DC01
name: DEBIAN12
Samba/SMB
Samba is the free implementation of SMB, which is a common protocol to share folders in Windows environments, including Active Directory.
Apart from SMB, it is common to use the name CIFS to refer to the same protocol, even if CIFS was a previous protocol of SMB (same situation as SSL and TLS). Actually, the SMB service of Active Directory is called CIFS.
As I mentioned previously, SMB uses Kerberos under the hood as authentication protocol, and in the same way as LDAP, it sends a ticket when a new connection is established with the target server.
In the case of Debian, the samba-tools
package contains the required tools and
libraries to communicate with SMB as a client. For instance, we can use
smbclient
to list shared folders in servers of a domain:
$ smbclient --use-krb5-ccache=$KRB5CCNAME -L dc01.dev.lab
Sharename Type Comment
--------- ---- -------
ADMIN$ Disk Remote Admin
C$ Disk Default share
IPC$ IPC Remote IPC
NETLOGON Disk Logon server share
SYSVOL Disk Logon server share
SMB1 disabled -- no workgroup available
Tools for GNU/Linux integration in Active Directory
Once we have seen the protocols, lets review some key tools and components for integrating GNU/Linux in Active Directory.
PAM
PAM (Pluggable Authentication Modules) is a set of GNU/Linux libraries that allows to integrate several authentication mechanisms. Programs that require authenticate system users, like SSH or login, can use PAM to benefit from all these authentication mechanisms, like passwords, pins, certificates, etc, with little effort.
Curiosity: SSH keys are not part of PAM, but an authentication mechanism of SSH itself.
PAM allows both local authentication, like checking passwords in /etc/shadow, and remote authentication, by using protocols like Kerberos (through sssd as we will see later).
Besides, PAM also allow other actions like changing user passwords, setting the environment variables or mounting user directory when a user logs in.
We can check the files in the /etc/pam.d
folder to see what PAM modules are
being used.
NSS
NSS (Name Service Switch) is a mechanism used in GNU/Linux to know where to find the information related to different system items, like users or domain names. In this regard the configuration file /etc/nsswitch.conf is used as reference.
For example, when an application wants to get information about an user, nsswitch is read to know what are the data sources, like the /etc/passwd local file or the sssd service.
$ cat /etc/nsswitch.conf | grep passwd
passwd: files systemd sss
Another common case are the domain names, where nsswitch indicates that information must be retrieved first from /etc/hosts, and if it is missed in the file, from a DNS requests.
$ cat /etc/nsswitch.conf | grep hosts
hosts: files dns
sssd
sssd (System Security Services Daemon) is like the glue that joins all the previously discussed protocols and programs, since it is a tool that uses many libraries to interact with directory services like Active Directory or FreeIPA, allowing their integration with PAM and NSS.
The integration would be something like this:
+-----------+ +---------------+ .--> | Samba/SMB | | PAM - pam_sss | ----. | +-----------+ +---------------+ | | v | | '------------. | | v | +------+ | +----------+ |--> | sssd | ---|--------------> | Kerberos | | +------+ | +----------+ | | ^ | | .-------------' +------------------+ | | ^ | NSS - libnss_sss | -' | +------+ +------------------+ '--> | LDAP | +------+
Joining the machine to the domain
In order to join the machine to the domain we can use the realm program, which configures sssd so we can use it to authenticate domain users.
Here is a summary of the packages we are going to install, so we can understand the purpose of each one:
-
sssd
: Installs the sssd daemon and the required modules to communicate with directory services. -
sssd-tools
: Installs the tools to control sssd, like sssctl. -
libnss-sss
: Installs the NSS library that allows the communication with sssd. -
libpam-sss
: Installs the PAM library that allows the communication with sssd. -
adcli
: Allows to join the machine to the domain. -
realmd
: Allows to join the machine to the domain by using adcli and sets the sssd configuration. -
pakcagekit
: Tool used by realmd to manage packages.
In order to install the packages we execute the following:
sudo apt update && sudo apt install -y sssd sssd-tools adcli libnss-sss libpam-sss realmd packagekit
Once the packages are installed, we can continue and join our machine to the domain. We can do this with any domain user or just with administrator accounts depending on the domain configuration. In my case I will do it with my Administrator account:
sudo realm join --user=Administrator dev.lab
If everything goes well the command should only ask for the user password and no
more output should be produced. Afterwards, we can verify we have joined the
domain with sssctl
or realm
:
$ sudo sssctl domain-list
dev.lab
$ sudo realm list
dev.lab
type: kerberos
realm-name: DEV.LAB
domain-name: dev.lab
configured: kerberos-member
server-software: active-directory
client-software: sssd
required-package: sssd-tools
required-package: sssd
required-package: libnss-sss
required-package: libpam-sss
required-package: adcli
required-package: samba-common-bin
login-formats: %U@dev.lab
login-policy: allow-realm-logins
Then we need to configure PAM to use sssd as a mechanism to authenticate
users. We need to execute pam-auth-update
and select "SSS
authentication". Besides, if we want to create a home directory for domain
users, we also need to select "Create home directory on login":
$ sudo pam-auth-update
Our configuration should be something like this:

When this is done we should be able to login with domain users in our machine. We can test this with SSH:
$ ssh Administrator@dev.lab@lab-debian12
Administrator@dev.lab@192.168.122.165's password:
Linux debian12-base 6.1.0-23-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.99-1 (2024-07-15) x86_64
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Sun Aug 18 17:48:53 2024 from 192.168.122.137
administrator@dev.lab@lab-debian12:~$
And we finally can login with domain users!! This should be enough for the most basic environments, but you can keep reading since I'm going to configure a few more things.
Authentication with the domain username, without the domain
A very comfortable thing we can do is to configure sssd so we don't need to specify the domain when we login with a domain user. So instead of writing "Administrator@dev.lab" we can just type "Administrator". In case of using SSH, instead of using the following form:
$ ssh Administrator@dev.lab@lab-debian12
We could use just the username:
$ ssh Administrator@lab-debian12
In order to do this we must configure sssd to use the domain as suffix for the
users. We can do this adding a default_domain_suffix
statement in
/etc/sssd/sssd.conf
like the next:
$ sudo head -6 /etc/sssd/sssd.conf
[sssd]
domains = dev.lab
config_file_version = 2
services = nss, pam
default_domain_suffix = dev.lab
Then we restart sssd
:
sudo systemctl restart sssd
And now we should be able to login by only specifying the username:
$ ssh Administrator@lab-debian12
Administrator@192.168.122.165's password:
Linux debian12-base 6.1.0-23-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.99-1 (2024-07-15) x86_64
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Sun Aug 18 18:07:39 2024 from 192.168.122.137
administrator@dev.lab@lab-debian12:~$
Perfect!! Now we can afford 2 seconds of typing and use as we wish. Not much, but it's a start.
Integrating domain groups with sudo
Another interesting thing is to use sudo with domain users. I would like to replicate the "Domain Admins" group behavior in Windows machine, where those are included as local administrators. In GNU/Linux to achieve a similar effect we can grant sudo to the "Domain Admins" group.
In order to do this we can add a rule like the following in /etc/sudoers
:
$ sudo cat /etc/sudoers | grep domain
"%domain admins@dev.lab" ALL=(ALL) ALL
Once this rule is added, we should be able to execute sudo
with the
Administrator
user:
administrator@dev.lab@lab-debian12:~$ sudo id
uid=0(root) gid=0(root) groups=0(root)
Another way to get the sudo rules, in addition to read /etc/sudoers
, is to
retrieve them from the Domain Controller. This process is carried by sssd so we
need to install the libsss-sudo
package:
sudo apt update && sudo apt install -y libsss-sudo
After the installation we can see that /etc/nsswitch.conf
file shows sss as a
provider for sudoers:
$ cat /etc/nsswitch.conf | grep sudoers
sudoers: files sss
On the other hand, we have to configure sssd
so it uses the sudo module. We
can do this by adding sudo
into the services
statement of
/etc/sssd/sssd.conf
.
$ sudo cat /etc/sssd/sssd.conf | grep services
services = nss, pam, sudo
By using this configuration sssd
will look for sudo rules in Active Directory
database (with LDAP). Therefore, the rules you want to introduce into sudo must
be written into Active Directory database, but how to do that is out of this
article scope. However you can check the following post to do it (I didn't
tested it):
Conclusion
In this article we have seen how to connect a Debian machine to an Active Directory environment. I hope you found it useful.
See you!!
References
-
Pierre Blazquez. "How-To: Join Debian 12 to an Active Directory Domain". Pierre Blazquez blog, 02 Feb, 2024, https://www.pierreblazquez.com/2024/02/04/how-to-join-debian-12-to-an-active-directory-domain/
-
noobient. "Integrating Ubuntu with Active Directory". noobient blog, 02 Nov, 2015, https://noobient.com/2015/11/02/integrating-ubuntu-with-active-directory/
-
Matei Cezar. "Integrate Ubuntu to Samba4 AD DC with SSSD and Realm – Part 15". Tecmint, 27 Nov, 2017, https://www.tecmint.com/integrate-ubuntu-to-samba4-ad-dc-with-sssd-and-realm/