Installation
  • 03 Apr 2024
  • Dark
    Light

Installation

  • Dark
    Light

Article Summary

The HUMAN Fastly VCL Enforcer uses many Fastly features and functionalities. Installing the enforcer can be done in the following steps:

  • Ensure all prerequisites are satisfied.
  • Add the HUMAN Enforcer VCL files, snippets, conditions, and logging endpoints.
  • Configure the HUMAN Enforcer using the PX_CONFIGS and PX_CUSTOM VCL files.
  • Modify the MAIN VCL file (or upload a default one) to invoke the enforcer flow.

Prerequisites

1. Enable HUMAN Support.

In order to enable the HUMAN support on your Fastly service, the HUMAN Fastly Enforcer requires advanced functionality from Fastly.

Send the following e-mail to support@fastly.com:

  • Subject: "Please enable HUMAN support for our Fastly service ID"
  • Body: Please enable HUMAN support for our service ID and confirm when it is completed.

Once Fastly enables HUMAN support, the following pragmas should be enabled at your service:

  • fix_unsent_body_drain - pragma that can be used in VCL to resolve an issue with HTTP response bodies not being fully sent to the client.
  • no_body_if_bereq_is_get_or_head - pragma that can be used in VCL to prevent a response body from being sent to the client if the request method is GET or HEAD.

You must request to enable functionality for each service ID that is being protected by HUMAN. If this functionality is not enabled, requests will fail with a 503 Service Unavailable error.

How to Verify

To check that the required pragmas are enabled, open the generated VCL file in your Fastly service and look for the following lines at the pragmas section at the top of the file:

Screenshot 2024-03-26 at 12.37.59.png

If both the fix_unsent_body_drain and no_body_if_bereq_is_get_or_head pragmas are there, HUMAN has been enabled for the service.

2. Set the Risk Cookie to V2 (Binary Score Cookie).

In order to use Fastly VCL integration, a binary score risk cookie must be defined in the HUMAN Portal.

HUMAN Portal Permissions

If you don't have permissions in the HUMAN Portal to perform the following steps, contact your HUMAN Solution Architect or HUMAN Support so they can make the required changes.

  1. Log into the HUMAN Security portal.
  2. Navigate to Products > Bot Defender > Policy Settings.
  3. Select the desired Policy Name and then click on Risk Cookie - Advanced in the Policy Information section.
  4. Under Select Cookie Version/s, ensure that only V2 is selected. Set the threshold score to 100 (or to the value provided by the HUMAN Support team).
  5. Click apply changes.

Uploading the HUMAN Enforcer Files

The HUMAN Fastly VCL Enforcer comprises logging endpoints, snippets, conditions, and custom VCL files. All these components work together to provide the required enforcement functionality.

Before starting the integration process, we recommend that any existing custom VCL files and snippets be reviewed by a HUMAN Solution Architect. Contact your HUMAN Solution Architect or HUMAN Support for more information.

1. Add the required Custom VCL files.

The HUMAN Fastly VCL Enforcer consists of 3 custom VCL files that need to be uploaded to your service. These three files define the logic, configurations, and desired customizations for the VCL enforcer. These VCL files will be provided to you by a HUMAN Solution Architect.

You may upload the files via the Fastly Console by following the instructions here or you can create the VCL files using the Fastly API or Fastly CLI.

Provided FileVCL File Name*Explanation
px.vclPXContains all the internal HUMAN core logic. This file should never be modified.
px_configs.vclPX_CONFIGSContains the enforcer configuration table and additional backend configs. This file may be modified.
px_custom.vclPX_CUSTOMContains the enforcer custom code, defined custom behavior and enforcer features. This file may be modified.

* VCL file names are case-sensitive.

Reserved Error Codes

The HUMAN Enforcer logic reserves a few error codes for specific cases to help navigate between different Fastly workflow states. These error codes should remain unused by other VCL logic in the Fastly services, as using any of the following codes may lead to unexpected behavior.

Error CodeMeaning
990custom_preflight_handler
991first_party_disabled
992first_party_xhr_disabled
995exceeded_rate_limit, s2s_high_score, cookie_high_score
996cookie_high_score

2. Add the required Logging Endpoints.

The HUMAN Enforcer uses two HTTPS logging endpoints: PX-Async-Activities and PX-Telemetry. The PX-Async-Activities logging endpoint sends asynchronous activities (e.g., page_requested, block) to HUMAN's servers. The PX-Telemetry endpoint enables the telemetry feature, which can send on-demand data about the enforcer configuration to HUMAN.

If you're using the Fastly Console, create the logging endpoints with the following settings (for any field not mentioned, use the default value).

  • PX-Async-Activities
    • Name: PX-Async-Activities
    • URL: https://fastly-async.perimeterx.com/api/v1/collector/s2s
    • Placement: none
    • Advanced Options
      • Content type: application/json
      • JSON log entry format: Array of JSON
  • PX-Telemetry
    • Name: PX-Telemetry
    • URL: https://fastly-async.perimeterx.com/api/v2/risk/telemetry
    • Placement: none
    • Maximum Logs: 1
    • Advanced Options
      • Content type: application/json

If you're using the Fastly API or Fastly CLI, the following JSON objects can be used to generate these same logging endpoints.

{
  "content_type": "application/json",
  "json_format": "1",
  "name": "PX-Async-Activities",
  "placement": "none",
  "url": "https://fastly-async.perimeterx.com/api/v1/collector/s2s"
}
{
  "content_type": "application/json",
  "json_format": "0",
  "name": "PX-Telemetry",
  "placement": "none",
  "url": "https://fastly-async.perimeterx.com/api/v2/risk/telemetry",
  "request_max_entries": 1
}

3. Add the required VCL Snippets.

VCL Snippets are small bits of logic that can be included and invoked at various points in the Fastly service. While most of the Enforcer logic is contained in the custom VCL files, snippets are required when it is necessary to modify the logic inside Fastly's default macros (more information here).

The px_shield snippet is required for Fastly Shielding functionality to stay enabled after a restart triggered by the Enforcer. See more information on enabling and disabling shielding here.

If you're using the Fastly Console, create the snippet with the following settings (for any field not mentioned, use the default value).

  • px_shield
    • Name: px_shield
    • Type: within subroutine - recv (vcl_recv)
    • VCL: set var.fastly_req_do_shield = (req.restarts == 0 || (req.restarts == 1 && req.http.px-tmp:internal-flow == "1"));
    • Advanced Options:
      • Priority: 1

If you're using the Fastly API or Fastly CLI, the following JSON object can be used to generate the same snippet.

{
    "name": "px_shield",
    "dynamic": "0",
    "type": "recv",
    "content": "set var.fastly_req_do_shield = (req.restarts == 0 || (req.restarts == 1 && req.http.px-tmp:internal-flow == \"1\"));",
    "priority": "1"
}

4. Add the optional WAF Prefetch Condition.

This step is not applicable if using Fastly Next-Gen (Signal Sciences) WAF. If you are using Fastly Next-Gen (Signal Sciences) WAF, reach out to your HUMAN Solution Architect.

If you are using Fastly WAF, we recommend adding condition to your Fastly service to address a potential issue that may arise from running WAF rules multiple times. This condition will effectively prevent the duplication of WAF activations and ensure a smoother operation of the integration for customers who have enabled Fastly WAF but have not implemented the WAF prefetch condition.

If you're using the Fastly Console, create the condition with the following settings (for any field not mentioned, use the default value).

  • PX-Waf-Prefetch-Condition
    • Name: PX-Waf-Prefetch-Condition
    • Type: prefetch
    • Apply If: req.backend.is_origin && !req.http.bypasswaf
    • Advanced Options:
      • Priority: 10

If you're using the Fastly API or Fastly CLI, the following JSON object can be used to generate the same condition.

{
    "name": "PX-Waf-Prefetch-Condition",
    "comment": "Condition to prevent duplicate activations of the WAF",
    "priority": "10",
    "type": "PREFETCH",
    "statement": "req.backend.is_origin && !req.http.bypasswaf"
}

5. Add the optional Logging Endpoints.

The HUMAN Fastly Enforcer can send messages about the Fastly request flow to logging endpoints configured in the Fastly Service. The enforcer can send two kinds of logs depending on the configured px_logger_severity: debug and error.

To receive enforcer logs, follow the steps below:

  1. Set the px_logger_severity configuration in the PX_CONFIG VCL file to the logging level desired. If error logs are desired, set px_enable_error_logs to "true".
  2. Create a logging endpoint with the name PX-Debug or PX-Error. Depending on the logging endpoint type, you'll have to configure where you want the logs to go (e.g., URL). Other settings can typically stay as the default values.
  3. Activate the service.
Need a Quick Logging Endpoint?

If you need to turn on enforcer logs temporarily and you don't have an existing logging endpoint where you can easily view the logs, Fastly's online log viewer may provide a quick and easy solution.

Configure the HUMAN Enforcer

1. Add your configurations to the PX_CONFIGS file.

The PX_CONFIGS file declares a Fastly VCL table named px_configs. This table is where the enforcer configuration is defined. All possible configurations for this table are documented here. At a minimum, the px_configs table should contain the application ID, authentication token, and cookie secret associated with your application.

table px_configs {
    "px_app_id": "<PX_APP_ID>",
    "px_cookie_secret": "<PX_COOKIE_SECRET>",
    "px_auth_token": "<PX_AUTH_TOKEN>"
}

The PX_CONFIGS file also declares a Fastly backend named PX_API . This backend will be used to execute Risk API requests. The only value that should be changed here is the value of .host, in which <PX_APP_ID> should be replaced with your application's ID. (For instance, if your app ID is PX12345678, then the .host value of the PX_API backend should be set to sapi-PX12345678.perimeterx.net.)

backend PX_API {
    # ...
    .host = "sapi-<PX_APP_ID>.perimeterx.net";
    # ...
}

All other settings in this file can be left as is.

2. Add custom logic to the PX_CUSTOM file.

The PX_CUSTOM file serves as an extension of the PX_CONFIGS file where more complicated configurations and custom enforcer logic can be defined. The implementations of the subroutines defined in this file can be modified to customize the enforcer behavior as desired. Explanations and sample implementations of all the subroutines are documented here.

Modify (or Add) the MAIN VCL File

There is no single entry point for VCL code. Instead, Fastly exposes a number of different subroutines that function as "hooks" during the various stages of the VCL request lifecycle. These specific subroutines (e.g., vcl_recv, vcl_deliver) must be defined in a special custom VCL file known as the MAIN file. Fastly uses a boilerplate MAIN file if one is not explicitly set.

Integrating the HUMAN enforcer into the MAIN VCL requires invoking the appropriate HUMAN subroutine in every VCL hook subroutine.

VCL Hook SubroutineHUMAN Enforcer Subroutine
vcl_recvpx_recv, px_recv_clustering_fixup*
vcl_hash-
vcl_hit-
vcl_misspx_miss
vcl_passpx_pass
vcl_fetchpx_fetch
vcl_deliverpx_deliver
vcl_errorpx_error
vcl_log-

* px_recv_clustering_fixup should be called after the #FASTLY recv macro.

If you DO NOT have an existing MAIN VCL file...

We recommend using our default MAIN VCL file, which is Fastly's boilerplate MAIN file with the HUMAN enforcer subroutines already added in all the right places.

The default MAIN VCL file code is available here:

include "PX_CONFIGS"
include "PX_CUSTOM"
include "PX"

sub vcl_recv {
    call px_recv;
#FASTLY recv
    call px_recv_clustering_fixup;

    # Normally, you should consider requests other than GET and HEAD to be uncacheable
    # (to this we add the special FASTLYPURGE method)
    if (req.method != "HEAD" && req.method != "GET" && req.method != "FASTLYPURGE") {
        return(pass);
    }

    return(lookup);
}

sub vcl_hash {
    #FASTLY hash
    set req.hash += req.http.host;
    set req.hash += req.url;
    return(hash);
}

sub vcl_hit {
#FASTLY hit
    return(deliver);
}

sub vcl_miss {
    call px_miss;
#FASTLY miss
    return(fetch);
}

sub vcl_pass {
    call px_pass;
#FASTLY pass
    return(pass);
}

sub vcl_fetch {
    call px_fetch;
#FASTLY fetch

    # In the event of a server-failure response from origin, retry once more
    if ((beresp.status == 500 || beresp.status == 503) && (req.restarts < 1 || is_px_server_failure()) && (req.method == "GET" || req.method == "HEAD")) {
        restart;
    }

    # Log the number of restarts for debugging purposes
    if (req.restarts > 0) {
        set beresp.http.Fastly-Restarts = req.restarts;
    }

    # If the response is setting a cookie, make sure it is not cached
    if (beresp.http.Set-Cookie) {
        return(pass);
    }

    # By default we set a TTL based on the `Cache-Control` header but we don't parse additional directives
    # like `private` and `no-store`.  Private in particular should be respected at the edge:
    if (beresp.http.Cache-Control ~ "(private|no-store)") {
        return(pass);
    }

    # If no TTL has been provided in the response headers, set a default
    if (!beresp.http.Expires && !beresp.http.Surrogate-Control ~ "max-age" && !beresp.http.Cache-Control ~ "(s-maxage|max-age)") {
        set beresp.ttl = 3600s;
    }

    return(deliver);
}

sub vcl_error {
    call px_error;
#FASTLY error
    return(deliver);
}

sub vcl_deliver {
    call px_deliver;
#FASTLY deliver
    return(deliver);
}

sub vcl_log {
#FASTLY log
}

It should look very similar to the boilerplate MAIN VCL file provided by Fastly.

If you DO have an existing MAIN VCL file...

Add the HUMAN Enforcer subroutines (e.g., px_recv, px_deliver) to your VCL hooks (e.g., vcl_recv, vcl_deliver) one by one. Follow these guidelines when adding these subroutine calls:

  • The HUMAN subroutines should be called as early as possible in the defined hook. This is because the subroutines use request headers and return statements to switch between different Fastly states and apply HUMAN enforcement logic only when necessary. Plus, calling the enforcement flow in the very beginning helps avoid invoking business logic unnecessarily.
  • The HUMAN subroutines should always be called before the Fastly macro (e.g., #FASTLY recv, #FASTLY deliver).

The only exception to the above is the px_recv_clustering_fixup subroutine, which should be called immediately after the #FASTLY recv macro.

RECV

sub vcl_recv {
    call px_recv;
    # ...
#FASTLY recv
    call px_recv_clustering_fixup;
    # ...
}

MISS

sub vcl_miss {
    call px_miss;
    # ...
#FASTLY miss
    # ...
}

PASS

sub vcl_pass {
    call px_pass;
    # ...
#FASTLY pass
    # ...
}

FETCH

sub vcl_fetch {
    call px_fetch;
    # ...
#FASTLY fetch
    # ...
}

DELIVER

sub vcl_deliver {
    call px_deliver;
    # ...
#FASTLY deliver
    # ...
}

ERROR

sub vcl_error {
    call px_error;
    # ...
#FASTLY error
    # ...
}

Was this article helpful?

What's Next