I have an Apache web-server that acts as a web front-end for iPhone and iPad applications that communicate by POST and JSON only.
Is there any way to prevent Apache from answering requests that are invalid? I can see my error log is filled with attempts to open files such as /admin.php /index.php etc - files that don't exist on my server.
I believe this is possible with IIS, but can you do the same thing with Apache?
Basically I want the request to appear timed out unless you post exactly the right content to the right file - or at least if you do not request an existing file. This would make the server appear non-existing to everyone but my iPhone users as all communication is SSL and directories are not really guess-able.
I did disable the ServerTokens and all that, but I still get File not found etc. when I access the server requesting a random file, which is what these bots do constantly.
You can limit what HTTP methods Apache responds to by using mod_rewrite to redirect or deny unwanted requests.
Note that JSON is not an HTTP method. GET, POST, PROPFIND etc are HTTP method. For a full list of HTTP methods please see: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
If your application truly does not need to honor GET requests, then you can block all other methods.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_METHOD} !^(POST) [NC]
RewriteRule ^(.*)$ - [F,L]
</IfModule>
I've not tested this but it should block anything other than a POST method. You can add multiple methods.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_METHOD} !^(POST|GET) [NC]
RewriteRule ^(.*)$ - [F,L]
</IfModule>
Would permit only POST and GET.
You may need to also specify 'Options FollowSymLinks` on some servers due to how rewrites are handled.
If you must permit GET requests, then you will see those not found errors. There is nothing that prevents someone from issuing a HTTP request for an object that does not exist.
Related
I used this code in my .htaccess file and it is working great to prevent hotlinking:
RewriteEngine On
RewriteCond %{HTTP_HOST}##%{HTTP_REFERER} !^([^#]*)##https?://\1/.*
RewriteRule \.(gif|jpg|jpeg|png|tif|pdf|wav|wmv|wma|avi|mov|mp4|m4v|mp3|zip?)$ - [F]
Now I want to allow one of my subdomains (cdn.example.com) to access my files using a GET request.
It is not possible to add http_reffer to my GET request! I should only handle it with .htaccess.
How should I add my subdomain as an exception in this code?
RewriteCond %{HTTP_HOST}##%{HTTP_REFERER} !^([^#]*)##https?://\1/.*
Use the following condition instead to allow for an optional cdn subdomain:
RewriteCond %{HTTP_HOST}##%{HTTP_REFERER} !^([^#]*)##https?://(cdn\.)?\1/
(The trailing .* is not required.)
UPDATE#1:
It is not possible to add http_reffer to my GET request!
Not sure exactly what you mean by this, but if the Referer header is not being sent with these requests for some reason (perhaps you have a restrictive Referrer-Policy?) then you will likely need to allow an empty referer.
To allow an empty Referer, add the following as the first condition:
RewriteCond %{HTTP_REFERER} !^$
:
However, this will also allow direct requests. But due to the unreliable nature of the Referer header you really need to allow an empty Referer header anyway since some legitimate users might be suppressing it.
Aside: These directives to prevent hotlinking also block search engines - if that is a concern?
UPDATE#2:
i have another server for cdn.mydomain.com . and on that server i have a php script that will convert images to specific format . i should allow this script to read images from main domain
:
i can't edit that php script to change request method
Ideally, the script would be sending a custom HTTP request header indicating that the request is coming from your "CDN". You could then check for this in the above directive to allow the request.
If all these requests are coming directly from this other server then you can perhaps allow all requests from this server - identified by the server's IP address.
For example, if 203.0.113.111 is your server's IP address, then:
RewriteEngine On
RewriteCond %{REMOTE_ADDR} !=203.0.113.111
RewriteCond %{HTTP_HOST}##%{HTTP_REFERER} !^([^#]*)##https?://\1/
RewriteRule \.(gif|jpg|jpeg|png|tif|pdf|wav|wmv|wma|avi|mov|mp4|m4v|mp3|zip?)$ - [F]
To maintain consistency across my app, I need all requests to include www so I use .htaccess file like this:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_HOST} !^(www\.) [NC]
RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,QSA,NC,L]
</IfModule>
It works just fine. HOWEVER, when POST requests are sent without the www the form data gets stripped out. Is this expected? Is there a way to correct this?
A Redirect response with status such as 301,302, or 303 is always handled as a GET in every browser I've encountered. Hence, a POST request redirected will be seen by the client browser and it will issue a GET request to the URL provided in the redirect response. See my answer to the following question and the comments others added for details how you might work around this gracefully:
Apache 301 Redirect and preserving post data
I have a folder containing various .php files, and I want to prevent direct access to them, BUT to index.php.
This is what I got so far, and it appears working:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond $1 !^(index\.php)
RewriteRule ^(.*)$ /403.php/$1 [R=403]
</IfModule>
Is this the correct way to do it? Also note that 403.php doesn't actually exist among the files I have in the folder.
EDIT: to better clarify what I'm trying to do -- I have a folder (we can assume named "includes") containing an index.php file, and various other files which are included by index.php.
I don't want users / malicious bots / whoever to be able to directly access anything in "includes" other than index.php.
In case they reach anything else (regardless whether the file exists or not), I want to send to the browser a 403 - Access Denied HTTP response code.
The correct way is to use the F flag, which simply returns a 403 forbidden and you can use - as the target which just means "do nothing and let the URI pass through unchanged":
RewriteEngine on
RewriteCond $1 !^(index\.php)
RewriteRule ^(.*)$ - [L,F]
Or you can try combining the condition with the rule:
RewriteEngine on
RewriteRule !index\.php$ - [L,F]
You can either create an error page. Actually, some control panels have an application that will allow their user to create an SSI-enabled 403 (Forbidden) page with .shtml file extension. In cPanel that app. is entitled with "Error Pages" which were found in the "Advanced" section, and the 403 page will be going to saved in 403.shtml basename. If you didn't found such kind of app., you can manually create an SSI-enabled HTML file, only if your server is configured to allow this. If it's not possible, you can still use another extension.
So, the more correct way is to remap the existed error page, such like this:
RewriteCond %{REQUEST_URI} !^/index\.php
RewriteRule ^(.*) /403.shtml
But anyway, what are you trying to do?
I'm trying to get site.com/api to internally redirect to api.site.com. Site.com's .htaccess:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^api/(.*)$ http://api.site.com/$1 [P,QSA,L]
</IfModule>
I have mod_proxy and mod_rewrite installed. What am I doing wrong? Is this even possible?
EDIT: site.com and api.site.com are on the same server. I wish to do the redirect as efficiently as possible. If there's a way to pass a request in a certain path directly to a file, ie /srv/www/api.site.com/index.php via mod_rewrite, that would be just as good.
The point of this is to have two separate entities but circumvent javascript's cross-domain policy. Having a delegate is not an option, I want there to be direct communication. JSONP is not an option.
Figured this out via a url rewrite.
RewriteRule ^api/(.*)$ /library/api.php/$1 [QSA,L]
/library/api.php includes the index script in /srv/www/api.site.com/index.php directly. It has to rewrite some of the parameters in $_SERVER, but since the api.site.com's index.php is a singleton, this more than serves my purposes.
Is there a way to do a redirect conditionally on the HTTP request method/verb? I want to redirect all PROPFIND requests to the document root, so that:
PROPFIND / HTTP/1.1
is redirected to /MyApp/carddav/, but
GET / HTTP/1.1
is handled normally. The reason I need to do this is because the CardDAV implementation in OS X Address Book always expects to be able to contact the CardDAV server at /, and I'm running it at /MyApp/carddav/ with Tomcat.
Ideally, this could be done with an .htaccess file that a user could simply drop into their web server document root, rather than modifying the httpd.conf file, but I could live with either approach.
I figured it out. I added this to the end of my httpd.conf file:
RewriteEngine on
RewriteCond %{REQUEST_METHOD} ^PROPFIND$
RewriteRule ^/$ /MyApp/carddav/ [R,L]