16

How can I configure apache so that it refuses connections coming directly to the IP address (http://xxx.xxx.xxx.xxx) instead of the vhost name http://example.com?

My VirtualHost configuration:

ServerName example.com

<VirtualHost *:80>

        ServerName example.com

        DocumentRoot /var/www/           
        <Directory /var/www/>                    
                AllowOverride All
                Order allow,deny
                allow from all
        </Directory>

</VirtualHost>

6 Answers 6

32

You cannot have it refuse connections, since the hostname (or IP) that the user is trying to use as their HTTP host is not known to the server until the client actually sends an HTTP request. The TCP listener is always bound to the IP address.

Would an HTTP error response be acceptable instead?

<VirtualHost *:80>
    ServerName catchall
    <Location />
        Order allow,deny
        Deny from all
    </Location>
</VirtualHost>

<VirtualHost *:80>
    ServerName example.com
    DocumentRoot /var/www/
    <Directory /var/www/>
        AllowOverride All
        Order allow,deny
        allow from all
    </Directory>
</VirtualHost>
9
  • Well, thin brings up a 403 Forbidden for requests not coming from the domain, which is not bad in my situation. However, I want the server to be "non existent" for those requests. I'm sure this can be done somehow, maybe not with apache but on system level?
    – Alex
    Mar 22, 2014 at 19:10
  • 3
    @Alex No, it's completely impossible. The TCP connection must be established and the client must send their HTTP request (or their SNI header, I suppose) before there's any way for the server to determine whether they're trying to hit the domain name or the IP address in their HTTP request. Mar 22, 2014 at 19:24
  • @ShaneMadden Completely impossible? I understand that the server needs to know the IP of the user before it can choose what to do with it, but it's completely impossible to not respond to this hit once it knows its identity? Can't the server just hang the connection until timeout? Oct 3, 2014 at 13:19
  • 3
    @HelpingHand Not the IP of the user. The server needs to know the host header the user will send in the HTTP request, which it doesn't have until after the TCP connection is fully established. Oct 3, 2014 at 15:13
  • 1
    @HelpingHand No, it doesn't have visibility into the HTTP communication happening in the connections. Oct 24, 2014 at 17:33
3

A clean way to handle this is with a RewriteRule as follows

<If "%{HTTP_HOST} == 'x.x.x.x'">
  RewriteRule ^.*$ http://www.example.com/$1 [L]
</If>

Though this does expose the site associated with the ip versus denying access to a server called by ip. But simple and clean if this is acceptable.

1
  • Don't forget RewriteEngine On
    – NicoMinsk
    Sep 15, 2022 at 8:24
1
<VirtualHost *:80>

ServerName xxx.xxx.xxx.xxx  #your server web server IP
        <Location />
                Order deny,allow
                Deny from all
        </Location>

</VirtualHost>

This is will Forbidden access for accessing by IP

0

You Have to go to lower layer it only comes to my mind in the firewall chain having a validation check for the REQUEST HOST & what you have with Apache this will allow the package to be ignored or dropped

1
  • It's perfectly possible to do this at the apache level though, so this would be overkill. A simple method would be to ensure the first vhost was a catchall which denied access in an HTTP friendly way.
    – Paul Dixon
    Jun 21, 2015 at 7:27
0

Since Apache 2.5.1 there's a parameter called StrictHostCheck. Simply open your /etc/apache2.conf file and add the following line:

StrictHostCheck ON

Then restart your apache2 service:

service apache2 restart

Since now, your website will be only accessible if the host matches the one set in ServerName (example.com, as in your example). All other requests will be denied with code 400 Bad Request.

Here you can find more documention on StrictHostCheck.

0

The order of VirtualHost is important to limit access by hostname. If you want to call only www.example.com and deny the rest, just use the VirtualHost tag with www.example.com on the bottom and use the rest on the top like this.

<VirtualHost *>
    ServerName null
</VirtualHost>

<VirtualHost *>
    ServerName www.example.com
</VirtualHost>

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .