2

Objective

I want to block the database access URLs, like https://example.com/web/database/selector or https://example.com/web/database/manager, in an Odoo deployment for all outside traffic but a couple of specific IPs.

To avoid encouraging people sniffing around to go deeper with an Access Denied or Unauthorized Access message, I'd like to do so with a 404 Page not Found error message, and for that 404 to use Odoo's 404 Error Template and not Nginx Template.

Screenshot of the desired result

What I have tried and I'm aware of

I know the simplest way to deny will be adding a location block like this:

# Odoo Server                                                                  #
upstream odoo {
    server 127.0.0.1:8069;
}

# HTTP Web Server
server {
    listen      80;
    listen [::]:80;
    server_name example.com www.example.com;

#   Block Database Manager/Selector Access via URL except for us
    location ~* /web/database/* {
        allow ###.###.###.###;
        deny all;
        proxy_pass http://odoo;
    }

#   Reverse Proxy Invocation for Odoo Server                                   #
    location / {
        proxy_pass  http://odoo;
    }

This works perfectly except that it launches an Nginx Template 403 Forbidden message, and my objective is a 404 Page not Found error message, it also is not styled, formatted, or anything so it's also not the Odoo 404 Template.

I have also tried the following location block:

# Odoo Server                                                                  #
upstream odoo {
    server 127.0.0.1:8069;
}

# HTTP Web Server
server {
    listen      80;
    listen [::]:80;
    server_name example.com www.example.com;

#   Block Database Manager/Selector Access via URL except for us
    location ~* /web/database/* {
        if ($remote_addr != ###.###.###.###) {
        return 404;
        proxy_pass http://odoo;
        }
    }

#   Reverse Proxy Invocation for Odoo Server                                   #
    location / {
        proxy_pass  http://odoo;
    }

This one will give me the 404 Page Not Found error message, however, it's the Nginx Template one, not Odoo's one, and the restriction doesn't work, I get the 404 Error even if the call comes from the IP ###.###.###.###.

However, if I change the != for a =, and to test also change the return to 444, it does recognize the IP ###.###.###.### as I now get an 'ERR_EMPTY_RESPONSE' message.

I have read about using IF inside a location block including the If is Evil article on nginx.com but it's supposed to work without issues on a return action.

# Odoo Server                                                                  #
upstream odoo {
    server 127.0.0.1:8069;
}

# HTTP Web Server
server {
    listen      80;
    listen [::]:80;
    server_name example.com www.example.com;

#   Block Database Manager/Selector Access via URL except for us
    location ~* /web/database/* {
        if ($remote_addr = ###.###.###.###) {
        return 444;
        proxy_pass http://odoo;
        }
    }

#   Reverse Proxy Invocation for Odoo Server                                   #
    location / {
        proxy_pass  http://odoo;
    }

What I have researched

It seems like this is achievable with a Rewrite instead by keeping it in the Web App and the URL used, I even found an example on how to achieve it on Apache, but all my attempts to try to understand it, or set it for Nginx have failed, it goes like this:

#Block database manager
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/web/database/manager [NC]
RewriteCond %{REMOTE_ADDR} !^##1\.###\.###\.###
RewriteCond %{REMOTE_ADDR} !^##2\.###\.###\.###
RewriteCond %{REMOTE_ADDR} !^##3\.###\.###\.###
RewriteRule ^ - [F]

#Block database selector
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/web/database/selector [NC]
RewriteCond %{REMOTE_ADDR} !^##1\.###\.###\.###
RewriteCond %{REMOTE_ADDR} !^##2\.###\.###\.###
RewriteCond %{REMOTE_ADDR} !^##3\.###\.###\.###
RewriteRule ^ - [F]

I also found this deployment that has what I want to implement, try this link

Current Nginx configuration file

This is my current Nginx Configuration File, everything is currently working including every feature of the app, but I do get the unwanted 403 Forbidden Access Nginx Template message when not coming from IP ###.###.###.###

I'm using Ubuntu 20.04, Odoo V15 and Nginx Version 1.22.0

# ============================================================================ #
#              Web Server NGINX Configuration for Example.com                  #
# ============================================================================ #

# ============================================================================ #
# 1. Services                                                                  #
# ============================================================================ #
#                                                                              #
# Odoo Server                                                                  #
upstream odoo {
    server 127.0.0.1:8069;
}

# Longpolling Server (A must for Workers > 0 in the odoo.conf and for Chat)    #
upstream longpolling {
    server 127.0.0.1:8072;
}
# --------------------------------------------------------------- End Services #

# ============================================================================ #
# 2. HTTP Web Server                                                           #
# ============================================================================ #
#                                                                              #
server {
    listen      80;
    listen [::]:80;
    server_name example.com www.example.com;
    access_log /var/log/nginx/example.com.access.log;
    error_log /var/log/nginx/example.com.error.log;

#   Redirect to HTTPS                                                          #
    location / {
        return 301 https://example.com$request_uri;
    }
}
# ------------------------------------------------------------ End HTTP Server #

# ============================================================================ #
# 3. HTTPS Web Server                                                          #
# ============================================================================ #
#                                                                              #
server {
    listen      443 ssl http2 default_server;
    listen [::]:443;
    server_name example.com www.example.com;
    proxy_read_timeout 720s;
    proxy_connect_timeout 720s;
    access_log /var/log/nginx/example.com.ssl.access.log;
    error_log /var/log/nginx/example.com.ssl.error.log;

#   Certificate and Key Path                                                   #
    ssl_certificate       /path/to/chained.crt;
    ssl_certificate_key   /path/to/private.key;

#   Proxy Performance Settings                                                 #
    proxy_buffers 16 64k;
    proxy_buffer_size 128k;

#   Proxy Security Settings                                                    #
    proxy_set_header      X-Forwarded-Host  $host;
    proxy_set_header      X-Forwarded-For   $proxy_add_x_forwarded_for;
    proxy_set_header      X-Forwarded-Proto $scheme;
    proxy_set_header      X-Real-IP         $remote_addr;
    proxy_set_header      X-Odoo-dbfilter   "TEST";
    proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;

#   Block Database Manager/Selector Access via URL except for us
    location ~* /web/database/* {
        allow ###.###.###.###;
        deny all;
        proxy_pass http://odoo;
    }

#   Reverse Proxy Invocation for Odoo Server                                   #
    location / {
        proxy_pass  http://odoo;
    }

#   Reverse Proxy Invocation for Longpolling                                   #
    location /longpolling {
        proxy_pass http://longpolling;
        proxy_redirect off;
    }

#   Reverse Proxy Invocation for Web Assets                                    #
    location ~* /web/static/ {
        proxy_cache_valid 200 60m;
        proxy_buffering on;
        expires 864000;
        proxy_pass http://odoo;
    }

#   Reverse Proxy Invocation for Web Images                                    #
    location ~* /website/image/ir.attachment/ {
        proxy_cache_valid 200 60m;
        proxy_buffering on;
        expires 864000;
        proxy_pass http://odoo;
    }

#   Access to Common gzip files                                                #
    gzip_types text/css text/less text/plain text/xml application/xml application/json application/javascript;
    gzip on;
}

# ####################### End NGINX Configuration File ####################### #

I also have a default.conf set to prevent access directly by the IP:

# ============================================================================ #
#              Web Server NGINX Configuration for Defaukt                      #
# ============================================================================ #

# ============================================================================ #
# 1. HTTP and HTTPS Web Server to Block Access by IP                           #
# ============================================================================ #
#                                                                              #

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

    listen      443 ssl default_server;
    listen [::]:443 default_server;
    ssl_reject_handshake on;

    server_name _;
    return 444;
}

# ####################### End NGINX Configuration File ####################### #

I'll appreciate to be pointed in the right direction or told what am I missing or doing wrong.

Thanks.

  • 1
    Does this answer your question? [Efficiently defining many nginx custom error pages](https://serverfault.com/questions/951260/efficiently-defining-many-nginx-custom-error-pages) – djdomi Jul 08 '22 at 17:33
  • Thanks! It's for sure eye-opening, I would need to figure out how to invoke Odoo's 404 Error URL and set it as NginX 404 Error Template, but still leaves me with 2 issues, I can't still Deny the URL for all IPs except mine, as the `IF` version of the Location with `$remote_addr` still doesn't work with `!=` and it will be obvious I'm redirecting to a 404 URL different than that the user put on the browser. – Alejandro Vidaurre Jul 08 '22 at 19:23
  • 1
    using if on nginx is a bad idea, you looking for allow and deny and remind that nginx read top down the config, so I would first deny all and then allow one ip. – djdomi Jul 08 '22 at 19:29
  • After fiddling for a while with the answer you suggested it gave me the result I was expecting, Thanks! – Alejandro Vidaurre Jul 08 '22 at 20:07

1 Answers1

2

Solved!

Thanks to djdomi I solved the problem I was having and got to the solution I needed, with the answer he referred.

What I did was add on my default.conf custom error redirects with:

error_page 403 /error/403;

Since the allow and deny parameters were working as intended but were showing the basic Nginx 403 Error, by defining a custom error redirect to it, now shows the Odoo 404 Error Template and the URL used by the user persists, I think it is because example.com/error/403 doesn't exist on the App, so for that matter feel free to use for Odoo specifically, one URL you're sure doesn't exist on your deployment and one that you will never use.

Here's the full default.conf in case someone needs it and it works perfectly with the example.com.conf I posted on the Question:

# ============================================================================ #
#              Web Server NGINX Configuration for Default                      #
# ============================================================================ #

# ============================================================================ #
# 1. HTTP and HTTPS Web Server to Block Access by IP                           #
# ============================================================================ #
#                                                                              #

# Custom Error to replace Nginx Error
error_page 403 /error/403;

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

    listen      443 ssl default_server;
    listen [::]:443 default_server;
    ssl_reject_handshake on;

    server_name _;
    return 444;
}

# ####################### End NGINX Configuration File ####################### #

Thanks, hope this helps someone else.

  • it was a pleasure for me to get you the information you needed ;) maybe you want to upvote my other post as well as a little reverse charge ;D – djdomi Jul 09 '22 at 07:53