When securing an Apache web server, administrators often need to restrict access to specific IP addresses while blocking all others. The traditional approach using Order, Allow, and Deny directives in Apache 2.2 has been deprecated in favor of the more flexible Require syntax in Apache 2.4.
For Apache 2.4+, you should use the Require directive within a block:
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html
Require all denied
Require ip 192.168.1.100
Require ip 203.0.113.45
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
If you're running older Apache versions, this format still works but isn't recommended for new deployments:
Order deny,allow
Deny from all
Allow from 192.168.1.100
Allow from 203.0.113.45
For directory-specific restrictions without modifying virtual hosts:
# .htaccess file contents
Require all denied
Require ip 192.168.1.100
Require ip 203.0.113.45
After making changes, always test your configuration:
sudo apachectl configtest
sudo systemctl restart apache2
Common issues include:
- Not reloading Apache after configuration changes
- Using deprecated directives on newer Apache versions
- Incorrect IP address formatting
For more complex requirements, consider these patterns:
# Allow entire subnet
Require ip 192.168.1.0/24
# Allow multiple specific IPs
Require ip 192.168.1.100 192.168.1.101
# Combine with other access controls
Require ip 192.168.1.100
Require valid-user
When implementing IP-based restrictions in Apache, many administrators encounter unexpected 403 Forbidden errors even for whitelisted IPs. The traditional Order, Allow, and Deny directives can behave counterintuitively if not properly configured.
For Apache 2.4+, the recommended method uses Require with RequireAll:
<Directory /var/www/html>
Require all denied
Require ip 192.168.1.100
Require ip 203.0.113.45
</Directory>
For older Apache versions (2.2), ensure proper directive ordering:
<Directory /var/www/html>
Order deny,allow
Deny from all
Allow from 192.168.1.100
Allow from 203.0.113.45
</Directory>
1. Order matters: The sequence of directives affects behavior
2. Network ranges: You can specify CIDR notation (192.168.1.0/24)
3. Configuration reload: Always test with apachectl configtest
For directory-level control:
# .htaccess file contents
<RequireAll>
Require ip 192.168.1.100
Require ip 203.0.113.45
</RequireAll>
Use these commands to verify:
curl -I http://yourserver.com
telnet yourserver.com 80
Remember to check Apache error logs for detailed rejection reasons:
tail -f /var/log/apache2/error.log