Overview
Your production WordPress site runs on a single EC2 instance (t4g.large / ARM Graviton) with the DNS A record pointing directly to the instance IP. AWS WAF can't attach to a bare EC2 — and the ALB migration attempted in December 2025 didn't go through due to .htaccess routing complexity, SSL termination conflicts, and DNS cutover risk on a live production domain. This document lays out how Wafway integrates into your existing setup without changing any of that.
All 7 Architectural Constraints Addressed
Wafway is deployed as a reverse proxy directly on your EC2 instance, sitting between the public internet and Apache. No ALB, no CloudFront, no DNS changes. Your .htaccess routing, SSL certificates, and all three WordPress installations continue to work exactly as they do today — Wafway inspects every inbound request before it reaches Apache, blocking threats and passing legitimate traffic through transparently. It runs natively on ARM64/Graviton as a single static binary.
No Infrastructure Changes
Installs on the existing EC2 instance. No ALB, no CloudFront, no DNS cutover, no target group configuration. The same IP serves the same domain.
Apache Routing Preserved
Wafway proxies to Apache on localhost. All .htaccess rules, mod_rewrite directives, permalink structures, and WordPress path routing remain untouched.
Enterprise-Grade Protection
12+ threat detectors covering OWASP Top 10, bot detection with 100+ signatures, rate limiting, geo-blocking, and compliance reporting — all without AWS WAF dependencies.
Your Current Architecture
This is the infrastructure topology Wafway integrates into:
| Component | Detail |
|---|---|
| EC2 Instance | i-04eb7ac3 • t4g.large (ARM/Graviton) • ap-south-1 |
| Public IP | 35.154.*.* (A record for flexiloans.com) |
| Web Server | Apache HTTP + PHP • Single VirtualHost • .htaccess routing |
| SSL | Terminated at Apache (Let's Encrypt / similar) |
| Applications | Static landing (/) + 3 WordPress installations (/loan, /blog, /hi/blog) |
| Existing WAF | Cannot be applied — AWS WAF requires ALB/CloudFront attachment |
| Prior ALB Attempt | Fl-Wordpress-ALB created Dec 24, 2025 • 0 registered targets • Abandoned |
Current Risk: Without a WAF, the EC2 instance is directly exposed to SQL injection, XSS, bot scraping, credential stuffing, and other OWASP Top 10 threats. Three WordPress installations on a single domain significantly increase the attack surface — WordPress remains the most targeted CMS globally.
How Wafway Addresses Each Constraint
AWS WAF can only attach to ALB, CloudFront, API Gateway, etc. It cannot attach to an EC2 instance or NLB. Since flexiloans.com resolves directly to the EC2 public IP (35.154.*.*), there is no supported WAF attachment point.
- Wafway is a standalone reverse proxy binary that runs directly on the EC2 instance
- It binds to ports 80/443, receives all inbound traffic, inspects it, then proxies clean requests to Apache on a local port (e.g., 127.0.0.1:8080)
- No ALB, CloudFront, or any AWS intermediary is needed
- Wafway is the WAF — it doesn't need to attach to anything
Complex .htaccess rules map /loan, /blog, /hi/blog to three different WordPress installations. ALB path-based routing cannot replicate mod_rewrite behavior. WordPress permalink rewrites, redirect chains, and security rules would all break.
- Wafway proxies to Apache on
127.0.0.1:8080, preserving the original request path and all headers - Apache still handles all .htaccess routing, mod_rewrite rules, and permalink structures — completely untouched
- WordPress siteurl/home settings require zero changes
- All three WP installations + static landing page work identically
- Wafway adds
X-Forwarded-For,X-Real-IPheaders so Apache sees the real client IP
SSL terminates at Apache (Let's Encrypt). Moving to ALB creates dual-SSL handling, wp-config.php HTTPS enforcement redirect loops, and mixed content issues from absolute URLs stored in the WordPress database.
- Option A (Recommended): Wafway terminates TLS on ports 443/80 using the same Let's Encrypt certificates, then proxies to Apache over HTTP on localhost. Apache's VirtualHost simply moves from port 443 to a local port.
- Option B: Wafway listens on a non-standard port, Apache stays on 80/443, and iptables redirects inbound traffic through Wafway first (transparent proxy mode).
- In both cases: no redirect loops, no mixed content, no wp-config.php changes. WordPress sees HTTPS via
X-Forwarded-Protoheader. - TLS 1.2+ enforced with modern cipher suites (ECDHE+AES-GCM)
Three separate WordPress installations (/loan, /blog, /hi/blog) share the same domain, VirtualHost, and IP. Each has its own wp-config.php, database, and plugins. Session handling and cookies may overlap. Moving one behind an ALB without the others is not feasible.
- Wafway sits in front of all paths simultaneously — every request through the single entry point is inspected
- Path-specific protection rules can be configured: e.g., stricter WAF sensitivity for
/loan(financial data) vs/blog(public content) - Per-path rate limiting: tighter limits on
/wp-adminand/wp-login.phpacross all three installations - Cookie and session handling remains Apache's responsibility — Wafway doesn't interfere
The root URL (/) serves static HTML while sub-paths serve WordPress. ALB routing offers no separation benefit since everything runs on the same EC2. CloudFront caching complicates WordPress dynamic content (admin sessions, PHP execution).
- Wafway does not need to differentiate between static and dynamic content — all requests are inspected equally at the HTTP layer
- No CDN caching complications: Wafway is a security proxy, not a cache layer
- Static pages benefit from bot protection and rate limiting just like WordPress pages
- Path-specific whitelisting available if static assets need WAF bypass for performance
No Auto Scaling Group, no launch template, no redundancy. Adding an ALB in front of a single instance adds complexity without HA benefit. The prior Fl-Wordpress-ALB attempt has an empty target group, suggesting migration failure.
- Wafway runs on the same instance — it adds zero network hops, zero additional infrastructure, and no extra single point of failure
- Resource footprint: ~30-50 MB RAM, negligible CPU on t4g.large (ARM-optimized binary)
- SystemD service with automatic restart ensures Wafway recovers from crashes
- Health check endpoint (
/health) can be monitored by existing AWS CloudWatch alarms - Backend health checks ensure Apache is responsive; if Apache goes down, Wafway returns a maintenance page
Switching the A record to an ALB/CloudFront ALIAS record risks downtime during DNS propagation. If the new configuration has issues (SSL mismatch, routing errors), the site goes down with no quick rollback path.
- Zero DNS changes required. The A record stays as 35.154.*.* pointing to the EC2 instance
- Wafway is deployed on the instance itself — traffic path is identical from the client's perspective
- No propagation window, no ALIAS record, no TTL concerns
- Instant rollback: stop Wafway, restore Apache to port 80/443. Recovery time: <10 seconds
- Can be tested in detect-only mode first (logs threats but doesn't block) to validate before enforcing
Architecture: Before & After
Before (Current State — Unprotected)
After (With Wafway — Enterprise Protection)
Key Point: The entire integration happens inside your existing EC2 instance. From the outside — same IP, same domain, same DNS. Every request now passes through Wafway's 12+ threat inspection engines before reaching Apache.
Wafway vs AWS WAF vs Cloudflare — for Your Architecture
| Capability | AWS WAF | Cloudflare | Wafway |
|---|---|---|---|
| Works with bare EC2 (no ALB/CDN) | ✗ | ✗ Requires DNS change | ✓ Runs on EC2 |
| Preserves .htaccess routing | ✗ Needs replication | ~ Proxy may interfere | ✓ Transparent |
| Zero DNS changes | ✗ Needs ALIAS | ✗ Needs NS change | ✓ |
| Zero downtime deployment | ✗ DNS propagation | ~ DNS propagation | ✓ |
| Instant rollback (<10 sec) | ✗ | ✗ DNS TTL | ✓ |
| ARM/Graviton native support | N/A (managed) | N/A (managed) | ✓ arm64 binary |
| SSL/TLS with no redirect loops | ✗ Complex setup | ~ Flexible mode | ✓ |
| OWASP Top 10 protection | ✓ Managed rules | ✓ | ✓ 12+ detectors |
| Bot detection (100+ signatures) | ~ Bot Control add-on | ✓ | ✓ Built-in |
| Admin dashboard | ✓ AWS Console | ✓ Cloudflare Dashboard | ✓ Self-hosted :9090 |
| PCI-DSS / SOC2 compliance logging | ✓ | ✓ | ✓ Built-in |
| SIEM integration (Splunk/ELK) | ~ Via CloudWatch | ~ Log push | ✓ Native |
| No per-request pricing | ✗ $0.60/M requests | ~ Tiered plans | ✓ Flat license |
| Data sovereignty (on-premise) | ✗ | ✗ | ✓ All data local |
Threat Coverage for Your WordPress Stack
WordPress is the most targeted CMS globally. Here's how Wafway's 12+ detectors map to the specific attack vectors relevant to your setup:
| Threat Detector | WordPress Relevance | Protection Detail |
|---|---|---|
| SQL Injection | Critical — WP uses MySQL extensively | Multi-level URL decoding, parameterized detection, evasion-aware pattern matching |
| XSS (Cross-Site Scripting) | Critical — Comments, forms, plugins | HTML entity decoding, JavaScript injection detection, event handler analysis |
| Command Injection | High — Vulnerable plugins may execute OS commands | Shell metacharacter detection, OS command pattern matching |
| Local File Inclusion (LFI) | High — wp-config.php exposure attempts | Wrapper detection (php://, data://), remote file inclusion blocking |
| Path Traversal | High — Access to /etc/passwd, wp-config.php | Directory traversal patterns, double-encoding evasion detection |
| SSRF | Medium — WP XML-RPC, pingbacks | Internal IP blocking, AWS metadata service (169.254.169.254) protection |
| XXE | Medium — XML-RPC endpoint | External DTD blocking, XML bomb protection, entity expansion limits |
| Bot Detection | Critical — Scraping, spam, brute force | 100+ bad bot signatures, good bot verification (Googlebot via rDNS), automation fingerprinting |
| Scanner Detection | High — WPScan, Nessus, Burp | Vulnerability scanner signatures (WPScan, SQLMap, Nikto, etc.) |
| Rate Limiting | Critical — wp-login.php brute force | Per-IP sliding window, challenge mode, path-specific limits for /wp-admin |
| Geo-blocking | Useful — Block high-risk regions | Country-level, VPN/proxy/Tor blocking, IP-to-country DB |
| Protocol Attacks | Medium — HTTP smuggling via Apache | Request smuggling detection, response splitting, null byte injection |
| DLP (Data Loss Prevention) | High — Credit card data in forms | Credit card, SSN, API key detection in responses; error message masking |
| Virtual Patching | Critical — Patch WP CVEs before updates | Custom patterns for specific CVEs — protect known vulnerabilities immediately without waiting for WordPress/plugin patches |
WordPress-Specific Tuning: Wafway ships with pre-built rules for wp-login.php brute force protection, XML-RPC abuse prevention, wp-admin IP-based access control, and automatic blocking of known WordPress exploit patterns (TimThumb, RevSlider, etc.). These are configured during integration.
Integration Steps
The integration is non-disruptive and can be completed during business hours with near-zero downtime.
Pre-Deployment: Upload Wafway Binary
SCP the ARM64 binary to the EC2 instance. Create configuration directory and wafway.yaml. No services are changed yet.
Configure Wafway
Create the wafway.yaml configuration with the backend pointing to Apache on localhost and protection mode set to detect-only for initial validation.
# /etc/wafway/wafway.yaml server: listen_addr: "0.0.0.0" listen_port: 443 http_port: 80 tls: enabled: true cert_file: "/etc/letsencrypt/live/flexiloans.com/fullchain.pem" key_file: "/etc/letsencrypt/live/flexiloans.com/privkey.pem" min_version: "TLS1.2" backend: url: "http://127.0.0.1:8080" # Apache moved to localhost:8080 health_check_path: "/healthz.html" health_check_interval: 30s protection: mode: "detect" # Log-only mode during validation phase sqli: { enabled: true, sensitivity: "medium" } xss: { enabled: true, sensitivity: "medium" } cmdinj: { enabled: true } lfi: { enabled: true } ssrf: { enabled: true } rate_limit: enabled: true requests_per_minute: 200 ban_duration: 10m admin: enabled: true listen_port: 9090 # Restrict via Security Group to internal IPs
Reconfigure Apache to Listen on Localhost
Change Apache's VirtualHost from port 80/443 to 127.0.0.1:8080. This is a single-line change in the Apache config.
Start Wafway & Restart Apache (Cutover)
This is the only moment with brief downtime (~2-3 seconds). Apache restarts on the new port, Wafway starts on 80/443.
Validate in Detect-Only Mode (24-48 hours)
Monitor the Wafway admin dashboard at :9090 to review all detections. Confirm no false positives on legitimate traffic. Review logs, tune sensitivity thresholds.
Switch to Enforce Mode
Change protection.mode from "detect" to "medium" in wafway.yaml. Wafway's hot-reload picks up the change automatically — no restart needed.
Integration Timeline
Risk Profile & Rollback
Deployment Risk: Low
No DNS changes, no infrastructure additions, no third-party dependencies. Wafway runs as a single binary on the existing instance. The cutover window is 2-3 seconds (Apache restart + Wafway start).
Rollback Risk: Low
Instant rollback: systemctl stop wafway && systemctl restart apache2 (revert Apache to port 80/443). Recovery time: <10 seconds. No DNS propagation wait.
Performance Risk: Low
Wafway adds <1ms latency per request (Go-optimized, single-binary, no garbage collection pauses). ARM64 native build means no emulation overhead on Graviton.
False Positive Risk: Mitigated
Detect-only mode for 24-48 hours catches false positives before enforcement. Path-specific whitelisting and per-detector sensitivity tuning available. WordPress-specific rule tuning included in deployment.
Emergency Rollback Procedure
What Else You Get
Beyond the core WAF protection, these enterprise capabilities are included out of the box:
| Feature | Description | Benefit for FlexiLoans |
|---|---|---|
| Admin Dashboard | Real-time monitoring portal on port 9090 with traffic analytics, threat visualization, and configuration management | Full visibility into security events without depending on AWS Console |
| SIEM Integration | Native Splunk HEC, Elasticsearch, and Syslog (CEF/LEEF) output | Plugs into your existing SOC/SIEM tooling directly |
| Compliance Reporting | PCI-DSS, SOC 2, HIPAA audit logging with tamper-detection hashing | Supports RBI/NBFC regulatory compliance requirements |
| Virtual Patching | Custom patterns for specific CVEs without waiting for vendor patches | Zero-day protection for WordPress and plugin vulnerabilities |
| Hot Reload | Configuration changes apply without restart or downtime | Tune rules, add IP blocks, adjust rate limits — all live |
| ML Anomaly Detection | Baseline learning for normal traffic patterns with statistical anomaly scoring | Detect novel attacks that signature-based detection would miss |
| DLP (Data Loss Prevention) | Detects credit card numbers, PAN (Aadhaar), API keys in responses | Prevents sensitive loan data from leaking in HTTP responses |
| RBAC & MFA | Role-based access control with multi-factor authentication for admin portal | Secure team access to WAF management |
| Health Monitoring | Backend health checks with configurable intervals and alerts | Immediate visibility if Apache or WordPress goes down |
| API Security | JWT validation, GraphQL protection, REST API rate limiting | Protect any APIs served alongside WordPress (future-proof) |
Scaling Path — When You Grow Beyond a Single EC2
The current solution is designed for your single-instance architecture today. But if you scale flexiloans.com to multiple EC2 instances behind an ALB or Auto Scaling Group in the future, Wafway scales with you — no migration, no replacement.
Option A: Wafway on Every Instance (Sidecar Model)
Each EC2 instance in your ASG runs its own Wafway binary alongside Apache. All Wafway nodes share state via Redis for coordinated security enforcement.
| Shared via Redis | What It Means |
|---|---|
| Distributed Rate Limits | An attacker hitting Instance 1 and Instance 2 alternately still gets rate-limited — the counter is global, not per-node |
| Shared IP Bans | If Wafway on Instance 1 bans an IP, it's instantly banned on Instance 2 and all other nodes |
| Bot Detection State | Challenge tokens and bot verification results are shared, so a legitimate user passing a challenge on one node doesn't get re-challenged on another |
| Session Tracking | Credential stuffing and brute force detection works across the cluster, not just per-instance |
Option B: Dedicated Wafway Instance (Gateway Model)
Run Wafway on a dedicated EC2 instance (or pair for HA) as the single entry point. All traffic flows through the Wafway gateway before reaching your backend instances. This is the classic WAF-as-gateway pattern.
Which Model to Pick?
| Consideration | Sidecar (on every instance) | Gateway (dedicated instance) |
|---|---|---|
| Best when | Auto Scaling Group, instances come and go | Fixed fleet, want centralized control |
| State sharing | Requires Redis (e.g., ElastiCache) | Single instance, no Redis needed |
| Network hops | Zero — WAF is on the same box | One extra hop (gateway → backend) |
| Failure blast radius | Per-instance — one Wafway down affects only that node | Central — gateway down means all traffic stops (use HA pair) |
| Config management | Config on each instance (bake into AMI or use user-data) | Single config, single admin portal |
| Works with existing ALB? | ✓ ALB → EC2 (Wafway → Apache) | ✓ Wafway → ALB → EC2 (Apache) |
For your current setup — single EC2, no ASG — the sidecar model is exactly what we're proposing. If you later move to multiple instances or EKS (as the instance name FlexiLoans-WordPressServer-24.04-EKS hints at), both scaling paths are available with zero changes to the WAF rules or protection config you've already tuned.
Summary
Wafway addresses all seven architectural constraints by operating as a reverse proxy directly on your EC2 instance. The integration requires:
The recommended path is to start with detect-only mode — this gives you immediate visibility into threats hitting your WordPress installations with zero risk. Once validated, switching to active enforcement is a single config change via hot-reload — no restart, no downtime.