Appearance
Using Basic HTTP Authentication scheme ​
Note that basic HTTP auth can be unsafe. Specially if not using HTTPS, since the password might be readable by someone sniffing your network.
To configure basic auth for a specific path (eg. /admin
) in nginx, see the configuration below:
server {
listen 443 ssl;
#...
location /admin {
auth_basic "Authorized Personnel Only";
auth_basic_user_file /path/to/.htpasswd;
#...
}
}
/path/to/.htpasswd
should point to a file generated using the htpasswd
tool from Apache (in Debian, package apache2-utils
).
sh
htpasswd -c /path/to/.htpasswd USERNAMEHERE
The tool will ask for a password and the file will be generated storing a hash of that password.
Reload nginx and you should be asked the user and password credentials when attempting to access the URL.
Restrict based on IP Address ​
If you always access your service from a fixed IP address (eg. from a local network) One interesting way to control access is filtering by IP address.
The below configuratin will grant access to the 192.168.178.1/24
network, excluding 192.168.178.2
.
location /admin {
#...
deny 192.168.178.2;
allow 192.168.178.1/24;
allow 127.0.0.1;
deny all;
#...
}
If your nginx installation has the ngx_http_geo_module
module you may also respond differently to the requests based on the IP. Like for example offering a redirection.
geo $authorizedIP {
default 0;
192.168.178.2 0;
192.168.178.1/24 1;
127.0.0.1 1;
}
server {
#...
location /admin {
if ($authorizedIP != 1) {
rewrite ^ http://www.example.com/test;
}
#...
}
}
Client Certificate ​
Another way to secure the access would be using a client certificate.
This will require that your server uses HTTPS (which you should already be using anyway if you want to be protected)
You can generate a client key and certificate as below (the sample uses 3650 days as expiration for the certificates, change that number to customize it to your situation).
sh
# Generate a CA certificate
openssl genrsa -out client-ca.key 4096
openssl req -x509 -new -nodes -key client-ca.key -sha256 -days 3650 -out client-ca.crt
# Create the Client key and sign it with the CA
openssl genrsa -out client.key 4096
openssl req -new -key client.key -out client.csr
openssl x509 -req -days 3650 -in client.csr -CA client-ca.crt -CAkey client-ca.key -set_serial 01 -out client.crt
# Generate PFX file to import in the client browser
openssl pkcs12 -export -out client.pfx -inkey client.key -in client.crt
The resulting client.pfx
file can then be imported into the browser from where you wish to access (check your browser settings).
server {
listen 443 ssl;
#...
ssl_client_certificate client-certs/client-ca.crt;
ssl_verify_client on;
#...
}
This will make it so ALL requests without a proper client certificate will receive a "400 Bad request - No required SSL certificate was sent" response.
But this will apply to every path on the server. If we want it to only apply to the specified path, we may set ssl_verify_client
to optional
and add a check in the path we want so we can either redirect the request to a different page (eg. using 301), or return with an 403 error.
server {
listen 443 ssl;
#...
ssl_client_certificate client-certs/client-ca.crt;
ssl_verify_client optional;
#...
location /admin {
if ($ssl_client_verify != SUCCESS) {
return 301 /;
}
#...
}
}
Other security measures ​
Remove support for older SSL/TLS protocols ​
Protocols such as TLSv1 or TLSv1.1 are vulnerable to attacks.
To make sure you only support v1.2 and v1.3, you may use the ssl_protocols
option as below:
server {
listen 443 ssl;
ssl_protocols TLSv1.2 TLSv1.3;
#...
}
You can test if it works or not with curl.
sh
curl -I -v --tlsv1 --tls-max 1.0 https://myserver/
curl -I -v --tlsv1.1 --tls-max 1.1 https://myserver/