# Passing / denying PHP requests

**URL:** <https://www.ruby-forum.com/t/passing-denying-php-requests/237092>\
**Category:** NGINX\
**Created:** [October 23, 2013, 4:31pm UTC](https://www.ruby-forum.com/t/passing-denying-php-requests/237092 "2013-10-23T16:31:23Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![alcina](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/a587f6/32.png) [@alcina](https://www.ruby-forum.com/u/alcina)\
**Post date:** [October 23, 2013, 4:31pm UTC](https://www.ruby-forum.com/t/passing-denying-php-requests/237092/1 "2013-10-23T16:31:23Z")

</div>

Hello-

I am trying to allow only the PHP files required for a given PHP  
package to function correctly, then deny access to all other PHP files  
to prevent people from snooping on the site’s configuration. I have  
created the location block, but I’m not so good with regular  
expressions and the block is assembled mostly through copy & paste.

location /installdirectory/ {  
# from nginx pitfalls page  
location ~\*  
(installdirectory/file\_a|installdirectory/file\_b|installdirectory/file\_c).php$  
{  
include global-configs/php.conf;  
}  
location ~\* installdirectory/.\*.php$ {  
deny all;  
}  
}

If someone can let me know if I am at least on the right track, I  
would appreciate it.

Thanks!

Paul

---

<div class="post-metadata">

**Author:** ![Paul\_NSPace](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/ed8c4c/32.png) [@Paul\_NSPace](https://www.ruby-forum.com/u/Paul_NSPace)\
**Post date:** [October 23, 2013, 6:49pm UTC](https://www.ruby-forum.com/t/passing-denying-php-requests/237092/2 "2013-10-23T18:49:59Z")

</div>

On Wed, Oct 23, 2013 at 07:30:19AM -0700, Paul N. Pace wrote:

Hi there,

> created the location block, but I’m not so good with regular  
> expressions and the block is assembled mostly through copy & paste.

If you don’t like regex, don’t use regex.

location = /installdirectory/file\_a.php {  
include global-configs/php.conf;  
};  
location = /installdirectory/file\_b.php {  
include global-configs/php.conf;  
};  
location = /installdirectory/file\_c.php {  
include global-configs/php.conf;  
};

You probably want another location{} to “deny”, and that might be  
“location ~ php$ {}”, or it might be that nested inside

location ^~ /installdirectory/ {}

depending on what else you want in the server config.

[http://nginx.org/r/location](http://nginx.org/r/location) for how the one location{} is chosen to  
handle a request.

## f

Francis D. removed\_email\_address@domain.invalid

---

<div class="post-metadata">

**Author:** ![Paul\_NSPace](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/ed8c4c/32.png) [@Paul\_NSPace](https://www.ruby-forum.com/u/Paul_NSPace)\
**Post date:** [October 23, 2013, 8:41pm UTC](https://www.ruby-forum.com/t/passing-denying-php-requests/237092/3 "2013-10-23T20:41:39Z")

</div>

On Wed, Oct 23, 2013 at 11:32:33AM -0700, Paul N. Pace wrote:

> On Wed, Oct 23, 2013 at 9:49 AM, Francis D. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

Hi there,

> “location ~ php$ { deny all; }” does not deny access to any php files,  
> even when nested in “location ^~ /installdirectory/ {}”. The previous  
> configuration “location ~\* installdirectory/._.php$ { deny all; }"  
> did block access to all php files. The "._.” - is that why one works  
> and the other doesn’t?

I suspect not.

What “location” lines do you have in the appropriate server{} block in  
your config file?

What one request do you make?

From that, which one location{} block is used to handle this one  
request?

> > [http://nginx.org/r/location](http://nginx.org/r/location) for how the one location{} is chosen to  
> > handle a request.
> 
> I read through the [nginx.org](http://nginx.org) explanation of the location directive,  
> but it isn’t helping me with understanding how to build the deny  
> statement.

Do whatever it takes to have these requests handled in a known  
location{}  
block.

Put the config you want inside that block.

If you enable the debug log, you will see lots of output, but it will  
tell  
you exactly which block is used, if it isn’t clear from the “location”  
documentation.

Cheers,

## f

Francis D. removed\_email\_address@domain.invalid

---

<div class="post-metadata">

**Author:** ![Paul\_NSPace](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/ed8c4c/32.png) [@Paul\_NSPace](https://www.ruby-forum.com/u/Paul_NSPace)\
**Post date:** [October 23, 2013, 8:33pm UTC](https://www.ruby-forum.com/t/passing-denying-php-requests/237092/4 "2013-10-23T20:33:28Z")

</div>

Thank you, Francis.

On Wed, Oct 23, 2013 at 9:49 AM, Francis D. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> If you don’t like regex, don’t use regex.
> 
> You probably want another location{} to “deny”, and that might be  
> “location ~ php$ {}”, or it might be that nested inside
> 
> location ^~ /installdirectory/ {}
> 
> depending on what else you want in the server config.

“location ~ php$ { deny all; }” does not deny access to any php files,  
even when nested in “location ^~ /installdirectory/ {}”. The previous  
configuration “location ~\* installdirectory/._.php$ { deny all; }"  
did block access to all php files. The "._.” - is that why one works  
and the other doesn’t?

> [http://nginx.org/r/location](http://nginx.org/r/location) for how the one location{} is chosen to  
> handle a request.

I read through the [nginx.org](http://nginx.org) explanation of the location directive,  
but it isn’t helping me with understanding how to build the deny  
statement.

---

<div class="post-metadata">

**Author:** ![Paul\_NSPace](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/ed8c4c/32.png) [@Paul\_NSPace](https://www.ruby-forum.com/u/Paul_NSPace)\
**Post date:** [October 25, 2013, 11:45pm UTC](https://www.ruby-forum.com/t/passing-denying-php-requests/237092/5 "2013-10-25T23:45:46Z")

</div>

Hi Francis, and again thanks for your help in this matter. I would  
have responded sooner but the day I was planning to resolve this issue  
I had an unseasonably long power outage.

On Wed, Oct 23, 2013 at 11:41 AM, Francis D. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> I suspect not.
> 
> What “location” lines do you have in the appropriate server{} block in  
> your config file?

hese are the location directives that would apply to the /forums/  
directory, the /installdirectory/ of the server block that I’m  
currently working on. This is an installation of Vanilla, but I’m  
trying to come up with a general template that I can apply to other  
packages (not a template as in one single file, but a way to apply  
directives to each package I use):

server {

location = /forums/index.php {  
include global-configs/php.conf;  
fastcgi\_split\_path\_info ^(.+.php)(.\*)$;  
}

location ^~ forums/ {  
location ~ php$ { deny all;}  
}

#location ~\* forums/.\*.php$ {

# deny all;

#}

location ~\* ^/forums/uploads/.\*.(html|htm|shtml|php)$ {  
types { }  
default\_type text/plain;  
}

location /forums/ {  
try\_files $uri $uri/ @forum;  
location ~\* /categories/([0-9]|[1-9][0-9]|[1-9][0-9][0-9])$ {  
return 404;  
}  
}

location @forum {  
rewrite ^/forums/(.+)$ /forums/index.php?p=$1 last;  
}  
}

> > statement.
> 
> Do whatever it takes to have these requests handled in a known location{}  
> block.
> 
> Put the config you want inside that block.

Do you mean that I should single out each php file and create a  
location block to deny access the file?

> If you enable the debug log, you will see lots of output, but it will tell  
> you exactly which block is used, if it isn’t clear from the “location”  
> documentation.

I navigated to /forums/login.php. Here seems to be the pertinent part  
of error.log:

2013/10/25 21:39:19 [debug] 2771#0: \*1 test location: “forums/”  
2013/10/25 21:39:19 [debug] 2771#0: \*1 test location: “/”  
2013/10/25 21:39:19 [debug] 2771#0: \*1 test location: “phpmyadmin/”  
2013/10/25 21:39:19 [debug] 2771#0: \*1 test location: “forums”  
2013/10/25 21:39:19 [debug] 2771#0: \*1 test location: “/”  
2013/10/25 21:39:19 [debug] 2771#0: \*1 test location: “index.php”  
2013/10/25 21:39:19 [debug] 2771#0: \*1 test location: ~  
“/categories/([0-9]|[1-9][0-9]|[1-9][0-9][0-9])$”  
2013/10/25 21:39:19 [debug] 2771#0: \*1 test location: ~ “/.”  
2013/10/25 21:39:19 [debug] 2771#0: \*1 test location: ~ “~$”  
2013/10/25 21:39:19 [debug] 2771#0: \*1 test location: ~ “piwik/config/”  
2013/10/25 21:39:19 [debug] 2771#0: \*1 test location: ~ “piwik/core/”  
2013/10/25 21:39:19 [debug] 2771#0: \*1 test location: ~  
“(piwik/index|piwik/piwik|piwik/js/index).php$”  
2013/10/25 21:39:19 [debug] 2771#0: _1 test location: ~  
"^/forums/uploads/._.(html|htm|shtml|php)$"  
2013/10/25 21:39:19 [debug] 2771#0: \*1 using configuration “/forums/”

I’m not sure which location block is “/forums/”. The login.php file is  
served as a downloadable file.

Thanks!

Paul

---

<div class="post-metadata">

**Author:** ![Paul\_NSPace](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/ed8c4c/32.png) [@Paul\_NSPace](https://www.ruby-forum.com/u/Paul_NSPace)\
**Post date:** [October 26, 2013, 2:49pm UTC](https://www.ruby-forum.com/t/passing-denying-php-requests/237092/6 "2013-10-26T14:49:04Z")

</div>

On Fri, Oct 25, 2013 at 02:44:57PM -0700, Paul N. Pace wrote:

> On Wed, Oct 23, 2013 at 11:41 AM, Francis D. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:
> 
> > On Wed, Oct 23, 2013 at 11:32:33AM -0700, Paul N. Pace wrote:

Hi there,

> Hi Francis, and again thanks for your help in this matter. I would  
> have responded sooner but the day I was planning to resolve this issue  
> I had an unseasonably long power outage.

No worries, there’s no rush on this.

> > > “location ~ php$ { deny all; }” does not deny access to any php files,  
> > > even when nested in “location ^~ /installdirectory/ {}”.
> > 
> > What “location” lines do you have in the appropriate server{} block in  
> > your config file?
> 
> hese are the location directives that would apply to the /forums/  
> directory, the /installdirectory/ of the server block that I’m  
> currently working on.

nginx has very specific rules on how the one location to handle this  
request is chosen. Until you understand those rules, you will be  
guessing  
whether or not your config will work. It’s simpler not to have to guess.

In this case, the request is “/forums/login.php”.

> location = /forums/index.php {

It cannot match that, because the request and the location are not equal  
(up to the first ? or # in the request).

> location ^~ forums/ {

It cannot match that (in fact, nothing normal can) because if the first  
character of a prefix match is not “/” it is unlikely to be useful.

> ```
> location ~ php$ { deny all;}
> 
> ```

It could match that, except it doesn’t because only top-level  
location{}s  
are considered initially.

> #location ~\* forums/.\*.php$ {

It could have matched that, except it is commented out.

> location ~\* ^/forums/uploads/.\*.(html|htm|shtml|php)$ {

It does not match that, because the request does not include “/uploads”.

> location /forums/ {

It can match that, because the location and the request have the same  
prefix.

> ```
> location ~* /categories/([0-9]|[1-9][0-9]|[1-9][0-9][0-9])$ {
> 
> ```

It does not match that.

> location @forum {

It does not match that, because named locations are not considered for  
an initial request.

So, of that set the only possible match is /forums/, where the  
configuration

> ```
> try_files $uri $uri/ @forum;
> 
> ```

says “serve it if the file exists”. The file exists, and nothing says  
to proxy\_pass or fastcgi\_pass or anything, so the file content should  
be sent as-is.

> > Do whatever it takes to have these requests handled in a known location{}  
> > block.
> > 
> > Put the config you want inside that block.
> 
> Do you mean that I should single out each php file and create a  
> location block to deny access the file?

You have one group of requests that you want handled in one way, and  
another group handled in another. You need some way of distinguishing  
those groups - either singly or using patterns.

> “/categories/([0-9]|[1-9][0-9]|[1-9][0-9][0-9])$”  
> 2013/10/25 21:39:19 [debug] 2771#0: \*1 test location: ~ “/.”  
> 2013/10/25 21:39:19 [debug] 2771#0: \*1 test location: ~ “~$”  
> 2013/10/25 21:39:19 [debug] 2771#0: \*1 test location: ~ “piwik/config/”  
> 2013/10/25 21:39:19 [debug] 2771#0: \*1 test location: ~ “piwik/core/”  
> 2013/10/25 21:39:19 [debug] 2771#0: \*1 test location: ~  
> “(piwik/index|piwik/piwik|piwik/js/index).php$”  
> 2013/10/25 21:39:19 [debug] 2771#0: _1 test location: ~  
> "^/forums/uploads/._.(html|htm|shtml|php)$"

The bit after "location: " on each line should look familiar from the  
complete list of location blocks in your real config file.

> 2013/10/25 21:39:19 [debug] 2771#0: \*1 using configuration “/forums/”
> 
> I’m not sure which location block is “/forums/”. The login.php file is  
> served as a downloadable file.

You’ve shown only one location block that has “/forums/” as its  
uri. That’s the one.

In that block, you say “send the file”, so that’s what nginx does.

I don’t think I can explain it any better than the combination of nginx  
documentation and previous list mails.

Perhaps if you put as the first line inside each location block ‘return  
200 “this is location N”;’, for varying values of N; then when you  
use “curl” to access each request in turn, it will become clear which  
location{} is chosen for each request, and it will become clear why that  
location was chosen.

Then you’ll be able to put the config you want in the location{} that  
is chosen.

Good luck with it,

## f

Francis D. removed\_email\_address@domain.invalid
