Route on Subnet
This page describes how to write configuration for subnet-based routing. For configuration in general, see Configuration.
For details on the subnets API, see Subnets API.
Subnet-based routing can be done either by using session groups and classifiers or by using the subnets API, allowing large amounts of named subnets.
Session Group Classifiers
Routing on subnets can be done through a combination of session group classifiers and Lua script weight functions. Configuring session groups and classifiers based on subnets and using them in routing may look like:
$ confcli services.routing.classifiers -w
Running wizard for resource 'classifiers'
Hint: Hitting return will set a value to its default.
Enter '?' to receive the help string
classifiers : [
classifier can be one of
1: anonymousIp
2: asnIds
3: contentUrlPath
4: contentUrlQueryParameters
5: geoip
6: hostName
7: ipranges
8: random
9: regexMatcher
10: stringMatcher
11: subnet
12: userAgent
Choose element index or name: ipranges
Adding a 'ipranges' element
classifier : {
name (default: ): ip_ranges_classifier
type (default: ipranges): ⏎
inverted (default: False): ⏎
ipranges : [
iprange (default: ): 10.0.0.0/8
Add another 'iprange' element to array 'ipranges'? [y/N]: y
iprange (default: ): 192.168.0.0/16
Add another 'iprange' element to array 'ipranges'? [y/N]: y
iprange (default: ): 2001:0db8:85a3::/128
Add another 'iprange' element to array 'ipranges'? [y/N]: ⏎
]
}
Add another 'classifier' element to array 'classifiers'? [y/N]: ⏎
]
Generated config:
{
"classifiers": [
{
"name": "ip_ranges_classifier",
"type": "ipranges",
"inverted": false,
"ipranges": [
"10.0.0.0/8",
"192.168.0.0/16",
"2001:0db8:85a3::/128"
]
}
]
}
Merge and apply the config? [y/n]: y
$ confcli services.routing.sessionGroups -w
Running wizard for resource 'sessionGroups'
Hint: Hitting return will set a value to its default.
Enter '?' to receive the help string
sessionGroups : [
sessionGroup : {
name (default: ): allowed_subnets
classifiers : [
classifier (default: ): ip_ranges_classifier
Add another 'classifier' element to array 'classifiers'? [y/N]: ⏎
]
}
Add another 'sessionGroup' element to array 'sessionGroups'? [y/N]: ⏎
]
Generated config:
{
"sessionGroups": [
{
"name": "allowed_subnets",
"classifiers": [
"ip_ranges_classifier"
]
}
]
}
Merge and apply the config? [y/n]: y
{
"session_groups": [
{
"id": 1,
"name": "allowed_subnets",
"classifiers": [
[
{
"id": 1,
"inverted": false,
"name": "allowed_subnet_classifier",
"rule": {
"rule_type": "ip_ranges_rule",
"source": "session/client_ip",
"ip_ranges": ["10.0.0.0/8", "192.168.0.0/16", "2001:0db8:85a3::/128"]
}
}
]
]
}
]
}
The field ip_ranges
is a list of CIDR-notation strings, supporting both IPv4
and IPv6 format. Incoming requests have their IP tested against the listed
ranges. The classifier evaluates as true if any of the ranges in the
classifier’s list matches the IP address of the request.
These session groups can then be used in routing as follows:
$ confcli services.routing.rules -w
Running wizard for resource 'rules'
Hint: Hitting return will set a value to its default.
Enter '?' to receive the help string
rules : [
rule can be one of
1: allow
2: consistentHashing
3: contentPopularity
4: deny
5: firstMatch
6: random
7: rawGroup
8: rawHost
9: split
10: weighted
Choose element index or name: split
Adding a 'split' element
rule : {
name (default: ): subnet_split_node
type (default: split): ⏎
rule (default: ): return in_session_group('allowed_subnets')
onMatch (default: ): allowed-host
onMiss (default: ): offload-host
}
Add another 'rule' element to array 'rules'? [y/N]: ⏎
]
Generated config:
{
"rules": [
{
"name": "subnet_split_node",
"type": "split",
"condition": "in_session_group('allowed_subnets')",
"onMatch": "allowed-host",
"onMiss": "offload-host"
}
]
}
Merge and apply the config? [y/n]: y
$ confcli services.routing.entrypoint subnet_split_node
services.routing.entrypoint = 'subnet_split_node'
{
"content_server": {
"http_enable": true,
"http_port": 80,
"https_enable": true,
"https_port": 443
},
"cdns": [
{
"id": "allowed-cdn",
"http_port": 80,
"https_port": 443,
"redirecting": false,
"manifest_availability_check": {
"enabled": false,
"session_group_ids": []
}
},
{
"id": "offload-cdn",
"http_port": 80,
"https_port": 443,
"redirecting": false,
"manifest_availability_check": {
"enabled": false,
"session_group_ids": []
}
}
],
"hosts": [
{
"id": "allowed-host",
"cdn_id": "allowed-cdn",
"host": "allowed-host.example"
},
{
"id": "offload-host",
"cdn_id": "offload-cdn",
"host": "offload-host.example"
}
],
"routing": {
"id": "routing_table",
"member_order": "sequential",
"members": [
{
"id": "allowed-node",
"host_id": "allowed-host",
"weight_function": "return in_session_group('allowed_subnets')"
},
{
"id": "offload-node",
"host_id": "offload-host",
"weight_function": "return 1"
}
]
},
"session_groups": [
{
"id": 1,
"name": "allowed_subnets",
"classifiers": [
[
{
"id": 1,
"inverted": false,
"name": "allowed_subnet_classifier",
"rule": {
"rule_type": "ip_ranges_rule",
"source": "session/client_ip",
"ip_ranges": ["10.0.0.0/8", "192.168.0.0/16", "2001:0db8:85a3::/128"]
}
}
]
]
}
]
}
Named Subnets
Named subnets are injected into the router in the form of JSON payloads to the Subnets API. Once the subnet data has been fed to the router, Lua functions can access the subnet name associated with an incoming request and use the result when it performs routing.
Note that confcli
cannot be used to inject named subnets into the router.
Assume we have injected the following subnet configuration into the router:
{
"10.0.0.0/8": "test_net_4",
"192.168.0.0/16": "test_net_4",
"2001:0db8:85a3::/128": "test_net_6"
}
A router configuration using this subnet configuration can then be constructed as:
$ confcli services.routing.rules -w
Running wizard for resource 'rules'
Hint: Hitting return will set a value to its default.
Enter '?' to receive the help string
rules : [
rule can be one of
1: allow
2: consistentHashing
3: contentPopularity
4: deny
5: firstMatch
6: random
7: rawGroup
8: rawHost
9: split
10: weighted
Choose element index or name: split
Adding a 'split' element
rule : {
name (default: ): subnet_split_node
type (default: split): ⏎
rule (default: ): in_subnet('test_net_4')
onMatch (default: ): allowed-host-4
onMiss (default: ): offload-host
}
Add another 'rule' element to array 'rules'? [y/N]: ⏎
]
Generated config:
{
"rules": [
{
"name": "subnet_split_node",
"type": "split",
"condition": "in_subnet('test_net_4')",
"onMatch": "allowed-host-4",
"onMiss": "offload-host"
}
]
}
Merge and apply the config? [y/n]: y
$ confcli services.routing.entrypoint subnet_split_node
services.routing.entrypoint = 'subnet_split_node'
{
"content_server": {
"http_enable": true,
"http_port": 80,
"https_enable": true,
"https_port": 443
},
"cdns": [
{
"id": "allowed-cdn",
"http_port": 80,
"https_port": 443,
"redirecting": false,
"manifest_availability_check": {
"enabled": false,
"session_group_ids": []
}
},
{
"id": "offload-cdn",
"http_port": 80,
"https_port": 443,
"redirecting": false,
"manifest_availability_check": {
"enabled": false,
"session_group_ids": []
}
}
],
"hosts": [
{
"id": "allowed-host-4",
"cdn_id": "allowed-cdn",
"address_family": "ipv4",
"host": "allowed-host4.example"
},
{
"id": "allowed-host-6",
"cdn_id": "allowed-cdn",
"address_family": "ipv6",
"host": "allowed-host6.example"
},
{
"id": "offload-host",
"cdn_id": "offload-cdn",
"address_family": "ipv4",
"host": "offload-host.example"
}
],
"routing": {
"id": "routing_table",
"member_order": "sequential",
"members": [
{
"id": "allowed-node-4",
"host_id": "allowed-host-4",
"weight_function": "return in_subnet('test_net_4')"
},
{
"id": "allowed-node-6",
"host_id": "allowed-host-6",
"weight_function": "return in_subnet('test_net_6')"
},
{
"id": "offload-node",
"host_id": "offload-host",
"weight_function": "return 1"
}
]
}
}
Note the absence of session groups in this configuration, instead relying solely on the named subnet API to making routing decisions based on subnets.