WAF
Filter, monitor, and block potentially harmful HTTP traffic with a Web Application Firewall (WAF) policy.About web application firewalls
WAFs protect your web apps by monitoring, filtering, and blocking potentially harmful HTTP traffic. You write a WAF policy by following a framework and ruleset. Then, you apply the WAF policy to the route for the apps that you want to protect. When Gloo Gateway receives an incoming request for that route (ingress traffic), the WAF intercepts and inspects the network packets and uses the rules that you set in the policy to determine access to the web app. The WAF policy also applies to any outgoing responses (egress traffic) along the route. This setup provides an additional layer of protection between your apps and end users.
Gloo supports the popular Web Application Firewall framework and ruleset ModSecurity version 3.0.4. ModSecurity uses a simple rules language to interpret and process incoming HTTP traffic. Because it is open source, ModSecurity is a flexible, cross-platform solution that incorporates transparent security practices to protect apps against a range web attacks.
You have several options for using ModSecurity to write WAF policies:
- Use publicly available rule sets that provide a generic set of detection rules to protect against the most common security threats. For example, the OWASP Core Rule Set is an open source project that protects apps against a wide range of attacks, including the “OWASP Top Ten.”
For your convenience, Gloo applies the OWASP Core Rule Set to your routes by default, but you can disable this feature by using the
disableCoreRuleSet
in your WAF policy. - Write your own custom rules by following the ModSecurity rules language. For examples, see Configure WAF policies.
For more information, see the Gloo Gateway API docs.
Before you begin
Follow the getting started instructions to:
- Set up Gloo Gateway in a single cluster.
- Deploy sample apps.
- Configure an HTTPS listener on your gateway and set up basic routing for the sample apps.
Configure WAF policies
You can apply a WAF policy at the route level. For more information, see Applying policies.
The following YAML configuration is for a basic WAF policy that denies requests if the User-Agent
header is set to the value scammer
. You can use this example to learn the basic parts of a WAF policy, as well as get ideas for how you might allow or deny traffic based on request headers.
apiVersion: security.policy.gloo.solo.io/v2
kind: WAFPolicy
metadata:
name: basic-auth
namespace: bookinfo
spec:
applyToRoutes:
- route:
labels:
route: ratings
config:
customInterventionMessage: custom-intervention-message
customRuleSets:
- ruleStr: |2
SecRuleEngine On
SecRule REQUEST_HEADERS:User-Agent "test([1-5])$" "deny,status:403,id:1,phase:1,msg:'blocked scammer'"
disableCoreRuleSet: true
priority: 0
Review the following table to understand this configuration. For more information, see the API docs.
Setting | Description |
---|---|
applyToRoutes |
Use labels to configure which routes to apply the policy to. This example label matches the app and route from the example route table that you previously applied. If omitted, the policy applies to all routes in the workspace. |
customInterventionMessage |
Return a custom message when the policy causes the gateway to intervene in the request. This example returns the message custom-intervention-message . |
customRuleSets |
Create a set of rules for the WAF policy to apply, based on the ModSecurity rules language. You can have multiple rule sets in a policy. Rule sets are applied in the order that they are configured, with later rule sets overwriting earlier ones in the case of a conflict. This example has only one rule set. |
- ruleStr |
You can write the custom rule set inline to the policy (ruleStr ), refer to .conf files of rule sets (files ), or refer to a directory of .conf files (directory ). This example writes the rule set inline. |
2 |
The number of rules in the inline rule set, such as 2 in this example. |
SecRuleEngine On |
This rule enables the rules engine (On ), which is Off by default. To run the rules engine to detect and log requests, but not to intervene such as by denying the request, set to DetectionOnly . |
SecRule REQUEST_HEADERS:User-Agent "test" "deny,status:403,id:107,phase:1,msg:'blocked scammer'" |
This rule inspects the request header "user-agent" . If the value of that header equals "test" , then the gateway denies the request and returns a 403 status. The WAF logs the rule message blocked scammer , which you might use as input in other custom rules. |
disableCoreRuleSet: true |
Include this setting to disable the OWASP core rule set from also being applied to requests along this route, such as for testing purposes or if you customize the core rule set yourself. |
You might want to allow access to a specific IP address or subnet range, such as an access control list (ACL) for internal services or to enforce a network boundary between different environments like staging and production. You can use a WAF filter with custom ModSecurity rules to set up an allowlist, such as with the following example to allow access from a local workstation.
- Enable source IP preservation in the Istio ingress gateway that your Gloo virtual gateway selects. For more information, see the Istio docs. If applicable, make sure that the load balancer in front of your cluster environment permits source IP preservation. In this example, the source IP address of your local workstation must be preserved when the traffic from your workstation is forwarded by the load balancer to the gateway. This way, the gateway can see the original client IP as the remote address, and use this address in the WAF rules to allow the IP address.
- Create a custom rule set to allow the IP address of your local workstation in the
config
section of your WAF policy.apiVersion: security.policy.gloo.solo.io/v2 kind: WAFPolicy metadata: name: basic-auth namespace: bookinfo spec: applyToRoutes: - route: labels: route: ratings config: customRuleSets: - ruleStr: |2 SecRuleEngine On SecRule REMOTE_ADDR "!@ipMatch 173.175.0.0/16" "phase:1,deny,status:403,id:1,msg:'block ip'"
Review the following table to understand this configuration. For details on the other settings, see the Header example
tab or the API docs.
Setting | Description |
---|---|
customRuleSets |
Create a set of rules for the WAF policy to apply, based on the ModSecurity rules language. You can have multiple rule sets in a policy. Rule sets are applied in the order that they are configured, with later rule sets overwriting earlier ones in the case of a conflict. This example has only one rule set. |
- ruleStr |
You can write the custom rule set inline to the policy (ruleStr ), refer to .conf files of rule sets (files ), or refer to a directory of .conf files (directory ). This example writes the rule set inline. |
2 |
The number of rules in the inline rule set, such as 2 in this example. |
SecRuleEngine On |
This rule enables the rules engine (On ), which is Off by default. To run the rules engine to detect and log requests, but not to intervene such as by denying the request, set to DetectionOnly . |
SecRule REMOTE_ADDR "!@ipMatch 173.175.0.0/16" "phase:1,deny,status:403,id:1,msg:'block ip'" |
This rule inspects the remote address of the request. If the IP address is not within the 173.175.0.0/16 network range, then the gateway denies the request and returns a 403 status. The WAF logs the rule message block ip , which you might use as input in other custom rules. |
You can improve the performance of certain services by not sending the body of requests to the ModSecurity WAF ruleset. For example, calls from gRPC services can timeout if the gRPC call is a stream, because the WAF filter requires an end stream to be specified to finish evaluating intervention. To avoid this timeout, add the requestHeadersOnly: true
and responseHeadersOnly: true
entries to the WAF config, such as in the following example.
apiVersion: security.policy.gloo.solo.io/v2
kind: WAFPolicy
metadata:
name: basic-auth
namespace: bookinfo
spec:
applyToRoutes:
- route:
labels:
route: ratings
config:
requestHeadersOnly: true
responseHeadersOnly: true
Gloo audit logging for WAF works differently than native ModSecurity, because Gloo is optimized for performance in Envoy and Kubernetes cloud environments. Instead of using the ModSecurity audit engine, Gloo exposes the audit logs as part of the Envoy gateway's access logging.
The following ModSecurity directives that configure the audit engine are ignored, even if set:
SecAuditEngine
. Instead, use theaction
property of the audit logging configuration to choose when to log.SecAuditLog
SecAuditLogStorageDir
SecAuditLogType
Although the way that audit logging works is different, you still can use the features that ModSecurity audit logging provides:
SecAuditLogFormat
SecAuditLogParts
SecAuditLogRelevantStatus
noauditlog
, when the action isRELEVANT_ONLY
Review the following configuration file and table description to understand audit logging-specific settings. For details on the other settings, see the Header example
tab.
apiVersion: security.policy.gloo.solo.io/v2
kind: WAFPolicy
metadata:
name: basic-auth
namespace: bookinfo
spec:
applyToRoutes:
- route:
labels:
route: ratings
config:
customInterventionMessage: custom-intervention-message
customRuleSets:
- ruleStr: |2
SecRuleEngine On
SecAuditLogFormat JSON
SecRule REQUEST_HEADERS:User-Agent "test" "deny,status:403,id:107,phase:1,msg:'blocked scammer'"
disableCoreRuleSet: true
auditLogging:
action: ALWAYS
location: FILTER_STATE
Review the following table to understand this configuration. For more information, see the API docs.
Setting | Description |
---|---|
SecAuditLogFormat JSON |
Set audit log format to JSON. To use regular string format, omit this directive. |
auditLogging |
Use this audit logging stanza to tell the WAF filter how to log transactions. |
action: ALWAYS |
Describe the action to take. Possible values are:
|
location: FILTER_STATE |
Determine how to expose audit logs in the access logs. You can expose audit logs via access logs in two ways, depending on your performance requirements:
|
Verify WAF policies
The verification steps in this topic are specific to the header example in Configure WAF policies. Note that the steps for verifying other WAF policy examples might vary.
-
Download the example WAF policy for the
ratings
route that you reviewed in the previous section. -
Apply the example WAF policy.
kubectl apply --context ${MGMT_CONTEXT} -f waf-policy_bookinfo_basic-auth.yml
kubectl apply --context ${REMOTE_CONTEXT1} -f waf-policy_bookinfo_basic-auth.yml
-
Include the
user-agent: test1
header in a request to theratings
app.curl -vik -H "User-Agent: test1" --resolve www.example.com:443:${INGRESS_GW_IP} https://www.example.com:443/ratings/1
Example output: Notice that your request is now denied with a
403
error and thecustom-intervention-message
.HTTP/2 403 ... custom-intervention-message* Closing connection 0
-
Optional: Clean up the resources that you created.
kubectl -n bookinfo delete wafpolicy basic-auth