Стоит система ubuntu 13.10, установил apache, для быстрого добавления хостов установил mod_macro.
Вот код макроса:
<Macro VHost $host $path>
<VirtualHost *:80>
DocumentRoot "$path"
ServerAdmin admin@localhost
ServerName $host
ServerAlias www.$host
DirectoryIndex index.php index.html index.htm index.shtml
<Directory "$path">
Options FollowSymLinks
Options all
AllowOverride All
allow from all
</Directory>
</VirtualHost>
</Macro>
Use VHost blog.loc /home/www-data/www/blog
При попытке открыть blog.loc выдает:
Forbidden
You don't have permission to access / on this server.
Apache/2.4.6 (Ubuntu) Server at blog.loc Port 80
В первую очередь установил права на папку:sudo chmod -R 777 /home/www-data/www/blog
Не помогло.
Следующим шагом установил права 777 на все вышестоящие папкиsudo chmod -R 777 /home
Что характерно, если поменятьUse VHost blog.loc /home/www-data/www/blog
наUse VHost blog.loc /var/www/blog
(для проверки создал папку blog в /var/www) то запускается нормально
Подскажите, что я делаю не так?
Update October 2016
4 years ago, since this answer is used as a reference by many, and while I learned a lot from security perspective during these years,
I feel I am responsible to clarify some important notes, and I’ve update my answer accordingly.
The original answer is correct but not safe for some production environments,
in addition I would like to explain some issues that you might fall into while setting up your environment.
If you are looking for a quick solution and SECURITY IS NOT A MATTER, i.e development env, skip and read the original answer instead
Many scenarios can lead to 403 Forbidden:
A. Directory Indexes (from mod_autoindex.c
)
When you access a directory and there is no default file found in this directory
AND Apache Options Indexes
is not enabled for this directory.
A.1. DirectoryIndex
option example
DirectoryIndex index.html default.php welcome.php
A.2. Options Indexes
option
If set, Apache will list the directory content if no default file found (from the above 👆🏻 option)
If none of the conditions above is satisfied
You will receive a 403 Forbidden
Recommendations
- You should not allow directory listing unless REALLY needed.
- Restrict the default index
DirectoryIndex
to the minimum. - If you want to modify, restrict the modification to the needed directory ONLY, for instance, use
.htaccess
files, or put your modification inside the<Directory /my/directory>
directive
B. deny,allow
directives (Apache 2.2)
Mentioned by @Radu, @Simon A. Eugster in the comments
You request is denied, blacklisted or whitelisted by those directives.
I will not post a full explanation, but I think some examples may help you understand,
in short remember this rule:
IF MATCHED BY BOTH, THE LAST DIRECTIVE IS THE ONE THAT WILL WIN
Order allow,deny
Deny will win if matched by both directives (even if an allow
directive is written after the deny
in the conf)
Order deny,allow
allow will win if matched by both directives
Example 1
Order allow,deny
Allow from localhost mydomain.example
Only localhost
and *.mydomain.example
can access this, all other hosts are denied
Example 2
Order allow,deny
Deny from evil.example
Allow from safe.evil.example # <-- has no effect since this will be evaluated first
All requests are denied, the last line may trick you, but remember that if matched by both the last win rule (here Deny is the last), same as written:
Order allow,deny
Allow from safe.evil.example
Deny from evil.example # <-- will override the previous one
Example 4
Order deny,allow
Allow from site.example
Deny from untrusted.site.example # <-- has no effect since this will be matched by the above `Allow` directive
Requests are accepted from all hosts
Example 4: typical for public sites (allow unless blacklisted)
Order allow,deny
Allow from all
Deny from hacker1.example
Deny from hacker2.example
Example 5: typical for intranet and secure sites (deny unless whitelisted)
Order deny,allow
Deny from all
Allow from mypc.localdomain
Allow from managment.localdomain
C. Require
directive (Apache 2.4)
Apache 2.4 use a new module called mod_authz_host
Require all granted
=> Allow all requests
Require all denied
=> Deny all requests
Require host safe.example
=> Only from safe.example
are allowed
D. Files permissions
One thing that most people do it wrong is configuring files permissions,
The GOLDEN RULE is
STARTS WITH NO PERMISSION AND ADD AS PER YOUR NEED
In Linux:
-
Directories should have the
Execute
permission -
Files should have the
Read
permission -
YES, you are right DO NOT ADD
Execute
permission for files
for instance, I use this script to setup the folders permissions
# setting permissions for /var/www/mysite.example
# read permission ONLY for the owner
chmod -R /var/www/mysite.example 400
# add execute for folders only
find /var/www/mysite.example -type d -exec chmod -R u+x {} ;
# allow file uploads
chmod -R /var/www/mysite.example/public/uploads u+w
# allow log writing to this folder
chmod -R /var/www/mysite.example/logs/
I posted this code as an example, setup may vary in other situations
Original Answer
I faced the same issue, but I solved it by setting the options directive either in the global directory setting in the httpd.conf
or in the specific directory block in httpd-vhosts.conf
:
Options Indexes FollowSymLinks Includes ExecCGI
By default, your global directory settings is (httpd.conf line ~188)
:
<Directory />
Options FollowSymLinks
AllowOverride All
Order deny,allow
Allow from all
</Directory>
set the options to:
Options Indexes FollowSymLinks Includes ExecCGI
Finally, it should look like:
<Directory />
#Options FollowSymLinks
Options Indexes FollowSymLinks Includes ExecCGI
AllowOverride All
Order deny,allow
Allow from all
</Directory>
Also try changing Order deny,allow
and Allow from all
lines by Require all granted
.
Appendix
Directory Indexes source code (some code remove for brevity)
if (allow_opts & OPT_INDEXES) {
return index_directory(r, d);
} else {
const char *index_names = apr_table_get(r->notes, "dir-index-names");
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01276)
"Cannot serve directory %s: No matching DirectoryIndex (%s) found, and "
"server-generated directory index forbidden by "
"Options directive",
r->filename,
index_names ? index_names : "none");
return HTTP_FORBIDDEN;
}
Introduction
Apache is a popular open-source app for running web servers, owing to its reliability and stability. Despite its ease of use, it’s not uncommon to encounter a ‘403 Forbidden’ error after setting up a website using Apache.
In this tutorial, we will go over potential causes of the Apache ‘403 Forbidden’ error and different ways you can fix it.
Prerequisites
- A user account with root or sudo privileges
- Access to the command line terminal
- An installed version of Apache web server
Apache 403 Forbidden: Effects and Possible Causes
The Apache ‘403 Forbidden’ error appears when you try to load a web page with restricted access. Depending on your browser and the website in question, there are different versions of the 403 error message:
- Forbidden
- Error 403
- HTTP Error 403.14 – Forbidden
- 403 Forbidden
- HTTP 403
- Forbidden: You don’t have permission to access the site using this server
- Error 403 – Forbidden
- HTTP Error 403 – Forbidden
There are several potential reasons why the Apache 403 error occurs:
- The first option is a permission error in the webroot directory, where users don’t have access to website files.
- The second possible reason for a 403 error is missing or incorrect settings in the Apache configuration files.
- Finally, failing to set up a default directory index also triggers a 403 error message in Apache.
How to Fix ‘403 Forbidden’ in Apache
If you have come across an Apache ‘403 Forbidden’ message, there are several ways to fix it:
Method 1: Setting File Permissions and Ownership
If you suspect the cause of the 403 error to be incorrect file permissions, use:
sudo chmod -R 775 /path/to/webroot/directory
The chmod command sets the execute permission for the webroot directory and read permission for the index.html
file.
To change directory ownership, use:
sudo chown -R user:group /path/to/webroot/directory
Where:
user
is the user account with root privileges on your web server.group
iswww-data
orapache
.
Restart the Apache web server for the changes to take effect.
If you are working with Ubuntu, use the following command to restart Apache:
sudo systemctl restart apache2
If you are working with Centos, use:
sudo systemctl restart httpd
Method 2: Setting Apache Directives
It is possible that the proper require directive is not configured and restricts access to resources. To fix it:
1. Access Apache’s main configuration file. For Ubuntu, use:
sudo nano /etc/apache2/apache2.conf
For Centos, use:
sudo nano /etc/httpd/httpd.conf
2. Once you open the configuration file, scroll down to the following section:
3. If the final line in the <Directory /var/www/>
section contains Require all denied
, change it to Require all granted
.
4. Press Ctrl+X
and then Y
to save changes to the Apache configuration file.
5. Restart the Apache web server for the changes to take effect. For Ubuntu, use:
sudo systemctl restart apache2
For Centos, use:
sudo systemctl restart httpd
Method 3: Adding a Default Directory Index
When a user visits a URL that requests a directory, the web server looks for a file in the given directory. If the file or any similar files are not found, and directory index listings are disabled, the web server displays the ‘403 Forbidden’ error message.
To fix the issue, add a default directory index.
1. Access Apache’s main configuration file by using:
sudo nano /etc/apache2/apache2.conf
2. Scroll down to find out the default index file name:
DirectoryIndex index.html index.cgi index.pl index.php index.xhtml
3. Make sure there is a file in the webroot folder with this name and upload it if it’s missing.
Conclusion
After following this tutorial, you should be able to determine the cause of an Apache ‘403 Forbidden’ error and fix any issues you may find.
If you want to find out more about 403 forbidden error, read our article 403 forbidden error — what is it and how to fix it.
1. You should configure your /etc/hosts file like that:
127.0.0.1 localhost
127.0.0.1 test-site
127.0.1.1 my-hostname
# The following lines are desirable for IPv6 capable hosts. etc...
Where test-site
is the second «localhost». And my-hostname
is the «System hostname» defined in /etc/hostname
.
2. You should define and enable a Virtual Host (VH):
There is a default HTTP VH. It’s placed in /etc/apache2/sites-available/
. The filename is 000-default.conf
. You have to edit it (you can rename it, if you want, or make some other .conf files, based on it) and after that you have to enable it.
You can enable it manually through creation of «soft, symbolic link»:
sudo ln -s /etc/apache2/sites-available/000-default.conf /etc/apache2/sites-enabled/
Or you can use Apache2 tool called a2ensite, which make the same:
sudo a2ensite 000-default.conf
Let’s assume there has 3 Virtual Hosts, enabled SSL, and registered private domain (SOS.info for an example):
/etc/apache2/sites-available/http.SOS.info.conf
/etc/apache2/sites-available/https.SOS.info.conf
And one which is created for the purposes of this topic:
/etc/apache2/sites-available/http.test-site.conf
The content of First 2 VHs is:
$ cat /etc/apache2/sites-available/
http.SOS.info.conf
<VirtualHost *:80>
ServerName SOS.info
ServerAlias www.SOS.info
ServerAdmin admin@SOS.info
# Redirect Requests to SSL
Redirect permanent "/" "https://SOS.info/"
ErrorLog ${APACHE_LOG_DIR}/http.SOS.info.error.log
CustomLog ${APACHE_LOG_DIR}/http.SOS.info.access.log combined
</VirtualHost>
This one redirects all HTTP requests to HTTPS.
$ cat /etc/apache2/sites-available/
https.SOS.info.conf
<IfModule mod_ssl.c>
<VirtualHost _default_:443>
ServerName SOS.info
ServerAlias www.SOS.info
ServerAdmin admin@SOS.info
DocumentRoot /var/www/html
SSLEngine on
SSLCertificateFile /etc/ssl/certs/SOS.info.crt
SSLCertificateKeyFile /etc/ssl/private/SOS.info.key
SSLCertificateChainFile /etc/ssl/certs/SOS.info.root-bundle.crt
#etc..
</VirtualHost>
</IfModule>
This is the HTTPS VH.
The content of these two files can be posted in one file, but in this case their management (a2ensite
/a2dissite
)will be more difficult.
The third Virtual Host is that, which is created for our purposes:
$ cat /etc/apache2/sites-available/
http.test-site.conf
<VirtualHost *:80>
ServerName test-site
ServerAlias test-site.SOS.info
DocumentRoot /var/www/test-site
DirectoryIndex index.html
ErrorLog ${APACHE_LOG_DIR}/test-site.error.log
CustomLog ${APACHE_LOG_DIR}/test-site.access.log combined
<Directory /var/www/test-site>
# Allow .htaccess
AllowOverride All
Allow from All
</Directory>
</VirtualHost>
3. With this configuration you should access:
http://localhost # pointed to the directory of the mine Domain
https://localhost # iin our case: /var/www/html (SOS.info), but you should get an error, because the SSL certificate
http://SOS.info # which redirects to https://SOS.info
https://SOS.info # you should have valid SSL certificate
http://www.SOS.info # which is allied to http://SOS.info and redirects to https://SOS.info
https://www.SOS.info # which is allied to https://SOS.info
On the main example you should access and:
http://test-site # pointed to the directory /var/www/test-site
http://test-site.SOS.info # which is allied to http://test-site
Try to open the site in the web browser or just try (in the terminal) with next commands:
$ curl -L http://test-site/index.html
$ curl -L http://test-site.SOS.info/index.html
Of course, you need to have some index.html
pages in their DocumentRoot
I will leave next notes by reason of pedantry
4. You need properly configured `/etc/apache2/apache2.conf`.
Ii is good idea to spend some time to improve your server’s security. These manuals are about the security configuration: 1st and 2nd. Here you can get free SSL certificate. These sites will help you to check your progress: 1st and 2nd.
According to above security manuals /etc/apache2/apache2.conf
file must looks like:
Mutex file:${APACHE_LOCK_DIR} default
PidFile ${APACHE_PID_FILE}
Timeout 60
#KeepAlive Off
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 5
HostnameLookups Off
ErrorLog ${APACHE_LOG_DIR}/error.log
LogLevel warn
IncludeOptional mods-enabled/*.load
IncludeOptional mods-enabled/*.conf
Include ports.conf
<Directory />
Options None FollowSymLinks
AllowOverride None
Require all denied
</Directory>
<Directory /var/www/>
Options None FollowSymLinks
AllowOverride None
Require all granted
</Directory>
AccessFileName .htaccess
<FilesMatch "^.ht">
Require all denied
</FilesMatch>
LogFormat "%v:%p %h %l %u %t "%r" %>s %O "%{Referer}i" "%{User-Agent}i"" vhost_combined
LogFormat "%h %l %u %t "%r" %>s %O "%{Referer}i" "%{User-Agent}i"" combined
LogFormat "%h %l %u %t "%r" %>s %O" common
LogFormat "%{Referer}i -> %U" referer
LogFormat "%{User-agent}i" agent
IncludeOptional conf-enabled/*.conf
IncludeOptional sites-enabled/*.conf
# Hide Server type in the http error-pages
ServerSignature Off
ServerTokens Prod
# Etag allows remote attackers to obtain sensitive information
FileETag None
# Disable Trace HTTP Request
TraceEnable off
# Set cookie with HttpOnly and Secure flag.
# a2enmod headers
Header edit Set-Cookie ^(.*)$ $1;HttpOnly;Secure
# Clickjacking Attack
Header always append X-Frame-Options SAMEORIGIN
# CX-XSS Protection
Header set X-XSS-Protection "1; mode=block"
# Disable HTTP 1.0 Protocol
RewriteEngine On
RewriteCond %{THE_REQUEST} !HTTP/1.1$
RewriteRule .* - [F]
# Change the server banner @ ModSecurity
# Send full server signature so ModSecurity can alter it
ServerTokens Full
# Alter the web server signature sent by Apache
<IfModule security2_module>
SecServerSignature "Apache 1.3.26"
</IfModule>
Header set Server "Apache 1.3.26"
Header unset X-Powered-By
# Hde TCP Timestamp
# gksu gedit /etc/sysctl.conf
# >> net.ipv4.tcp_timestamps = 0
# Test: sudo hping3 SOS.info -p 443 -S --tcp-timestamp -c 1
# Disable -SSLv2 -SSLv3 and weak Ciphers
SSLProtocol all -SSLv2 -SSLv3
SSLHonorCipherOrder on
SSLCipherSuite "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA EECDH EDH+aRSA !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !RC4"
5. Set up the Firewall.
To allow/deny external access to your web server you can use UFW (Uncomplicated Firewall):
sudo ufw allow http
sudo ufw allow https
To allow only tcp
protocol use:
sudo ufw allow http/tcp
sudo ufw allow https/tcp
You can use and the port number directly:
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
Just in case you can reload the «rules table»:
sudo ufw reload
You can use and UFW’s GUI interface, called gufw.
sudo apt update
sudo apt install gufw
gufw &
Choice the Office
profile. It will set: Status:ON
, Incoming:Deny
and Outgoing:Allow
and add your rules.
6. If you have a router don’t forget to forward some ports:
If you have a router and you want your web server to be accessible from Internet, don’t forget to add some port forwarding. Something like this.
Update October 2016
4 years ago, since this answer is used as a reference by many, and while I learned a lot from security perspective during these years,
I feel I am responsible to clarify some important notes, and I’ve update my answer accordingly.
The original answer is correct but not safe for some production environments,
in addition I would like to explain some issues that you might fall into while setting up your environment.
If you are looking for a quick solution and SECURITY IS NOT A MATTER, i.e development env, skip and read the original answer instead
Many scenarios can lead to 403 Forbidden:
A. Directory Indexes (from mod_autoindex.c
)
When you access a directory and there is no default file found in this directory
AND Apache Options Indexes
is not enabled for this directory.
A.1. DirectoryIndex
option example
DirectoryIndex index.html default.php welcome.php
A.2. Options Indexes
option
If set, Apache will list the directory content if no default file found (from the above 👆🏻 option)
If none of the conditions above is satisfied
You will receive a 403 Forbidden
Recommendations
- You should not allow directory listing unless REALLY needed.
- Restrict the default index
DirectoryIndex
to the minimum. - If you want to modify, restrict the modification to the needed directory ONLY, for instance, use
.htaccess
files, or put your modification inside the<Directory /my/directory>
directive
B. deny,allow
directives (Apache 2.2)
Mentioned by @Radu, @Simon A. Eugster in the comments
You request is denied, blacklisted or whitelisted by those directives.
I will not post a full explanation, but I think some examples may help you understand,
in short remember this rule:
IF MATCHED BY BOTH, THE LAST DIRECTIVE IS THE ONE THAT WILL WIN
Order allow,deny
Deny will win if matched by both directives (even if an allow
directive is written after the deny
in the conf)
Order deny,allow
allow will win if matched by both directives
Example 1
Order allow,deny
Allow from localhost mydomain.example
Only localhost
and *.mydomain.example
can access this, all other hosts are denied
Example 2
Order allow,deny
Deny from evil.example
Allow from safe.evil.example # <-- has no effect since this will be evaluated first
All requests are denied, the last line may trick you, but remember that if matched by both the last win rule (here Deny is the last), same as written:
Order allow,deny
Allow from safe.evil.example
Deny from evil.example # <-- will override the previous one
Example 4
Order deny,allow
Allow from site.example
Deny from untrusted.site.example # <-- has no effect since this will be matched by the above `Allow` directive
Requests are accepted from all hosts
Example 4: typical for public sites (allow unless blacklisted)
Order allow,deny
Allow from all
Deny from hacker1.example
Deny from hacker2.example
Example 5: typical for intranet and secure sites (deny unless whitelisted)
Order deny,allow
Deny from all
Allow from mypc.localdomain
Allow from managment.localdomain
C. Require
directive (Apache 2.4)
Apache 2.4 use a new module called mod_authz_host
Require all granted
=> Allow all requests
Require all denied
=> Deny all requests
Require host safe.example
=> Only from safe.example
are allowed
D. Files permissions
One thing that most people do it wrong is configuring files permissions,
The GOLDEN RULE is
STARTS WITH NO PERMISSION AND ADD AS PER YOUR NEED
In Linux:
-
Directories should have the
Execute
permission -
Files should have the
Read
permission -
YES, you are right DO NOT ADD
Execute
permission for files
for instance, I use this script to setup the folders permissions
# setting permissions for /var/www/mysite.example
# read permission ONLY for the owner
chmod -R /var/www/mysite.example 400
# add execute for folders only
find /var/www/mysite.example -type d -exec chmod -R u+x {} ;
# allow file uploads
chmod -R /var/www/mysite.example/public/uploads u+w
# allow log writing to this folder
chmod -R /var/www/mysite.example/logs/
I posted this code as an example, setup may vary in other situations
Original Answer
I faced the same issue, but I solved it by setting the options directive either in the global directory setting in the httpd.conf
or in the specific directory block in httpd-vhosts.conf
:
Options Indexes FollowSymLinks Includes ExecCGI
By default, your global directory settings is (httpd.conf line ~188)
:
<Directory />
Options FollowSymLinks
AllowOverride All
Order deny,allow
Allow from all
</Directory>
set the options to:
Options Indexes FollowSymLinks Includes ExecCGI
Finally, it should look like:
<Directory />
#Options FollowSymLinks
Options Indexes FollowSymLinks Includes ExecCGI
AllowOverride All
Order deny,allow
Allow from all
</Directory>
Also try changing Order deny,allow
and Allow from all
lines by Require all granted
.
Appendix
Directory Indexes source code (some code remove for brevity)
if (allow_opts & OPT_INDEXES) {
return index_directory(r, d);
} else {
const char *index_names = apr_table_get(r->notes, "dir-index-names");
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01276)
"Cannot serve directory %s: No matching DirectoryIndex (%s) found, and "
"server-generated directory index forbidden by "
"Options directive",
r->filename,
index_names ? index_names : "none");
return HTTP_FORBIDDEN;
}