Overview
StackPath provides WAF Enterprise customers with the ability to create, edit and manage their own advanced custom rules. Much like our basic custom rules, users are able to create rules using If/Then statements, but with an added level of sophistication.
Creating an Advanced Rule
Advanced Rules differ from basic WAF Custom Rules in that they support the use of more advanced conditions using CEL Syntax expressions.
Because of the highly technical aspect of this functionality, this ability is currently only available through our API. You can use our API documentation as a guide in constructing your own Advanced Rules
Please see Advanced Rules - Objects, Attributes, and Types for a list of all available objects you can use in your expressions along with their respective attributes and types and Advanced Rules - Source Field Objects for a list of the available source
field objects you can use in your expressions along with their respective attributes and types.
Advanced Rule Object
The Advanced Rule object contains the following properties:
{
"name": "string",
"source": "string",
"enabled": true,
"description": "string",
"phase": "EXECUTION_PHASE_UNSPECIFIED",
"ruleAction": {
"allow": {},
"block": {
"statusCode": "STATUS_CODE_UNSPECIFIED",
"actionDuration": "string"
},
"captcha": {},
"handshake": {},
"monitor": {},
"tag": {
"tags": [
"string"
]
}
}
}
|
The name of the rule |
Can contain only ASCII letters, numbers, spaces, periods, and colons |
|
|
The action to execute when a condition is true |
|
On tag action, the tag field should be provided On block action, setting up the |
|
The condition segment of the rule |
Can reference namespace objects: request, whois, session, response, tags, user_agent, client_data as well as use data and functions Support python operand syntax: and, or, in, not, ==, !=, >, <, etc. Support CEL operand syntax: ||, && |
Source namespace object will be covered in a separate table below. NOTE: every string value should warp with a |
|
Whether or not an Advanced WAF Rule is enabled |
Boolean: |
Default value: |
|
A string to describe the purpose of the rule |
Any string |
|
|
The request processing phase. |
|
Default value: |
|
A custom HTTP status code that the WAF returns if a rule blocks a request |
None (default: 403), 405, 403, 429, 418 |
Status code can be defined only when the |
|
The duration of an action |
A string with a number followed by: m - minutes s - seconds h - hours d - days i.e. |
When setting |
|
A user defined tag to attack the request |
String. Tags with spaces will be converted to underscore line |
Tag based rules are informative rules. NOTE: tag value should warp with |
Best Practices
You can use our API documentation as a guide in constructing your own Advanced Rules. Below are a few examples of Advances Rules created via our API using cURL.
Rate Limit
Block IPs that hit more than 200 requests per 5 seconds (changeable) when the following cookies do not exist (more examples can be found in our Rate Limitation guide):
curl --request POST \
--url https://gateway.stackpath.com/waf/v1alpha/stacks/test_stack_id/sites/test_site_id/advanced_rules \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--data '
{
"ruleAction": {"block": {"statusCode": "FORBIDDEN_403"}},
"phase": "ACCESS",
"name": "Block Scrappers",
"description": "Block IPs that hit more than 200 requests per 5 seconds for any `events` paths",
"enabled": false,
"source": "request.rate_limit([], '.*events', 5, 200, [], [], '', 'ip') and not ('mb-web-ui' in request.headers['Cookie'] or 'mb-mobile-ios' in request.headers['Cookie'] or 'mobile-android' in request.headers['Cookie'] or 'mb-mobile-android' in request.headers['Cookie'] or 'session-token' in request.headers['Cookie']) and not request.headers['session']"
}
'
Penalty Rule
Will block the IPs that were detected with certain TLS fingerprint for the next 5 minutes (chained rule):
curl --request POST \
--url https://gateway.stackpath.com/waf/v1alpha/stacks/test_stack_id/sites/test_site_id/advanced_rules \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--data '
{
"ruleAction": {"block": {"statusCode": "FORBIDDEN_403", "actionDuration": "5m"}},
"phase": "ACCESS",
"name": "Penalty TLS fingerprint",
"description": "Block and tag IPs that are detected with certain TLS finger print for the next 5 minutes",
"enabled": false,
"source": "request.ja3 == 'e2925c27149b0d0dc34373d55040dde1'"
}
'
curl --request POST \
--url https://gateway.stackpath.com/waf/v1alpha/stacks/test_stack_id/sites/test_site_id/advanced_rules \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--data '
{
"ruleAction": {"block": {}},
"phase": "ACCESS",
"name": "Block Penalty",
"description": "Block request that are detected with `penalty` tag",
"enabled": false,
"source": "tags.exists('penalty')"
}
'
Validate set of countries
Validate with JavaScript challenge IPs that are coming from the following countries without certain cookies:
curl --request POST \
--url https://gateway.stackpath.com/waf/v1alpha/stacks/test_stack_id/sites/test_site_id/advanced_rules \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--data '
{
"ruleAction": {"handshake": {}},
"phase": "ACCESS",
"name": "Validate set of countries",
"description": "Validate with JavaScript challenge IPs that are coming from the following countries",
"enabled": false,
"source": "whois.country in ['BR', 'VN', 'ID', 'TH', 'ME', 'XK', 'LK'] and not ('mb-web-ui' in request.headers['Cookie'] or 'mb-mobile-ios' in request.headers['Cookie'] or 'mobile-android' in request.headers['Cookie'] or 'mb-mobile-android' in request.headers['Cookie'])"
}
'
Whitelist Clients
Allow action for certain clients:
curl --request POST \
--url https://gateway.stackpath.com/waf/v1alpha/stacks/test_stack_id/sites/test_site_id/advanced_rules \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--data '
{
"ruleAction": {"allow": {}},
"name": "Whitlist knowen IPs",
"enabled": false,
"source": "request.ip == '117.20.32.5' or request.ip == '117.20.32.4' or request.ip_in_range('72.21.217.0', '72.21.217.255')"
}
'
Tag Generating rule
Tag and Allow registered clients:
NOTE: The tag value should warp with the "
character and NOT'
.
curl --request POST \
--url https://gateway.stackpath.com/waf/v1alpha/stacks/test_stack_id/sites/test_site_id/advanced_rules \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--data '
{
"name": "Tag registered clients",
"description": "Detect and tag registered clients by cookie",
"source": "'mb-mobile-android' in request.headers['Cookie']",
"ruleAction": {"tag": {"tags": ["registered"]}}
}
'
curl --request POST \
--url https://gateway.stackpath.com/waf/v1alpha/stacks/test_stack_id/sites/test_site_id/advanced_rules \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--data '
{
"name": "Allow registered clients",
"description": "Allow registered clients",
"source": "tags.exists('registered')",
"ruleAction": {"allow": {}}
}
'
Define Login Pages
curl --request POST \
--url https://gateway.stackpath.com/waf/v1alpha/stacks/test_stack_id/sites/test_site_id/advanced_rules \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--data '
{
"name": "Detect and Tag Login Pages",
"source": "['url1/login','url2/signup'] in request.uri",
"ruleAction": {"tag": {"tags": ["login page"]}}
}
'
Review Existing Rules
Once an Advanced Rule has been created, users are able to see these rules represented in the StackPath Portal. From here, you can toggle the rule on or off from within the UI.