- Overview
- Create external objects
- Create BIG-IP iRules
- Create BIG-IP iRules LX
- Create TMOS SMTP objects
- Create APM Active Directory AAA object
- Create APM policy
- Create APM hosted content
- Apply APM customization (standard)
- Apply APM customization (modern)
- Create OTP-APM virtual server
- Create APM HTTP AAA object
- Create OTP-LTM virtual server
- Upload encryption key
This manual will guide you through the OTP application installation process on F5 BIG-IP. You need to have LTM, APM and iRulesLX provisioned modules on your BIG-IP. It is better to have AFM provisioned module to be able to defend from various attacks. You also need to have Active Directory and SMTP server.
OTP application consists of:
- OTP-APM virtual server used as OTP configuration portal. Portal is used for creation and modification of assigned OTP token
- OTP Verify iRule used for BIG-IP applications that do support APM iRule Event
- OTP-LTM virtual server used for BIG-IP applications that do not support APM iRule Event (like VMware Horizon Client)
- BIG-IP partition. Select tenant that will be used to deploy OTP application. Standard impementation uses scheme Active Directory domain = BIG-IP partition
- BIG-IP client SSL profile. Select a client SSL profile with Perfect Forward Secrecy (PFS) configured
- IP address for OTP-APM virtual server. This address will be used for an OTP configuration portal
- IP address for OTP-LTM virtual server. This address will be used for applications that do not support APM iRule Event
- IP addresses of DNS servers that are able to resolve LDAP fully qualified domain name
- LDAP scheme. Valid values are ldap:// or ldaps://. First is recommended for usage because second leads to strange errors which are sourced from ldapjs NPM package
- LDAP fully qualified domain name. DNS domain name or host name if you use single LDAP server. For example, if you have Active Directory with corp.contoso.com DNS domain name which resolves to more than one Active Directory Domain Controller, it will be the best available option (from the High-Availability perspective). iRule LX will resolve FQDN to all available server names and try each one in case previous failed
- LDAP port. Valid values are 389 or 636. First is recommended for usage because second leads to strange errors which are sourced from ldapjs NPM package
- LDAP user distinguished name. Distinguished name of Active Directory user with permissions to modify attribute selected to store encrypted OTP secret value. Distingushed name may not contain non-ASCII symbols because APM allows VPE to save ASCII symbols only
- LDAP user password. Password for Active Directory user. Password may not contain non-ASCII symbols because APM allows VPE to save ASCII symbols only
- LDAP attribure. Name of the Active Directory attribure to store encrypted OTP secret value. Standard implementation uses attribute name extensionAttribute2, but you are free to choose another one. Selected attribute must be available for read/write operations for LDAP user
- LDAP group distinguished name. Distinguished name of Active Directory group that will allow access to OTP configuration portal. Standard implementation uses Fetch Nested Groups AD Query option, so this group may be nested in Active Directory. Distinguished name may contain UTF-8 symbols if it was retrieved from the localized Active Directory. APM will automatically encode this string as HEX and prefix it with "0x" in such case
- SMTP server host name. FQDN of SMTP server that is able to deliver email to BIG-IP administrators and users. Server must support authenticated and nonauthenticated connections. Authenticated connection is used to deliver messages to BIG-IP administrators and unauthenticated connection is used to deliver noreply messages to regular users
- SMTP user. Username for authenticated SMTP connection
- SMTP password. Password for authenticated SMTP connection
- SMTP address for BIG-IP administrators. Email address of BIG-IP administrators that will receive Internal Error messages
- SMTP address for noreply. Email address that is not available for reply, this address will be used for mesasges delivered to users
- LDAP administrator login. SamAccountName of the Active Directory administrator to be used for Active Directory AAA object. This account must be a member of CONTOSO\Domain Admins group to fetch Active Directory password policies to support password-related functionality
- LDAP administrator password. Password for Active Directory administrator
Example list of external objects:
- CONTOSO
- /CONTOSO/PFS_clientssl
- 192.0.2.1 (for otp.contoso.com)
- 192.0.2.2 (for ltm-otp.contoso.com)
- 198.51.100.10 and 198.51.100.11
- ldap://
- corp.contoso.com (resolves to 198.51.100.10 and 198.51.100.11)
- 389
- CN=bigip2faldapuser,OU=Service Accounts,DC=corp,DC=contoso,DC=com
- COMPLEX_2FA_PASSWORD_STRING
- extensionAttribute2
- CN=OTP_Allow,OU=Service Groups,DC=corp,DC=contoso,DC=com
- smtp.contoso.com
- bigipsmtpuser@contoso.com
- COMPLEX_SMTP_PASSWORD_STRING
- bigipadmins@contoso.com
- noreply@contoso.com
- bigipaddsadminuser
- COMPLEX_ADDS_PASSWORD_STRING
You can safely choose another directory services, like Apache Directory Server, OpenLDAP or other software. In the core this solution uses NPM package ldapjs which is compatible with any directory service with LDAP enabled access. Users in you directory services catalog must have valid email addresses stored in one of the attributes because these addresses are used to deliver messages about OTP token operations.
- Log in to BIG-IP GUI as a user with Administrator privileges
- Check that current partition is Common
- Go to Local Traffic -> iRules -> iRule List
- Add iRule with name OTP and paste contents of OTP.tcl file
- Add iRule with name APM-OTP-Create_irule and paste contents of APM-OTP-Create.tcl file
- Add iRule with name APM-OTP-Trusted_irule and paste contents of APM-OTP-Trusted.tcl file
- Add iRule with name APM-OTP-Verify_irule and paste contents of APM-OTP-Verify.tcl file
- Add iRule with name LTM-OTP-Verify_irule and paste contents of LTM-OTP-Verify.tcl file
- Log in to BIG-IP GUI as a user with Administrator privileges
- Check that current partition is Common
- Go to System -> Resource Provisioning and check that iRules Language Extensions (iRulesLX) is licensed and provisioned. If not you have to enable it. Remember that module reprovision may disrupt traffic processing on BIG-IP
- Go to Local Traffic -> iRules -> LX Workspaces
- Add new workspace with name LDAP-Modify_space
- Add iRule with name APM-LDAP-Modify_irule and paste contents of APM-LDAP-Modify.tcl file
- Add extension with name APM-LDAP-Modify_ilx
- Replace contents of file index.js with contents of APM-LDAP-Modify.js file
- Log in to BIG-IP CLI as a user with Administrator privileges
- Execute command
bash
- Execute command
cd /var/ilx/workspaces/Common/LDAP-Modify_space/extensions/APM-LDAP-Modify_ilx/
- Execute command
npm install ldapjs@1.0.2 --no-bin-links --save
- Log in to BIG-IP GUI as a user with Administrator privileges
- Check that current partition is Common
- Go to Local Traffic -> iRules -> LX Pugins
- Add new plugin with name LDAP-Modify_plugin
- Select ilx-extension from Log Publisher. More about ilx-extension may be found in Jason Rahm's article on DevCentral
- Select LDAP-Modify_space from From Workspace
- Go to Local Traffic -> iRules -> LX Pugins -> LDAP-Modify_plugin -> Extensions -> APM-LDAP-Modify_ilx
- Add 500 to Maximum Restarts
- Log in to BIG-IP GUI as a user with Administrator privileges
- Check that current partition is Common
- Got to System -> Configuration -> Device -> SMTP
- Add new SMTP object with name CONTOSO-Authenticated_smtp
- Add smtp.contoso.com to SMTP Server Host Name
- Add BIG-IP hostname to Local Host Name
- Add bigipsmtpuser@contoso.com to From Address
- Select Enabled from Use Authentication
- Add bigipsmtpuser to Username
- Add COMPLEX_SMTP_PASSWORD_STRING to Password
- Add new SMTP object with name CONTOSO-Unauthenticated_smtp
- Add smtp.contoso.com to SMTP Server Host Name
- Add BIGIP_HOSTNAME to Local Host Name
- Add BIGIP_HOSTNAME@contoso.com to From Address
- Log in to BIG-IP GUI as a user with Administrator privileges
- Check that current partition is Common
- Go to System -> Resource Provisioning and check that Access Policy (APM) is licensed and provisioned. If not you have to enable it. Remember that module reprovision may disrupt traffic processing on BIG-IP
- Select partition CONTOSO to deploy a new APM policy
- Go to Access -> Authentication -> Active Directory
- Add new Active Directory server with name ActiveDirectory_aaa
- Add corp.contoso.com to Domain Name
- Add /CONTOSO/ActiveDirectory_pool to Domain Controller Pool Name
- Add all domain controller servers to Domain Controllers
- Add bigipaddsadminuser to Admin Name
- Add COMPLEX_ADDS_PASSWORD_STRING to Admin Password
- Add COMPLEX_ADDS_PASSWORD_STRING to Verify Admin Password
- Log in to BIG-IP GUI as a user with Administrator privileges
- Check that current partition is Common
- Go to System -> Resource Provisioning and check that Access Policy (APM) is licensed and provisioned. If not you have to enable it. Remember that module reprovision may disrupt traffic processing on BIG-IP
- Select partition CONTOSO to deploy a new APM policy
- Go to Access -> Profiles / Policies -> Access Profiles (Per-Session Policies)
- Add new policy with name APM-OTP-Create_access
- Select All from Profile Type
- Select Modern from Customization Type if you plan to use modern APM customization (TMOS version 15.1.x and above)
- Select English (en) from Languages
- Use Visual Policy Editor to apply Access Policy as explained in Policy Description (standard) document if you plan to use standard APM customization or you use legacy software (TMOS version 15.0.x and below)
- Use Visual Policy Editor to apply Access Policy as shown below and explained in Policy Description (modern) document if you plan to use modern APM customization (TMOS version 15.1.x and above)
- Log in to BIG-IP GUI as a user with Administrator privileges
- Check that current partition is Common
- Go to System -> Resource Provisioning and check that Access Policy (APM) is licensed and provisioned. If not you have to enable it. Remember that module reprovision may disrupt traffic processing on BIG-IP
- Go to Access -> Webtops -> Hosted Content -> Manage Files
- Upload new file with name qrcode.js
- Select file qrcode.js
- Select session from Secure Level
- Navigate to Edit File Properties and select JavaScript from Mime Type
- Navigate to Manage Access and select checkbox for APM profile /CONTOSO/APM-OTP-Create_access under Retain Public Access
- Check that Publicly Accessible URI for file qrcode.js is /public/share/qrcode.js
As you can see QR generator code is a pure JavaScipt code which is stored on BIG-IP and rendered in user's browser, so there were no external connections from OTP configuration portal or user's browser to Google servers, for example. This may be crucial for secure environments.
- Log in to BIG-IP GUI as a user with Administrator privileges
- Check that current partition is Common
- Go to System -> Resource Provisioning and check that Access Policy (APM) is licensed and provisioned. If not you have to enable it. Remember that module reprovision may disrupt traffic processing on BIG-IP
- Select partition CONTOSO to apply APM customization
- Go to Access -> Profiles / Policies -> Customization -> Advanced
- Navigate to Customization Settings -> Access Profiles -> /CONTOSO/APM-OTP-Create_access -> Macros -> OTP Create -> Message Pages -> QR Display -> message_box.inc
- Find enclosing HTML tag
</head>
and insert on previous line<script language="JavaScript" src="/public/share/qrcode.js"></script>
- Save Draft
- Save all changes
- Apply Access Policy
- Log in to BIG-IP GUI as a user with Administrator privileges
- Check that current partition is Common
- Go to System -> Resource Provisioning and check that Access Policy (APM) is licensed and provisioned. If not you have to enable it. Remember that module reprovision may disrupt traffic processing on BIG-IP
- Select partition CONTOSO to apply APM customization
- Go to Access -> Profiles / Policies -> Customization -> General
- Switch from Branding to Text view
- Navigate to Customization Settings -> Access Profiles -> /CONTOSO/APM-OTP-Create_access -> Common -> External Scripts/Styles
- Add /public/share/qrcode.js to External JavaScript 1 Address
- Execute on local machine command
echo $(openssl dgst -sha384 -binary f5_otp/ifiles/qrcode.js | openssl base64 -A)
to extract SRI hash value - Add extracted SRI hash value to External JavaScript 1 Subresource Integrity
- Go to Access -> Profiles / Policies -> Customization -> Advanced
- Navigate to Customization Settings -> Access Profiles -> /CONTOSO/APM-OTP-Create_access -> Macros -> OTP Create -> Message Pages -> QR Display -> user-message.js
- Insert contents of user-message.js file
- Save Draft
- Save all changes
- Apply Access Policy
- Log in to BIG-IP GUI as a user with Administrator privileges
- Check that current partition is Common
- Go to System -> Resource Provisioning and check that Access Policy (APM) is licensed and provisioned. If not you have to enable it. Remember that module reprovision may disrupt traffic processing on BIG-IP
- Select partition CONTOSO to deploy a new virtual server
- Go to Local Traffic -> Virtual Servers -> Virtual Server List
- Add new virtual server with name APM-OTP-Create_redir_vs
- Add 192.0.2.1 to Destination Address/Mask, where 192.0.2.1 is an IP address which will be used for APM based OTP modify virtual server
- Add 80 to Service Port
- Select http from HTTP Profile (Client)
- Select /Common/_sys_https_redirect from iRules
- Add new virtual server with name APM-OTP-Create_vs
- Add 192.0.2.1 to Destination Address/Mask, where 192.0.2.1 is an IP address which will be used for APM based OTP modify virtual server
- Add 443 to Service Port
- Select http from HTTP Profile (Client)
- Select /CONTOSO/PFS_clientssl from SSL Profile (Client), where PFS_clientssl is a client SSL profile with Perfect Forward Secrecy (PFS) configured
- Select /CONTOSO/APM-OTP-Create_access from Access Profile
- Select /Common/APM-OTP-Create_irule, /Common/APM-OTP-Verify_irule and /Common/LDAP-Modify_plugin/APM-LDAP-Modify_irule from iRules
TMSH commands:
create ltm virtual /CONTOSO/APM-OTP-Create_redir_vs { destination /CONTOSO/192.0.2.1:http ip-protocol tcp mask 255.255.255.255 partition CONTOSO profiles { tcp { } http { } } rules { _sys_https_redirect } }
create ltm virtual /CONTOSO/APM-OTP-Create_vs { destination /CONTOSO/192.0.2.1:https ip-protocol tcp mask 255.255.255.255 partition CONTOSO profiles { tcp {} http {} PFS_clientssl { context clientside } } rules { APM-OTP-Create_irule APM-OTP-Verify_irule LDAP-Modify_plugin/APM-LDAP-Modify_irule } }
- Log in to BIG-IP GUI as a user with Administrator privileges
- Check that current partition is Common
- Go to System -> Resource Provisioning and check that Access Policy (APM) is licensed and provisioned. If not you have to enable it. Remember that module reprovision may disrupt traffic processing on BIG-IP
- Go to Access -> Authentication -> HTTP
- Add new HTTP server with name LTM-OTP-Verify_http
- Select Form Based from Authentication Type
- Select GET from Form Method
- Add http://ltm-otp.contoso.com/otp_verify to Form Action, where ltm-otp.contoso.com resolves to IP address 192.0.2.2 which will be used for LTM based OTP verification virtual server
- Add below text to Hidden Form Parameters/Values:
secret_value %{session.custom.otp.secret_value}
secret_keyfile %{session.custom.otp.secret_keyfile}
secret_hmac %{session.custom.otp.secret_hmac}
otp_value %{session.custom.otp.otp_value}
otp_numdig %{session.custom.otp.otp_numdig}
timestep_value %{session.custom.otp.timestep_value}
timestep_num %{session.custom.otp.timestep_num}
aaa_name %{session.custom.otp.aaa_name}
user_name %{session.custom.otp.user_name}
security_attempt %{session.custom.otp.security_attempt}
security_period %{session.custom.otp.security_period}
security_delay %{session.custom.otp.security_delay}
- Select By Specific String in Response from Successful Logon Detection Match Type
- Add 200 OK to Successful Logon Detection Match Value
TMSH command:
create apm aaa http LTM-OTP-Verify_http { auth-type form-based form-action http://ltm-otp.contoso.com/otp_verify form-fields "secret_value %{session.custom.otp.secret_value} secret_keyfile %{session.custom.otp.secret_keyfile} secret_hmac %{session.custom.otp.secret_hmac} otp_value %{session.custom.otp.otp_value} otp_numdig %{session.custom.otp.otp_numdig} timestep_value %{session.custom.otp.timestep_value} timestep_num %{session.custom.otp.timestep_num} aaa_name %{session.custom.otp.aaa_name} user_name %{session.custom.otp.user_name} security_attempt %{session.custom.otp.security_attempt} security_period %{session.custom.otp.security_period} security_delay %{session.custom.otp.security_delay}" form-method get success-match-type string success-match-value "200 OK" }
- Log in to BIG-IP GUI as a user with Administrator privileges
- Check that current partition is Common
- Go to Local Traffic -> Virtual Servers -> Virtual Server List
- Add new virtual server with name LTM-OTP-Verify_vs
- Add 192.0.2.2 to Destination Address/Mask
- Add 80 to Service Port
- Select http from HTTP Profile (Client)
- Select /Common/LTM-OTP-Verify_irule from iRules
ATTENTION! You need to secure this virtual server with custom iRule or AFM that will restrict connections to sourced from this BIG-IP or trusted servers only. AFM is the prefered solution.
TMSH command:
create ltm virtual LTM-OTP-Verify_vs { destination 192.0.2.2:http ip-protocol tcp mask 255.255.255.255 profiles { tcp { } http { } } rules { LTM-OTP-Verify_irule } }
- Prepare encryption key file in format compatible with AES::decrypt command. This step is crucial because current key stored in file is public and unsafe. Please change it in your environment
- Log in to BIG-IP GUI as a user with Administrator privileges
- Check that current partition is Common
- Go to System -> File Management -> iFile List
- Import file domain-otpenc.key with name CONTOSO-otpenc-key, where CONTOSO is a domain/tenant name
- Select partition CONTOSO to create a new iFile
- Go to Local Traffic -> iRules -> iFile List
- Add new iFile with name otpenc-key
- Select CONTOSO-otpenc-key from File Name, where CONTOSO is a domain/tenant name
ATTENTION! File uploaded to this GitHub repository contains very simple and guessable encryption key. You MUST create your own.