DEV Community

Cover image for Solved: WAF for nginx-ingress (or alternatives?)
Darian Vance
Darian Vance

Posted on • Originally published at wp.me

Solved: WAF for nginx-ingress (or alternatives?)

🚀 Executive Summary

TL;DR: The standard NGINX Ingress Controller in Kubernetes lacks built-in WAF capabilities, leaving services vulnerable to attacks like SQL injection. This guide outlines three battle-tested solutions: integrating ModSecurity directly, leveraging a managed Cloud WAF, or adopting an alternative Ingress Controller with native WAF features.

🎯 Key Takeaways

  • The standard Kubernetes NGINX Ingress Controller is a Layer 7 reverse proxy, not a security tool designed for inspecting malicious payloads.
  • ModSecurity can be integrated directly with NGINX Ingress using ConfigMap and Ingress annotations, providing full control but requiring significant tuning of the OWASP Core Rule Set to prevent false positives.
  • Managed Cloud WAFs (e.g., AWS WAF, Azure WAF, Google Cloud Armor) offload WAF functionality to the edge, reducing cluster overhead and management complexity at a pay-as-you-go cost.
  • Alternative Ingress Controllers like Kong or Traefik Enterprise offer tightly integrated, often commercially supported WAF capabilities, simplifying configuration via Kubernetes-native CRDs.
  • Always run ModSecurity in detection-only mode (SecRuleEngine DetectionOnly) before enabling blocking (SecRuleEngine On) in production to identify and tune legitimate requests flagged by default rules.
  • When using a Cloud WAF, ensure your Load Balancer and NGINX Ingress correctly pass and trust the X-Forwarded-For header to prevent incorrect rate-limiting based on the Load Balancer’s IP.

Struggling to integrate a Web Application Firewall (WAF) with your NGINX Ingress in Kubernetes? This guide provides three battle-tested solutions for protecting your services, from in-cluster ModSecurity to managed cloud WAFs.

WAF for NGINX Ingress: A Senior Engineer’s No-BS Guide to Kubernetes Security

I remember it was a Tuesday. Of course, it was a Tuesday. We’d just pushed the new ‘user-profile-service’ to production. High-fives all around. Two hours later, I get a panicked Slack message from a junior engineer. A routine security scan, one we’d forgotten to run in staging, was lighting up our new endpoint like a Christmas tree. Basic SQL injection payloads were sailing right through our NGINX Ingress and hitting the service. The security team was… not pleased. That was the day we stopped treating a WAF as a “nice-to-have” and got serious about integrating one properly. If you’re here, you’re probably facing a similar headache. Let’s get you through it.

First, Why Is This Even a Problem?

Let’s be clear: the standard Kubernetes NGINX Ingress Controller is a fantastic piece of engineering. It’s a brilliant Layer 7 reverse proxy and load balancer. What it is not, out of the box, is a security tool. Its job is to route traffic based on hostnames and paths, not to inspect the payload of that traffic for malicious intent. When you need to block threats like Cross-Site Scripting (XSS), SQL Injection (SQLi), or path traversal attacks, you need a proper Web Application Firewall. The challenge isn’t just picking a WAF; it’s about integrating it cleanly into the Kubernetes networking flow without creating a performance bottleneck or a management nightmare.

So, after that lovely Tuesday incident, we evaluated our options. Here are the three main paths you can take, based on my experience in the trenches.

Solution 1: The In-Cluster Brawler – Using ModSecurity

This is the “do-it-yourself” approach. The official NGINX Ingress Controller can be compiled with ModSecurity, a powerful open-source WAF engine. You’re essentially activating a dormant feature within the controller itself. It inspects traffic right as it enters the cluster, before it’s routed to your services.

How It Works:

You enable ModSecurity and configure its rules using the main NGINX ConfigMap and per-Ingress annotations. You’ll want to use the OWASP Core Rule Set (CRS) as your foundation.

First, enable it globally in your nginx-configuration ConfigMap:

apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-configuration
  namespace: ingress-nginx
data:
  enable-modsecurity: "true"
  enable-owasp-core-rules: "true"
  modsecurity-transaction-id: "$request_id"
Enter fullscreen mode Exit fullscreen mode

Then, you can fine-tune or enable it for a specific application using annotations on the Ingress resource itself:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: user-profile-ingress
  annotations:
    nginx.ingress.kubernetes.io/modsecurity-transaction-id: "$request_id"
    nginx.ingress.kubernetes.io/modsecurity-snippet: |
      SecRuleEngine On
      # Add custom rule overrides here to prevent false positives
      SecRuleRemoveById 942100
Enter fullscreen mode Exit fullscreen mode

The Verdict:

  • Pros: No extra cost for software. It’s all contained within your cluster, giving you full control. Great for learning the guts of how a WAF works.
  • Cons: The OWASP CRS is notorious for false positives. You will spend significant time tuning rules for your specific application. It also consumes CPU and memory directly on your Ingress controller pods, which can impact routing performance under heavy load.

A Word of Warning: Never, ever, run ModSecurity in blocking mode (SecRuleEngine On) in production without first running it in detection-only mode (SecRuleEngine DetectionOnly). Watch the logs for a few days. You will be shocked at how many legitimate requests get flagged by the default ruleset. Tune first, block later.

Solution 2: The Managed Approach – Cloud Provider WAFs

This is my preferred approach for most production systems. Instead of running the WAF inside your cluster, you place a managed WAF service from your cloud provider (like AWS WAF, Azure WAF, or Google Cloud Armor) in front of the Load Balancer that serves your Ingress Controller.

How It Works:

The traffic flow looks like this: Internet -> Cloud WAF -> Cloud LoadBalancer (NLB/ALB) -> NGINX Ingress Pods -> Your Service.

You configure the WAF in your cloud provider’s console or via Terraform/IaC. You can apply managed rule sets that are updated for you (e.g., “OWASP Top 10,” “Known Bad IPs,” “SQLi common attacks”). The WAF inspects and blocks traffic before it ever touches your Kubernetes cluster, which is a huge win.

The Verdict:

  • Pros: Drastically less management overhead. The rule sets are curated and updated by experts. It offloads the performance-intensive inspection work from your cluster. It can also protect against DDoS attacks at the edge.
  • Cons: It costs money. You pay per rule and per million requests. It also introduces another component into your architecture that needs to be configured and monitored correctly. Can feel like a bit of a “black box.”

Pro Tip: When using a cloud WAF, ensure your Load Balancer and NGINX Ingress are configured to correctly pass and trust the X-Forwarded-For header. Otherwise, your WAF might rate-limit based on your Load Balancer’s IP instead of the actual client’s IP, causing major outages.

Solution 3: The “Rip and Replace” – Alternative Ingress Controllers

Sometimes, the problem isn’t the WAF; it’s that you’re trying to hammer a screw with NGINX. If security is a paramount and complex concern, you might be better off using an Ingress Controller that was built with these features as a primary concern.

How It Works:

You replace the standard NGINX Ingress Controller with a different one, like Kong, Traefik Enterprise, or F5 NGINX App Protect. These often come with tightly integrated, commercially supported WAF capabilities that are much easier to configure than a manual ModSecurity setup.

For example, with Kong, you might apply a WAF plugin via a Custom Resource Definition (CRD) directly in Kubernetes, making the configuration feel much more “cloud-native.”

The Verdict:

  • Pros: A seamless, integrated experience. Configuration is often done via Kubernetes-native CRDs. Commercial support is available if you run into trouble.
  • Cons: This is the most disruptive option, as it requires migrating your Ingress definitions. The most powerful features are often part of a paid, enterprise subscription.

Quick Comparison Table

Approach Cost Management Overhead Performance Impact
1. ModSecurity (In-Cluster) Low (compute resources) High (rule tuning) Medium (on Ingress pods)
2. Cloud WAF (Managed) Medium (pay-as-you-go) Low Low (on cluster), handled at edge
3. Alternative Ingress Medium to High (licensing) Low to Medium Varies (often optimized)

My Final Take

There is no silver bullet. For a startup or a small team, starting with ModSecurity (Solution 1) is a great, low-cost way to get compliant and protected. Just be prepared to invest the time in tuning. For any serious production workload where reliability and low operational overhead are key, I strongly advocate for a Cloud WAF (Solution 2). It lets your team focus on building features, not on becoming full-time WAF rule experts. If you’re building a new platform from scratch or your current Ingress solution is already causing headaches, then evaluating an Alternative Ingress Controller (Solution 3) is a smart strategic move.

Whatever you choose, do something. Don’t wait for that Tuesday afternoon panic. Good luck out there.


Darian Vance

👉 Read the original article on TechResolve.blog


☕ Support my work

If this article helped you, you can buy me a coffee:

👉 https://buymeacoffee.com/darianvance

Top comments (0)