As a developer with a dynamic IP address, I frequently face the challenge of securing access to my development server. Whitelisting IPs becomes impractical when my public IP changes daily. Apache's SetEnvIf
provided an elegant solution by checking custom headers, but how can we achieve similar functionality in Nginx?
Nginx's map
directive offers a powerful way to create conditional variables based on request headers. Here's how to implement header-based access control:
map $http_x_custom_auth $is_allowed {
default 0;
"secret-token-123" 1;
}
server {
listen 80;
server_name dev.example.com;
location /protected/ {
if ($is_allowed = 0) {
return 403;
}
# Your regular configuration here
}
}
For simpler cases, you can use Nginx's if
directive directly:
location /private/ {
if ($http_x_my_header != "expected-value") {
return 403;
}
# Rest of your configuration
}
While this method is convenient, consider these security enhancements:
- Combine with basic authentication for multi-factor security
- Use HTTPS to prevent header sniffing
- Rotate your secret token periodically
To test your setup, you can add custom headers using browser extensions or curl:
curl -H "X-Custom-Auth: secret-token-123" https://dev.example.com/protected/
For team access, you can validate against multiple possible values:
map $http_x_dev_access $valid_user {
default "";
"dev1-pass" "developer1";
"dev2-pass" "developer2";
}
server {
# ...
location /team/ {
if ($valid_user = "") {
return 403;
}
# Log access by developer name
access_log /var/log/nginx/team_access.log combined;
add_header X-Developer $valid_user;
}
}
Many developers working with dynamic IP addresses face the challenge of securely accessing development servers. While IP-based restrictions are common, they become impractical when your IP changes frequently. The Apache approach using SetEnvIf
to check custom headers provides an elegant solution, and here's how to implement similar functionality in Nginx.
The key directive we'll use is if
combined with $http_
variables that represent request headers. For a header named X-Secret-Token
, Nginx exposes it as $http_x_secret_token
(note the lowercase conversion).
location /protected/ {
if ($http_x_secret_token != "your-secret-value") {
return 403;
}
# Your normal configuration for the protected area
try_files $uri $uri/ =404;
}
For better security and flexibility, consider these enhancements:
map $http_x_dev_access $is_allowed {
default 0;
"sup3rS3cr3t!" 1;
}
server {
# ... other server configuration ...
location /dev/ {
if ($is_allowed = 0) {
return 403;
}
# Development configuration
autoindex on;
# ... other dev-specific settings ...
}
}
Here's a complete configuration snippet for a development environment:
http {
# Define header validation at http level for reuse
map $http_x_dev_auth $valid_dev {
default "";
"Bearer dGVzdDEyMzQ=" "authorized"; # Base64-encoded token
}
server {
listen 80;
server_name dev.example.com;
location / {
if ($valid_dev != "authorized") {
return 401 'Authentication Required';
}
root /var/www/dev;
index index.html;
autoindex on;
}
}
}
- Always use HTTPS when implementing header-based authentication
- Consider combining with basic auth for additional security
- Rotate your secret tokens periodically
- Log failed attempts to monitor for brute force attacks
For more complex scenarios, you might consider:
- Nginx's auth_request module
- Lua scripting with OpenResty
- Third-party modules like nginx-auth-ldap