|
| 1 | +--- |
| 2 | +# We use sentence case and present imperative tone |
| 3 | +title: "Secure traffic using mTLS" |
| 4 | +# Weights are assigned in increments of 100: determines sorting order |
| 5 | +weight: 100 |
| 6 | +# Creates a table of contents and sidebar, useful for large documents |
| 7 | +toc: true |
| 8 | +# Types have a 1:1 relationship with Hugo archetypes, so you shouldn't need to change this |
| 9 | +nd-content-type: how-to |
| 10 | +# Intended for internal catalogue and search, case sensitive: |
| 11 | +# Agent, N4Azure, NIC, NIM, NGF, NAP-DOS, NAP-WAF, NGINX One, NGINX+, Solutions, Unit |
| 12 | +nd-product: NAP-WAF |
| 13 | +--- |
| 14 | + |
| 15 | +This topic describes how to secure traffic between NGINX and the F5 WAF enforcer using mTLS. |
| 16 | + |
| 17 | +It explains how to generate the necessary certificates, then update configuration files to use them. |
| 18 | + |
| 19 | +A mutual TLS (mTLS) connection creates authentication between both NGINX (client) and F5 WAF Enforcer (server). |
| 20 | + |
| 21 | +This adds an extra layer of security, ensuring that both parties are who they claim to be. |
| 22 | + |
| 23 | +## Generate certificates and keys |
| 24 | + |
| 25 | +To enable mTLS, you must first create certificates. |
| 26 | + |
| 27 | +{{< call-out "note" >}} |
| 28 | + |
| 29 | +The following commands will generate self-signed certificates in _/etc/ssl/certs/_ valid for the default period of 30 days. You can adjust the command to fit your needs. |
| 30 | + |
| 31 | +For instance, to specify a different validity period, add the _-days_ option followed by the number of days you want the certificate to be valid (Such as _-days 90_). |
| 32 | + |
| 33 | +{{< /call-out >}} |
| 34 | + |
| 35 | +First, create the certificate authority files: |
| 36 | + |
| 37 | +```shell |
| 38 | +mkdir -p /etc/ssl/certs |
| 39 | +openssl genpkey -algorithm RSA -out /etc/ssl/certs/app_protect_server_ca.key |
| 40 | +openssl genpkey -algorithm RSA -out /etc/ssl/certs/app_protect_client_ca.key |
| 41 | +openssl req -x509 -new -key /etc/ssl/certs/app_protect_server_ca.key -out /etc/ssl/certs/app_protect_server_ca.crt -subj "/O=F5/OU=app-protect/CN=mTLS Server Root CA" |
| 42 | +openssl req -x509 -new -key /etc/ssl/certs/app_protect_client_ca.key -out /etc/ssl/certs/app_protect_client_ca.crt -subj "/O=F5/OU=app-protect/CN=mTLS Client Root CA" |
| 43 | +``` |
| 44 | + |
| 45 | +Then, create the server (F5 WAF enforcer) files: |
| 46 | + |
| 47 | +```shell |
| 48 | +openssl genpkey -algorithm RSA -out /etc/ssl/certs/app_protect_server.key |
| 49 | +openssl req -new -key /etc/ssl/certs/app_protect_server.key -out /etc/ssl/certs/app_protect_server_csr.crt -subj "/O=F5/OU=app-protect/CN=mTLS" |
| 50 | +openssl x509 -req -in /etc/ssl/certs/app_protect_server_csr.crt -CA /etc/ssl/certs/app_protect_server_ca.crt -CAkey /etc/ssl/certs/app_protect_server_ca.key -out /etc/ssl/certs/app_protect_server.crt -CAcreateserial |
| 51 | +``` |
| 52 | + |
| 53 | +Finally, create the client (NGINX) files: |
| 54 | + |
| 55 | +```shell |
| 56 | +openssl genpkey -algorithm RSA -out /etc/ssl/certs/app_protect_client.key |
| 57 | +openssl req -new -key /etc/ssl/certs/app_protect_client.key -out /etc/ssl/certs/app_protect_client_csr.crt -subj "/O=F5/OU=app-protect/CN=mTLS" |
| 58 | +openssl x509 -req -in /etc/ssl/certs/app_protect_client_csr.crt -CA /etc/ssl/certs/app_protect_client_ca.crt -CAkey /etc/ssl/certs/app_protect_client_ca.key -out /etc/ssl/certs/app_protect_client.crt -CAcreateserial |
| 59 | +``` |
| 60 | + |
| 61 | +## Update configuration files |
| 62 | + |
| 63 | +To enable mTLS, you must add F5 WAF enforcer to a [`stream {}`](https://nginx.org/en/docs/stream/ngx_stream_core_module.html#stream) context. |
| 64 | + |
| 65 | +Modify an existing block or create one with the following information: |
| 66 | + |
| 67 | +```nginx {hl_lines=[3, 8, 12, 13, 14]} |
| 68 | +stream { |
| 69 | + upstream enforcer { |
| 70 | + server 127.0.0.1:4431; |
| 71 | + } |
| 72 | +
|
| 73 | + server { |
| 74 | + listen 5000; |
| 75 | + proxy_pass enforcer; |
| 76 | + proxy_ssl_server_name on; |
| 77 | + proxy_timeout 60m; |
| 78 | + proxy_ssl on; |
| 79 | + proxy_ssl_certificate /etc/ssl/certs/app_protect_client.crt; |
| 80 | + proxy_ssl_certificate_key /etc/ssl/certs/app_protect_client.key; |
| 81 | + proxy_ssl_trusted_certificate /etc/ssl/certs/app_protect_server_ca.crt; |
| 82 | + } |
| 83 | +``` |
| 84 | + |
| 85 | +- _upstream enforcer_ specifices the server, which listens on port 4431 by default |
| 86 | +- _proxy_pass_ indicates that requests should be routed through the enforcer upstream |
| 87 | +- _proxy_ssl_certificate_ and _proxy_ssl_certificate_key_ are for the client (NGINX) credentials |
| 88 | +- _proxy_ssl_trusted_certificate_ enables the server (enforcer) verification |
| 89 | + |
| 90 | +This stream server should then be used as the _app_protect_enforcer_address_ value: |
| 91 | + |
| 92 | +```shell |
| 93 | +app_protect_enforcer_address 127.0.0.1:5000; |
| 94 | +``` |
| 95 | + |
| 96 | +A fully configured file might look similar to the following example: |
| 97 | + |
| 98 | +```nginx {hl_lines=[12,13,14, 18, 22, 23, 24, 33]} |
| 99 | +user nginx; |
| 100 | +worker_processes auto; |
| 101 | +worker_shutdown_timeout 10s; # NGINX gives worker processes 10 seconds to gracefully terminate before it will actively close connections |
| 102 | +load_module modules/ngx_http_app_protect_module.so; |
| 103 | +error_log /var/log/nginx/error.log notice; |
| 104 | +
|
| 105 | +events { |
| 106 | + worker_connections 65536; |
| 107 | + } |
| 108 | +
|
| 109 | +stream { |
| 110 | +upstream enforcer { |
| 111 | + server 127.0.0.1:4431; |
| 112 | +} |
| 113 | +
|
| 114 | +server { |
| 115 | + listen 5000; |
| 116 | + proxy_pass enforcer; |
| 117 | + proxy_ssl_server_name on; |
| 118 | + proxy_timeout 60m; |
| 119 | + proxy_ssl on; |
| 120 | + proxy_ssl_certificate /etc/ssl/certs/app_protect_client.crt; |
| 121 | + proxy_ssl_certificate_key /etc/ssl/certs/app_protect_client.key; |
| 122 | + proxy_ssl_trusted_certificate /etc/ssl/certs/app_protect_server_ca.crt; |
| 123 | +} |
| 124 | +
|
| 125 | +http { |
| 126 | + include /etc/nginx/mime.types; |
| 127 | + default_type application/octet-stream; |
| 128 | + sendfile on; |
| 129 | + keepalive_timeout 65; |
| 130 | +
|
| 131 | + app_protect_enforcer_address 127.0.0.1:5000; |
| 132 | +
|
| 133 | + server { |
| 134 | + listen 80; |
| 135 | + server_name localhost; |
| 136 | + proxy_http_version 1.1; |
| 137 | +
|
| 138 | + app_protect_enable on; |
| 139 | + app_protect_policy_file app_protect_default_policy; |
| 140 | + app_protect_security_log_enable on; |
| 141 | + app_protect_security_log log_all syslog:server=127.0.0.1:514; |
| 142 | +
|
| 143 | + location / { |
| 144 | + client_max_body_size 0; |
| 145 | + default_type text/html; |
| 146 | + # Pass traffic to backend |
| 147 | + proxy_pass http://127.0.0.1:8080/; |
| 148 | + } |
| 149 | + } |
| 150 | +} |
| 151 | +``` |
| 152 | + |
| 153 | +{{< call-out "note" >}} |
| 154 | + |
| 155 | +With a [Virtual machine or bare metal]({{< ref "/waf/install/virtual-environment.md" >}}) installation, you have finished all necessary steps. |
| 156 | + |
| 157 | +{{< /call-out >}} |
| 158 | + |
| 159 | +## Modify Docker compose file |
| 160 | + |
| 161 | +{{< call-out "warning" >}} |
| 162 | + |
| 163 | +This section **only** applies to installations using Docker. |
| 164 | + |
| 165 | +{{< /call-out >}} |
| 166 | + |
| 167 | +To use mTLS with Docker, you must modify your compose files. |
| 168 | + |
| 169 | +The certificates folder _/etc/ssl/certs/_ must be added to the _volumes:_ sections of the NGINX and WAF enforcer services. |
| 170 | + |
| 171 | +And the individual certificate and key files must be added to the _environment:_ section of the WAF enforcer service, using the correct names. |
| 172 | + |
| 173 | +This example highlights the required fields: |
| 174 | + |
| 175 | +```yaml {hl_lines=[11, 22, 23, 24, 27]} |
| 176 | +services: |
| 177 | + nginx: |
| 178 | + container_name: nginx |
| 179 | + image: nginx-app-protect-5 |
| 180 | + volumes: |
| 181 | + - app_protect_bd_config:/opt/app_protect/bd_config |
| 182 | + - app_protect_config:/opt/app_protect/config |
| 183 | + - app_protect_etc_config:/etc/app_protect/conf |
| 184 | + - /conf/nginx.conf:/etc/nginx/nginx.conf |
| 185 | + - /conf/default.conf:/etc/nginx/conf.d/default.conf |
| 186 | + - /path/to/your/certs:/etc/ssl/certs |
| 187 | + networks: |
| 188 | + - waf_network |
| 189 | + ports: |
| 190 | + - "80:80" |
| 191 | + |
| 192 | + waf-enforcer: |
| 193 | + container_name: waf-enforcer |
| 194 | + image: "private-registry.nginx.com/nap/waf-enforcer:<version-tag>" |
| 195 | + environment: |
| 196 | + - ENFORCER_PORT=4431 |
| 197 | + - ENFORCER_SERVER_CERT=/etc/ssl/certs/app_protect_server.crt |
| 198 | + - ENFORCER_SERVER_KEY=/etc/ssl/certs/app_protect_server.key |
| 199 | + - ENFORCER_CA_FILE=/etc/ssl/certs/app_protect_client_ca.crt |
| 200 | + volumes: |
| 201 | + - app_protect_bd_config:/opt/app_protect/bd_config |
| 202 | + - /path/to/your/certs:/etc/ssl/certs |
| 203 | + networks: |
| 204 | + - waf_network |
| 205 | + restart: always |
| 206 | + |
| 207 | + waf-config-mgr: |
| 208 | + container_name: waf-config-mgr |
| 209 | + image: "private-registry.nginx.com/nap/waf-config-mgr:<version-tag>" |
| 210 | + volumes: |
| 211 | + - app_protect_bd_config:/opt/app_protect/bd_config |
| 212 | + - app_protect_config:/opt/app_protect/config |
| 213 | + - app_protect_etc_config:/etc/app_protect/conf |
| 214 | + restart: always |
| 215 | + network_mode: none |
| 216 | + depends_on: |
| 217 | + waf-enforcer: |
| 218 | + condition: service_started |
| 219 | + |
| 220 | + networks: |
| 221 | + waf_network: |
| 222 | + driver: bridge |
| 223 | + |
| 224 | + volumes: |
| 225 | + app_protect_bd_config: |
| 226 | + app_protect_config: |
| 227 | + app_protect_etc_config: |
| 228 | +``` |
| 229 | + |
0 commit comments