Nginx Security – Disable Directory Browsing Not Working

djangonginxSecurity

I have a Django application in production and my web server is Nginx.

My application is located at /home/rouizi/blog and let say my domain name is example.com.
I want to prevent that users can read my files that are located inside the blog folder.

For instance, with my actual configuration, if someone access exemple.com/manage.py he can see the content of that file. I want instead to show him a 404 not found error.

Here is my nginx configuration:

/etc/nginx/nginx.conf

user www-data;
worker_processes auto;

pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
        worker_connections 1024;
}

http {
        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;
        types_hash_max_size 2048;

        include /etc/nginx/mime.types;
        default_type application/octet-stream;

        ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
        ssl_prefer_server_ciphers on;

        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;

        include /etc/nginx/conf.d/*.conf;

       add_header    X-Content-Type-Options nosniff;
       add_header    X-Frame-Options SAMEORIGIN;
       add_header    X-XSS-Protection "1; mode=block";

       server_tokens off;
       keepalive_timeout 75;
}

/etc/nginx/conf.d/example.conf

server {
    if ($host = www.example.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot

    if ($host = example.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    listen         80;
    server_name    example.com www.example.com;
    return         301 https://example.com$request_uri;
}

server {
    listen                          443 ssl http2 default_server;
    listen                          [::]:443 ssl http2 default_server;
    
    #  ssl stuff

    server_name                     example.com www.example.com;
    root                            /home/rouizi/blog/;
    index                           index.html;

    location /static {
        alias /home/rouizi/blog/staticfiles/;
     }

    location / {
        proxy_set_header Host $http_host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_redirect off;
        if (!-f $request_filename) {
            proxy_pass http://127.0.0.1:8000;
            break;
        }
    }

    gzip             on;
    gzip_comp_level  3;
    gzip_types       text/plain text/css application/javascript image/*;
}

What I tried so far:

I added the directive autoindex on; and reload nginx. Not worked

I added an empty index.html file inside the blog directory and reload nginx. Not worked

How can I solve this problem ?

Edit

I found that If I put my ip address instead of my domain name in the server_name directive the directory browsing is disabled:

/etc/nginx/conf.d/example.conf

# ...

server {
    # ...
    #  ssl stuff

    server_name                     139.151.187.143;
    
    # ...

}

Just like that if I go to exemple.com/manage.py or other files I get a 404 not found error from my Dango application. But also static and media files are no longer served.

Anyone can explain why ? Is this reloated to my DNS hosting provider ?

Best Answer

Serving anything other than the files specifically copied to a static folder is not typically what you want for Django-powered applications.

The typical setup works like this:

  1. everything in /static gets handled by the web server (this is what the location /static {} block is about: the alias points to the directory where the django collectstatic commands places static files)
  2. similar handling of a /media location, as necessary
  3. everything else gets forwarded to the wsgi application (meaning your program files are not directly accessed by the nginx server)

What you want it probably remove the root /home/rouizi/blog/; and unconditionally (not inside a if (!-f $request_filename) { block) forward requests to your wsgi application.