I am setting up a server for my university which has to be only accessible from inside their network. This I can easily do with nginx. Unfortunatley there are some people that do not have access to this network/IP range. I could use Basic Authentication With Source IP Whitelisting but I would prefer to use a certificate.
Is there a way to first check, if the access is from within the allowed IP Range and if not asking for a certificate?
I tried something like:
server {
        root /var/www/html;
        
        index index.html index.htm index.nginx-debian.html;
        listen [::]:443 ssl ipv6only=on; # managed by Certbot
        listen 443 ssl; # managed by Certbot
        ssl_certificate /etc/letsencrypt/live/test.de/fullchain.pem; # managed by Certbot
        ssl_certificate_key /etc/letsencrypt/live/test.de/privkey.pem; # managed by Certbot
        include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
        ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
        # server_name _;
        server_name test.de;
        
        
        ssl_client_certificate /etc/nginx/client_certs/ca.crt;
        ssl_verify_client optional;
        error_log /var/log/nginx/errors.log debug;
        location / {
            satisfy any;
            allow 123.0.0.0/16;
            allow 456.0.0.0/16;
            deny all;
            
            if ($ssl_client_verify != SUCCESS) {
                return 403;
            }
            try_files $uri $uri/ =403;
        }
}
server {
    if ($host = test.de) {
        return 301 https://$host$request_uri;
    } # managed by Certbot
    listen 80 ;
    listen [::]:80 ;
    server_name test.de;
    return 404; # managed by Certbot
}
which is not working.
I could use a check for the IP before checking the ssl_client_verify like
if ($remote_addr = 1.2.3.4 ) 
       {
        proxy_pass http://10.10.10.1; 
        break; 
       }
 if ($ssl_client_verify != "SUCCESS") 
       { return 403; }
but this would not be feasible for every single ip adress.
How could I handle this efficiently?
Thank you in advance ~Fabian
                        
You may be able to use a
geoblock instead of theallow/denystatements and use$ssl_client_verifyas the default value.For example:
See this document for details.