Nginx: combine Advanced ACL and IP ACL

Started by tblum, November 10, 2023, 09:28:55 AM

Previous topic - Next topic
Hi,
I'd like to configure nginx so that authentication against our LDAP will be nessecary only from outside our local networks. I have configures advanced ACL. It work, the user is prompted to login and nginx takes the LDAP credentials. I also configured IP ACL with default action set to "deny" and our IP-ranges to "allow". In the "HTTP-Server"-section of the nginx configuration, I have set the Advanced ACL Backend to LDAP and IP ACL to the configured one. "Satisfy" is configured as "any". In the "Location" I have set Advanced ACL and the IP ACL to the configured one and "Satisfy" to "any". Nevertheless, I have to enter my LDAP credentials, even when I'm connated to our local network. What am I missing?
Best regards
Thomas

Hi!
should work the way you need it.
are you sure that the config does not contain additional inclusions (_pre/_post confs) and nginx sees requests from the LAN as requests from the "allowed" subnet(s)?

Hi, thank you for your reply and sorry for my late reaction, I was out of office for some days and forgot it, then.
So, I don't think that there are includes that are responsible for the behaviour, but maybe, I am missing something, perhaps, you can have a look, too:


# cat /usr/local/etc/nginx/nginx.conf

load_module /usr/local/libexec/nginx/ngx_stream_module.so;
load_module /usr/local/libexec/nginx/ngx_http_naxsi_module.so;
load_module /usr/local/libexec/nginx/ngx_mail_module.so;
load_module /usr/local/libexec/nginx/ngx_http_brotli_filter_module.so;
load_module /usr/local/libexec/nginx/ngx_http_brotli_static_module.so;
load_module /usr/local/libexec/nginx/ngx_http_js_module.so;
load_module /usr/local/libexec/nginx/ngx_http_vhost_traffic_status_module.so;

user www staff;
worker_processes 1;

#error_log  /var/log/nginx/error.log;
error_log  syslog:server=unix:/var/run/log,facility=local6,nohostname warn;

events {
    worker_connections  1024;
}

http {
include       mime.types;



log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                  '$status $body_bytes_sent "$http_referer" '
                  '"$http_user_agent" "$http_x_forwarded_for"';
log_format  main_ext  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for" '
                      '"$host" sn="$server_name" '
                      'rt=$request_time '
                      'ua="$upstream_addr" us="$upstream_status" '
                      'ut="$upstream_response_time" ul="$upstream_response_length" '
                      'cs=$upstream_cache_status';
log_format  handshake   '"$http_user_agent" "$ssl_ciphers" "$ssl_curves"';
log_format  anonymized  ':: - $remote_user [$time_local] "$request" '
                  '$status $body_bytes_sent "$http_referer" '
                  '"$http_user_agent" "$http_x_forwarded_for"';

#tcp_nopush     on;
# https intercept detection
js_import /usr/local/opnsense/scripts/nginx/ngx_functions.js;
js_set $tls_intercepted ngx_functions.check_intercept;

# 200M should be big enough for file servers etc.
client_max_body_size 200M;
brotli_static on;
brotli on;
gzip_static on;
gzip on;
server_tokens off;
sendfile Off;
default_type  application/octet-stream;
keepalive_timeout 60;

map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

# Map used in location.conf for proxy_ssl_name
map $ssl_server_name $upstream_sni_name {
    default $ssl_server_name;
    '' $host;
}

include http_post/*.conf;

# TODO add when core is ready for allowing nginx to serve the web interface
# include nginx_web.conf;




# UPSTREAM SERVERS
upstream upstream<crypticnumbersandlettersupstream1> {
server myfirstupstream.mydomain.de:8090 weight=1;

}
upstream upstream<crypticnumbersandlettersupstream2> {
server mysecondupstream.mydomain.de:8080 weight=1;

}


include opnsense_http_vhost_plugins/*.conf;

server {

    listen 80;
    listen [::]:80;

    listen 443 http2 ssl;
    listen [::]:443 http2 ssl;

    ssl_certificate_key /usr/local/etc/nginx/key/opnsense.mydomain.de.key;
    ssl_certificate /usr/local/etc/nginx/key/opnsense.mydomain.de.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_dhparam /usr/local/opnsense/data/OPNsense/Nginx/dh-parameters.4096.rfc7919;
    ssl_ciphers ECDHE-ECDSA-CAMELLIA256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-CAMELLIA256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-CAMELLIA128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-CAMELLIA128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-CAMELLIA256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-CAMELLIA256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-CAMELLIA128-SHA256:ECDHE-RSA-AES128-SHA256;
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:50m;
    ssl_session_tickets off;
    ssl_prefer_server_ciphers on;
    ssl_stapling off;

    sendfile On;
    server_name  opnsense.mydomain.de;

    client_header_buffer_size 1k;
    large_client_header_buffers 4 8k;
    charset utf-8;
    access_log  /var/log/nginx/opnsense.mydomain.de.access.log main;
    access_log  /var/log/nginx/tls_handshake.log handshake;
    error_log  /var/log/nginx/opnsense.mydomain.de.error.log error;
    satisfy any;
    #include tls.conf;
    error_page 403 /opnsense_error_403.html;
    error_page 404 /opnsense_error_404.html;
    error_page 405 /waf_denied.html;
    error_page 500 501 502 503 504 /opnsense_server_error.html;

    location = /opnsense_error_403.html {
        internal;
        root /usr/local/etc/nginx/views;
    }
    location = /opnsense_error_404.html {
        internal;
        root /usr/local/etc/nginx/views;
    }
    location = /opnsense_server_error.html {
        internal;
        root /usr/local/etc/nginx/views;
    }
    # location to ban the host permanently
    set $naxsi_extensive_log 0;
    location @permanentban {
        access_log /var/log/nginx/permanentban.access.log main;
        internal;
        add_header "Content-Type" "text/plain; charset=UTF-8" always;
        return 403 "You got banned permanently from this server.";
    }
    error_page 418 = @permanentban;
    location = /waf_denied.html {
        root /usr/local/etc/nginx/views;
        access_log /var/log/nginx/waf_denied.access.log main;
    }
    # block based on User Agents - stuff I have found over the years in my server log
    if ($http_user_agent ~* Python-urllib|Nmap|python-requests|libwww-perl|MJ12bot|Jorgee|fasthttp|libwww|Telesphoreo|A6-Indexer|ltx71|okhttp|ZmEu|sqlmap|LMAO/2.0|l9explore|l9tcpid|Masscan|zgrab|Ronin/2.0|Hakai/2.0) {
      return 418;
    }
        if ($http_user_agent ~ "Indy\sLibrary|Morfeus Fucking Scanner|MSIE [0-6]\.\d+")
    {
      return 418;
    }
    if ($http_user_agent ~ ^Mozilla/[\d\.]+$)
    {
      return 418;
    }

    location = /opnsense-report-csp-violation {
      include       fastcgi_params;
      fastcgi_param QUERY_STRING $query_string;
      fastcgi_param SCRIPT_FILENAME /usr/local/opnsense/scripts/nginx/csp_report.php;
      fastcgi_param TLS-Cipher $ssl_cipher;
      fastcgi_param TLS-Protocol $ssl_protocol;
      fastcgi_param TLS-SNI-Host $ssl_server_name;
      fastcgi_param SERVER-UUID "<some-cryptic-numbers-and-letters>";
      fastcgi_intercept_errors on;
      fastcgi_pass  unix:/var/run/php-webgui.socket;
    }
    location /opnsense-auth-request {
      internal;
      fastcgi_pass  unix:/var/run/php-webgui.socket;
      fastcgi_index index.php;
      fastcgi_param TLS-Cipher $ssl_cipher;
      fastcgi_param TLS-Protocol $ssl_protocol;
      fastcgi_param TLS-SNI-Host $ssl_server_name;
      fastcgi_param Original-URI $request_uri;
      fastcgi_param Original-HOST $host;
      fastcgi_param SERVER-UUID "<some-cryptic-numbers-and-letters>";
      fastcgi_param SCRIPT_FILENAME  /usr/local/opnsense/scripts/nginx/ngx_auth.php;
      fastcgi_param AUTH_SERVER "LDAP";
      fastcgi_intercept_errors on;
      include        fastcgi_params;
    }
    if ($scheme != "https") {
        return 302 https://$host$request_uri;
    }
    include <some-cryptic-numbers-and-letters>_pre/*.conf;


location  /myupstream1 {
    BasicRule wl:19;
    DeniedUrl "/waf_denied.html";
        # IP ACL
        allow x1.y1.z1.0/24;
        allow x2.y2.0.0/16;
        allow x3.y3.z3.0/24;
        allow x4.y4.z4.0/24;
        allow x5.y5.z5.0/24;
        allow x6.y6.z6.154/32;
        allow x7.y7.z7.44/32;
        allow x8.y8.z8.0/24;
        deny all;
    satisfy any;
    autoindex off;
    auth_request /opnsense-auth-request;
    http2_push_preload on;
    proxy_set_header Host $host;
    proxy_http_version 1.1;
    proxy_set_header Authorization $http_authorization;
    proxy_pass_header Authorization;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
    proxy_set_header X-TLS-Cipher $ssl_cipher;
    proxy_set_header X-TLS-Protocol $ssl_protocol;
    proxy_set_header X-TLS-SNI-Host $ssl_server_name;
    # proxy headers for backend server
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-Port $server_port;
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header X-TLS-Client-Intercepted $tls_intercepted;
    proxy_read_timeout 86400s;
    proxy_ignore_client_abort off;
    proxy_request_buffering on;
    proxy_max_temp_file_size 1024m;
    proxy_buffering on;
    proxy_pass http://upstream<yetanotercrypticnumbersandletters>;
    proxy_hide_header X-Powered-By;
    include <some-cryptic-numbers-and-letters>_post/*.conf;
}
location  / {
    BasicRule wl:19;
    DeniedUrl "/waf_denied.html";
    if ($scheme != "https") {
        return 302 https://$host$request_uri;
    }
    root /srv/crm;
    index index.html;
    autoindex off;
    http2_push_preload off;
    include <some-more-cryptic-numbers-and-letters>_post/*.conf;
}
location  /myupstream2 {
    BasicRule wl:19;
    DeniedUrl "/waf_denied.html";
    autoindex off;
    http2_push_preload on;
    proxy_set_header Host $host;
    proxy_set_header X-TLS-Cipher $ssl_cipher;
    proxy_set_header X-TLS-Protocol $ssl_protocol;
    proxy_set_header X-TLS-SNI-Host $ssl_server_name;
    # proxy headers for backend server
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-Port $server_port;
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header X-TLS-Client-Intercepted $tls_intercepted;
    proxy_ignore_client_abort off;
    proxy_request_buffering on;
    proxy_max_temp_file_size 1024m;
    proxy_buffering on;
    proxy_pass http://upstream<stillmorecrypticnumbersandletters>;
    proxy_hide_header X-Powered-By;
    include <third-set-of-cryptic-numbers-and-letters-with-hyphen>_post/*.conf;
}
    include <some-cryptic-numbers-and-letters>_post/*.conf;

}

}
stream {
    # LOG FORMATS
    log_format main '$remote_addr [$time_local] '
                     '$protocol $status $bytes_sent $bytes_received '
                     '$session_time';
    log_format anonymized ':: [$time_local] '
                     '$protocol $status $bytes_sent $bytes_received '
                     '$session_time';

    # UPSTREAM SERVERS
    upstream upstream<crypticnumbersandlettersupstream1> {
        server myupstream1.mydomain.de:8090 weight=1;
    }
    upstream upstream<crypticnumbersandlettersupstream2> {
        server myupstream2.mydomain.de:8080 weight=1;
    }
    upstream upstream<crypticnumbersandlettersupstream3> {
        server w.x.y.z:443 weight=1;
    }

    # upstream maps


    include opnsense_stream_vhost_plugins/*.conf;

}
# mail {
# }



Hi!
Config looks good at first glance. Now I can only assume that there is an upstream proxy, which is why the OPN-nginxplugin sees the "wrong" ip. At the time of the authentication request, which address will appear in the log with a 401 response, does it correspond to what is allowed in the ACL?