Configuring APM Client Side NTLM Authentication
Introduction There have been a ton of requests on the boards for a simplified client side NTLM configuration, so based on Michael Koyfman’s excellent Leveraging BIG-IP APM for seamless client NTLM Authentication, I’ve put together this article to show the very basic requirements for setting up APM client side NTLM authentication. So why APM client side NTLM? Like Kerberos, NTLM can provide seamless (i.e.. transparent) logon for local clients. It’s arguably not as secure as Kerberos as authentication protocols go, but if you’ve ever worked with Kerberos, you’ll likely appreciate that NTLM is simpler and a bit more flexible. APM’s client side NTLM authentication is also considerably different than the other client side methods that generally include visual policy authentication agents and a AAA configuration. This difference allows client side NTLM to be enabled and disabled per request as needed by Microsoft Exchange and Secure Web Gateway access features. APM’s client side NTLM is controlled by a feature called ECA, or External Client Authentication. Let’s jump right in and look at how ECA is used to configure NTLM. There have been some changes to the way client side NTLM functions between APM versions, so this article will focus on 11.6. Configuration Step 1: Create a virtual server It may seem counter-intuitive to create the virtual server first, but you’ll need it in step 5 below. Nothing fancy here, just create a standard virtual server and assign an HTTP profile and pool. Of course if you’re offloading SSL (which you should be) also include a client SSL profile. Step 2: Configure system DNS APM needs to be able to resolve the Active Directory domain controller(s), so you’ll need to specify the DNS for the domain. In the BIG-IP management GUI, navigate to System -> Configuration -> Device -> DNS. In the DNS Lookup Server List section, add the IP address of any AD DNS server(s). You can do the same in the TM shell as follows: tmsh modify sys dns name-servers replace-all-with { [IP address of DC DNS server] } Step 3: Create an Active Directory NTLM machine account This step creates a computer account in the Active Directory that APM will use to validate the NTLM tokens from clients. This machine account will be used in a pass-through authentication capacity. Please see the following Microsoft article for more information on NTLM Pass-Through Authentication. In the BIG-IP management GUI, navigate to Access Policy -> Access Profiles -> NTLM -> Machine Account. Click the Create button. At a minimum you need an arbitrary profile object name, the name of the computer account to create (it must not already exists), the domain FQDN (the DCs will be resolved via DNS SRV queries), and the credentials of a user with privileges to create computer accounts. To specify a single domain controller, enter that DC’s FQDN into the Domain Controller FQDN field. Click the Join button to proceed. You can do the same in the TM shell as follows: tmsh create apm ntlm machine-account [profile object name] domain-fqdn [domain FQDN] machine-account-name [new machine account name] administrator-name [admin name] administrator-password ["admin password"] If the command is successful you’ll see a new computer account in the Active Directory. Step 4: Create an NTLM Auth Configuration Now let’s add that computer account object to an NTLM Auth configuration. In the BIG-IP management GUI, navigate to Access Policy -> Access Profiles -> NTLM -> NTLM Auth Configuration. Click the Create button. Give it an arbitrary object profile name and specify the previously-created machine account name. Add the FQDN for a domain controller to the Domain Controller FQDN List field. Note: You must add at least one domain controller here. If you don’t specify anything, users will be allowed access without any NTLM token validation. In some APM versions the Domain Controller FQDN List field displays as mandatory and in others optional. In all cases it is absolutely required. Click the finished button to proceed. You can do the same in the TM shell as follows: tmsh create apm ntlm ntlm-auth [profile object name] machine-account-name [machine account object name] Step 5: Enable the ECA profile for a specific virtual server Unlike the other APM client side authentication methods, there’s no GUI option to enable APM client side NTLM. To do that you need to apply the ECA profile to a virtual via the TM shell. tmsh modify ltm virtual [virtual server name] profiles add { eca } Step 6: Create an iRule to enable client side NTLM This is where all of the magic happens. Create this very simple iRule and apply it to your virtual server: when HTTP_REQUEST { ECA::enable ECA::select select_ntlm:/Common/my-ntlm-machine-auth } That’s it. You need to enable ECA and then specify the name of the NTLM Auth configuration object (created in step 4 above). I would also point out here that client side NTLM authentication is a bit different from Kerberos in that ECA is generally going to issue a 401 Unauthorized NTLM challenge on every new request. If this proves to add too much overhead, the following modification to the above iRule will allow NTLM to be processed once at the beginning of the session. The APM session cookie is used thereafter to maintain the session. when HTTP_REQUEST { if { [ACCESS::session data get session.ntlm.last.result] eq 1 } { ECA::disable } else { ECA::enable ECA::select select_ntlm:/Common/my-ntlm-machine-auth } } Step 7: Create an access profile Create a standard access profile and configure the visual policy like this: There’s nothing to configure inside the NTLM Auth Result agent so it’s just there to validate the returned session.ntlm.last.result session variable. Add this access profile to the virtual server. Step 8: Modify the client browser to support NTLM authentication By default modern browsers do not, for obvious security reasons, send credentials to any web site that asks for them, so you have to explicitly define what sites the browser can send credentials to. For Microsoft Internet Explorer that’s as simple as adding the site to the Local Intranet Sites list. In Internet Explorer, go to Tools -> Internet Options. Open the Security tab, select Local intranet and then click the Sites button. Now click the Advanced button. Add the APM virtual server’s URL here. You can specify the exact URL here (ex. https://ntlm-test.domain.com) or a wildcard (ex. *.domain.com) to cover everything under a given domain. This should also cover Chrome and Opera running in Windows. For Firefox, navigate to the config URL at about:config and type “trusted” in the Search field. You’ll see a short list of keys with the word “trusted” in them. Double click the “network.automatic-ntlm-auth.trusted-uris” key and add either the full FQDN of a specific APM virtual server (ex. ntlm-test.domain.com) or for an entire domain just the domain component itself (ex. .domain.com). Testing and Troubleshooting With your browser(s) configured, go ahead and test. If you get prompted for username and password, NTLM authentication has failed. Probably one of the best first things to do is to open a console (SSH) shell and tail the APM and LTM logs. In many cases the error will be screaming at you from one of these logs. # cd /var/log # tail –f ltm apm Here are some possible causes for client side NTLM authentication to fail: Your browser isn’t correctly configured to send credentials to this site: Review the browser’s security configurations. I mentioned earlier that IE’s Local intranet sites list must include the FQDN of the APM virtual server. Make sure you’re indeed using the Local intranet sites list and not one of the other sites lists. There is also another setting in IE that can cause issues. This setting is enabled by default, but you could be in an environment where it has been disabled by policy. Under the Security tab of IE’s Internet Options, click on the “Custom level…” button, scroll all the way to the bottom of that list and look for the “Automatic logon only in Intranet zone” option. This needs to be checked and is the reason why you add the APM virtual server to the Local intranet sites list. You’re not logged in as a domain member and/or your workstation is not domain joined: Check that you’re actually logged into the domain from a domain-joined workstation. APM can’t access the specified domain controller in the NTLM Auth config: You may see messages in the LTM log like “NT_STATUS_INVALID_COMPUTER_NAME”. This is indicating that APM cannot resolve the address of the domain controller specified in the NTLM Auth configuration. If the domain controller just isn’t available, you may see the “NT_STATUS_HOST_UNREACHABLE” error message. NTLM is not enabled or configured correctly in the Active Directory: You may see messages in the APM log like “NT_STATUS_NETWORK_ACCESS_DENIED” or “NT_STATUS_PIPE_NOT_AVAILABLE”. These are indication that there’s probably something wrong on the Windows domain controller side. You may want to take a look at local or domain group policy settings and NTLM event logs. Worst case the NTLM machine account is corrupt: If all else fails, delete and recreate the NTLM machine account. You’ll need to delete it in APM and in the domain. Wait for replication to finish if there are multiple DCs and you’re using the same machine name, or simply use a different machine name. Let’s now see what that client side NTLM authentication looks like on the wire. For this part I’m going to fire up WireShark and filter on “ntlmssp” The ECA profile is responsible for generating the 401 Unauthorized response to the client’s initial request. In that 401 response is the WWW-Authenticate header and NTLM challenge. If there’s something wrong you may also see error messages manifest in the Wireshark captures. Cross-domain Considerations Client side APM NTLM authentication natively works across domains if the domains are in a forest trust, external two-way trust, or external one-way outgoing trust. For non-trusting domains, since the NTLM Auth config profile is assigned first, there’s no native way to switch between profiles based on something in the client’s NTLM challenge response. If you can identify the clients by some other characteristic, a unique IP subnet for example, that might be an option. Expanding Possibilities Now that we have APM client side NTLM humming along, let’s look at some other things you can do with it. A successful client side NTLM authentication will produce a few interesting session values: session.logon.last.username – the APM session variable that contains the logged in username session.logon.last.domain – the APM session variable that contains the domain of the logged in user session.logon.last.machinename – the APM session variable that contains the logged in user’s workstation name These session variables can be used and evaluated inside the visual policy and in iRules. For example, let’s say you want to do an AD query with the username to see if the user is in a specific AD group: The ECA profile also creates three other values that can be used in iRules: ECA::status – the authentication status for that individual request. It’s usually either STATUS_SUCCESS or STATUS_ACCESS_DENIED ECA::username – the same information in the username session variable ECA::domainname – the same information in the domain session variable ECA::client_machine_name – the same information in the machine name session variable Since the ECA profile is also enabled at will, there are some other things you can do with it. One example would be to enable and disable client side NTLM based on the requested URI: when HTTP_REQUEST { if { [HTTP::uri] starts_with “/protected_uri” } { ECA::enable ECA::select select_ntlm:/Common/my-ntlm-machine-auth } else { ECA::disable } } And finally you have two ECA events, ECA_REQUEST_ALLOWED and ECA_REQUEST_DENIED that can be used to trigger specific actions on successful authentication or denied logon attempts, respectively. Well that’s it for now. If you have any questions please post them below and I’ll try to answer. Otherwise stay tuned for more BIG-IP APM articles. Thanks.10KViews1like43CommentsKerberos Delegation and NTLM auth Exchange 2013
This is related to a previous post about the Exchange iApp. Everything is working for both internal and internal connections except from Outlook Anywhere clients attempting to connect to the external VS and auth via RPC over HTTP. I enabled all debug logs for APM and ECA since that seemed to be where the failure was occuring. I noticed the following and cannot make much sense of it. Any help would be appreciated. Below is the log file comparison between a successful auth though the internal iApp vs the failed auth through the external iApp. This is just a snippet of the full log. Everything before these lines in the log is the same for both internal and external connections. It seems to fail when the BigIP tries to make a call to itself to process the logon request, anyone ever see this before? Internal success: Aug 12 13:22:12 JHHCF5 debug eca[7237]: 0162000c:7: [Common] 10.1.12.9:46380 (0x09a8b9c8) Server challenge: 24296533D8C59FB4 Aug 12 13:22:12 JHHCF5 debug nlad[8603]: 01620000:7: <0x559058f0> clntsvc: processing 'logon' request on connection[18] from 127.0.0.1:43935 Aug 12 13:22:12 JHHCF5 debug nlad[8603]: 01620000:7: <0x559058f0> client[5]: is ready Aug 12 13:22:12 JHHCF5 debug nlad[8603]: 01620000:7: <0x5624cb90> NLAD_TRACE: nlclnt[53403010a / 01] sending logon = 0xC00000E5 Aug 12 13:22:12 JHHCF5 debug nlad[8603]: 01620000:7: <0x5624cb90> nlclnt[53403010a] logon: entering user GRicketts domain JHHC wksta JHHC04619LT Failed auth: Aug 12 12:51:10 JHHCF5 debug nlad[8603]: 01620000:7: <0x559058f0> clntsvc: processing 'logon' request on connection[38] from 127.0.0.1:44495 Aug 12 12:51:10 JHHCF5 warning nlad[8603]: 01620000:4: <0x559058f0> clntsvc: no client for id 6 to service request from connection[38] from 127.0.0.1:44495 Aug 12 12:51:10 JHHCF5 debug nlad[8603]: 01620000:7: <0x559058f0> nla_rq: response with status [0xc00000ab,NT_STATUS_INSTANCE_NOT_AVAILABLE] for type 'logon' client 6 context 0x5ab82b90 24 bytes to connection[38] from 127.0.0.1:44495: took 0 milli-seconds Aug 12 12:51:10 JHHCF5 debug eca[7237]: 0162000c:7: [Common] 12.181.141.210:45214 (0x5bf14c28) nla_agent::logon, rc = STATUS_NO_LOGON_SERVERS (3221225566)4.9KViews0likes38CommentsLeveraging BIG-IP APM for seamless client NTLM Authentication
Many customers express interest to use F5 Access Policy Manager for transparent seamless authentication for their users. There are a couple of leading use cases that drive that desired behavior: Providing silent seamless authentication to Windows-based applications such as Exchange or Sharepoint from the domain-joined machines. The premise is is that if the user is logged in to their domain-joined machine, no matter where they are, they should be able to perform seamless NTLM authentication to their applications such as Sharepoint based on the Windows Integrated Authentication settings. Providing SAML Identity Provider services with APM. When users access SAML-enabled applications, they are asking for SAML assertions. Because APM can act as either native SAML 2.0 IDP or as a proxy to other SAML IDPs such as ADFS, for example, customer desire silent authentication to those IDP services from the domain-joined machines in order to seamlessly enable to SaaS applications such as Office 365, SalesForce.com, Google Apps, etc. APM can perform three types of 401-based challenge authentication: Basic, NTLM, and Kerberos. Basic always requires user’s intervention, but Kerberos and NTLM can enable users to seamlessly authenticate to the APM virtual server and allow it to either securely proxy connection to the backend application such as Sharepoint, leveraging Kerberos Constrained Delegation as the SSO mechanism, or acting as SAML IDP and issuing assertions to the SAML Service Providers based upon user identity extracted during NTLM authentication or Kerberos ticket. Today, we are going to examine the second use case on how to configure APM to perform client NTLM authentication and use it in the context of sending a SAML assertion to the Office 365 service. It is assumed below that user knows how to configure APM for standard forms-based authentication and also has at least one existing policy(although you can create a new one from the scratch). One of the easiest ways to test this is to deploy the Office 365 configuration using the iApp and the modify configuration to enable NTLM authentication. The steps below assume that you either have a working Office 365 configuration based on the iApp, or you have an equivalent policy that you can modify. First, and foremost, we need to create an NTLM Machine Account object. Under Access Policy, go to Access Profiles->NTLM->Machine Account, and click on Create to join the BIG-IP to the domain and create unique computer object in Active Directory Keep in mind that you will need to create a unique account in Active Directory for your BIG-IP. In the example above, the account name is bigip1. Create a “NTLM Auth Configuration” using the above machine account name. Under Access Policy, go to Access Profiles->NTLM->NTLM Auth Configuration and click on Create. Give the configuration the name, select the Machine Account Name value based on the object you created in Step 1, and add as many FQDNs for the AD domain controllers in your infrastructure Now we need to create an iRule that will help us handle NTLM authentication to the BIG-IP properly. You need to modify the sec on cline of the RULE_INIT event to match the name of the NTLM Auth configuration you created in step 2. You will also need to replace all instances of appname with a unique identifier. Go to Local Traffic->iRules->iRules List and click on Create. Give the iRule name of “ntlm-auth-iRule” and paste the iRule into the BIG-IP: when RULE_INIT { set static::appname_ntlm_retries 2 set static::appname_ntlm_config "/Common/appname_ntlm_config" set static::appname_access_log_prefix "01490000:7:" set static::appname_ntlm_on_demand_prfx "$static::appname_access_log_prefix \[NTLM-ON-DEMAND\]" } when ACCESS_SESSION_STARTED { ACCESS::session data set "session.ntlm.last.retries" 0 } when HTTP_REQUEST { log -noname accesscontrol.local1.debug "$static::appname_ntlm_on_demand_prfx Request: [HTTP::uri]" switch -glob -- [string tolower [HTTP::uri]] { "/ntlm/auth" { set sid [ACCESS::session sid] log -noname accesscontrol.local1.debug "$static::appname_ntlm_on_demand_prfx sid: $sid" set referer [HTTP::header value Referer] log -noname accesscontrol.local1.debug "$static::appname_ntlm_on_demand_prfx Referer: $referer" set x_session_id [ HTTP::header value X-Session-Id ] if { [ string length $x_session_id ] != 0 } { set sid $x_session_id } set retries [ACCESS::session data get -sid $sid "session.ntlm.last.retries"] log -noname accesscontrol.local1.debug "$static::appname_ntlm_on_demand_prfx retries: $retries" set auth_result [ACCESS::session data get -sid $sid "session.ntlm.last.result"] log -noname accesscontrol.local1.debug "$static::appname_ntlm_on_demand_prfx auth result: $auth_result" if { ($auth_result == 1) || ($retries == $static::appname_ntlm_retries) && ($auth_result != 1) } { ECA::disable log -noname accesscontrol.local1.debug "$static::appname_ntlm_on_demand_prfx Redirect to: $referer" HTTP::redirect "$referer" } else { ECA::enable ECA::select select_ntlm:$static::appname_ntlm_config } unset x_session_id unset referer } default { ECA::disable } } } when CLIENT_ACCEPTED { set second_pass pass[IP::client_addr][TCP::client_port] # Check if this is the first or second time passing through this virtual if { [ table lookup $second_pass ] == "1" } { set wait_timeout 3000 set wait_delay 100 set wait_total 0 set disable_ssl disablessl[IP::client_addr][TCP::client_port] # Wait for SERVER_CONNECTED event to complete while { [ table lookup $disable_ssl ] != 0 && [ table lookup $disable_ssl ] != 1 && $wait_total < $wait_timeout } { set wait_total [ expr "$wait_total + $wait_delay" ] after $wait_delay } unset wait_delay wait_timeout # Check table value set by SERVER_CONNECTED to disable ssl set disable_ssl_value [ table lookup $disable_ssl ] if { $disable_ssl_value == "1" } { set command "SSL::disable" eval $command unset command } elseif { $disable_ssl_value != 0 } { log -noname accesscontrol.local1.notice "$static::appname_ntlm_on_demand_prfx Error: SERVER_CONNECTED event not completed after $wait_total ms" } table delete $disable_ssl table delete $second_pass unset disable_ssl wait_total } else { # This is the first time through this virtual. Set clientssl flag set client_ssl clientssl[IP::client_addr][TCP::client_port] if { [ catch { PROFILE::clientssl name } ] } { table add $client_ssl "0" } else { table add $client_ssl "1" } unset client_ssl } unset second_pass } when SERVER_CONNECTED { set client_ssl clientssl[IP::client_addr][TCP::client_port] set disable_ssl_value 0 # Check clientssl flag set from CLIENT_ACCEPTED. if { [ table lookup $client_ssl ] == "1" } { if { [ catch { PROFILE::serverssl name } ] } { # Clientssl is present but serverssl is not. Disable clientssl set disable_ssl_value 1 } table delete $client_ssl } set disable_ssl disablessl[IP::client_addr][TCP::client_port] table add $disable_ssl $disable_ssl_value unset disable_ssl unset client_ssl disable_ssl_value } when ECA_REQUEST_ALLOWED { log -noname accesscontrol.local1.debug "$static::appname_ntlm_on_demand_prfx NTLM Auth succeed" ACCESS::session data set session.ntlm.last.username "[ECA::username]" ACCESS::session data set session.ntlm.last.domainname "[ECA::domainname]" ACCESS::session data set session.ntlm.last.machinename "[ECA::client_machine_name]" ACCESS::session data set session.ntlm.last.status "[ECA::status]" ACCESS::session data set session.ntlm.last.result 1 ACCESS::disable HTTP::header insert X-Session-Id $sid log -noname accesscontrol.local1.debug "$static::appname_ntlm_on_demand_prfx use virtual: [ virtual name ]" # Set flag for next CLIENT_ACCEPTED telling it that it is the second pass through virtual set second_pass pass[IP::client_addr][TCP::client_port] table add $second_pass "1" unset second_pass # Connect to itself in order to generate HTTP response use virtual [ virtual name ] } when ECA_REQUEST_DENIED { log -noname accesscontrol.local1.debug "$static::appname_ntlm_on_demand_prfx NTLM Auth succeed" if { [ACCESS::session data get session.ntlm.last.retries] != $static::appname_ntlm_retries } { incr retries ACCESS::session data set session.ntlm.last.retries $retries } } After creating this iRule, assign it to the APM Virtual Server. Now you can create or modify your existing policy as below. Let’s examine how the policy depicted below is structured. The assumption is that the policy is going to be used to authenticate both internal and external users. If the users are coming in from the internal corporate network, we want to steer them straight to the NTLM authentication, if not, we want to use forms-based login for to authenticate them. I’ve started the policy with IP Subnet Match action to steer clients from certain networks to the NTLM authentication. One the desired source networks are matched, we move on to an External Login Page object that will send user back to the APM virtual and request NTLM authentication. Let’s examine how the policy depicted above is structured. The assumption is that the policy is going to be used to authenticate both internal and external users. If the users are coming in from the internal corporate network, we want to steer them straight to the NTLM authentication, if not, we want to use forms-based login for to authenticate them. I’ve started the policy with IP Subnet Match action to steer clients from certain networks to the NTLM authentication. Once the desired source networks are matched, we create an External Login Page object that will send user back to the APM virtual and request NTLM authentication. After sending the user to the “external login page”, which in fact is just a request to the same virtual server that is handled by the iRule that enables NTLM authentication between the client and BIG-IP, we need to check the status of the NTLM authentication, so we add the “NTLM Auth Result Check” action to see if the NTLM authentication was successful. If so, we need to populate the username session variable to enable APM to use it in session reporting/tracking, SAML assertion, SSO, etc. Now you can assign necessary resources to the user session. In this example, we are assigning APM to act as the IDP to Office 365. After you finished creating or modifying the Access Policy, make sure it is assigned to the APM virtual. Now we need to associate a ECA profile with the Virtual Server in order to enable NTLM functionality. This assignment needs to be performed via the command line. Establish an SSH connection in the box and enter TMSH and type the following commands, substituting the name of your virtual server for the highlighted portion /sys modify /ltm virtual NTLM-AUTH-vs profiles add { eca } save config list /ltm virtual NTLM-AUTH-vs Note the ‘eca’ profile associated with the virtual server 6. Next, we need to modify how the virtual server handles preservation of the original source port of the connection. This can be done either from the BIG-IP Administrative interface, or from the command line. Both examples are shown below. Command Line Interface Using the same SSH session as established in Step 5, type the following commands substituting the name of your virtual server for the highlighted portion: modify /ltm virtual NTLM-AUTH-vs source-port preserve-strict save /sys config BIG-IP Administrative Interface From the main menu, go to Local Traffic > Virtual Servers > Virtual Server List. Click on the APM virtual server. Under Configuration, select Advanced. For Source Port, select Preserve Strict. Click Update.” 7. Last, but not least, you need ensure that the machine you’re using to achieve the silent sign-on has the APM Virtual FQDN added to its Local Intranet zone as per the picture below. Voila! You should be all set. Point your browser on the machine to the FQDN of the APM Virtual Server where you assigned the new policy and iRule, and you should be silently authenticated. If you are interested in performing SSO to applications such as Sharepoint, you will need to setup Kerberos SSO in order to perform single sign-on to the Sharepoint based on the NTLM authentication.2.8KViews0likes33CommentsKerberos: can't get S4U2Self ticket for user Exch2016@MYDOMAIN.COM - Server not found in Kerberos database (-1765328377)
We are publishin Exchange 2016 in F5 APM. We are facing an issue for Outlook Anywhere as NTLM authentication is used. I have used latest available iApp for the exchange 2016 deployment and followed deployment guide. Configured Machine Account as well as NTLM Auth configuration. Created delegation account in AD. User is not getting authenticated while accessing Outlook client from outside the office. following error logs I can see from APM Nov 1 13:00:58 F5APM info websso.3[8870]: 014d0011:6: 6cbcede9: Websso Kerberos authentication for user 'Exch2016' using config '/Common/exch_2016.app/exch_ntlm_kerberos_edge_sso' Nov 1 13:00:58 F5APM debug websso.3[8870]: 014d0046:7: 6cbcede9: adding item to WorkQueue Nov 1 13:00:58 F5APM debug websso.3[8870]: 014d0021:7: sid:6cbcede9 ctx:0x87b57e0 SPN = HTTP/mymail.mydomain.com@ABC.NET Nov 1 13:00:58 F5APM debug websso.3[8870]: 014d0023:7: S4U ======> ctx: 6cbcede9, sid: 0x87b57e0, user: Exch2016@MYDOMAIN.COM, SPN: HTTP/mymail.mydomain.com@ABC.NET Nov 1 13:00:58 F5APM debug websso.3[8870]: 014d0001:7: Getting UCC:Exch2016@MYDOMAIN.COM@ABC.NET, lifetime:36000 Nov 1 13:00:58 F5APM debug websso.1[8768]: 014d0001:7: fetched new TGT, total active TGTs:1Nov 1 13:00:58 F5APM debug websso.1[8768]: 014d0001:7: TGT: client=svc_apm@ABC.NET server=krbtgt/ABC.NET@ABC.NET expiration=Tue Nov 1 23:00:58 2016 flags=40610000Nov 1 13:00:58 F5APM debug websso.1[8768]: 014d0001:7: TGT expires:1478030458 CC count:0Nov 1 13:00:58 F5APM debug websso.1[8768]: 014d0001:7: Initialized UCC:Exch2016@MYDOMAIN.COM@ABC.NET, lifetime:36000 kcc:0x9177068 Nov 1 13:00:58 F5APM debug websso.1[8768]: 014d0001:7: UCCmap.size = 1, UCClist.size = 1 Nov 1 13:00:58 F5APM debug websso.1[8768]: 014d0001:7: S4U ======> - NO cached S4U2Proxy ticket for user: Exch2016@MYDOMAIN.COM server: HTTP/mymail.mydomain.com@ABC.NET - trying to fetch Nov 1 13:00:58 F5APM debug websso.1[8768]: 014d0001:7: S4U ======> - NO cached S4U2Self ticket for user: Exch2016@MYDOMAIN.COM - trying to fetch Nov 1 13:00:58 F5APM err websso.1[8768]: 014d0005:3: Kerberos: can't get S4U2Self ticket for user Exch2016@MYDOMAIN.COM - Server not found in Kerberos database (-1765328377) Nov 1 13:00:58 F5APM err websso.1[8768]: 014d0024:3: 6cbcede9: Kerberos: Failed to get ticket for user Exch2016@MYDOMAIN.COM Nov 1 13:00:58 F5APM debug websso.1[8768]: 014d0001:7: ctx: 0x9037f10, SERVER: TMEVT_NOTIFY Nov 1 13:00:58 F5APM err websso.1[8768]: 014d0048:3: 6cbcede9: failure occurred when processing the work item Nov 1 13:00:58 F5APM debug websso.1[8768]: 014d0001:7: ctx: 0x9037f10, SERVER: TMEVT_RESPONSE Nov 1 13:00:58 F5APM debug websso.1[8768]: 014d0001:7: 6 headers received Nov 1 13:00:58 F5APM debug websso.1[8768]: 014d0001:7: http header *[:status][401 Unauthorized] (len=16) Nov 1 13:00:58 F5APM debug websso.1[8768]: 014d0001:7: http header *[WWW-Authenticate][NTLM] (len=4) Nov 1 13:00:58 F5APM debug websso.1[8768]: 014d0001:7: http header [Server][Microsoft-IIS/8.5] (len=17) Nov 1 13:00:58 F5APM debug websso.1[8768]: 014d0001:7: http header [Date][Tue, 01 Nov 2016 10:02:13 GMT] (len=29) Nov 1 13:00:58 F5APM debug websso.1[8768]: 014d0001:7: http header [request-id][e006ab17-b82a-48aa-91a2-dadcd6e5d604] (len=36) Nov 1 13:00:58 F5APM debug websso.1[8768]: 014d0001:7: http header [Content-Length][0] (len=1) Nov 1 13:00:58 F5APM debug websso.1[8768]: 014d0001:7: Halted SSO retry for request It would be appreciated if anyone have an idea about issue. Nelgin1.3KViews0likes4CommentsDoS and NTLM Brute force protection for HTTP(s) traffic
Problem this snippet solves: This snippet has been designed to mainly protect against NTLM's Denial of Service and brute force attacks against web application that use this authentication mecanism. This irule help companies to fight against brute force attacks at the HTTP layer. You can combine this irule with another one on non-http traffic to provide a brute force protection across multiple layers. For pure HTTP application, you should prefer the Brute force protection provided by the ASM module. How to use this snippet: This irule should be installed on each Virtual Server that require NTLM protection. In a Microsoft Skype for Business deployment, you may need to protect following services : Web Services Conf Autodiscover Exchange Web Services TO BE DONE : Provide a way to unlock blocked users External links Github : https://github.com/e-XpertSolutions/f5 Related Articles DoS and NTLM Brute force protection for SIP flow Credits This irule is based on NTLM logger Code : when RULE_INIT { array set NTLMFlags { unicode 0x00000001 oem 0x00000002 req_target 0x00000004 unknown1 0x00000008 sign 0x00000010 seal 0x00000020 datagram 0x00000040 lmkey 0x00000080 netware 0x00000100 ntlm 0x00000200 unknown2 0x00000400 unknown3 0x00000800 ntlm_domain 0x00001000 ntlm_server 0x00002000 ntlm_share 0x00004000 NTLM2 0x00008000 targetinfo 0x00800000 128bit 0x20000000 keyexch 0x40000000 56bit 0x80000000 } set static::irule_name "irule-ntlm-bruteforce" set static::email_domain "domain.com" set static::user_domain "DOMAIN" set static::log_server "" set static::log_pri "local0." set static::fail_tab "NTLMfails" set static::blacklist_tab "NTLMblackhole" set static::userfail_tab "NTLMUserfails" set static::userblacklist_tab "NTLMUserblackhole" set static::max_failures 5 set static::fail_memory 300 set static::block_duration 300 } when CLIENT_ACCEPTED { if {[table lookup -subtable $static::blacklist_tab [IP::client_addr]] == 1} { log $static::log_pri "[virtual] - BLACKHOLED IPADDR [IP::client_addr]:[TCP::client_port] (Reputation=[IP::reputation [IP::client_addr]])" reject return } } when HTTP_REQUEST { if {[table lookup -subtable $static::blacklist_tab [IP::client_addr]] == 1} { log $static::log_pri "[virtual] - BLACKHOLED IPADDR [IP::client_addr]:[TCP::client_port] (Reputation=[IP::reputation [IP::client_addr]])" reject return } if {[HTTP::header Authorization] starts_with "NTLM "} { set ntlm_msg [ b64decode [split [lindex [HTTP::header Authorization] 1] ] ] binary scan $ntlm_msg a7ci protocol zero type if { $type eq 3 } { binary scan $ntlm_msg @12ssissississississii \ lmlen lmlen2 lmoff \ ntlen ntlen2 ntoff \ dlen dlen2 doff \ ulen ulen2 uoff \ hlen hlen2 hoff \ slen slen2 soff \ flags set ntlm_domain {}; binary scan $ntlm_msg @${doff}a${dlen} ntlm_domain set ntlm_user {}; binary scan $ntlm_msg @${uoff}a${ulen} ntlm_user set ntlm_host {}; binary scan $ntlm_msg @${hoff}a${hlen} ntlm_host set unicode [expr {$flags & 0x00000001}] if {$unicode} { set ntlm_domain_convert "" foreach i [ split $ntlm_domain ""] { scan $i %c c if {$c>1} { append ntlm_domain_convert $i } elseif {$c<128} { set ntlm_domain_convert $ntlm_domain_convert } else { append ntlm_domain_convert \\u[format %04.4X $c] } } set ntlm_domain $ntlm_domain_convert set ntlm_user_convert "" foreach i [ split $ntlm_user ""] { scan $i %c c if {$c>1} { append ntlm_user_convert $i } elseif {$c<128} { set ntlm_user_convert $ntlm_user_convert } else { append ntlm_user_convert \\u[format %04.4X $c] } } set ntlm_user $ntlm_user_convert set ntlm_host_convert "" foreach i [ split $ntlm_host ""] { scan $i %c c if {$c>1} { append ntlm_host_convert $i } elseif {$c<128} { set ntlm_host_convert $ntlm_host_convert } else { append ntlm_host_convert \\u[format %04.4X $c] } } set ntlm_host $ntlm_host_convert } binary scan $ntlm_msg @${ntoff}a${ntlen} ntdata binary scan $ntlm_msg @${lmoff}a${lmlen} lmdata binary scan $ntdata H* ntdata_h binary scan $lmdata H* lmdata_h set interesting 1 if { ($ntlm_domain equals $static::user_domain or [string tolower $ntlm_user] ends_with $static::email_domain) } { set attack 1 if {[table lookup -subtable $static::userblacklist_tab $ntlm_user] == 1} { # Block ntlm_user exceeding the number of failed logons in the timeout period log $static::log_pri "[virtual] - BLACKHOLED $ntlm_domain\\$ntlm_user from $ntlm_host at [IP::client_addr]:[TCP::client_port] (Reputation=[IP::reputation [IP::client_addr]])" reject return } else { log $static::log_pri "[virtual] - Login attempt by $ntlm_domain\\$ntlm_user from $ntlm_host for [HTTP::uri]." } } else { set attack 0 log $static::log_pri "[virtual] - Not a valid user - Login attempt by $ntlm_domain\\$ntlm_user from $ntlm_host for [HTTP::uri]." } return [list type $type flags [format 0x%08x $flags] \ ntlm_domain $ntlm_domain ntlm_host $ntlm_host ntlm_user $ntlm_user \ lmhash $lmdata nthash $ntdata] } } } when HTTP_RESPONSE { if {[info exists interesting] && $interesting == 1} { set client [IP::client_addr]:[TCP::client_port] set node [IP::server_addr]:[TCP::server_port] set nodeResp [HTTP::status] if { $nodeResp == 401 and ([info exists attack] and $attack == 1)} { log $static::log_pri "[virtual] - invalid credentials detected for $ntlm_user" table set -subtable $static::fail_tab -notouch -excl [IP::client_addr] 0 indef $static::fail_memory table incr -subtable $static::fail_tab [IP::client_addr] if {[table lookup -subtable $static::fail_tab [IP::client_addr]] >= $static::max_failures} { set now [clock seconds] set now_date [split [clock format $now -format {%X %x}] " "] set later [expr {$now + $static::block_duration}] set later_date [split [clock format $later -format {%X %x}] " "] log $static::log_pri "[virtual] - BLACKHOLING IPADDR - [IP::client_addr] (Reputation=[IP::reputation [IP::client_addr]]) at $now_date until $later_date" table set -subtable $static::blacklist_tab -excl [IP::client_addr] 1 indef $static::block_duration } if {[info exists ntlm_user]} { table set -subtable $static::userfail_tab -notouch -excl $ntlm_user 0 indef $static::fail_memory table incr -subtable $static::userfail_tab $ntlm_user if {[table lookup -subtable $static::userfail_tab $ntlm_user] >= $static::max_failures} { set now [clock seconds] set later [expr {$now + $static::block_duration}] log $static::log_pri "[virtual] - BLACKHOLING USER - $ntlm_user at $now_date until $later_date" table set -subtable $static::userblacklist_tab -excl $ntlm_user 1 indef $static::block_duration } } } } } Tested this on version: 11.5857Views0likes3CommentsNTLM Authenticated Proxy External Monitor
Problem this snippet solves: NTLM Authenticated Proxy External Monitor How to use this snippet: This monitor is used to monitor the availability of a web page through a NTLM authenticated proxy. The default HTTP monitor relies on receiving a 401 Authenticate message to trigger the NTLM handshake, proxies respond with a 407 Proxy Authenticate message instead, which causes the monitor to fail. Set the following variable: URI-The requested host/page to send the request to. (e.g. www.host.com/page1 or https://www.host.com/page.html) USER-Proxy Username PASS-Proxy Password RECV-Receive String to look for Code : #!/bin/sh # #Name:external_monitor_NTLM_Proxyauth #Author:Matt Elkington #Contact:melkington@integrity360.com #Date:23/01/2017 #Description:An external monitor to allow monitoring of a host through a NTLM Authenticated proxy #This is to work around the fact that the standard http monitor will only use NTLM if #it receives a 401 Authenticate message and ignores a 407 Proxy Authenticate message # #Change Log #VersionChangeDate #1.0Initial Monitor23/01/2017 # # #Port and IP address are supplied automatically a variables $1 and $2 byt the LTM: #$1 = IP (nnn.nnn.nnn.nnn notation) #$2 = port (decimal, host byte order) # #The following variables must be set in the monitor definitation: # #URI-The requested host/page to send the request to. (e.g. www.host.com/page1 or https://www.host.com/page.html) #USER-Proxy Username #PASS-Proxy Password #RECV-Receive String to look for # # remove IPv6/IPv4 compatibility prefix (LTM passes addresses in IPv6 format) NODE=`echo ${1} | sed 's/::ffff://'` PORT=${2} PIDFILE="/var/run/`basename ${0}`.${NODE}_${PORT}.pid" # kill of the last instance of this monitor if hung and log current pid if [ -f $PIDFILE ] then echo "EAV exceeded runtime needed to kill ${IP}:${PORT}" | logger -p local0.error kill -9 `cat $PIDFILE` > /dev/null 2>&1 fi echo "$$" > $PIDFILE # send request & check for expected response curl ${URI} --proxy ${NODE}:${PORT} -U ${USER}:${PASS} --proxy-ntlm -k | grep -i "${RECV}" 2>&1 > /dev/null # mark node UP if expected response was received if [ $? -eq 0 ] then # Remove the PID file rm -f $PIDFILE echo "UP" else # Remove the PID file rm -f $PIDFILE fi exit Tested this on version: 11.6649Views0likes0CommentsNTLM Authentication issue
Hi, I'm setting up APM for authentication for Exchange 2013. In certain scenarios NTLM authentication is used to authenticate the client, and SSO via kerberos at the back end. This all works fine. The issue is that the NTLM machine account password sometime expires and is not automatically renewed, causing NTLM auth to fail. If I manually re-new the password all is fine again. So my main questions is: Does F5 not automatically renew its NTLM machine auth password? The policy in AD for the machine account is all default settings (30 days lifetime I think). Side question: How is NTLM machine auth password synced in a HA environment? At the moment we use manual sync, and based on the timestamps for the NTLM machine auth password a new password is synced to the standby device when you sync configuration. Assuming you have renewed the password and NOT synced the configuration, and then failover to to the other BIGIP, will NTLM auth fail? (Thus requiring automatic sync?) Thanks517Views0likes2CommentsMixed 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, Kai512Views0likes1CommentNTLM Machine Account Issues - APM
Good afternoon - I am hoping someone can point me in the right direction. I'm trying to use the iApp to deploy RDP Gateway using APM (using this template - ). Part of the config is to create a new NTLM Machine account. I had no issues creating the account - and the iApp deployment went swimmingly well. I also verified that the machine account showed up in AD as a computer account. However, I am seeing these errors in the APM logs: May 15 17:40:32 f5lab debug nlad[6379]: 01620000:7: <0x56900b70> nlclnt[2a8e2c794]: is now initializing. May 15 17:40:32 f5lab debug nlad[6379]: 01620000:7: <0x56900b70> NLAD_TRACE: cli_full_connection(output_cli = (nil), my_name = "F5LAB", dest_host = "domaincontroller.domain.local", port = 445, service = "IPC$", service_type = "IPC", user = "F5LAB$", domain = "DOMAIN") May 15 17:40:32 f5lab debug nlad[6379]: 01620000:7: <0x56900b70> NLAD_TRACE: cli_full_connection(output_cli = (nil)) = 0xC000006D May 15 17:40:32 f5lab err nlad[6379]: 01620000:3: <0x56900b70> nlclnt[2a8e2c794] init: Error [0xc000006d,NT_STATUS_LOGON_FAILURE] connecting to DC 10.11.12.13 I also cannot renew the NTLM account password from the GUI as I get this error: Could not connect to domain domain controller of realm 'domain.local' machine account update for 'f5lab' failed: Preauthentication failed, principal name: f5lab@domain.local. Invalid user credentials. (-1765328360) I'm running on 12.1.3.4 and have tried the following: Recreated the NTLM account, multiple times. I know I have permissions as the account does show up in AD, and I do have domain admin level permissions Restarted the eca service (bigstart restart eca) Restarted the nlad service (bigstart restart nlad) Restarted the F5 appliance itself. Verified that the DNS settings are configured properly. The F5 is able to resolve the domain controller IP from the alias. No firewall exists between this F5 and the domain controller. Has anyone seen this and if so - can anyone point me in the right direction? I thought I'd try here before opening a support ticket with F5.500Views0likes4Comments