Lewati ke isi

Setup Nginx as a Reverse Proxy and WAF with ModSecurity in Docker

Nginx is a highly versatile web server which can effectively function as a reverse proxy and web application firewall (WAF). To function as a WAF, the ModSecurity WAF module is usually used with the OWASP ModSecurity Core Rule Set.

The ModSecurity WAF module will check incoming requests and outgoing responses against the rules it has loaded. If the request matches one of the rules, it will be ended before it is passed to the web application. The OWASP ModSecurity Core Rule Set contains generic rules intended to protect web applications from a variety of common attacks such as SQL injection and XSS.

I run a few different applications using Docker, mostly because it makes them easier for me to manage and update. Part of this includes an Nginx container which acts as a reverse proxy for the other web application containers. To help increase security I used a Nginx image with a WAF built in.

Creating the reverse proxy docker network

The network used by the reverse proxy to connect to the containers we’d like to expose will be used by a few different services. Because of this, it is best to create it separately. We can do this with a quick docker command.

docker network create reverse-proxy

Setup Nginx with ModSecurity Web Application Firewall

The free Nginx docker image does not include the ModSecurity module required load and process the OWASP ModSecurity Core Rule Set. This leaves the option of building a new image which includes the necessary module or finding an image from a different provider which already includes the module.

Thankfully, OWASP provides this docker image includes ModSecurity and the core rule set. This makes everything simpler and easier to manage, as to update the rules of Nginx version only the new docker image needs updating and the container recreating.

The following docker compose file will create a container which connects to the reverse-proxy network which will allow it to communicate with the containers it needs to proxy requests for. It will also setup a volume binds to allow the proxy configuration to be managed. This is a file named proxy.conf.

  • Nginx WAF Docker Compose
#root@kernel:/home/agungsurya/modsecuritydokcer/docker-compose.yml
version: "3.3"

services:
  reverseproxy:
    container_name: reverse-proxy-nginx-agungsurya
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /home/agungsurya/modsecuritydokcer/proxy.conf:/etc/nginx/conf.d/proxy.conf:ro
      - /home/agungsurya/modsecuritydokcer/apache-selfsigned.key:/etc/ssl/private/apache-selfsigned.key:ro
      - /home/agungsurya/modsecuritydokcer/apache-selfsigned.crt:/etc/ssl/certs/apache-selfsigned.crt:ro
      - /home/agungsurya/modsecuritydokcer/403.html:/var/www/html/403.html:ro
    environment:
      - PROXY=1
    restart: always
    image: agungsurya/reverse-proxy-nginx-modsecurity:v1
    networks:
      reverse-proxy:
        aliases:
          - reverse-proxy-nginx
networks:
  reverse-proxy:
    external: true
  • Proxy Configuration
#root@kernel:/home/agungsurya/modsecuritydokcer# cat proxy.conf
server {
  listen 80;
  listen [::]:80;

  server_name modsecurity.agungsurya.my.id;

  location / {
      proxy_pass http://prometheus.agungsurya.my.id/;


  }
}


 server {
    listen 443 ssl;
    listen [::]:443 ssl;

    ssl_certificate /etc/ssl/certs/apache-selfsigned.crt;
    ssl_certificate_key /etc/ssl/private/apache-selfsigned.key;


#/etc/ssl/private/apache-selfsigned.key
#/etc/ssl/certs/apache-selfsigned.crt

    server_name modsecurity.agungsurya.my.id;

    location / {
        proxy_pass https://prometheus.agungsurya.my.id;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Port $server_port;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

   }
}

tambahan kalau menggunakan https jika tidak menggunakan https hapus server listen ssl nya cukup seperti ini kalau http saja

server {
  listen 80;
  listen [::]:80;

  server_name modsecurity.agungsurya.my.id;

  location / {
      proxy_pass http://prometheus.agungsurya.my.id/;


  }
}

ini ssl cert kalau pakai https

agungsurya@kernel:~/modsecuritydokcer$ cat apache-selfsigned.crt

-----BEGIN CERTIFICATE-----
MIIDazCCAlOgAwIBAgIUCLH2azWbzhbm/r/L4M+icU7KprgwDQYJKoZIhvcNAQEL
BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMzA0MTAwOTE5NTlaFw0yNDA0
MDkwOTE5NTlaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw
HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEB
AQUAA4IBDwAwggEKAoIBAQDn5mtohGoHYIZiFkBtOZmw3CiBSOXduiioG9TRfvQH
l82aw+9bkOtq9pdRpOM2GVwDkooTMK0Xq14Ce7CbiM+3QtbzpYtktgmKEO1wJ/+y
bRlZzYWNHhXMIhLnPWhvPIyO2iEuUXWupc9QBJTTs1xb4k02XsB3shXjR29bMbqD
1FTumW/4joUKCp/EeyejHTLPRVhhkENhigfy+7tyq1WislRnUmdMdKYnPyvVqHDH
/KnHGDeeaZ1F83Woh8EDWFpgF73VToQnnyAFJSokqGl+RRHvyTgfBPoGaGEbKnCp
y+whpnvPF2PxGsLjMFYe9qxyNF3uLHu0I9pCDt/FAkCrAgMBAAGjUzBRMB0GA1Ud
DgQWBBS0pjmFGXeMtMRI0a0hY6AzuXrZcDAfBgNVHSMEGDAWgBS0pjmFGXeMtMRI
0a0hY6AzuXrZcDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCr
bgUA7Wv3fDq0qQ1wpY+m5/4geEbcwqSeqFp+3FlQAneH6EUNqRnJqwCtO47i2YCu
8F4ivYJ1KXcXg6acZsvOCdT7OGj1iG3UWfhq9JD1u/Row1Bl1ZIFTP3gT4ddcaEX
NGkrxKz7nsQBxI3fqNOffuMf9TuN8d/x271KETfdzBvNvHK8zniasDabRBqxeOLH
lDJLt8usbQwI1kDefdragq36udCpl4ZN8xYLL8lhJZew+qoEHNACKbAhjYK+FrW5
DlXBAuhSpMuujlTNmDBGCjPlKQWefGfUkf2juEFy0xP9cdoedeqEqCxeWWXbbNgF
W5iNLFtyQueMl7wncjHt
-----END CERTIFICATE-----

root@kernel:/home/agungsurya/modsecuritydokcer# cat apache-selfsigned.key

-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDn5mtohGoHYIZi
FkBtOZmw3CiBSOXduiioG9TRfvQHl82aw+9bkOtq9pdRpOM2GVwDkooTMK0Xq14C
e7CbiM+3QtbzpYtktgmKEO1wJ/+ybRlZzYWNHhXMIhLnPWhvPIyO2iEuUXWupc9Q
BJTTs1xb4k02XsB3shXjR29bMbqD1FTumW/4joUKCp/EeyejHTLPRVhhkENhigfy
+7tyq1WislRnUmdMdKYnPyvVqHDH/KnHGDeeaZ1F83Woh8EDWFpgF73VToQnnyAF
JSokqGl+RRHvyTgfBPoGaGEbKnCpy+whpnvPF2PxGsLjMFYe9qxyNF3uLHu0I9pC
Dt/FAkCrAgMBAAECggEAI2JOuuy9avETqtgfWNXZpBlWWt0Ufz++SrcDGDuJS7ai
KikXFtR8KgmEmZy8XeRXsbnZ30dlmeoi1uPS/6B2pU1fFAqLREDcdW3TdPIS0MGs
hRMte2n+7x4MiVke3B4+ijYxVZUbYkctj1WWSd52dhSygwcefK+2fu6cSKtup1o5
LGXH0IBCYBS4hb16ElLuR1FHyG826AcMbqnxY5/WUaEm6WkGRrK4h//MOwPbluw9
c7ZLXuZahI/0dEsEYfurfBkrBpfUeqddY2zJg0a+FB132fetCPzfp9OtTuHJVHXB
gMjTwf2eLcgumcVc/rgLUmQYxXp+L3Hjh/DARYK0OQKBgQD51Fx3HUi8Lwl3dbCs
bnAAV8cqyQIhEgexK5FfuRPEN8903vxT+O9/IWNDcby4F56pttCXyHJRRmBOjXFl
Itj8lu+80bKrpN+f7DfCR0dsTdQXPFokBhPe4L5mWrYX2pniGaANcwy6ZTkWXCq3
qHcg3tFS84Rt1m9o/aKNN/iNIwKBgQDtoLFa0EnClUz2QXQA6unCx08qJJTBfOMV
gm8dRng9JEs1/xTH9iAmC2BCp1dtpIOoTEsuQkEb+V4Omqet8ph+dk0DxbKlNTid
a2UHkkcaJ83jbFlu61ZFX8kWzu7xIlW9a8kp9tEEwk/Fhe9Sn7A00Upx/BrKhGVX
jldmyAfK2QKBgQDD/+9rI/ZkbSKoLhUlsp78JeGDl5+sAlE2lk+/IZx4XLDNqAOe
fbanrrIJv7mnVCCOVXbhHclSKjx0ZFOKXQSPZns/T+U09GzdMp2sNe+68HRsplSx
3nLIcNnvw0sI+9+umxwOcSyTL8bR3A1HeUu85hKjWZmT8qAFZreYw0iksQKBgQCQ
jU82OjyUdPQzXU+u+zgmd84NieE/7rPJMuZa/bJJJ1nlR/2hQnT+D6+H/HovxYMd
jwOw6TboSILSCXx1UX04eMiSweHRpBWDlYAI4hAEtjAF57RjyB9b5k/SYyFxaHyV
1QqzT2SJK5cRRk92iJPNHX/W5RB7H5zybTF34bjzyQKBgG76C3BIWsYOZpFM7NFo
MWTVO8IeWw0ThzLEluCqU4QIDOL+TgohdXnJwahVRiJKxoJ55ZuvvOBGCK3JAviH
OkEs6O9UgKFAU6+kYGXhQtH+xQTUTp0IiDm1xCnmz75QVmahKVHcEC658B7h0pcT
aM4h/l3BndCfMcpn0a12cl7+
-----END PRIVATE KEY-----

Starting to Reverse Proxy

Starting to Reverse Proxy You will need to make sure that all volume binds and container names match the above, or have been amended to match your environment as needed. When this is all in place you can start the reverse proxy using docker compose with the following command.

docker-compose up

Nginx as a Reverse Proxy and WAF with ModSecurity in action

sebelum instalasi server proxy waf nginx dengan modsecurity alisa server langsung tanpa proxy

sesudah instalasi dan konfigurasi server proxy waf nginx dengan modsecurity alisa server dengan proxy nginx