PerimeterX F5 BIG-IP SDK
- Dependencies
- Installation
- First-Party Integration
- Upgrading
- Basic Usage Example
- Block Score Configuration
- Configuration
- Configurational Classes
- Advanced Blocking Response
- Troubleshooting
- F5 >= v11.5
- HSSR and HSSR-helper iRules (F5 DevCentral)
This guide describes the step necessary to complete to install a fully functioning PerimeterX module on a F5 appliance
For access to the Enforcer's SDK, contact your PerimeterX Solution Architect or PerimeterX Support
Note: The BIG-IP device must have public internet access in order to communicate with the PerimeterX cloud services. Make sure to include the proper routing and gateway configuration.
Import the HSSR and HSSR-helper iRules downloaded from F5 DevCentral. These iRules are used for http client communication and TLS/SSL communication with PerimeterX backends.
Important Note: Make sure that the iRule names are: HSSR and HSSR-helper (corresponding to each rule).
- Edit the
px-datagroup.txtfile and replace all instances ofAPP_IDwith PerimeterX's app id. - In the same file, replace
AUTH_TOKENandCOOKIE_SECRETwith the correct PerimeterX values. sshto the F5 instance and run the content ofpx-datagroup.txtin the shell. This will create the configuration data group for the iRule.
- Under
Local Traffic->Pools->Pool List, create a new pool. - Set the pool name to:
px_backend_pool. - Set
Health Monitorto tcp_half_open. - Select
new FQDN Node. - Set
Node Nameto your app id.
Note: App id can be retrieved from the PerimeterX portal under Admin->Applications.
- Set
Addressto sapi-<APP_ID>.perimeterx.net - Set the
Service Portto 443. - Set
Auto Populateto Enabled. - Click
Add&Finished
- Under
Local Traffic->Virtual Servers->Virtual Servers List, create new virtual server. This virtual server must have external access for the pool members. - Set
Nametopx_backend_<APP_ID>_vip. The naming convention is important as the PerimeterX iRule uses this vip to send backend requests.
note: Make sure to replace <APP_ID> with the same app id used in the previous section.
- Set
Source Addressto 0.0.0.0/0 - Set
Destination Address/MaskSet any ip of a node that doesn't exist (for example: 10.0.0.30). - Set
Service Portto a random, not publicly accessible port. (for example: port 55000). - Set
HTTP Profileto http. - Configure the SSL Profile (Server) to use
serverssl. - Configure the Source Address Translation to
Auto Map. - Under
Resourcesenable theHSSR-helperiRule. - Set
px_backend_poolas the Default pool.
this step is crucial for the PerimeterX iRule to send statistics to PerimeterX backend and show data in the portal. In order to send statistics and logs from the PerimeterX module in an asynchronous way, we will use Syslog.
Note: PerimeterX backends are set to reject any unauthorized IP address, please contact your designated PerimeterX Solution Architect to authorize your backends IP address with PerimeterX backends.
- Under
Local Traffic->Profiles->SSL->Servercreate a new profile. - Set
Nametopx-syslog-ssl-profile. - Set
Parent Profiletoserverssl-insecure-compatible. - Click
Finished.
- Under
Local Traffic->Pools->Pool Listcreate a new pool. - Set
Nametopx_secure_syslog_pool. - Set the node to
New FQDN Node. - Set
Node Nametopx_activities_node. - Set
FQDNtopx-fst-syslog.perimeterx.net. - Set
Service Portto6514. - Set
Auto PopulatetoEnabled. - Click
AddandFinished.
- Under
Local Traffic->Virtual Servers->Virtual Servers List, create new virtual server. This virtual server must have external access for the pool members. - Set
Nametopx_syslog_vs. - Set
Source Addressto 0.0.0.0/0 - Set
Destination Address/MaskSet any ip of a node that doesn't exist (for example: 10.0.0.20). - Set
Service Portto 514. - Configure the SSL Profile (Server) to use
px-syslog-ssl-profile. - Set
px_secure_syslog_poolas the Default pool. - Click
Finished.
- Under
Local Traffic->Pools->Pool Listcreate a new pool. - Set
Nametopx_syslog_pool. The naming convention is important as the PerimeterX iRule use this vip to send backend requests. - Set
Health Monitortotcp_half_open. - Set the node to
New Node. - Set
Node Nametopx_vs_syslog. - Set
Addressto the same address as thepx_syslog_vsvirtual server (in the example above 10.0.0.20). - Set
Service Portto 514. - Click
AddandFinished.
- Under
System->Logs->Configuration->Log Destinationscreate a new destination. - Set
Nametoperimeterx_hsl. - Set
TypetoRemote-High-Speed Log. - Set
Pool Nametopx_syslog_pool. - Set
ProtocoltoTCP. - Click
Finished.
- Under
System->Logs->Configuration->Log Destinationscreate a new destination. - Set
Nametoperimeterx_syslog. - Set
TypetoRemote Syslog. - Set
Syslog FormattoSyslog - Set
Forward Totoperimeterx_hsl. - Click
Finished.
- Under
System->Logs->Configuration->Log Publisherscreate a new publisher. - Set
Nametoperimeterx-publisher. - Under
Destinationsmoveperimeterx_syslogtoSelected. This will forward the logs to the hsl we previously configured. - Click
Finished.
- Under
System->Logs->Configuration->Log Filterscreate a new filter. - Set
Nametoperimeterx_filter. - Set
SeveritytoDebug. - Set
Sourcetoall. - Set
Message IDto01070410(or any other random number). - Under
Log Publisherselectperimeterx-publisher. - Click
Finished.
- Create a new iRule named
px. - Copy the content of
px.tclinto thepxiRule and update the following keys under RULE_INIT:
- APP_ID - The PerimeterX custom application id in the format of _PX**_**__ .
- AUTH_TOKEN - The JWT token used for REST API. The Authentication Token is generated in PerimeterX Portal -> Application page.
- COOKIE_SECRET - The key used by the cookie signing page. The Cookie Key is generated in the PerimeterX Portal -> Policy page.
Note: If you configured a pool for PerimeterX activities report (
px_syslog_pool) - uncomment theCLIENT_ACCEPTEDrule (lines 2-4) in the iRule editor.
- Add the
pxiRule to the Virtual Server you want to protect with PerimeterX.
First-Party Mode enables the module to send/receive data to/from the sensor, acting as a reverse-proxy for client requests and sensor activities. To setup First-Party mode on F5 BigIP:
- Under
Local Traffic->Pools->Pool List, create a new pool. - Set the pool name to:
px_client_pool. - Set
Health Monitorto tcp_half_open. - Select
new FQDN Node. - Set
Node NameandAddresstoclient.perimeterx.net - Set the
Service Portto 443. - Set
Auto Populateto Enabled. - Click
Add&Finished.
- Under
Local Traffic->Pools->Pool List, create a new pool. - Set the pool name to:
px_captcha_pool. - Set
Health Monitorto tcp_half_open. - Select
new FQDN Node. - Set
Node NameandAddresstocaptcha.px-cdn.net - Set the
Service Portto 443. - Set
Auto Populateto Enabled. - Click
Add&Finished.
- Under
Local Traffic->Pools->Pool List, create a new pool. - Set the pool name to:
px_xhr_pool. - Set
Health Monitorto tcp_half_open. - Select
new FQDN Node. - Set
Node Nameandaddresstocollector-<APP_ID>.perimeterx.net
Note: App id can be retrieved from the PerimeterX portal under Admin->Applications.
- Set the
Service Portto 443. - Set
Auto Populateto Enabled. - Click
Add&Finished
Contact PerimeterX Support or your assigned PerimeterX Solution Architect for details.
when HTTP_REQUEST {
set module_version "F5 BIG-IP 2.5.0"
set app_id [class lookup "app_id" pxconfig]
set cookie_secret_key [class lookup "cookie_secret_key" pxconfig]
set auth_token [class lookup "auth_token" pxconfig]
set enable_module [class lookup "enable_module" pxconfig]
set module_mode [class lookup "module_mode" pxconfig]
set whitelisted_routes_class [class lookup "whitelisted_routes_class" pxconfig]
set specific_routes_class [class lookup "specific_routes_class" pxconfig]
set sensitive_routes_class [class lookup "sensitive_routes_class" pxconfig]
set send_page_activities 1
set send_block_activities 1
set excluded_extensions "\.(css|bmp|tif|ttf|docx|woff2|js|pict|tiff|eot|xlsx|csv|eps|woff|xls|jpeg|jpg|doc|ejs|otf|pptx|gif|pdf|swf|svg|ps|ico|pls|midi|svgz|class|png|ppt|mid|webp|jar)$"
set risk_vs [class lookup "risk_vs" pxconfig]
set risk_timeout [class lookup "risk_timeout" pxconfig]
set debug 0
set ip_header [class lookup "ip_header" pxconfig]
set sensitive_headers [list "cookie"]
set custom_logo [class lookup "custom_logo" pxconfig]
set js_ref [class lookup "js_ref" pxconfig]
set css_ref [class lookup "css_ref" pxconfig]
set collector_url "https://collector-${app_id}.perimeterx.net"
set allowed_domains [list ""]
set whitelist_ips [list ""]
set enable_module_header_name [class lookup "enable_module_header_name" pxconfig]
set bypass_monitor_header [class lookup "bypass_monitor_header" pxconfig]
set enable_advanced_blocking_response [class lookup "enable_advanced_blocking_response" pxconfig]
set custom_cookie_header [class lookup "custom_cookie_header" pxconfig]
set enable_first_party [class lookup "enable_first_party" pxconfig]
set enable_sensor_injection [class lookup "enable_sensor_injection" pxconfig]
}
Enforcer configuration is stored in "Data Group" named pxconfig.
- Edit the
px-datagroup.txtfile and replace all instances ofAPP_IDwith PerimeterX's app id. - In the same file, replace
AUTH_TOKENandCOOKIE_SECRETwith the correct PerimeterX values. sshto the F5 instance and run the content ofpx-datagroup.txtin the shell. This will create the configuration data group for the iRule.
The following command could be used to modify a single data-group item:
modify /ltm data-group internal pxconfig records modify { KEY_NAME { data VALUE } }
Where:
KEY_NAMEis the name of the configurationVALUEis the value
Example (change Enforcer to "blocking" mode):
modify /ltm data-group internal pxconfig records modify { module_mode { data 2 } }
app_idcookie_keyauth_token
Configuring the block score is done in the portal
BIGIP F5 Enforcer uses a binary cookie. The binary cookie does not store the score value on the cookie on the parsed jSON; it is simply being calculated
In order to set a blocking threshold to the binary cookie:
- Log into the PerimeterX Portal
- On Admin tab select POLICIES
- Select Risk Cookie drop-down menu
- Select "Advanced Mode" and press Continue
- Unselect v1/v3 if selected and select v2, the binary score should be un-greyed
- Set a value and apply changes
| Directive | Description | Default | Value |
|---|---|---|---|
| app_id | PX applic ation id | NONE | String |
| cookie_secret_key | Cookie hashing secret (salt) | NONE | String |
| auth_token | JWT used to authenticate with px servers | NONE | String |
| enable_module | Sets the module on/off | 1 | int |
| module_mode | Sets the module working mode, 2 - blocking, 1 - sync monitor, 0 - async monitor | 2 - blocking | int |
| whitelisted_routes_class | Name of the class for whitelist routes, please read additional information | px_<APP_ID>_whitelisted_routes | String |
| whitelisted_query_params_class | Name of the class for whitelist query parameters | px_<APP_ID>_whitelisted_query_params | String |
| specific_routes_class | Name of the class for specific routes, please read additional information | px_APP_ID_specific_routes | String |
| sensitive_routes_class | Name of the class for sensitive routes, please read additional information | px_APP_ID_specific_routes | String |
| send_page_activities | Toggles send page requested activity | 0 | int |
| send_block_activities | Toggles send block activities | 1 | int |
| excluded_extensions | Flags which extentions the moudle will skip | regex String | String |
| risk_vs | Correlates with the virtual server for making risk api calls | px_backend_APP_ID_vip | String |
| risk_timeout | Sets the timeout for api calls (in milliseconds | 2500 | int |
| debug | Toggles debug mode on/off, see troubleshooting for more information | 0 | int |
| ip_header | Custom user header that contains real user ip | NONE | String |
| sensitive_headers | List of sensitive headers not to send in risk api calls | ["cookie"] | list |
| custom_logo | Path to url that contains a logo to be displayed on default block page | NONE | String |
| jf_ref | Path to url that contains a custom js file to inject into the default block page | NONE | String |
| css_ref | Path to url that contains a custom css file to inject into the default block page | NONE | String |
| allowed_domains | A list of domain names on which the enforcer will run on. Run on all if blank | [""] | list |
| enable_module_header_name | The header name that should be used to enable the module (The header's value should be True) |
None | String |
| whitelist_ips | A list of ips/CIDRs to whitelist. If empty all the requests will be processed. | [""] | list |
| bypass_monitor_header | The header name that can be used to bypass monitor mode on blocking activities. | NONE | String |
| enable_advanced_blocking_response | Toggles the use of advanced blocking response | 1 | int |
| custom_cookie_header | A header name which will be used to extract the PerimeterX cookie from. | NONE | String |
| enable_first_party | Toggles first party mode on/off. | 1 | int |
| enable_sensor_injection | Toggles sensor injection on/off | 0 | int |
Some of the directives on the config may require a specific name that contains the appID of the application taken from the portal.
The name on the configuration must be identical to the name configured on the data group/virtual server/pool.
In case there is a mismatch on the name it may lead to errors on the module
Activities such as page_requested, block or async_monitor are sent through Syslog. This allows the module to send these activities to the PerimeterX backend without blocking the request.
PerimeterX processes URI paths with general- and sub-delimiters according to RFC 3986. General delimiters (e.g., ?, #) are used to separate parts of the URI. Sub-delimiters (e.g., $, &) are not used to split the URI as they are considered valid characters in the URI path.
This configuration enables the module only when the configured header is present and its value is set to True.
If enable_module_header_name configuration is empty then the module_enabled configuration will determine if the module is enabled or not.
Example:
when HTTP_REQUEST {
...
set send_page_activities 1
set send_block_activities 1
set enable_module_header_name "X-PX-ENABLE-MODULE"
}Allows you to test an enforcer’s blocking flow while you are still in Monitor Mode.
When the header name is set(eg. x-px-block) and the value is set to 1, when there is a block response (for example from using a User-Agent header with the value of PhantomJS/1.0) the Monitor Mode is bypassed and full block mode is applied. If one of the conditions is missing you will stay in Monitor Mode. This is done per request.
To stay in Monitor Mode, set the header value to 0.
The Header Name is configurable using the bypass_monitor_header property.
when HTTP_REQUEST {
...
set bypass_monitor_header "x-px-block"
...
}The px_add_custom_parameters function allows you to add up to 10 custom parameters to be returned to PerimeterX servers on risk_api calls. When configured, the function is called before setting the payload on every risk_api request to PerimeterX servers. The parameters should be passed in the correct order (ie. if userid is set to custom-param1 in the PerimeterX console, it should always be sent as x-px-custom-param1).
To add a custom parameter, add the header key (for exapmle: x-px-custom-param<number>) and value to the custom_parameters list in the px_add_custom_parameters function. The header key will be evaluated before being sent to ensure the right pattern (x-px-custom-param<x>) is used.
proc px_add_custom_parameters {} {
# Custom function to add custom parameters to risk_api and async activities.
set custom_parameters [list]
# INSERT LOGIC HERE
lappend custom_parameters "x-px-custom-param1" "UID"
lappend custom_parameters "x-px-custom-param3" "SessionID"
# The function must always return the custom_parameters list.
return $custom_parameters
}PerimeterX's iRule is able to inject the PerimeterX JavaScript sensor to HTML pages, by setting the enable_sensor_injection configuration property to 1. When the configuration is enabled, the iRule will remove the Accept-Header from the incoming request so the origin will NOT return the content compressed, even if the client accepts compression. Make sure to enable compression on the LTM level if you use script injection.
When set, this property enables sending a header with the name of x-px-score containing the PerimeterX score to the origin.
Possible values:
- 0 - means header is disabled
- 1 - means header is enabled
Default: 0
enable_score_header: 1This feature extracts credentials (hashed username and password) from requests and sends them to PerimeterX as additional info in the risk api call. The feature can be toggled on and off, and may be set for a specific path.
configuration options:
- ci_login_credentials_extraction_enabled - enable/disable the login extraction feature. Possible values:
1(enable),0(disable). - ci_login_credentials_extraction_class - name of the class containing the specific login extraction endpoint details.
- ci_credentials_intelligence_version - the version of credentials intelligence to use. Possible values:
multistep_ssofor multi step login process,v2for standard mode. - ci_compromised_credentials_header - name of the header to use for sending the compromised credentials result back to the origin.
- ci_additional_s2s_activity_header_enabled - enable/disable the feature for sending the s2s activity back as a header to the origin. This feature is used for sending additional data on the request back to PerimeterX's server from the origin. Possible values:
1(enable),0(disable). - ci_send_raw_username_on_additional_s2s_activity - enable/disable sending the raw user name back on the s2s activity header. Possible values:
1(enable),0(disable). - ci_login_successful_reporting_method - reporting method of a successful login. Possible values:
headerfor header name/value configuration,statusfor a specific status code indicating a successful login.- ci_login_successful_header_name - specify a header name to extract a successful login indicator. Will only be used if
ci_login_successful_reporting_methodis set toheader. - ci_login_successful_header_value - specify the header value that indicate a successful login indicator. Will only be used if
ci_login_successful_reporting_methodis set toheader. - ci_login_successful_status - specify a status code indicating a successful login. Will only be used if
ci_login_successful_reporting_methodis set tostatus.
- ci_login_successful_header_name - specify a header name to extract a successful login indicator. Will only be used if
Configure the extraction in the class configured in ci_login_credentials_extraction_class:
- path: The path for the login request, for example:
/path. - method: The HTTP method used for submiting the login request, for example :
POST. - sent_through: What is the type of payload the credentials are passing by. Possible values:
body,headerorquery-string. - user_field: The user name field name, for example:
username. - pass_field: The password field name, for example:
password.
Enable the extraction of JWT fields from requests and add them to the risk, page requested and block activities.
configuration options:
- jwt_cookie_name: The cookie name that should contain the JWT token.
- jwt_cookie_user_id_field_name: The field name in the JWT object, extracted from the JWT cookie, that contains the user ID to be extracted.
- jwt_cookie_additional_field_names: The field names in the JWT object, extracted from the JWT cookie, that should be extracted in addition to the user ID.
- jwt_header_name: The header name that should contain the JWT token.
- jwt_header_user_id_field_name: The field name in the JWT object, extracted from the JWT header, that contains the user ID to be extracted.
- jwt_header_additional_field_names: The field names in the JWT object, extracted from the JWT header, that should be extracted in addition to the user ID.
- On
Local Traffic->iRules->Data Group Listcreate a new Data Group. - Set the
Nametopx_<APP_ID>_whitelisted_routes. Make sure to replace<APP_ID>with your PerimeterX app id. - Set
TypetoString. - For each route you wish to whitelist, set the
Stringproperty ofString Recordto the prefix of the route and clickAdd. - Click
Finished.
- On
Local Traffic->iRules->Data Group Listcreate a new Data Group. - Set the
Nametopx_<APP_ID>_whitelisted_query_params. Make sure to replace<APP_ID>with your PerimeterX app id. - Set
TypetoString. - For each URI query parameter you wish to whitelist, set the
Stringproperty to the query key andValueproperty to the query regex value and clickAdd. - Click
Finished.
- On
Local Traffic->iRules->Data Group Listcreate a new Data Group. - Set the
Nametopx_<APP_ID>_specific_routes. Make sure to replace<APP_ID>with your PerimeterX app id. - Set
TypetoString. - For each route you wish to whitelist, set the
Stringproperty ofString Recordto the prefix of the route and clickAdd. - Click
Finished.
- On
Local Traffic->iRules->Data Group Listcreate a new Data Group. - Set the
Nametopx_<APP_ID>_sensitive_routes. Make sure to replace<APP_ID>with your PerimeterX app id. - Set
TypetoString. - For each route you wish to whitelist, set the
Stringproperty ofString Recordto the prefix of the route and clickAdd. - Click
Finished.
In special cases, (such as XHR post requests) a full Captcha page render might not be an option. In such cases, using the Advanced Blocking Response returns a JSON object continaing all the information needed to render your own Captcha challenge implementation, be it a popup modal, a section on the page, etc. The Advanced Blocking Response occurs when a request contains the Accept header with the value of application/json. A sample JSON response appears as follows:
{
"appId": String,
"jsClientSrc": String,
"firstPartyEnabled": Boolean,
"vid": String,
"uuid": String,
"hostUrl": String,
"blockScript": String
}Once you have the JSON response object, you can pass it to your implementation (with query strings or any other solution) and render the Captcha challenge.
In addition, you can add the _pxOnCaptchaSuccess callback function on the window object of your Captcha page to react according to the Captcha status. For example when using a modal, you can use this callback to close the modal once the Captcha is successfullt solved.
An example of using the _pxOnCaptchaSuccess callback is as follows:
window._pxOnCaptchaSuccess = function (isValid) {
if (isValid) {
alert("yay");
} else {
alert("nay");
}
};For Advanced Blocking Resposne sample please refer to the abr-samples Github repository.
To troubleshoot the iRule added to the F5 BIG-IP, ssh into the BIG-IP machine, type bash in the command prompt and then check the ltm logs located in /var/log/ltm
tail -f /var/log/ltm












