Hi,

I have the following code in my .htaccess file to block an IP from accessing a file on my site and it works fine.

<Files mypage.html>
    Order Deny,Allow
    Deny from XXX.XXX.XXX.XXX
</Files>

Is there a way to block an IP from accessing a page (e.g., mydomain.com/mypage/)? Thanks for a any ideas.

Member Avatar for diafol

Dont understand what the issue is. If you got it to work?

mydomain.com/mypage/ I'm assuming is a rewrite for mydomain.com/mypage.html

It works for mydomain.com/mypage.html but not for mydomain.com/mypage/.

It is not a rewrite for mypage.html, it is a dynamically generated permalink (as in blogs, forums etc.).

mydomain.com/mypage/ <- is what user sees.
mydomain.com/page.php?page=mypage <- is the rewritten url.

Member Avatar for diafol

in that case page.php is what you want in the file tag

That will block the IP from accessing all pages, I want to block the IP from accessing one specific page, /mypage/, is that possible (without a password mechanism)?

Member Avatar for diafol

Hmm. I don't think you can block via File/FileMatch/LocationMatch on querystring.

Any other options I can use? My purpose is to prevent a certain IP from accessing a page on my site. Maybe redirect that IP to somewhere else, if I can't block?

Member Avatar for diafol

ANybody?

Hi hi!

If considering only Apache you can try with the Location directive:

<Location /mypage/>
    order deny, allow
    deny from 10.0.0.120
</Location>

The applicable context for this directive is server config or virtual host, it means you cannot apply it into the .htaccess file and after each change you need to reload the server:

If you cannot access Apache configuration files, the other solution is to apply a rule to the rewrite conditions, for example:

RewriteCond %{REMOTE_ADDR} =123\.45\.67\.[8-9]
RewriteRule ^/mypage/ - [F]

Check the documentation below, there are several examples:

Note: in the documentation you will read about Denying Hosts in a Blacklist, this is not a perfect solution because all requests are queued and managed by Apache main process, so if you have a lot of connections, it can become a bottleneck.

Hi cereal, thanks for the detailed reply.

I need to do this in the .htaccess file so your second suggestion seems to be what I need. I understand you can block a single IP modifying the IP address in the code you provided, but what does [8-9] mean exactly? Also, how can I block a range of IP like 111.111.111.111/24, with a CIDR value?

Thanks.

what does [8-9] mean exactly?

This is used to define a range. The mod_rewrite module does not support the CIDR notation, in your case you could write:

RewriteCond %{REMOTE_ADDR} ^111\.111\.111\.$

Or:

RewriteCond %{REMOTE_ADDR} ^111\.111\.111\.[0-9]{1,3}$

By using Apache 2.4 there is another alternative: you can use the IF directive with Require, the matching rule would look like this:

<IF "%{REQUEST_URI} ^/mypage/$">
    Require not ip 111.111.111.0/24
</IF>
Member Avatar for diafol

@ademmeda

I was under the impression that you couldn't get /mypage/ to work.

@diafol, yes I couldn't make it work because I was trying with the Files directive which only works for files and not for rewritten URLs. cereal's Rewrite suggestion did the job.

@cereal, thanks for the clarification. Also thanks for mentioning the IF alternative. Does it require a specific module to work? Do you think it would be safe to assume majority of Apache servers (shared hosting etc.) would be using Apache 2.4+ by now?

IF is part of the core since 2.4, while Require is part of mod_authz_core, which is loaded by default and available since version 2.3, at least in debian & co.

Do you think it would be safe to assume majority of Apache servers (shared hosting etc.) would be using Apache 2.4+ by now?

I don't know, I don't have the numbers but I hope so: 2.4 is stable, while 2.2 is in legacy status and updated only for bug fixes and security patches.

There are a lot of differences between 2.2 and 2.4 but, unless using a specific unsupported module, I would always expect to find the latest stable version.

If you're trying to create a safer approach then use IfModule and IfVersion:

<IfModule mod_version>
    <IfVersion >= 2.4>
        <IfModule mod_authz_core>
            # execute code here
        </If>
    </If>
</If>

Or simply check if mod_authz_core is available.

@cereal, thank you so much. Your suggestion will simplify things for me considerably and I am glad I asked this here. I have been checking so many sites/forums etc. and this is the only and simplest solution that will work nicely in my script. Thanks and have a nice day! :)

commented: you're welcome :) +13

I just checked my shared hosting account and their Apache version is 2.2.24, so I can't use the IF directive. I guess most servers will not have updated to 2.4 yet, so I will have to use Rewrite which will add a lot of math for figuring out the representation of IP CIDR values.

You could implement this check directly in your PHP application. For example with rlanvin/php-ip library you can do:

$block = new IPBlock::create('111.111.111.111/24');

if($block->contains($_SERVER['REMOTE_ADDR']))
{
    header('HTTP/1.1 403 Forbidden');
    include $_SERVER['DOCUMENT_ROOT'] . '/error403.html';
    exit;
}

Assuming you're using a switch statement, when the case is mypage you run the IP check:

<?php

    switch($_GET['page'])
    {
        case 'mypage':
            # do check here
            break;

        # other code ...
    }

The same, for rewritten links, can be applied through parse_url(). A part this I don't have other ideas, bye!

@cereal, thanks so much for all the help.

You're welcome! If we are done, please mark the thread solved. Bye!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.