Nginx mp4 hotlink protection doesnt work - nginx

I am trying to block hotlinking of my mp4 with nginx "valid_referers" :
valid_referers none blocked mysite.com;
if ($invalid_referer) {
return 403;
}
But it doesnt work at all, the mp4 still display on the websites who are stealing the video and if I put some random domain instead of "mysite.com" the video still work.
If it can help, this is what my server conf file look like :
server {
listen 80;
server_name dl.mysite.com;
root /home/videos;
index index.php index.html;
autoindex off;
location ~ /\. {
deny all;
}
# serve static files directly
location ~* \.(jpg|jpeg|gif|css|png|js|ico|html)$ {
access_log off;
expires max;
}
# streaming
location ~ \.mp4$ {
valid_referers none blocked mysite.com;
if ($invalid_referer) {
return 403;
}
gzip off;
gzip_static off;
mp4;
mp4_buffer_size 1M;
mp4_max_buffer_size 300M;
}
location ~ .flv$ {
flv;
}
# removes trailing slashes
if (!-d $request_filename)
{
rewrite ^/(.+)/$ /$1 permanent;
}
# canonicalize codeigniter url end points
if ($request_uri ~* ^(/lobby(/index)?|/index(.php)?)/?$)
{
rewrite ^(.*)$ / permanent;
}
# removes trailing "index" from all controllers
if ($request_uri ~* index/?$)
{
rewrite ^/(.*)/index/?$ /$1 permanent;
}
# unless the request is for a valid file (image, js, css, etc.), send to bootstrap
if (!-e $request_filename)
{
rewrite ^/(.*)$ /index.php?/$1 last;
break;
}
# catch all
error_page 404 /index.php;
location ~ \.php$ {
try_files $uri =404;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_read_timeout 600;
include fastcgi_params;
}
}
I am doing something wrong ?

I had the same problem in past. I thought it was not working, but actually, it was working. Just make sure you are not allowing anyone except you.
Sometimes leechers try null or empty referrers to bypass this and there is no possible solution to this. One possible solution I can suggest to block the resource directory. See https://www.atulhost.com/hotlink-protection-nginx this man explained everything in a simple way.

Related

WordPress Multisite - Static content - 404 Not Found

I have installed a Wordpress in a Sub directory called /WordPressDemo.
There is a domain called demo.example.com with the document root / which means that you need to enter demo.example.com/WordPressDemo to access the WordPress.
I use nGINX what causes alot of trouble, I managed to get the basic links (e.g. permalinks) working, so the multisite itself works, the only problem is that it is requesting the static data from the wrong path.
Example:
It requests: http://demo.example.com/WordPressDemo/MULTISITE-NAME/wp-includes/js/jquery/jquery.js?ver=1.11
but should request
http://demo.example.com/WordPressDemo/wp-includes/js/jquery/jquery.js?ver=1.11
My current nginx directives:
if (!-e $request_filename) {
rewrite /wp-admin$ $scheme://$host$uri/ permanent;
rewrite ^/WordPressDemo(/[^/]+)?(/wp-.*) /WordPressDemo$2 last;
rewrite ^/WordPressDemo(/[^/]+)?(/.*\.php)$ /WordPressDemo$2 last;
}
location / {
try_files $uri $uri/ /WordPressDemo/index.php?$args ;
}
location ~ \.php$ {
try_files $uri /WordPressDemo/index.php;
include fcgi.conf;
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
location ~* ^.+\.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
access_log off; log_not_found off; expires max;
}
Have you looked into the Wordpress codex?
Anyway, you may be interested in adapting this code:
# WordPress multisite subdirectory rules.
# Designed to be included in any server {} block.
# This order might seem weird - this is attempted to match last if rules below fail.
# http://wiki.nginx.org/HttpCoreModule
location / {
index index.php;
try_files $uri $uri/ /index.php?$args;
}
# Directives to send expires headers and turn off 404 error logging.
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
expires 24h;
log_not_found off;
}
location ~ ^/[_0-9a-zA-Z-]+/files/(.*)$ {
try_files /sites/$blogid/files/$2 /wp-includes/ms-files.php?file=$2 ;
access_log off; log_not_found off; expires max;
}
#avoid php readfile()
location ^~ /sites {
internal;
alias /var/www/mu/sites ;
access_log off; log_not_found off; expires max;
}
# Uncomment one of the lines below for the appropriate caching plugin (if used).
#include global/wordpress-ms-subdir-wp-super-cache.conf;
#include global/wordpress-ms-subdir-w3-total-cache.conf;
# Rewrite multisite '.../wp-.*' and '.../*.php'.
if (!-e $request_filename) {
rewrite /wp-admin$ $scheme://$host$uri/ permanent;
rewrite ^/[_0-9a-zA-Z-]+(/wp-.*) $1 last;
rewrite ^/[_0-9a-zA-Z-]+(/.*\.php)$ $1 last;
}
# Pass all .php files onto a php-fpm/php-fcgi server.
location ~ \.php$ {
# Zero-day exploit defense.
# http://forum.nginx.org/read.php?2,88845,page=3
# Won't work properly (404 error) if the file is not stored on this server, which is entirely possible with php-fpm/php-fcgi.
# Comment the 'try_files' line out if you set up php-fpm/php-fcgi on another machine. And then cross your fingers that you won't get hacked.
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
include fastcgi_params;
fastcgi_pass 127.0.0.1:9000;
fastcgi_cache_bypass $no_cache
fastcgi_cache_bypass $no_cache;
fastcgi_no_cache $no_cache;
fastcgi_cache WORDPRESS;
fastcgi_cache_valid 6000m;
}
location ~ /purge(/.*) {
fastcgi_cache_purge WORDPRESS "$scheme$request_method$host$1";
}
Does it answer your question?

Nginx deny doesn't work for folder files

I'm trying to restrict access to my site to allow only specific IPs and I've got the following problem: when I access www.example.com deny works perfectly, but when I try to access www.example.com/index.php it returns "Access denied" page AND php file is downloaded directly in browser without processing.
I do want to deny access to all the files on the website for all IPs but mine. How should I do that?
Here's the config I have:
server {
listen 80;
server_name example.com;
root /var/www/example;
location / {
index index.html index.php; ## Allow a static html file to be shown first
try_files $uri $uri/ #handler; ## If missing pass the URI to front handler
expires 30d; ## Assume all files are cachable
allow my.public.ip;
deny all;
}
location #handler { ## Common front handler
rewrite / /index.php;
}
location ~ .php/ { ## Forward paths like /js/index.php/x.js to relevant handler
rewrite ^(.*.php)/ $1 last;
}
location ~ .php$ { ## Execute PHP scripts
if (!-e $request_filename) { rewrite / /index.php last; } ## Catch 404s that try_files miss
expires off; ## Do not cache dynamic content
fastcgi_pass 127.0.0.1:9001;
fastcgi_param HTTPS $fastcgi_https;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params; ## See /etc/nginx/fastcgi_params
}
}
That is because your deny/allow rule applies to just one location.
Remove that and try:
server {
listen 80;
server_name example.com;
root /var/www/example;
if ($remote_addr != "YOUR.PUBLIC.IP") {return 403;}
...
}
As the test is outside any specific locationblock, it will apply to all cases.
Note also that IF is not evil here since it just "returns".
OK, so I've found the solution. Nginx processes the most exact regex which in this case is the regex for php files. To make the config work all further locations must be defined within / location rule except for #handler (you cannot put under any rule - only as root)
server {
listen 80;
server_name example.com;
root /var/www/example;
location / {
index index.html index.php; ## Allow a static html file to be shown first
try_files $uri $uri/ #handler; ## If missing pass the URI to front handler
expires 30d; ## Assume all files are cachable
allow my.public.ip;
deny all;
location ~ .php/ { ## Forward paths like /js/index.php/x.js to relevant handler
rewrite ^(.*.php)/ $1 last;
}
location ~ .php$ { ## Execute PHP scripts
if (!-e $request_filename) { rewrite / /index.php last; } ## Catch 404s that try_files miss
expires off; ## Do not cache dynamic content
fastcgi_pass 127.0.0.1:9001;
fastcgi_param HTTPS $fastcgi_https;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params; ## See /etc/nginx/fastcgi_params
}
}
location #handler { ## Common front handler
rewrite / /index.php;
}
}

Nginx auth_basic and rewrite in subdirectory does not work

I'm trying to add a project to a subfolder of existing webserver with Nginx. Here's my simple config:
server {
listen 80 default_server;
server_name localhost;
root /var/www;
[...]
location = /my-project { return 301 /my-project/; }
location /my-project/ {
alias /var/www/my-project/web/;
index index.php;
location ~ /[^/]+/control(/|$) {
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/htpasswd;
if (-f $request_filename) { break; }
rewrite ^(.*)$ /my-project/index.php last;
}
if (-f $request_filename) { break; }
rewrite ^ /my-project/index.php last;
location ~ ^/[^/]+/index\.php$ {
include fastcgi_params;
fastcgi_pass unix:/var/run/fcgi.sock;
fastcgi_param SCRIPT_FILENAME $document_root/index.php;
}
}
}
Because there is an rewrite directive inside /control location block, the auth_basic never gets triggered, because Nginx executes rewrites before authentication. In which way should I modify the config, that auth does work?
PS: try_files doesn't seem to work, because it serves files from root (/) webfolder!? When I replace the if and following rewrite with try_files $uri /my-project/index.php?$query_string; I get a 404, because Nginx tries to serve the file /var/wwwindex.php (have a look at missing slash and the root folder /var/www instead of alias).
EDIT 18.09.2013:
As VBart suggests I'm using now the following configuration to get authentication to work
location ~ ^/(?<dir>my-project)(?<path>/.*)$ {
root /var/www/$dir/web;
location ~ ^/[^/]+/control(/|$) {
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/htpasswd;
try_files $path /$dir/index.php?$query_string;
}
try_files $path /$dir/index.php?$query_string;
location ~ ^/[^/]+/index\.php$ {
include fastcgi_params;
fastcgi_pass unix:/var/run/fcgi.sock;
fastcgi_param SCRIPT_FILENAME $document_root/index.php;
}
}
Use:
error_page 404 =200 /my-project/index.php;
instead of ugly rewrites:
if (-f $request_filename) { break; }
rewrite ^(.*)$ /my-project/index.php last;
Reference:
http://nginx.org/r/error_page
http://wiki.nginx.org/IfIsEvil
http://wiki.nginx.org/Pitfalls
P.S. try_files doesn't work with alias because of bug: http://trac.nginx.org/nginx/ticket/97, but you can replace alias with root directive: http://nginx.org/r/root

nginx change root folder for specific url

I have a configuration file like this one below:
server {
listen 80;
server_name localhost;
#charset utf-8;
root html/laravel/public;
index index.html index.php;
#browse folders if no index file
autoindex on;
# enforce NO www
if ($host ~* ^www\.(.*))
{
set $host_without_www $1;
rewrite ^/(.*)$ $scheme://$host_without_www/$1 permanent;
}
# serve static files directly
location ~* \.(jpg|jpeg|gif|css|png|js|ico|html)$ {
access_log off;
#expires max;
}
# removes trailing slashes (prevents SEO duplicate content issues)
if (!-d $request_filename)
{
rewrite ^/(.+)/$ /$1 permanent;
}
# canonicalize codeigniter url end points
# if your default controller is something other than "welcome" you should change the following
# if ($request_uri ~* ^(/lobby(/index)?|/index(.php)?)/?$)
# {
# rewrite ^(.*)$ / permanent;
# }
# removes trailing "index" from all controllers
if ($request_uri ~* index/?$)
{
rewrite ^/(.*)/index/?$ /$1 permanent;
}
# unless the request is for a valid file (image, js, css, etc.), send to bootstrap
if (!-e $request_filename)
{
rewrite ^/(.*)$ /index.php?/$1 last;
break;
}
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
location /backend/ {
root /html/frontend;
}
location ~ \.php$ {
include fastcgi.conf;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi_params;
}
location ~ /\.ht {
deny all;
}
# catch all
# error_page 404 /index.php;
# location ~ \.php$ {
# try_files $uri =404;
# fastcgi_pass unix:/tmp/php.socket;
# fastcgi_index index.php;
# #include fastcgi_params;
# include /home/tamer/code/nginx/fastcgi_params;
# }
# access_log /home/tamer/code/laravel/storage/logs.access.log;
# error_log /home/tamer/code/laravel/storage/logs.error.log;
}
I have to change root folder to html/backend for any url with $host/backend/. All rules for load pages have to be the same, only root folder have to change.
How can I do that?
server {
location / {
root /data/www;
}
location /images/ {
root /data;
rewrite ^/images/(.+?)$ $1 break; #following is the explation
}
}
use break to continue; the root in location will take effect
use last to internal simulate request; the root in location will not take effect
use permanent to 301 redirect;
use redirect to 302 redirect;
adding 127.0.0.1 to server_name to be able to use the link you provided in the comment 127.0.0.1
server_name localhost 127.0.0.1;
also you still need to have the backend location with root inside it.
location /backend/ {
root /html/backend;
}
I'll take a wild guess here:
location /backend/ {
root /html/backend;
try_files $uri $uri/ /index.php?_url=$uri&$args;
}
This means: all requests to .../backend/* will be redirected to the location block of php followed after:
location ~ \.php${ ... }
and php will handle those requests as backend scripts
Nginx Beginner's Guide has this example:
server {
location / {
root /data/www;
}
location /images/ {
root /data;
}
}
So in theory this should work for you:
server {
listen 80;
server_name localhost;
location / {
root html/laravel/public;
}
location /backend/ {
root html/backend;
}
# common config goes here
}
If I understood the question correctly you can use alias to change just the OS search path for a specific location:
Defines a replacement for the specified location. For example, with the following configuration on request of “/i/top.gif”, the file /data/w3/images/top.gif will be sent.
location /i/ {
alias /data/w3/images/;
}
You need to define new location and use alias instead of root or else the behaviour would be funky. Also you need to define location for .php to use $request_filename.
location /backend {
alias /html/backend;
try_files $uri $uri/ /index.php$is_args$args;
location ~ \.php$ {
fastcgi_param SCRIPT_FILENAME $request_filename;
}
}

Nginx proxy_pass to another port with Wordpress

My problem is following: I use Wordpress on Nginx with "pretty links". I also run 2 other services on ports 88 and 1234 and I want to make a subdomains bugs.mydomain and mail.mydomain. I did the proxypass on location / but it's working only for the main directory, anything that is after the domain/ is falling into Wordpress "pretty links" mechanism. Do you have any idea how to solve this? My config files below:
The server config:
server {
listen <IP>:80;
root /usr/share/nginx/www/domain;
index index.html index.htm index.php;
server_name domain www.domain;
location / {
try_files $uri $uri/ /index.html;
if ( $host ~ "bugs.domain" ) {
proxy_pass http://domain:88;
}
if ( $host ~ "mail.domain" ) {
proxy_pass http://domain:1234;
}
}
location /doc/ {
alias /usr/share/doc/;
autoindex on;
allow 127.0.0.1;
deny all;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
}
location ~ /\.ht {
deny all;
}
include /home/domain/public_html/nginx.conf;
}
the config for specified domain (with Wordpress):
#First there is many rewrites for the W3TC plugin, like minification, caches etc
if ($host ~* ^www\.(.*))
{
set $host_without_www $1;
rewrite ^/(.*)$ $scheme://$host_without_www/$1 permanent;
}
#
# unless the request is for a valid file, send to bootstrap
if (!-e $request_filename)
{
rewrite ^(.+)$ /index.php?q=$1 last;
}
Now, when I enter domain:88 or domain:1234 it works. When I enter bugs.domain the website loads, but no CSS or images works as the url is bugs.domain/somapath and this falls into the Wordpress bootstrap. I run out of the ideas.
why create only 1 server with if's in it, separate the servers
server {
listen 80;
server_name bugs.example.com;
proxy_pass http://example.com:88;
}
server {
listen 80;
server_name mail.example.com;
proxy_pass http://example.com:1234;
}
server {
listen 80;
# the rest of your main server
#
}
So the problem was completely different then I thought. it was failing on this line:
try_files $uri $uri/ /index.html;
The problem was, that file index.html didn't exist, I only had index.php. Changing it solved the problem.

Resources