FreeRADIUS Active Directory Integration with NTLM-MSCHAP

We must install and configure Active Directory and DNS server in Windows 2008 or Wındows 2012 server. In my environment I used windows 2008 R2.

AD (Active Directory) and DNS: VELO.LAN
AD hostname: DC.VELO.LAN
AD IP address:


For example you can use topology as below:

In FreeBSD we will give the hostname as subdomain of our Domain Controller and add this to startup file.

# echo 'hostname="FREERADIUS.VELO.LAN"' >> /etc/rc.conf

Synchronizing date/time from our AD server and add AD IP as our nameserver.

# ntpdate
# echo 'search VELO.LAN' > /etc/resolv.conf
# echo "nameserver" >> /etc/resolv.conf

For name resolves our server we can add hostname our server to /etc/hosts file or add A record as subdomain in AD. But I used in /etc/hosts file:

# echo " FREERADIUS.VELO.LAN FREERADIUS" >> /etc/hosts

From internal needs add lines to our kernel file:

# echo "kern.maxfiles=25600" >> /etc/sysctl.conf
# echo "kern.maxfilesperproc=16384" >> /etc/sysctl.conf
# echo "net.inet.tcp.sendspace=65536" >> /etc/sysctl.conf
# echo "net.inet.tcp.recvspace=65536" >> /etc/sysctl.conf
# /etc/rc.d/sysctl restart

Updating FreeBSD package repository and install samba41:

# pkg update
# pkg install samba41
# rehash

Create /etc/krb5.conf file and add lines below(Note: Change VELO.LAN to your domain name):

# ee /etc/krb5.conf
default_realm = VELO.LAN
dns_lookup_realm = true
dns_lookup_kdc = true
ticket_lifetime = 24h
renew_lifetime = 7d
forwardable = yes

Edit group: and passwd: lines in /etc/nsswitch.conf file as below(This is priority for name resolution in operation system):

group: files winbind
passwd: files winbind

Create the /usr/local/etc/smb4.conf file and add lines below. Please note the names VELO and VELO.LAN you must be change this to your own names:

workgroup = VELO
server string = Samba Server Version %v
security = ads
realm = VELO.LAN
domain master = no
local master = no
preferred master = no
use sendfile = true

idmap config * : backend = tdb
idmap config * : range = 100000-299999
idmap config VELO : backend = rid
idmap config VELO : range = 10000-99999
winbind separator = +
winbind enum users = yes
winbind enum groups = yes
winbind use default domain = yes
winbind nested groups = yes
winbind refresh tickets = yes
template homedir = /home/%D/%U
template shell = /bin/false

Join our server to VELO.LAN domain controller. For test purpose I used Administrator account but, you must use different account with minimal restrictions:

# net ads join -U administrator
Enter administrator's password: ******
Using short domain name -- VELO
Joined 'FREERADIUS' to dns domain 'VELO.LAN'

Check your connection. The answer must be “Join is OK”.

# net ads testjoin

Add samba daemon to startup file and start:

# echo 'samba_server_enable="YES"' >> /etc/rc.conf
# echo 'winbindd_enable="YES"' >> /etc/rc.conf
# echo 'smbd_enable="YES"' >> /etc/rc.conf
# echo 'nmbd_enable="YES"' >> /etc/rc.conf
# service samba_server start

For login to domain controller we need to get ticket with kerberos(Write password for Administrator account from Domain Controller):

# kinit administrator
administrator@VELO.LAN's Password:******

Check your ticket:

# klist
Credentials cache: FILE:/tmp/krb5cc_0
Principal: administrator@VELO.LAN

Issued Expires Principal
May 5 10:33:43 2015 May 5 20:33:43 2015 krbtgt/VELO.LAN@VELO.LAN

After that checking winbind
Command output must show users from domain controller.

# wbinfo –u

Command output must show groups from domain controller.

# wbinfo –g

You can check any of domain users from console with syntax below(if credentials is right the output must be succeeded):

# wbinfo -a username%paassword
plaintext password authentication succeeded
challenge/response password authentication succeeded

restart samba daemon again:

# service samba_server restart

After successfully connection to domain controller, we must integrate FreeRADIUS to domain controller with NTLM(NT Lan Manager) module.

Note: The difference between NTLM and LDAP module is NTLM supports MSCHAP,EAP(more
secure), PAP but, LDAP supports pap method.

Install FreeRADIUS2.2 from repositories and rehash binary path.

# pkg install freeradius
# rehash

Checking connection with NTLM. Write domain admin password(if output will be so NT_STATUS_OK: Success (0x0), then NTLM module is working):

# ntlm_auth --request-nt-key --username=administrator

Going to FreeRADIUS configuration folder:

# cd /usr/local/etc/raddb/

Open MSCHAP configuration module and find line /path/to/ntlm_auth. Remove comment symbol “#” and write full path to binary ntlm_auth file. For full path to ntlm_auth file you can use command below:

# whereis ntlm_auth
ntlm_auth: /usr/local/bin/ntlm_auth

Open configration file for mschap module and changing path for path which found before(Note: Don’t touch other configurations)

# ee modules/mschap
ntlm_auth = "/usr/local/bin/ntlm_auth --request-nt-key --username=%{%{Stripped-User-Name}:-%{%{User-Name}:-None}} --challenge=%{%{mschap:Challenge}:-00} --nt-response=%{%{mschap:NT-Response}:-00}"

For test purpose open 2 SSH console.
In the first console sreeen. Starting FreeRADIUS with debug mode. You must see lines below(Just wait):

# radiusd –fX
Sending Access-Accept of id 198 to port 56224
MS-CHAP-MPPE-Keys = 0x0000000000000000f1eef4a31ec3792beebab6d25e82b72a0000000000000000
MS-MPPE-Encryption-Policy = 0x00000001
MS-MPPE-Encryption-Types = 0x00000006
Finished request 0.
Going to the next request
Waking up in 4.9 seconds.
Cleaning up request 0 ID 198 with timestamp +4
Ready to process requests.

In the second console page try connect with username, which have got from domain controller(I used jamal). The syntax must be as below. If you will see Access-Accept it means this is working:
radtest username “password” freeradius-server-ip 10 pre-shared-secret-key

# radtest -t mschap jamal "C123456789c" localhost 0 testing123
Sending Access-Request of id 33 to port 1812
User-Name = "jamal"
NAS-IP-Address =
NAS-Port = 0
Message-Authenticator = 0x00000000000000000000000000000000
MS-CHAP-Challenge = 0x106f51f972e17124
MS-CHAP-Response = 0x000100000000000000000000000000000000000000000000000024c9483ba63f967effa5e499715e679c5d1f0f942a36420b
rad_recv: Access-Accept packet from host port 1812, id=33, length=84
MS-CHAP-MPPE-Keys = 0x0000000000000000f1eef4a31ec3792beebab6d25e82b72a0000000000000000
MS-MPPE-Encryption-Policy = 0x00000001
MS-MPPE-Encryption-Types = 0x00000006

In the first console page the output must be so:

Found Auth-Type = MSCHAP
# Executing group from file /usr/local/etc/raddb/sites-enabled/default
+group MS-CHAP {
[mschap] Client is using MS-CHAPv1 with NT-Password
[mschap] expand: %{Stripped-User-Name} ->
[mschap] ... expanding second conditional
[mschap] expand: %{User-Name} -> camal
[mschap] expand: %{%{User-Name}:-None} -> jamal
[mschap] expand: --username=%{%{Stripped-User-Name}:-%{%{User-Name}:-None}} -> --username=jamal
[mschap] mschap1: 58
[mschap] expand: %{mschap:Challenge} -> 5872c80af597f400
[mschap] expand: --challenge=%{%{mschap:Challenge}:-00} -> --challenge=5872c80af597f400
[mschap] expand: %{mschap:NT-Response} -> bd785869e3086f6f8af55af3ac177b59e925e2a8bafe1f9f
[mschap] expand: --nt-response=%{%{mschap:NT-Response}:-00} -> --nt-response=bd785869e3086f6f8af55af3ac177b59e925e2a8bafe1f9f
Exec output: NT_KEY: F1EEF4A31EC3792BEEBAB6D25E82B72A
Exec plaintext: NT_KEY: F1EEF4A31EC3792BEEBAB6D25E82B72A
[mschap] Exec: program returned: 0
[mschap] adding MS-CHAPv1 MPPE keys
++[mschap] = ok
+} # group MS-CHAP = ok
# Executing section post-auth from file /usr/local/etc/raddb/sites-enabled/default
+group post-auth {
++[exec] = noop
+} # group post-auth = noop
Sending Access-Accept of id 133 to port 38369
MS-CHAP-MPPE-Keys = 0x0000000000000000f1eef4a31ec3792beebab6d25e82b72a0000000000000000
MS-MPPE-Encryption-Policy = 0x00000001
MS-MPPE-Encryption-Types = 0x00000006
Finished request 3.
Going to the next request
Waking up in 4.9 seconds.
Cleaning up request 3 ID 133 with timestamp +295
Ready to process requests.

After successfully tests we must send interrupt signal to FreeRADIUS debug mode with Ctrl+C commmand, then add daemon to startup file as below:

# echo 'radiusd_enable="YES"' >> /etc/rc.conf
# service radiusd start