Skip to main content

Control access to the content with country, referrer, IP, and user agents policies

Country, referrer, IP, and user agent policies limit which requests a CDN resource accepts. The list on each policy is the set of exceptions to the selected mode.

Access policies

Allow by default accepts every request except the listed values, while Block by default accepts only the listed values.

  1. 1

    Open Access

    In the CDB Technical Web Portal, navigate to CDN:

    1. Open the resource.
    2. Select Access.
  2. 2

    Set the policy mode

    Turn on the policy, then select Allow by default or Block by default.

  3. 3

    Save the resource

    Click Save changes.

Referrer

A referrer policy checks the domain that sent the request. Turn on Enable referrer access policy.

Referrer access policy with Allow by default selected
Referrer access policy with Block by default selected

Enter a domain or a wildcard, with no scheme:

  • www.domain.com matches that domain
  • *.domain.com matches every subdomain of domain.com

Country

Unlike a referrer, a country policy checks where the request comes from. Turn on Enable country access policy.

Country access policy with Allow by default selected
Country access policy with Block by default selected

The Choose a country field takes a two-letter uppercase ISO 3166-1 alpha-2 code.

IP address

An IP policy checks the client address, and it accepts both IPv4 and IPv6. Turn on Enable IP access policy.

IP access policy with Allow by default selected
IP access policy with Block by default selected

Enter an address with a prefix in IP with a subnet mask. The CDN stores it as a network address, so 192.168.3.2 becomes 192.168.3.2/32.

User agent

A user agent policy checks the User-Agent header, and it also accepts an empty value or a pattern. Turn on Enable user agents policy.

User agents policy with Block by default selected

The User-Agent field accepts an Empty value, an exact string of at most 220 characters, or a pattern. Empty value matches a request that sends no User-Agent header.

Empty value in the User-Agent field

A pattern starts with ~ for case-sensitive matching, or with ~* for case-insensitive matching. Select at least one entry, and allow 15 minutes for the change to take effect.

country_acl, referrer_acl, ip_address_acl, and user_agent_acl limit which requests a CDN resource accepts.

When policy_type is allow, every request is accepted except the values in excepted_values, while deny accepts only those values.

allow matches Allow by default, while deny matches Block by default.

policy_type accepts allow or deny, and any other value, including block, returns HTTP 400.

enabled, policy_type, and excepted_values are required. An empty excepted_values list returns HTTP 400.

Omit a field to leave that policy unset.

An API token is required.

Export these variables. CDN_RESOURCE_ID is the id from list CDN resources.

export GCORE_API_KEY="{YOUR_API_KEY}"
export CDN_RESOURCE_ID="{YOUR_RESOURCE_ID}"

Policy values

The four objects share enabled, policy_type, and excepted_values. Only the contents of excepted_values change.

Country codes

excepted_values takes two-letter uppercase country codes, so DE is stored, while de and USA return HTTP 400.

Send country_acl with policy_type allow and excepted_values set to DE.

import os

from gcore import CDB

client = CDB()
resource_id = int(os.environ["CDN_RESOURCE_ID"])

resource = client.cdn.cdn_resources.update(
    resource_id,
    options={
        "country_acl": {
            "enabled": True,
            "policy_type": "allow",
            "excepted_values": ["DE"],
        },
    },
)
print(
    resource.options.country_acl.enabled,
    resource.options.country_acl.policy_type,
    resource.options.country_acl.excepted_values,
)
package main

import (
    "context"
    "fmt"
    "os"
    "strconv"

    gcore "github.com/G-Core/gcore-go"
    "github.com/G-Core/gcore-go/cdn"
)

func main() {
    client := gcore.NewClient()
    ctx := context.Background()
    resourceID, err := strconv.ParseInt(os.Getenv("CDN_RESOURCE_ID"), 10, 64)
    if err != nil {
        panic(err)
    }

    resource, err := client.CDN.CDNResources.Update(ctx, resourceID, cdn.CDNResourceUpdateParams{
        Options: cdn.CDNResourceUpdateParamsOptions{
            CountryACL: cdn.CDNResourceUpdateParamsOptionsCountryACL{
                Enabled:        true,
                PolicyType:     "allow",
                ExceptedValues: []string{"DE"},
            },
        },
    })
    if err != nil {
        panic(err)
    }
    fmt.Println(resource.Options.CountryACL.Enabled, resource.Options.CountryACL.PolicyType, resource.Options.CountryACL.ExceptedValues)
}
curl -X PATCH "https://api.cdb-staging.cdn.orange.com/cdn/resources/$CDN_RESOURCE_ID" \
  -H "Authorization: APIKey $GCORE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "options": {
      "country_acl": {
        "enabled": true,
        "policy_type": "allow",
        "excepted_values": ["DE"]
      }
    }
  }'

The API returns HTTP 200:

{
  "id": 12345,
  "options": {
    "country_acl": {
      "enabled": true,
      "policy_type": "allow",
      "excepted_values": ["DE"]
    }
  }
}

Referrer domains

Unlike a country code, a referrer value is a domain or a *. wildcard, with no URL scheme. A value that includes a scheme returns HTTP 400.

none together with a domain is stored, while a list that contains only none returns HTTP 400.

Send referrer_acl with policy_type deny and a wildcard in excepted_values.

import os

from gcore import CDB

client = CDB()
resource_id = int(os.environ["CDN_RESOURCE_ID"])

resource = client.cdn.cdn_resources.update(
    resource_id,
    options={
        "referrer_acl": {
            "enabled": True,
            "policy_type": "deny",
            "excepted_values": ["*.example.com"],
        },
    },
)
print(
    resource.options.referrer_acl.enabled,
    resource.options.referrer_acl.policy_type,
    resource.options.referrer_acl.excepted_values,
)
package main

import (
    "context"
    "fmt"
    "os"
    "strconv"

    gcore "github.com/G-Core/gcore-go"
    "github.com/G-Core/gcore-go/cdn"
)

func main() {
    client := gcore.NewClient()
    ctx := context.Background()
    resourceID, err := strconv.ParseInt(os.Getenv("CDN_RESOURCE_ID"), 10, 64)
    if err != nil {
        panic(err)
    }

    resource, err := client.CDN.CDNResources.Update(ctx, resourceID, cdn.CDNResourceUpdateParams{
        Options: cdn.CDNResourceUpdateParamsOptions{
            ReferrerACL: cdn.CDNResourceUpdateParamsOptionsReferrerACL{
                Enabled:        true,
                PolicyType:     "deny",
                ExceptedValues: []string{"*.example.com"},
            },
        },
    })
    if err != nil {
        panic(err)
    }
    fmt.Println(resource.Options.ReferrerACL.Enabled, resource.Options.ReferrerACL.PolicyType, resource.Options.ReferrerACL.ExceptedValues)
}
curl -X PATCH "https://api.cdb-staging.cdn.orange.com/cdn/resources/$CDN_RESOURCE_ID" \
  -H "Authorization: APIKey $GCORE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "options": {
      "referrer_acl": {
        "enabled": true,
        "policy_type": "deny",
        "excepted_values": ["*.example.com"]
      }
    }
  }'

The API returns HTTP 200:

{
  "id": 12345,
  "options": {
    "referrer_acl": {
      "enabled": true,
      "policy_type": "deny",
      "excepted_values": ["*.example.com"]
    }
  }
}

IP addresses

An IP value checks the client address rather than a name. 192.168.3.2/32, 10.0.0.0/8, and 2a03:d000:2980:7::8/128 are stored, while the host address 192.168.3.2 is stored as 192.168.3.2/32.

Send ip_address_acl with policy_type allow and excepted_values set to 192.168.3.2/32.

import os

from gcore import CDB

client = CDB()
resource_id = int(os.environ["CDN_RESOURCE_ID"])

resource = client.cdn.cdn_resources.update(
    resource_id,
    options={
        "ip_address_acl": {
            "enabled": True,
            "policy_type": "allow",
            "excepted_values": ["192.168.3.2/32"],
        },
    },
)
print(
    resource.options.ip_address_acl.enabled,
    resource.options.ip_address_acl.policy_type,
    resource.options.ip_address_acl.excepted_values,
)
package main

import (
    "context"
    "fmt"
    "os"
    "strconv"

    gcore "github.com/G-Core/gcore-go"
    "github.com/G-Core/gcore-go/cdn"
)

func main() {
    client := gcore.NewClient()
    ctx := context.Background()
    resourceID, err := strconv.ParseInt(os.Getenv("CDN_RESOURCE_ID"), 10, 64)
    if err != nil {
        panic(err)
    }

    resource, err := client.CDN.CDNResources.Update(ctx, resourceID, cdn.CDNResourceUpdateParams{
        Options: cdn.CDNResourceUpdateParamsOptions{
            IPAddressACL: cdn.CDNResourceUpdateParamsOptionsIPAddressACL{
                Enabled:        true,
                PolicyType:     "allow",
                ExceptedValues: []string{"192.168.3.2/32"},
            },
        },
    })
    if err != nil {
        panic(err)
    }
    fmt.Println(resource.Options.IPAddressACL.Enabled, resource.Options.IPAddressACL.PolicyType, resource.Options.IPAddressACL.ExceptedValues)
}
curl -X PATCH "https://api.cdb-staging.cdn.orange.com/cdn/resources/$CDN_RESOURCE_ID" \
  -H "Authorization: APIKey $GCORE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "options": {
      "ip_address_acl": {
        "enabled": true,
        "policy_type": "allow",
        "excepted_values": ["192.168.3.2/32"]
      }
    }
  }'

The API returns HTTP 200:

{
  "id": 12345,
  "options": {
    "ip_address_acl": {
      "enabled": true,
      "policy_type": "allow",
      "excepted_values": ["192.168.3.2/32"]
    }
  }
}

User agent strings

A user agent value can be an exact string, an empty string, or a pattern, unlike the names and addresses above.

A pattern starts with ~ for case-sensitive matching, or with ~* for case-insensitive matching. Each value can contain at most 220 characters, so a value of 221 characters returns HTTP 400.

Send user_agent_acl with policy_type deny and excepted_values set to an empty string and ~*mozilla.*.

import os

from gcore import CDB

client = CDB()
resource_id = int(os.environ["CDN_RESOURCE_ID"])

resource = client.cdn.cdn_resources.update(
    resource_id,
    options={
        "user_agent_acl": {
            "enabled": True,
            "policy_type": "deny",
            "excepted_values": ["", "~*mozilla.*"],
        },
    },
)
print(
    resource.options.user_agent_acl.enabled,
    resource.options.user_agent_acl.policy_type,
    resource.options.user_agent_acl.excepted_values,
)
package main

import (
    "context"
    "fmt"
    "os"
    "strconv"

    gcore "github.com/G-Core/gcore-go"
    "github.com/G-Core/gcore-go/cdn"
)

func main() {
    client := gcore.NewClient()
    ctx := context.Background()
    resourceID, err := strconv.ParseInt(os.Getenv("CDN_RESOURCE_ID"), 10, 64)
    if err != nil {
        panic(err)
    }

    resource, err := client.CDN.CDNResources.Update(ctx, resourceID, cdn.CDNResourceUpdateParams{
        Options: cdn.CDNResourceUpdateParamsOptions{
            UserAgentACL: cdn.CDNResourceUpdateParamsOptionsUserAgentACL{
                Enabled:        true,
                PolicyType:     "deny",
                ExceptedValues: []string{"", "~*mozilla.*"},
            },
        },
    })
    if err != nil {
        panic(err)
    }
    fmt.Println(resource.Options.UserAgentACL.Enabled, resource.Options.UserAgentACL.PolicyType, resource.Options.UserAgentACL.ExceptedValues)
}
curl -X PATCH "https://api.cdb-staging.cdn.orange.com/cdn/resources/$CDN_RESOURCE_ID" \
  -H "Authorization: APIKey $GCORE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "options": {
      "user_agent_acl": {
        "enabled": true,
        "policy_type": "deny",
        "excepted_values": ["", "~*mozilla.*"]
      }
    }
  }'

The API returns HTTP 200:

{
  "id": 12345,
  "options": {
    "user_agent_acl": {
      "enabled": true,
      "policy_type": "deny",
      "excepted_values": ["", "~*mozilla.*"]
    }
  }
}

Limit which requests a CDN resource accepts with the Terraform provider v2. When policy_type is allow, every request is accepted except the values in excepted_values, while deny accepts only those values. An empty excepted_values list returns HTTP 400 and the message This list may not be empty. Run terraform apply after editing options.

Access policy values

The four objects use enabled, policy_type, and excepted_values. country_acl set to allow with DE accepts every country except DE, while referrer_acl set to deny accepts only the wildcard in excepted_values, and that value has no URL scheme. ip_address_acl set to allow with 192.168.3.2/32 accepts every address except that network, and a host address without a prefix is stored with /32, so 192.168.3.2 becomes 192.168.3.2/32. user_agent_acl set to deny with an empty string and ~*mozilla.* accepts a missing User-Agent header and a case-insensitive match of mozilla.*.

resource "gcore_cdn_origin_group" "example" {
  name = "my-origin-group"

  sources = [
    {
      source  = "example.com"
      enabled = true
    }
  ]
}

resource "gcore_cdn_resource" "example" {
  cname           = "cdn.example.com"
  origin_group    = gcore_cdn_origin_group.example.id
  origin_protocol = "HTTPS"

  options = {
    country_acl = {
      enabled         = true
      policy_type     = "allow"
      excepted_values = ["DE"]
    }

    referrer_acl = {
      enabled         = true
      policy_type     = "deny"
      excepted_values = ["*.example.com"]
    }

    ip_address_acl = {
      enabled         = true
      policy_type     = "allow"
      excepted_values = ["192.168.3.2/32"]
    }

    user_agent_acl = {
      enabled         = true
      policy_type     = "deny"
      excepted_values = ["", "~*mozilla.*"]
    }
  }
}