Skip to content

Commit 8280e8d

Browse files
ADubhlaoichkudriavitskymjangmouraddmeiriohad-perets
authored
feat: NGINX App Protect 5.7 / 4.15 Release (#571)
This commit adds the documentation changes for NGINX App Protect WAF version 5.7 & 4.15. For information about feature changes, check the release notes. --- Co-authored-by: kudriavitsky <[email protected]> Co-authored-by: Mike Jang <[email protected]> Co-authored-by: mouraddmeiri <[email protected]> Co-authored-by: ohad-perets <[email protected]> Co-authored-by: Daniel Edgar <[email protected]>
1 parent 7de6e60 commit 8280e8d

File tree

20 files changed

+1396
-104
lines changed

20 files changed

+1396
-104
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
Enable Forward Proxy Settings for IP Intelligence Client.
2+
3+
To configure proxy settings, edit the client configuration file:
4+
Path:
5+
```shell
6+
/etc/app_protect/tools/iprepd.cfg
7+
```
8+
Example configuration:
9+
```shell
10+
EnableProxy=True
11+
ProxyHost=5.1.2.4
12+
ProxyPort=8080
13+
ProxyUsername=admin # Optional
14+
ProxyPassword=admin # Optional
15+
CACertPath=/etc/ssl/certs/ca-certificates.crt # Optional
16+
```
17+
After saving the changes, restart the client to apply the new settings.
18+
```shell
19+
/opt/app_protect/bin/iprepd /etc/app_protect/tools/iprepd.cfg > ipi.log 2>&1 &
20+
```
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#### IP-Address-Lists feature as part of Override Rules feature.
2+
3+
The Override Rules feature allows you to override original or parent policy settings.
4+
5+
Rules are defined using specific conditions, which can include an IP Address Lists based on the declarative policy JSON schema.
6+
7+
When triggered, the rule is applied to the _clientIp_ attribute using the _matches_ function.
8+
9+
'clientIp.matches(ipAddressLists["standalone"])'
10+
11+
Here is a policy example:
12+
13+
```json
14+
{
15+
"policy": {
16+
"name": "ip_group_override_rule",
17+
"template": {
18+
"name": "POLICY_TEMPLATE_NGINX_BASE"
19+
},
20+
"applicationLanguage": "utf-8",
21+
"caseInsensitive": false,
22+
"enforcementMode": "blocking",
23+
"ip-address-lists": [
24+
{
25+
"name": "standalone",
26+
"ipAddresses": [
27+
{
28+
"ipAddress": "1.1.1.1/32"
29+
}
30+
]
31+
}
32+
],
33+
"override-rules": [
34+
{
35+
"name": "myRule1",
36+
"condition": "clientIp.matches(ipAddressLists['standalone'])",
37+
"actionType": "extend-policy",
38+
"override": {
39+
"policy": {
40+
"enforcementMode": "transparent"
41+
}
42+
}
43+
}
44+
]
45+
}
46+
}
47+
```
48+
49+
The previous example policy contains an IP address lists with the name "standalone", used for the override rule condition "clientIp.matches(ipAddressLists['standalone'])".
50+
The condition means that the rule enforcement is applied and override base policy enforcement when clientIp is matched to one of ipAddresses in ipAddressList with name "standalone".
51+
The value used for the override condition must exist and exactly match the name in "ip-address-lists".
52+
53+
#### Possible errors
54+
55+
| Error text | Input | Explanation |
56+
| -----------| ------------- | ------------ |
57+
| _Invalid field invalidList_ | _clientIp.matches(invalidList['standalone']);_ | An incorrect keyword was used instead of _ipAddressLists_ |
58+
| _Invalid value empty string_ | _clientIp.matches(ipAddressLists['']_ | An empty name was provided |
59+
| _Failed to compile policy - 'ipGroupOverridePolicy'_ | _uri.matches(ipAddressLists['standalone']);_ | Used _ipAddressLists_ without the _clientIP_ attribute |
60+
61+
62+
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
IP address lists is a feature to organize lists of allowed and forbidden IP addresses across several lists with common attributes.
2+
3+
This allows you to control unique policy settings for incoming requests based on specific IP addresses.
4+
5+
Each IP address list contains a unique name, enforcement type (_always_, _never_ and _policy-default_), and list of IP addresses.
6+
7+
8+
An example of a declarative policy using IP address lists configuration:
9+
10+
```json
11+
{
12+
"policy": {
13+
"name": "IpGroups_policy",
14+
"template": {
15+
"name": "POLICY_TEMPLATE_NGINX_BASE"
16+
},
17+
"applicationLanguage": "utf-8",
18+
"caseInsensitive": false,
19+
"enforcementMode": "blocking",
20+
"ip-address-lists": [
21+
{
22+
"name": "Standalone",
23+
"description": "Optional Description",
24+
"blockRequests": "policy-default",
25+
"setGeolocation": "IN",
26+
"ipAddresses": [
27+
{
28+
"ipAddress": "1.2.3.4/32"
29+
},
30+
{
31+
"ipAddress": "1111:fc00:0:112::2"
32+
}
33+
]
34+
}
35+
]
36+
}
37+
}
38+
39+
```
40+
The example with IP-Group definition in external file external_ip_groups.json:
41+
42+
```json
43+
{
44+
"policy": {
45+
"name": "IpGroups_policy2",
46+
"template": {
47+
"name": "POLICY_TEMPLATE_NGINX_BASE"
48+
},
49+
"applicationLanguage": "utf-8",
50+
"caseInsensitive": false,
51+
"enforcementMode": "blocking",
52+
"ip-address-lists": [
53+
{
54+
"name": "external_ip_groups",
55+
"description": "Optional Description",
56+
"blockRequests": "always",
57+
"setGeolocation": "IL",
58+
"$ref": "file:///tmp/policy/external_ip_groups.json"
59+
}
60+
]
61+
}
62+
}
63+
```
64+
Example of the file external_ip_groups.json
65+
66+
```json
67+
{
68+
"name": "External IP address lists",
69+
"description": "Optional Description",
70+
"blockRequests": "always",
71+
"setGeolocation": "IR",
72+
"ipAddresses": [
73+
{
74+
"ipAddress": "66.51.41.21"
75+
},
76+
{
77+
"ipAddress": "66.52.42.22"
78+
}
79+
]
80+
}
81+
```
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
2+
3+
NGINX App Protect WAF provides an IP Intelligence feature, which allows customizing the enforcement based on the source IP of the request to limit access from IP addresses with questionable reputation. Please note that:
4+
- The IP intelligence feature is **disabled** by default and needs to be installed, enabled, and configured within the policy.
5+
- To review the installation steps, please refer to the administration guide: [App Protect v4]({{< ref "/nap-waf/v4/admin-guide/install.md#Prerequisites" >}}) / [App Protect v5]({{< ref "/nap-waf/v5/admin-guide/install.md#Prerequisites" >}})
6+
- The system must have an active Internet connection and a working DNS.
7+
- If NGINX App Protect is behind a firewall, ensure external access to vector.brightcloud.com over port 443 - this is the IP Intelligence server used for data retrieval.
8+
- If NGINX App Protect accesses the Internet through a forward proxy server, ensure that it is configured correctly [App Protect v4]({{< ref "/nap-waf/v4/configuration-guide/configuration.md#ip-intelligence-forward-proxy-configuration" >}}) / [App Protect v5]({{< ref "/nap-waf/v5/configuration-guide/configuration.md##ip-intelligence-forward-proxy-configuration" >}}).
9+
10+
Once installed, make sure to enable the feature in the two relevant sections of the policy:
11+
1. By enabling the corresponding violation in the violation list: `"name": "VIOL_MALICIOUS_IP"` and assigning the appropriate `block` and `alarm` values to the violation.
12+
13+
2. By enabling the feature in the corresponding IP Intelligence JSON section: `"ip-intelligence": {"enabled": true}` and defining actions for the IP Intelligence categories listed below.
14+
15+
An example policy where both elements are enabled, and all the IP intelligence categories are configured to `block` and `alarm` can be found here:
16+
17+
```json
18+
{
19+
"policy": {
20+
"name": "ip_intelligency_policy",
21+
"template": {
22+
"name": "POLICY_TEMPLATE_NGINX_BASE"
23+
},
24+
"applicationLanguage": "utf-8",
25+
"caseInsensitive": false,
26+
"enforcementMode": "blocking",
27+
"blocking-settings": {
28+
"violations": [
29+
{
30+
"name": "VIOL_MALICIOUS_IP",
31+
"alarm": true,
32+
"block": true
33+
}
34+
]
35+
},
36+
"ip-intelligence": {
37+
"enabled": true,
38+
"ipIntelligenceCategories": [
39+
{
40+
"category": "Anonymous Proxy",
41+
"alarm": true,
42+
"block": true
43+
},
44+
{
45+
"category": "BotNets",
46+
"alarm": true,
47+
"block": true
48+
},
49+
{
50+
"category": "Cloud-based Services",
51+
"alarm": true,
52+
"block": true
53+
},
54+
{
55+
"category": "Denial of Service",
56+
"alarm": true,
57+
"block": true
58+
},
59+
{
60+
"category": "Infected Sources",
61+
"alarm": true,
62+
"block": true
63+
},
64+
{
65+
"category": "Mobile Threats",
66+
"alarm": true,
67+
"block": true
68+
},
69+
{
70+
"category": "Phishing Proxies",
71+
"alarm": true,
72+
"block": true
73+
},
74+
{
75+
"category": "Scanners",
76+
"alarm": true,
77+
"block": true
78+
},
79+
{
80+
"category": "Spam Sources",
81+
"alarm": true,
82+
"block": true
83+
},
84+
{
85+
"category": "Tor Proxies",
86+
"alarm": true,
87+
"block": true
88+
},
89+
{
90+
"category": "Web Attacks",
91+
"alarm": true,
92+
"block": true
93+
},
94+
{
95+
"category": "Windows Exploits",
96+
"alarm": true,
97+
"block": true
98+
}
99+
]
100+
}
101+
}
102+
}
103+
```
104+
105+
This policy will basically block `"block": true` all IP addresses that are part of any threat category and add a log entry `"alarm": true` for the transaction.
106+
107+
The IP address database is managed by an external provider and is constantly updated (every 1 minute by default). The database also categorizes IP addresses into one or more threat categories. These are the same categories that can be configured individually in the IP intelligence section:
108+
- Anonymous Proxy
109+
- BotNets
110+
- Cloud-based Services
111+
- Denial of Service
112+
- Infected Sources
113+
- Mobile Threats
114+
- Phishing Proxies
115+
- Scanners
116+
- Spam Sources
117+
- Tor Proxies
118+
- Web Attacks
119+
- Windows Exploits
120+
121+
Note that since the IP address database is constantly updated, IP address enforcement is also expected to change. IP Addresses may be added, removed, or moved from one category to another based on the reported activity of the IP address.
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
```dockerfile
2+
# syntax=docker/dockerfile:1
3+
4+
# Base Image
5+
FROM rockylinux:9
6+
7+
# Install NGINX OSS and NGINX App Protect WAF v5 module
8+
RUN --mount=type=secret,id=nginx-crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode=0644 \
9+
--mount=type=secret,id=nginx-key,dst=/etc/ssl/nginx/nginx-repo.key,mode=0644 \
10+
dnf -y install wget ca-certificates yum-utils \
11+
&& wget -P /etc/yum.repos.d https://cs.nginx.com/static/files/dependencies.repo \
12+
&& echo "[nginx-mainline]" > /etc/yum.repos.d/nginx.repo \
13+
&& echo "name=nginx mainline repo" >> /etc/yum.repos.d/nginx.repo \
14+
&& echo "baseurl=http://nginx.org/packages/mainline/centos/\$releasever/\$basearch/" >> /etc/yum.repos.d/nginx.repo \
15+
&& echo "gpgcheck=1" >> /etc/yum.repos.d/nginx.repo \
16+
&& echo "enabled=1" >> /etc/yum.repos.d/nginx.repo \
17+
&& echo "gpgkey=https://nginx.org/keys/nginx_signing.key" >> /etc/yum.repos.d/nginx.repo \
18+
&& echo "module_hotfixes=true" >> /etc/yum.repos.d/nginx.repo \
19+
&& echo "[app-protect-x-oss]" > /etc/yum.repos.d/app-protect-${UBI_VERSION}-x-oss.repo \
20+
&& echo "name=nginx-app-protect repo" >> /etc/yum.repos.d/app-protect-${UBI_VERSION}-x-oss.repo \
21+
&& echo "baseurl=https://pkgs.nginx.com/app-protect-x-oss/centos/${UBI_VERSION}/\$basearch/" >> /etc/yum.repos.d/app-protect-${UBI_VERSION}-x-oss.repo \
22+
&& echo "sslclientcert=/etc/ssl/nginx/nginx-repo.crt" >> /etc/yum.repos.d/app-protect-${UBI_VERSION}-x-oss.repo \
23+
&& echo "sslclientkey=/etc/ssl/nginx/nginx-repo.key" >> /etc/yum.repos.d/app-protect-${UBI_VERSION}-x-oss.repo \
24+
&& echo "gpgcheck=0" >> /etc/yum.repos.d/app-protect-${UBI_VERSION}-x-oss.repo \
25+
&& echo "enabled=1" >> /etc/yum.repos.d/app-protect-${UBI_VERSION}-x-oss.repo \
26+
&& dnf clean all \
27+
&& dnf install -y app-protect-module-oss \
28+
&& dnf clean all \
29+
&& rm -rf /var/cache/dnf \
30+
&& ln -sf /dev/stdout /var/log/nginx/access.log \
31+
&& ln -sf /dev/stderr /var/log/nginx/error.log
32+
33+
# Expose port
34+
EXPOSE 80
35+
36+
# Define stop signal
37+
STOPSIGNAL SIGQUIT
38+
39+
# Set default command
40+
CMD ["nginx", "-g", "daemon off;"]
41+
```
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
```dockerfile
2+
# syntax=docker/dockerfile:1
3+
4+
# Base Image
5+
FROM rockylinux:9
6+
7+
# Install NGINX Plus and NGINX App Protect WAF v5 module
8+
RUN --mount=type=secret,id=nginx-crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode=0644 \
9+
--mount=type=secret,id=nginx-key,dst=/etc/ssl/nginx/nginx-repo.key,mode=0644 \
10+
dnf -y install wget ca-certificates \
11+
&& wget -P /etc/yum.repos.d https://cs.nginx.com/static/files/dependencies.repo \
12+
&& wget -P /etc/yum.repos.d https://cs.nginx.com/static/files/${NGINX_PLUS_REPO} \
13+
&& echo "[app-protect-x-plus]" > /etc/yum.repos.d/app-protect-${UBI_VERSION}-x-plus.repo \
14+
&& echo "name=nginx-app-protect repo" >> /etc/yum.repos.d/app-protect-${UBI_VERSION}-x-plus.repo \
15+
&& echo "baseurl=https://pkgs.nginx.com/app-protect-x-plus/centos/${UBI_VERSION}/\$basearch/" >> /etc/yum.repos.d/app-protect-${UBI_VERSION}-x-plus.repo \
16+
&& echo "sslclientcert=/etc/ssl/nginx/nginx-repo.crt" >> /etc/yum.repos.d/app-protect-${UBI_VERSION}-x-plus.repo \
17+
&& echo "sslclientkey=/etc/ssl/nginx/nginx-repo.key" >> /etc/yum.repos.d/app-protect-${UBI_VERSION}-x-plus.repo \
18+
&& echo "gpgcheck=0" >> /etc/yum.repos.d/app-protect-${UBI_VERSION}-x-plus.repo \
19+
&& echo "enabled=1" >> /etc/yum.repos.d/app-protect-${UBI_VERSION}-x-plus.repo \
20+
&& dnf clean all \
21+
&& dnf install -y app-protect-module-plus \
22+
&& dnf clean all \
23+
&& rm -rf /var/cache/dnf \
24+
&& ln -sf /dev/stdout /var/log/nginx/access.log \
25+
&& ln -sf /dev/stderr /var/log/nginx/error.log
26+
27+
# Expose port
28+
EXPOSE 80
29+
30+
# Define stop signal
31+
STOPSIGNAL SIGQUIT
32+
33+
# Set default command
34+
CMD ["nginx", "-g", "daemon off;"]
35+
```

0 commit comments

Comments
 (0)