Skip to main content

Block and allow traffic by country, IP and list

You create source policies for country and IP rules, reuse a custom IP list and assign the policies to a group.

Note: Balancer is in beta. Endpoints, fields and behavior may change before general availability, and the feature must be enabled on your account before use. Contact your NetActuate account manager to request access.

Prerequisites​

  • Balancer access and a key in the BALANCER_API_KEY environment variable with permission for these operations.
  • The API host shown in the Balancer portal. Replace <your-api-host> in every example with that host.
  • A shell, curl and Python 3 for examples that build JSON from environment variables.
  • An HTTP group and reviewed source ranges and country codes. The documentation range is an example; use your own trusted range when configuring access.

Resource identifiers come from your API responses. Set each variable when its value is available, before the first step that uses it.

Environment variableValue
ALLOW_POLICY_IDReturned resource identifier, or your selected scope identifier.
BLOCK_POLICY_IDReturned resource identifier, or your selected scope identifier.
CUSTOM_LIST_IDReturned resource identifier, or your selected scope identifier.
GROUP_IDReturned resource identifier, or your selected scope identifier.
HTTP_LB_IDReturned resource identifier, or your selected scope identifier.

For an identifier, enter the value returned for your resource and export it:

read -r -p 'ALLOW_POLICY_ID: ' ALLOW_POLICY_ID
export ALLOW_POLICY_ID

Steps​

  1. Create a reusable IP list.

    curl --silent --show-error --include \
    --request POST \
    --url "https://<your-api-host>/custom-lists" \
    --header "x-api-key: $BALANCER_API_KEY" \
    --header "Content-Type: application/json" \
    --data-binary '{"name":"trusted_ips","kind":"ip"}'

    API reference: Create a reusable account-wide custom list

    Expected: HTTP 200. The following shows the response fields to check; additional data depends on your saved resources. Resource identifiers are illustrative.

    {
    "code": 200,
    "result": "success",
    "data": {
    "customListId": 1
    }
    }

    Set CUSTOM_LIST_ID to the returned customListId.

  2. Add a range.

    curl --silent --show-error --include \
    --request POST \
    --url "https://<your-api-host>/custom-lists/$CUSTOM_LIST_ID/items" \
    --header "x-api-key: $BALANCER_API_KEY" \
    --header "Content-Type: application/json" \
    --data-binary '{"value":"192.0.2.0/24"}'

    API reference: Create one custom list item

    Expected: HTTP 200. The following shows the response fields to check; additional data depends on your saved resources. Resource identifiers are illustrative.

    {
    "code": 200,
    "result": "success",
    "data": {
    "customListItemId": 1
    }
    }
  3. Create an allow policy.

    curl --silent --show-error --include \
    --request POST \
    --url "https://<your-api-host>/allow-policies" \
    --header "x-api-key: $BALANCER_API_KEY" \
    --header "Content-Type: application/json" \
    --data-binary '{"name":"trusted_sources"}'

    API reference: Create a reusable allow policy

    Expected: HTTP 200. The following shows the response fields to check; additional data depends on your saved resources. Resource identifiers are illustrative.

    {
    "code": 200,
    "result": "success",
    "data": {
    "allowPolicyId": 1
    }
    }

    Set ALLOW_POLICY_ID to the returned allowPolicyId.

  4. Reference the trusted list.

    python3 - <<'PYBODY' | \
    curl --silent --show-error --include \
    --request POST \
    --url "https://<your-api-host>/allow-policies/$ALLOW_POLICY_ID/rules" \
    --header "x-api-key: $BALANCER_API_KEY" \
    --header "Content-Type: application/json" \
    --data-binary @-
    import json, os
    print(json.dumps({'rule': {'type': 'ip_custom_list', 'customListId': int(os.environ['CUSTOM_LIST_ID'])}}))
    PYBODY

    API reference: Create an allow policy rule

    Expected: HTTP 200. The following shows the response fields to check; additional data depends on your saved resources. Resource identifiers are illustrative.

    {
    "code": 200,
    "result": "success",
    "data": {
    "allowPolicyRuleId": 1
    }
    }
  5. Create a block policy.

    curl --silent --show-error --include \
    --request POST \
    --url "https://<your-api-host>/block-policies" \
    --header "x-api-key: $BALANCER_API_KEY" \
    --header "Content-Type: application/json" \
    --data-binary '{"name":"blocked_sources"}'

    API reference: Create a reusable block policy

    Expected: HTTP 200. The following shows the response fields to check; additional data depends on your saved resources. Resource identifiers are illustrative.

    {
    "code": 200,
    "result": "success",
    "data": {
    "blockPolicyId": 1
    }
    }

    Set BLOCK_POLICY_ID to the returned blockPolicyId.

  6. Block one country.

    curl --silent --show-error --include \
    --request POST \
    --url "https://<your-api-host>/block-policies/$BLOCK_POLICY_ID/rules" \
    --header "x-api-key: $BALANCER_API_KEY" \
    --header "Content-Type: application/json" \
    --data-binary '{"rule":{"type":"country","value":"BR"}}'

    API reference: Create a block policy rule

    Expected: HTTP 200. The following shows the response fields to check; additional data depends on your saved resources. Resource identifiers are illustrative.

    {
    "code": 200,
    "result": "success",
    "data": {
    "blockPolicyRuleId": 1
    }
    }
  7. Block an IP range.

    curl --silent --show-error --include \
    --request POST \
    --url "https://<your-api-host>/block-policies/$BLOCK_POLICY_ID/rules" \
    --header "x-api-key: $BALANCER_API_KEY" \
    --header "Content-Type: application/json" \
    --data-binary '{"rule":{"type":"ip_cidr","value":"198.51.100.0/24"}}'

    API reference: Create a block policy rule

    Expected: HTTP 200. The following shows the response fields to check; additional data depends on your saved resources. Resource identifiers are illustrative.

    {
    "code": 200,
    "result": "success",
    "data": {
    "blockPolicyRuleId": 1
    }
    }
  8. Assign both policies.

    python3 - <<'PYBODY' | \
    curl --silent --show-error --include \
    --request PATCH \
    --url "https://<your-api-host>/http-loadbalancers/$HTTP_LB_ID/groups/$GROUP_ID" \
    --header "x-api-key: $BALANCER_API_KEY" \
    --header "Content-Type: application/json" \
    --data-binary @-
    import json, os
    print(json.dumps({'allowPolicyId': int(os.environ['ALLOW_POLICY_ID']), 'blockPolicyId': int(os.environ['BLOCK_POLICY_ID'])}))
    PYBODY

    API reference: Update an HTTP group configuration

    Expected: HTTP 200. The following shows the response fields to check; additional data depends on your saved resources. Resource identifiers are illustrative.

    {
    "code": 200,
    "result": "success",
    "data": {
    "groupId": 1
    }
    }
  9. Read the effective assignment.

    curl --silent --show-error --include \
    --request GET \
    --url "https://<your-api-host>/http-loadbalancers/$HTTP_LB_ID/groups/$GROUP_ID" \
    --header "x-api-key: $BALANCER_API_KEY"

    API reference: Get HTTP group

    Expected: HTTP 200. The following shows the response fields to check; additional data depends on your saved resources. Resource identifiers are illustrative.

    {
    "code": 200,
    "result": "success",
    "data": {
    "groupId": 1
    }
    }

Verify​

Test from a controlled matching source and a source outside the rules. A source block returns 403 before origin. A source allow is evaluated before source blocking, request budgets and WAF. Under-attack handling can run earlier. For a literal allow, use an allow rule of type country or ip_cidr with its value; for a list block, use a block rule of type ip_custom_list with customListId.

Use your configured site domain in this traffic check:

curl --silent --show-error --include "https://example.com/"

Expected: the site behavior described above. The application response body and status depend on your origin and selected policies.

An API mutation saves desired configuration first. Readback and a live traffic check answer different questions. No fixed propagation time is established.

Troubleshooting​

SymptomCauseFix
Block is bypassedAn earlier source allow matchesReview trusted ranges and allow policy assignment.
List reference is rejectedList kind, ownership or permissions do not matchUse a same-account list of the expected kind.
Policy deletion failsA group or route still references itRemove assignments before deleting the policy.
Traffic returns 502Selected policy is missing or inactiveCheck the effective policy and its state.

Limits and defaults​

SettingLimit or default
Custom list nameMaximum 64 characters; starts with a lowercase letter; remaining characters are lowercase letters, digits or underscores
Custom list kindsip, asn, hostname or country
Source rule kindscountry, asn, ip_cidr, ip_custom_list, asn_custom_list or country_custom_list
Literal source ruleOne match value per rule
List item valueMaximum 255 characters
Active lists per account100
Active items per list1000
Active items per account10000

API status codes​

StatusMeaning
200Request succeeds; inspect returned data.
400Invalid arguments or configuration.
401Authentication or authorization denied.
404Resource or parent is unavailable.
409Resource state conflicts with the operation.
412Inspect the returned error details.
500The request encounters a server error.
  • DELETE /allow-policies/{allowPolicyId}
  • DELETE /allow-policies/{allowPolicyId}/rules/{allowPolicyRuleId}
  • DELETE /block-policies/{blockPolicyId}
  • DELETE /block-policies/{blockPolicyId}/rules/{blockPolicyRuleId}
  • DELETE /custom-lists/{customListId}
  • DELETE /custom-lists/{customListId}/items/{customListItemId}
  • GET /allow-policies
  • GET /allow-policies/{allowPolicyId}
  • GET /allow-policies/{allowPolicyId}/rules
  • GET /allow-policies/{allowPolicyId}/rules/{allowPolicyRuleId}
  • GET /block-policies
  • GET /block-policies/{blockPolicyId}
  • GET /block-policies/{blockPolicyId}/rules
  • GET /block-policies/{blockPolicyId}/rules/{blockPolicyRuleId}
  • GET /custom-lists
  • GET /custom-lists/{customListId}
  • GET /custom-lists/{customListId}/items
  • GET /http-loadbalancers/{httpLbId}/groups/{groupId}
  • PATCH /allow-policies/{allowPolicyId}
  • PATCH /allow-policies/{allowPolicyId}/rules/{allowPolicyRuleId}
  • PATCH /block-policies/{blockPolicyId}
  • PATCH /block-policies/{blockPolicyId}/rules/{blockPolicyRuleId}
  • PATCH /custom-lists/{customListId}
  • PATCH /http-loadbalancers/{httpLbId}/groups/{groupId}
  • POST /allow-policies
  • POST /allow-policies/{allowPolicyId}/rules
  • POST /block-policies
  • POST /block-policies/{blockPolicyId}/rules
  • POST /custom-lists
  • POST /custom-lists/{customListId}/items
  • PUT /custom-lists/{customListId}/items

API reference​

Need Help?​

Contact your account manager or use the Balancer portal.