Kong Plugin
Getting Started
Dependencies
- Kong (2.x and 3.x Kong versions are supported)
- LuaJIT
- Lua CJSON
- Lua Resty HTTP
- Lua Resty Nettle
- lustache
- GNU Nettle >= v3.2
To install package dependencies on Ubuntu run:
sudo apt-get update && sudo apt-get install lua-cjson libnettle6 nettle-dev luarocks luajit libluajit-5.1-dev ca-certificates
All Lua dependencies are automatically fulfilled with Luarocks.
Installation
Installation can be done using luarocks.
$ luarocks install kong-plugin-perimeterx
Manual installation can accomplished by downloading the sources for this repository and running sudo make install
.
Additional steps for installing on Amazon Linux
Make sure to change the path shown below in the "Lua CA Certificates" section as Amazon Linux stores the CA required in a different location than shown.
If running Amazon Linux this is the trusted certificate path please use:
lua_ssl_trusted_certificate "/etc/pki/tls/certs/ca-bundle.crt";
NGINX Configuration File Requirements
Resolver
Add the directive resolver A.B.C.D;
in the HTTP section of your configuration. This is required so NGINX can resolve the HUMAN API DNS name. A.B.C.D
is the IP address of your DNS resolver.
Lua CA Certificates
To support TLS to HUMAN servers, you must point Lua to the trusted certificate location (actual location may differ between Linux distributions).
lua_ssl_trusted_certificate "/etc/ssl/certs/ca-certificates.crt";
lua_ssl_verify_depth 3;
In CentOS/RHEL systems, the CA bundle location may be located at /etc/pki/tls/certs/ca-bundle.crt
.
Basic Usage Example
Ensure that you followed the NGINX Configuration Requirements section before proceeding.
Load the plugin by adding perimeterx
to the custom_plugins
list in your Kong configuration (on each Kong node).
kong.yaml "plugins" section example:
...
plugins:
- name: perimeterx
config:
px_appId: --REPLACE--
auth_token: --REPLACE--
cookie_secret: --REPLACE--
px_debug: true
block_enabled: true
Note
You can also set this property via its environment variable equivalent:
KONG_CUSTOM_PLUGINS
.
To apply HUMAN enforcement, add the HUMAN plugin to your API(s).
curl -i -X POST \
--url http://localhost:8001/apis/<api-name>/plugins/ \
--data 'name=perimeterx' \
--data 'config.px_appId=PX_APP_ID' \
--data 'config.auth_token=AUTH_TOKEN' \
--data 'config.cookie_secret=COOKIE_KEY'
You can find your app ID, authentication token, and cookie key under your account's admin section in HUMAN Portal
Upgrading
To upgrade to the latest Enforcer version run the following command in luarocks:
luarocks install perimeterx-kong-plugin
For more information, contact HUMAN Support.
Configuration Options
PII (Personally Identifiable Information) Anonymization
Personally Identifiable Information (PII) is information that can be used on its own or with other information to identify a single person, or to identify an individual in context.
It is important for us to keep personal private information out of our servers. Therefore, by default, we do not send the request body and cookies to HUMAN backend servers, the entire communication is based on headers data.
PII is not a recommended setting. If PII is essential for your organization, contact HUMAN Support.
When PII is enabled, HUMAN does not store a client’s full IP information (Client IP, HTTP Headers). In IPv4 this is done by zeroing 4th IP octet (for example, the IP 1.2.3.4 will be stored as 1.2.3.0). In IPv6 this is done by zeroing the last four (4) octets (for example, the IP 1:2:3:4:1:2:3:4 will be stored as 1:2:3:4:1:2:3:0).
Removing the IP's last octet can result small reduction of detection capability, usually for the models and signatures that are based on IPs.
Configuring Required Parameters
Configuration options are set via Kong's admin API, as config parameter.
Required parameters:
- px_appId
- cookie_secret
- auth_token
First-Party Configuration
First-Party Mode
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.
First-Party Mode may require additional changes on the JS Sensor Snippet. For more information, refer to the HUMAN Portal.
--data 'config.first_party_enabled=true'
The following routes must be enabled for First-Party Mode for the HUMAN Kong plugin:
/<PX_APP_ID without PX prefix>/xhr/*
/<PX_APP_ID without PX prefix>/init.js
/<PX_APP_ID without PX prefix>/captcha/*
- If the HUMAN Kong module is enabled on
location /
, the routes are already open and no action is necessary.
Note
The HUMAN Kong Plugin Configuration Requirements must be completed before proceeding to the next stage of installation.
First-Party JS Snippet
After configuring the Enforcer to handle First Party requests, complete the steps in Integrate 1st-Party JS Snippet to confirm your snippet is configured to serve the Javascript Sensor via First-Party.
Changing the Minimum Score for Blocking
Default blocking value: 100
--data 'config.blocking_score=60'
Blocking Mode
Default: false
--data 'config.block_enabled=true'
The HUMAN plugin is enabled in monitor only mode by default.
Setting the block_enabled flag to true will activate the module to enforce the blocking score. The HUMAN module will block users crossing the block score threshold that you define. If a user crosses the minimum block score then the user will receive the block page.
Enabled Routes
The enabled routes variable allows you to implicitly define a set of routes which the plugin will be active on. Supplying an empty list will set all application routes as active.
Default: Empty list (all routes)
--data 'config.enabled_routes=/blockhere'
Sensitive Routes
Lists of route prefixes and suffixes. The HUMAN module will always match the request URI with these lists, and if a match is found will create a server-to-server call, even if the cookie is valid and its score is low.
Default: Empty list
--data 'config.sensitive_routes_prefix=/login,/user/profile'
--data 'config.sensitive_routes_suffix=/download'
Filter sensitive headers
A list of sensitive headers can be configured to prevent specific headers from being sent to HUMAN servers (lower case header names). Filtering cookie headers for privacy is set by default, and can be overridden on the pxConfig
variable.
Default: cookie, cookies
--data 'config.sensitive_headers=cookie,cookies,secret-header'
API Timeout Milliseconds
Note
Controls the timeouts for HUMAN requests. The API is called when a Risk Cookie does not exist, or is expired or invalid.
API Timeout in milliseconds (float) to wait for the HUMAN server API response.
Default: 1000
--data 'config.s2s_timeout=250'
Send Page Activities
A boolean flag to determine whether or not to send activities and metrics to HUMAN, on each page request. Disabling this feature will prevent HUMAN from receiving data populating the HUMAN portal, containing valuable information such as the amount of requests blocked and other API usage statistics.
Default: true
--data 'config.send_page_requested_activity=false'
Debug Mode
Enables debug logging mode.
Default: false
--data 'config.px_debug=true'
Extracting the real IP address from a request
Note
It is important that the real connection IP is properly extracted when your NGINX server sits behind a load balancer or CDN. The HUMAN module requires the user's real IP address.
For the HUMAN NGINX module to see the real user's IP address, you need to set ip_headers
, a list of headers to extract the real IP from, ordered by priority.
Default with no predefined header: ngx.var.remote_addr
Example:
--data 'config.ip_headers=X-TRUE-IP,X-Forwarded-For'
Custom Block Page
Customizing block page can be done by 2 methods:
Modifying default block pages
HUMAN default block page can be modified by injecting custom css, javascript and logo to page
default values: nil
Example:
--data 'config.custom_logo= http://www.example.com/logo.png'
--data 'config.css_ref=http://www.example.com/style.css'
--data 'config.js_ref=http://www.example.com/script.js'
Redirect to a custom block page url
Users can customize the blocking page to meet their branding and message requirements by specifying the URL to a blocking page HTML file. The page can also implement reCaptcha. See NGINX - LUA Module ) for examples of a customized Captcha page.
default: nil
--data 'config.custom_block_url=http://www.example.com/block.html'
Note
This URI MUST be allowed under
config.whitelist.uri_full
to avoid infinite redirects to the block page.
API Protection Mode
For the case where kong is used for API calls and not serving HTML pages, users can set the plugin into API protection mode.
In this mode, when the system decides to block a request, instead of rendering an HTML block/captcha page, it will return a JSON object
that contains a URL for optional redirect on the user's client side.
The end user can be redirected this way to a custom captcha page, and after solving the captcha challenge, will be redirected back to the page they came from or to a default location.
Note
When setting the configuration of
api_protection_mode
totrue
, users must also setapi_protection_block_url
which is the address of the custom block page, and api_protection_default_redirect_url which is the default location for redirect after solving captcha.
Example:
--data 'config.api_protection_mode=true'
--data 'config.api_protection_block_url=http://www.example.com/block.html'
--data 'config.api_protection_default_redirect_url=http://www.example.com/home.html'
Response may look like:
{
"reason": "blocked",
"redirect_to": "http://www.example.com/block.html?url=aHR0cDovL2xvY2FsaG9zdDo4MDAwLz9nZmQ9ZmdkZmc=&uuid=11a12b80-b40c-11e7-8050-eb8403f523e5&vid=ef77a690-9bc8-11e7-9c31-970ffdcc0e6d"
}
Redirect on Custom URL
The _M.redirect_on_custom_url
flag provides 2 options for redirecting users to a block page.
default: false
--data 'config.redirect_on_custom_url=false'
By default, when a user crosses the blocking threshold and blocking is enabled, the user will be redirected to the block page defined by the _M.custom_block_url
variable, responding with a 307 (Temporary Redirect) HTTP Response Code.
Setting the flag to flase will consume the page and serve it under the current URL, responding with a 403 (Unauthorized) HTTP Response Code.
Setting the flag to false does not require the block page to include any of the coming examples, as they are injected into the blocking page via the HUMAN Nginx Enforcer._
Setting the flag to true (enabling redirects) will result with the following URL upon blocking:
http://www.example.com/block.html?url=L3NvbWVwYWdlP2ZvbyUzRGJhcg==&uuid=e8e6efb0-8a59-11e6-815c-3bdad80c1d39&vid=08320300-6516-11e6-9308-b9c827550d47
Note
The url variable is comprised of URL Encoded query parameters (of the originating request) and then both the original path and variables are Base64 Encoded (to avoid collisions with block page query params).
Custom blockpage requirements:
When captcha is enabled, and _M.redirect_on_custom_url
is set to true, the block page must include the following:
- The
<body>
section must include:
<div id="px-captcha"></div>
<script>
window._pxAppId = '<APP_ID>';
window._pxJsClientSrc = 'https://client.perimeterx.net/<APP_ID>/main.min.js';
window._pxHostUrl = 'https://collector-<APP_ID>.perimeterx.net';
</script>
<script src="https://captcha.px-cdn.net/<APP_ID>/captcha.js?a=c&m=0"></script>
#### Configuration example:
```bash
--data 'config.custom_block_url=/block.html'
--data 'config.redirect_on_custom_url=true'
Block page implementation full example:
<html>
<head>
</head>
<body>
<h1>You are Blocked</h1>
<p>Try and solve the captcha</p>
<div id="px-captcha"></div>
<script>
window._pxAppId = '<APP_ID>';
window._pxJsClientSrc = 'https://client.perimeterx.net/<APP_ID>/main.min.js';
window._pxHostUrl = 'https://collector-<APP_ID>.perimeterx.net';
</script>
<script src="https://captcha.px-cdn.net/<APP_ID>/captcha.js?a=c&m=0"></script>
</body>
<html>
Sensitive GraphQL Operations
For those using GraphQL endpoints, it is possible to trigger server-to-server risk calls on particular operation types or names. Like the sensitive routes feature, a request that contains an operation of the configured type or name will trigger a server call to HUMAN servers every time that operation is performed.
If an operation type (e.g., query
, mutation
) is configured in px_sensitive_graphql_operation_types
, all GraphQL operations of that type will be treated as sensitive. If an operation name is configured in px_sensitive_graphql_operation_names
, all GraphQL operations with that name will be treated as sensitive.
Sensitive GraphQL Operation Types
Sets the list of one or more operation types (e.g., query, mutation)
Default: nil (none)
--data 'config.px_sensitive_graphql_operation_types=Type1,Type2,Type3'
Sensitive GraphQL operation names
Sets the list of one or more operation names
Default: nil (none)
--data 'config.px_sensitive_graphql_operation_names=Name1,Name2,Name3'
Sensitive GraphQL routes
Sets the list of one or more GraphQL routes.
Default: /graphql
--data 'config.px_graphql_routes=/graphql, /graphql/csrf'
Multiple App Support
The HUMAN Enforcer allows for multiple configurations for different apps.
If your HUMAN account contains several Applications (as defined via the portal), follow these steps to create different configurations for each Application.
Since Kong supports multiple APIs, you can also use the same HUMAN Application with different configuration for different APIs, but for best results in our detection,
it is best to use different Applications and policies for different APIs.
Additional Activity Handler
Adding an additional activity handler is done by setting the `additional_activity_handler`Â property with a user defined function. The `additional_activity_handler` function is executed before data is sent to the HUMAN Portal.
Because of technical limitations of the Kong platform, you cannot set this function using the admin API. Instead, you need to edit the HUMAN plugin's handler.lua
file, and add the function directly to the configuration.
Default: None
function additional_activity_handler(event_type, ctx, details)
local cjson = require "cjson"
if (event_type == 'block') then
ngx.log(ngx.ERR, "PerimeterX: [" .. event_type .. "] blocked with score: " .. ctx.block_score .. ". Details: " .. cjson.encode(details))
else
ngx.log(ngx.ERR, "PerimeterX: [" .. event_type .. "]. Details: " .. cjson.encode(details))
end
end
function PXHandler:init_worker(config)
PXHandler.super.init_worker(self)
...
config.additional_activity_handler = additional_activity_handler
end
Allowing
Allowing (bypassing enforcement) is configured under in the whitelist
table.
There are several different types of filters that can be configured.
whitelist_uri_full = { _M.custom_block_url },
whitelist_uri_prefixes = {},
whitelist_uri_suffixes = {'.css', '.bmp', '.tif', '.ttf', '.docx', '.woff2', '.js', '.pict', '.tiff', '.eot', '.xlsx', '.jpg', '.csv', '.eps', '.woff', '.xls', '.jpeg', '.doc', '.ejs', '.otf', '.pptx', '.gif', '.pdf', '.swf', '.svg', '.ps', '.ico', '.pls', '.midi', '.svgz', '.class', '.png', '.ppt', '.mid', 'webp', '.jar'},
whitelist_ip_addresses = {},
whitelist_ua_full = {},
whitelist_ua_sub = {}
- whitelist_uri_full : for value
{'/api_server_full'}
- will filter requests to/api_server_full?data=1
but not to/api_server?data=1
- whitelist_uri_prefixes : for value
{'/api_server'}
- will filter requests to/api_server_full?data=1
but not to/full_api_server?data=1
- whitelist_uri_suffixes : for value
{'.css'}
- will filter requests to/style.css
but not to/style.js
- whitelist_ip_addresses : for value
{'192.168.99.1'}
- will filter requests coming from any of the listed ips. - whitelist_ua_full : for value
{'Mozilla/5.0 (compatible; pingbot/2.0; http://www.pingdom.com/)'}
- will filter all requests matching this exact UA. - whitelist_ua_sub : for value
{'GoogleCloudMonitoring'}
- will filter requests containing the provided string in their UA.
Contributing
Fork/Clone
Create a fork of the repository, and clone it locally.
Create a branch on your fork, preferably using a descriptive branch name.
Pull Request
After you have completed the process, create a pull request. Please provide a complete and thorough description explaining the changes. Remember, this code has to be read by our maintainers, so keep it simple, smart and accurate.
Updated 9 days ago