Nginx Logo
# Web Server Setup # Overview This document explains how to configure the **web server** in the DMZ, using **Docker Compose** and **Nginx** as a reverse proxy to host several vulnerable web applications (OWASP Juice Shop, WebGoat, bWAPP, etc.). This configuration is designed for a lab environment dedicated to offensive security testing, in addition to an already configured pfSense firewall. # Table of Contents 1. [Overview](#overview) 2. [Prerequisites](#prerequisites) 3. [Docker Compose](#docker-compose) 4. [Nginx Configuration](#nginx-configuration) 5. [Place Configuration Files](#place-configuration-files) 6. [Test Configuration](#test-configuration) 7. [Hosts File Configuration](#hosts-file-configuration-wan-side) # Prerequisites Before starting, ensure the following are in place: - Have installed and configured the pfSense VM - Have installed the web server (DMZ-WEB01-LIN) - A dedicated user (ex: `webadmin`) with necessary permissions to manage containers and configuration files. # Steps ## Docker Compose This section details Docker container configuration to host vulnerable web applications, as well as Nginx reverse proxy setup. ### I. Docker Compose Installation If not already done, install Docker Compose by following the [official documentation](https://docs.docker.com/compose/install/). ### **II. Create `docker-compose.yml` File** After installing Docker Compose, create a file named `docker-compose.yml`. This file defines the following services: - **Nginx reverse proxy**: Routes traffic from WAN to applications based on hostnames. - **Vulnerable web applications**: Juice Shop, WebGoat, bWAPP, NodeGoat, VAmPI. - **Databases**: MongoDB containers for NodeGoat. Content of the `docker-compose.yml` file: ```yaml services: # ------------------------------ # Nginx Server (reverse proxy) # ------------------------------ proxy: image: nginx:alpine container_name: webapps-proxy restart: unless-stopped ports: - "80:80" volumes: - ./nginx.conf:/etc/nginx/nginx.conf:ro depends_on: - juice-shop - webgoat - bwapp - nodegoat - vampi networks: - default # ------------------------------ # NodeGoat # ------------------------------ nodegoat-db: image: mongo:4.4 container_name: nodegoat-db restart: unless-stopped volumes: - nodegoat-db-data:/data/db nodegoat: build: ./nodegoat container_name: nodegoat depends_on: - nodegoat-db environment: - DB_HOST=nodegoat-db - DB_PORT=27017 - VIRTUAL_HOST=nodegoat.lab volumes: - nodegoat-data:/usr/src/app/data restart: unless-stopped # ------------------------------ # Juice Shop # ------------------------------ juice-shop: image: bkimminich/juice-shop container_name: juice-shop environment: - VIRTUAL_HOST=juice.lab restart: unless-stopped # ------------------------------ # WebGoat # ------------------------------ webgoat: image: webgoat/webgoat container_name: webgoat environment: - VIRTUAL_HOST=webgoat.lab - VIRTUAL_PORT=8080 - TZ=Europe/Paris - WEBGOAT_CONTEXT_PATH=/WebGoat expose: - "8080" - "9090" volumes: - webgoat-data:/home/webgoat restart: unless-stopped # ------------------------------ # bWAPP # ------------------------------ bwapp: image: raesene/bwapp container_name: bwapp environment: - VIRTUAL_HOST=bwapp.lab restart: unless-stopped volumes: - bwapp-data:/var/www/html # ------------------------------ # VAmPI (Vulnerable API) # ------------------------------ vampi: image: erev0s/vampi container_name: vampi environment: - VIRTUAL_HOST=vampi.lab - VIRTUAL_PORT=5000 expose: - "5000" restart: unless-stopped # ------------------------------ # Volumes # ------------------------------ volumes: nodegoat-data: nodegoat-db-data: bwapp-data: webgoat-data: ``` ### III. Start Containers To start all containers defined in the `docker-compose.yml` file ```bash docker compose up -d ``` ## Nginx Configuration This section describes Nginx reverse proxy configuration, which routes requests to applications based on defined hostnames. ### **I. Create `nginx.conf` File** This file configures Nginx to: - **Route traffic** to each application based on `server_name`. - **Manage HTTP headers** for seamless integration. - **Support external applications** (Metasploitable2, Metasploitable3). > **Note**: These hostnames are arbitrary and can be replaced by any name you want. This is an example of the configuration for the lab. Content of the `nginx.conf` file: ```bash user nginx; worker_processes auto; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; # Logs (optional) access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; # ------------------------------ # 1. Juice Shop (default port) # ------------------------------ server { listen 80; server_name juice.lab; location / { proxy_pass http://juice-shop:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } # ------------------------------ # 2. WebGoat (default port) # ------------------------------ server { listen 80; server_name webgoat.lab; location / { proxy_pass http://webgoat:8080/; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_cookie_path /WebGoat /; proxy_redirect off; } } # ------------------------------ # 3. WebWolf (default port) # ------------------------------ server { listen 80; server_name webwolf.lab; location / { proxy_pass http://webgoat:9090/; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_cookie_path /WebWolf /; proxy_redirect off; } } # ------------------------------ # 4. bWAPP # ------------------------------ server { listen 80; server_name bwapp.lab; location / { proxy_pass http://bwapp; } } # ------------------------------ # 5. NodeGoat # ------------------------------ server { listen 80; server_name nodegoat.lab; location / { proxy_pass http://nodegoat:4000; } } # ------------------------------ # 6. VAmPI # ------------------------------ server { listen 80; server_name vampi.lab; location / { proxy_pass http://vampi:5000; } } # ------------------------------ # 7. Metasploitable2 # ------------------------------ server { listen 80; server_name ms2.lab; location / { proxy_pass http://192.168.20.104:80; proxy_set_header Host $host; } } server { listen 80; server_name ms2-8180.lab; location / { proxy_pass http://192.168.20.104:8180; proxy_set_header Host $host; } } # ------------------------------ # 8. Metasploitable3 Linux # ------------------------------ server { listen 80; server_name ms3linux.lab; location / { proxy_pass http://192.168.20.106:80; proxy_set_header Host $host; } } server { listen 80; server_name ms3linux-8080.lab; location / { proxy_pass http://192.168.20.106:8080; proxy_set_header Host $host; } } # ------------------------------ # 9. Metasploitable3 Windows # ------------------------------ server { listen 80; server_name ms3win.lab; location / { proxy_pass http://192.168.20.107:80; proxy_set_header Host $host; } } server { listen 80; server_name ms3win-8282.lab; location / { proxy_pass http://192.168.20.107:8282; proxy_set_header Host $host; } } server { listen 80; server_name ms3win-8484.lab; location / { proxy_pass http://192.168.20.107:8484; proxy_set_header Host $host; } } server { listen 80; server_name ms3win-4848.lab; location / { proxy_pass https://192.168.20.107:4848; proxy_set_header Host $host; } } server { listen 80; server_name ms3win-8585.lab; location / { proxy_pass http://192.168.20.107:8585; proxy_set_header Host $host; } } } ``` ## Place Configuration Files - Create a `/opt/webapps` directory and place the `docker-compose.yml` and `nginx.conf` files there. - Ensure the `webadmin` user has necessary permissions: ```bash sudo chown -R webadmin:webadmin /opt/webapps ``` ## Test Configuration - Verify that containers are started: ```bash docker ps ``` - Test access to applications via configured hostnames (e.g., `http://juice.lab`, `http://webgoat.lab`). Consult test files in `Docs/TESTS/Web_server.md` to validate connectivity and proper reverse proxy operation. > NodeGoat uses MongoDB in the `nodegoat-db` container. > > If the database is not correctly initialized (especially the counters collection), NodeGoat crashes, causing a 502 error via the Nginx proxy. > > To fix this error, initialize the `counters` collection in MongoDB. > > You can directly fix the NodeJS source code: > > ```bash > docker exec -it nodegoat sh > > vi /home/node/app/app/data/user-dao.js > ``` > > Then fix the similar part: > > ```jsx > this.getNextSequence = (name, callback) => { > db.collection("counters").findAndModify( > { > _id: name, > }, > [], > { > $inc: { > seq: 1, > }, > }, > { > new: true, > }, > (err, data) => > err ? callback(err, null) : callback(null, data.value.seq) > ); > }; > ``` ### **WAN-Side `hosts` File Configuration** **Objective**: Allow resolution of vulnerable application domain names from the WAN network, by associating each hostname with the **public IP address** of your web server (DMZ-WEB01-LIN). ### **1. Why Modify the `hosts` File?** - Vulnerable web applications (Juice Shop, WebGoat, etc.) are accessible via **virtual domain names** (e.g., `juice.lab`, `webgoat.lab`). - Without this configuration, requests to these domain names would fail, as they are not resolved by a public DNS. - This step is **mandatory** to access applications from the WAN (or from a machine external to the lab). ### **2. Configuration** 1. **Open the `hosts` file**: - **On Linux**: ```bash sudo nano /etc/hosts ``` - **On Windows**: - Open `Notepad` as administrator. - Go to `C:\Windows\System32\drivers\etc\hosts`. 2. **Add the following entries** (replace `` with your **WAN IP** of the pfSense machine): ``` # Vulnerable web applications (adapt with your WAN IP of the pfSense machine) juice.lab nodegoat.lab bwapp.lab vampi.lab webgoat.lab webwolf.lab ms2.lab ms2-8180.lab ms3linux.lab ms3linux-8080.lab ms3win.lab ms3win-8282.lab ms3win-8484.lab ms3win-4848.lab ms3win-8585.lab ``` **Example** (if WAN IP of the pfSense machine is `192.168.1.100`): ``` 192.168.1.100 juice.lab nodegoat.lab bwapp.lab vampi.lab webgoat.lab webwolf.lab 192.168.1.100 ms2.lab ms2-8180.lab 192.168.1.100 ms3linux.lab ms3linux-8080.lab 192.168.1.100 ms3win.lab ms3win-8282.lab ms3win-8484.lab ms3win-4848.lab ms3win-8585.lab ``` 3. **Save the file** and restart the network service if necessary: - **Linux**: ```bash sudo systemctl restart networking # or `sudo systemctl restart NetworkManager` ``` - **Windows**: - Run `ipconfig /flushdns` in a command prompt (admin). ### **3. Configuration Verification** - **Test DNS resolution** from your WAN machine: ```bash ping juice.lab ``` - **Expected result**: The command should return the configured WAN IP of the pfSense machine (e.g., `192.168.1.100`). - **Access applications** via a browser: - Open `http://juice.lab` or `http://webgoat.lab` in a browser. - **Expected result**: Applications should display without resolution errors. ### **4. Troubleshooting** - **Resolution problem**: - Verify that the `hosts` file has been modified with **correct permissions** (admin/root). - Ensure the **WAN IP** is correct (that of `FW-PFSENSE` WAN interface). - **Blocked access**: - Verify **NAT rules** on pfSense (port 80 must be redirected to `DMZ-WEB01-LIN`). - Ensure **Nginx** is running on the server: ```bash # Verify that the `webapps-proxy` container is "Up" docker ps ``` ### **5. Important Notes** - **Security**: - This configuration is **reserved for a lab environment**. In production, use a **real DNS** or a service like `dnsmasq` to manage resolution. - The `.lab` domain names are arbitrary and can be replaced by others (e.g., `.test`, `.local`). - **Persistence**: - `hosts` file modifications are **local** to each machine. For access from multiple WAN machines, repeat this configuration on each of them. - **Alternative**: - To avoid manually modifying each machine, configure a **local DNS server** (e.g., `dnsmasq`) to automatically resolve these domain names. For machines in the LAN segment, you can use the following `hosts` file: ``` # LAN 192.168.10.100 test.lab LAN-TEST-LIN 192.168.10.104 siem.lab LAN-SIEM-LIN 192.168.10.109 attack.lab LAN-ATTACK-LIN 192.168.10.30 minilab.dc LAN-DC01-WIN 192.168.10.31 minilab.ws01 LAN-WS01-WIN # DMZ 192.168.20.105 vuln-web.lab DMZ-WEB01-LIN 192.168.20.105 juice.lab bwapp.lab nodegoat.lab webgoat.lab vampi.lab 192.168.20.104 metasploitable2 ms2 DMZ-MS2-LIN 192.168.20.106 metasploitable3-lin ms3-lin DMZ-MS3-LIN 192.168.20.107 metasploitable3-win ms3-win DMZ-MS3-WIN # pfSense (LAN) 192.168.10.1 pfsense.lab pfsense.Lab4PurpleSec ``` # Resources - [Docker Compose Documentation](https://docs.docker.com/compose/install/) - [Configure Nginx as Reverse Proxy](https://www.digitalocean.com/community/tutorials/how-to-configure-nginx-as-a-reverse-proxy-on-ubuntu-22-04)