Forum Moderators: phranque

Message Too Old, No Replies

htaccess, grouping [OR] and [AND]

         

csdude55

8:39 pm on Oct 9, 2020 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I'm trying to tighten up my server's security by blocking access to PMA, cPanel, WHM, and CSF to pre-approved IP ranges. I haven't found a way to do this through CSF or cPHulk, so I'm down to doing it manually via .htaccess.

I'm out of practice here and can't remember... I'm pretty sure that I can't use ( ) here, so how do I correctly say:

(
if (a) ||
if (b) ||
if (c)
) &&
d


This is the real code I'm using, with ( ) plugged in so you can see what I'm trying to do:

(
RewriteCond %{REQUEST_URI} /phpMyAdmin/ [NC,OR]
RewriteCond %{REQUEST_URI} /cpanel/ [NC,OR]
RewriteCond %{REQUEST_URI} /frontend/ [NC,OR]
RewriteCond %{SERVER_PORT} ^2083$ [OR]

RewriteCond %{REQUEST_URI} /whm/ [NC,OR]
RewriteCond %{REQUEST_URI} /configserver/ [NC,OR]
RewriteCond %{SERVER_PORT} ^2087$
)

RewriteCond %{REMOTE_ADDR} !^123.45.
RewriteRule ^ - [F]

phranque

11:06 pm on Oct 9, 2020 (gmt 0)

WebmasterWorld Administrator 10+ Year Member Top Contributors Of The Month



that looks like it would do what you expect.

i would suggest a more efficient implementation, such as:
# if requested uri path begins with one of these directories
RewriteCond %{REQUEST_URI} ^/(phpMyAdmin|cpanel|frontend|whm|configserver)/ [NC,OR]
# or if requested server port is one of these
RewriteCond %{SERVER_PORT} ^208[37]$
# and if request is not from an IP that begins with...
RewriteCond %{REMOTE_ADDR} !^123\.45\.
# send a 403 response
RewriteRule ^ - [F]

lucy24

1:37 am on Oct 10, 2020 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



It may help to visualize OR as being exactly equivalent to | (pipe). You just have to make separate lines when you're looking at different conditions, like REQUEST_URI, REMOTE_ADDR and so on.

Speaking of which... Whenever possible, put the REQUEST_URI into the pattern of the rule, so the server doesn't have to evaluate conditions on every request ever.

csdude55

4:16 am on Oct 10, 2020 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Whenever possible, put the REQUEST_URI into the pattern of the rule, so the server doesn't have to evaluate conditions on every request ever.


Hmm. That makes sense, but I'm not sure if it's applicable here since I'm matching against SERVER_PORT and REMOTE_ADDR, too. I considered this:

RewriteCond %{SERVER_PORT} ^208[37]$
RewriteCond %{REMOTE_ADDR} !^123\.45\.

#Note, I can't use ^ because "phpMyAdmin" and "frontend" are third level
RewriteRule (?:phpMyAdmin|cpanel|frontend|whm|configserver)/ - [NC,F]


But if they went to example.com:2083 then it wouldn't match.

Are you suggesting another way to modify it?

phranque

5:59 am on Oct 10, 2020 (gmt 0)

WebmasterWorld Administrator 10+ Year Member Top Contributors Of The Month



I'm not sure if it's applicable here since I'm matching against SERVER_PORT and REMOTE_ADDR, too.

it isn't

lucy24

3:42 pm on Oct 10, 2020 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Is the overall idea here “Deny access to these specific areas, and these specific ports, unless the request is from this specific IP” (presumably your own address)? If so, another approach is to put a preliminary rule like
RewriteCond %{REMOTE_ADDR} ^123\.45\.
RewriteRule ^ - [L]
located in the same area where you give blanket access to robots.txt and your error documents (i.e. before all other RewriteRules, rather than at the end where you'd normally put [L] rules). This of course depends on whether there are other rules, such as internal rewrites, that have to apply to you too.

I'd still be inclined to make one rule just for the files:
RewriteRule ^(phpMyAdmin|cpanel|frontend|whm|configserver)/ - [F]
--after which all that remains is checking for the server port.

A lot of rules depend on what requests the site actually receives. For example, most of my access-control RewriteRules are constrained to (^|/|\.html)$ requests for pages, because robotic requests for non-page files are vanishingly rare, so no point in putting the server to all that extra work.

Edit:
But if they went to example.com:2083 then it wouldn't match.
It doesn't need to, because this pattern of requests is already covered by the part of your canonicalization redirect that looks at HTTP_HOST; they'll be forcibly redirected whether they like it or not.

phranque

12:38 am on Oct 11, 2020 (gmt 0)

WebmasterWorld Administrator 10+ Year Member Top Contributors Of The Month



I'd still be inclined to make one rule just for the files:

you still need to verify the requesting IP address before forbidding the request:
# send a 403 response if requested uri path contains one of these directory names and if request is not from an IP that begins with...
RewriteCond %{REMOTE_ADDR} !^123\.45\.
RewriteRule /(phpMyAdmin|cpanel|frontend|whm|configserver)/ - [F]


and then you should follow that with this:
# if requested server port is one of these
RewriteCond %{SERVER_PORT} ^208[37]$
# and if request is not from an IP that begins with this
RewriteCond %{REMOTE_ADDR} !^123\.45\.
# send a 403 response
RewriteRule ^ - [F]


i would guess the 2 rulesets in this order are more efficient than one.

this pattern of requests is already covered by the part of your canonicalization redirect that looks at HTTP_HOST; they'll be forcibly redirected whether they like it or not.

it probably wouldn't make sense to redirect a specific request of this port - to the home page or elsewhere.
it seems like a Forbidden response is more appropriate for such interlopers.