Showing results for 
Search instead for 
Did you mean: 
Login & Join the DevCentral Connects Group to watch the Recorded LiveStream (May 12) on Basic iControl Security - show notes included.

Mixed APM authentication


Hi Folks,


I'm tasked to create a unified APM Policy which is able to support the authentication methods below.


  • Forms (For Browsers)
  • Negotiate via Kerberos-Ticket (for Kerberos enabled clients)
  • Negotiate via NTLM (Fallback if Kerberos-Ticket can not obtained)
  • NTLM (Fallback for Negotiate unaware clients)
  • Basic (Fallback of last resort)


Performing selectively Forms, Negotiate via Kerberos, NTLM and Basic can be easily adopted reading available information. But "Negotiate via NTLMSSP" is somehow not supported by F5, or at least I cant find any information how to teach APM or ECA to consume negotiated NTLMSSP messages.


Before I start to develop a solution by myself, I would like to ask if someone has already a working iRule to support "Negotiate via NTLM" authentication as a fallback in the case the client is unable to provide Kerberos-Tickets (e.g. client is not domain joined, local useraccount is used, DC is not reachable, SPN does not exist, etc.)?


Cheers, Kai




Seems I've found a good enough solution...


A rather simple "Authorization" and "WWW-Authentication" header rewrite is able to transform and steer Negotiate-NTLMSSP authentication towards ECA in the case the client was unable to perform a Negotiate-Kerberos authentication.


The iRule below outlines what I did and can be used to extend an existing Negotiate-Kerberos enabled APM policy to support Negotiate-NTMLSSP as a fallback.

when HTTP_REQUEST { # if { $debug } { log -noname local0. "$log_prefix Checking if a Negotiate authentication was send by the client." } if { not [string match -nocase "negotiate*" [HTTP::header value Authorization]] } then { # if { $debug } { log -noname local0.debug "$log_prefix The request does not contain a Negotiate authentication header. Sending 401 response to the client to ask for credentials." }   HTTP::respond 401 \ content "Authentication required" \ noserver \ "WWW-Authenticate" "Negotiate" } elseif { [string match -nocase "negotiate tlrmtvnt*" [HTTP::header value Authorization]] } then { # if { $debug } { log -noname local0. "$log_prefix The client has send a Negotiate-NTLMSSP message. Transform the Negotiate-NTLMSSP message into a classic NTLM message." } HTTP::header replace Authorization "NTLM[string range [HTTP::header value Authorization] 9 end]" # if { $debug } { log -noname local0. "$log_prefix Enable ECA and assign NTLM auth configuration profile to pre-authenticate the NTLM authentication." } ECA::enable ECA::select select_ntlm:/Common/NTLM_ITACS } else { # if { $debug } { log -noname local0. "$log_prefix The client has send a Negotiate-Kerberos message. Passing the message directly to APM policy agent." } } # if { $debug } { log -noname local0. "$log_prefix Insert clientless-mode HTTP header to deactivate APM logon pages." } HTTP::header insert "clientless-mode" 1 } when HTTP_RESPONSE_RELEASE { # if { $debug } { log -noname local0. "$log_prefix Checking if a NTLM message was send to the client." } if { [string match -nocase "ntlm tlrmtvnt*" [HTTP::header value "WWW-Authenticate"]] } then { # if { $debug } { log -noname local0. "$log_prefix A NTLM message was send to the client. Transform the classic NTLM message into a Negotiate-NTLMSSP message." } HTTP::header replace "WWW-Authenticate" "Negotiate[string range [HTTP::header value "WWW-Authenticate"] 4 end]" } }

The required change to the APM policy is as simple as it could be. Just put a "NTLM Auth Result" action in front of the existing "HTTP 401 Response" / "Kerberos Auth" actions and connect them via the "fallback" branch of "NTLM Auth Result". 


Also keep in mind to add the ECA profile to your Virtual Server and tweak the iRule to match the name of your NTLM auth configuration... 😉


Cheers, Kai