Jump to content


Photo
- - - - -

How to: Nginx config with secure link streaming

nginx secure streaming nginx config

  • Please log in to reply
7 replies to this topic

#1 Damien

Damien

    Junior Member

  • Members
  • PipPipPip
  • 81 posts

Posted 16 March 2016 - 08:23 AM

This is my nginx config, been revised a few times now, it should work well. READ carefully and change server paths, location alias's and URL's where required through the config.

    # This first server section will strip WWW and return only http or https (default: http)
    # https: //support.google.com/webmasters/answer/66359?hl=en
    server {
     listen 80 default_server; # http://nginx.org/en/docs/http/request_processing.html
     server_name www.EXAMPLE.com;
     return 301 http://EXAMPLE.com$request_uri;
    } # end first server
 
    server {
     listen 80;# probably not required if things are standard. 
     client_max_body_size 500M; # allows file uploads up to 500 megabytes 
   
    # the important bits
     server_name EXAMPLE.com;
     root /srv/www/EXAMPLE/public_html;
     error_log /var/log/nginx/EXAMPLE.log warn;
 
    # add custom 404.html page to your public_html folder 
     error_page 404 /404.html;
 
    index index.php; # not required if you already have it in nginx.conf
 
    # https: //github.com/openresty/headers-more-nginx-module
    # more_clear_headers 'Server*';
    # more_clear_headers 'X-Powered*';
    # more_clear_headers 'X-Page*';
    # more_set_headers 'X-Powered-By: Hodor';
 
    location / {
 
            # Uncomment below 3 lines only if you want to enforce SSL connections 
            # if ($http_x_forwarded_proto "http") {
            # return 301 https: //EXAMPLE.com$request_uri;
            # }
 
        try_files $uri $uri/ /loader.php?$args; # this handles all rewrites
        autoindex on;
    }
 
    # 404
    location /404.html {
        internal;
    }
 
    ## Only requests to our Host are allowed i.e. nixcraft.in,images.nixcraft.in and www.nixcraft.in 
    if ($host !~ ^(YOURWEBSITE.com|www.YOURWEBSITE.com)$) {
        return 444;
    }
 
        # Uncomment for nuevoplayer iframe embed only 
        # location /embed {
        # rewrite ^/embed/(.*) /media/nuevo/embed.php?id=$1 last;
        # break; }
 
    location /media/videos/slides {
        # secure links may 403 your slides under /videos
        # remove if you have image errors.
        allow all;
    }
    location /media/videos/tmb {
        # secure links may 403 your thumbs under /videos 
        # remove if you have image errors.
        allow all;
    }
    
    # include our extra global configuration files
    # /usr/local/nginx/conf/globals folder (may vary)
        include global/expires_avs.conf;
        include global/securelinks_avs.conf;
 
    # Handle PHP 
        location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        if (!-f $document_root$fastcgi_script_name) {
            return 404;
            # This is a robust solution for path info security issue 
            # and works with "cgi.fix_pathinfo = 1" in /etc/php.ini (default)
        }
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        # Socket or TCP/IP 
        # listen /var/run/php5-fpm.sock 
        fastcgi_pass 127.0.0.1:9000;
        ## fastcgi_index index.php; # might throw an error when enabled
        include fastcgi_params;
        fastcgi_intercept_errors on;
    }
 
    # PHP-FPM Status Page 
    # example https: //easyengine.io/tutorials/php/fpm-status-page/
        # location ~ ^/(status|ping)$ {
        # access_log off;
        # allow 127.0.0.1;
        # allow 120.148.82.112;
        # deny all;
        # include fastcgi_params;
        # fastcgi_pass 127.0.0.1: 9000;
        # fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        # }
 
    # Another global include - the security conf 
        include global/ggvideoprotect.conf;
 
    # Some odd sites won't have configured favicon or robots.txt
    # and since its always grabbed, turn it off in access log
    # and turn off it's not-found error in the error log
    location /robots.txt {
        alias /srv/www/EXAMPLE/public_html/robots.txt;
        allow all;
        log_not_found off;
        access_log off;
    }
    
    location /favicon.ico {
        alias /srv/www/EXAMPLE/public_html/robots.txt;
        allow all;
        log_not_found off;
        access_log off;
    }

} #end second server

expires_avs.conf : Nginx sets the ‘Expires’ and ‘Cache-Control’ http request headers for images and javascript. RSS there if required.
securelinks_avs: This will create a random URL link for your video. These links will expire after a pre-set time, you’ll be forcing them to use your website video player embed - or nothing.
videoprotect.conf: This file will restrict access to the script tmp folders, also admin locations like includes and classes. We’ll also block access to any .files (beginning with a dot) and a range of other file types like direct downloading your .tpl theme files, .ini files, .log files etc.

 

/usr/local/nginx/conf/global/videoprotect.conf

# /usr/local/nginx/conf/global/videoprotect.conf

       # Prevent access to hidden files (starting with a dot) 
       # This is particularly important if you store .htpasswd files in the site hierarchy 
       location ~* (?:^|/)\. {
           deny all;
       }
       # Block access to adultvideoscript admin folders and tmp folders
       location ~ ^/(include|classes|modules|scripts|cache|tmp) {
           deny all;
           return 403;
       }
       # $wget yourwebsite.com/themes/something/custom/index.tpl - I just stole your shit with direct download of .tpl files
       location ~* (?:\.(?:bak|config|sql|log|fla|tpl|psd|ini|sh|inc|swp|dist)|~)$ {
           deny all;
       }

/usr/local/nginx/conf/global/expires_avs.conf

# /usr/local/nginx/conf/global/expires_avs.conf

       # Feed (if you have that mod it's useful)
       location ~* \.(?:rss|atom)$ {
         expires 1h;
         add_header Cache-Control "public";
       }
 
       # Media: images, icons, video, audio, HTC
       location ~* \.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|flv|ogg|ogv|webm|htc)$ {
         expires 1M;
         access_log off;
         add_header Cache-Control "public";
       }
 
       # CSS and Javascript
       location ~* \.(?:css|js)$ {
         expires 1y;
         access_log off;
         add_header Cache-Control "public";
       }

/usr/local/nginx/conf/global/securelinks_avs.conf

 # /usr/local/nginx/conf/global/securelinks_avs.conf

        location ^~ /media/videos {
        alias  /srv/www/EXAMPLE/public_html/media/videos;
        secure_link $arg_st,$arg_e;
        # change 'mysecret' password below & in avs PHP config
        secure_link_md5 mysecret$uri$arg_e;
 
        if ($secure_link = "") {
             return 403; # invalid hash or direct link
        }
        if ($secure_link = "0") {
             return 410; # link expired
        }
        mp4; # pseudo-streaming support
        expires max;
        gzip off;
        gzip_static off;
        directio 100m; # useful for serving large files:
        output_buffers 2 512k;
        open_file_cache off;
        }

Change securelinks_avs.conf secret word mysecret to something random, this is for generating secure video links later on;

secure_link_md5 mysecret$uri$arg_e;

If you have compiled nginx with –with-http_secure_link_module we will now make the changes needed to generate temporary links for your videos.  Nginx and AVS will generate a new link to a video file every time a user loads the page. This link is only valid for a short period of time. Once it has expired your users will need to request a new link.

 

IUKlbAu.jpg

 

Invalid or direct links to files will be forbidden.

 

tnb8Zju.jpg

 

Expired links die.

 

0lgFd50.jpg

in adultvideoscript’s web folder locate includes/config.inc.php you’ll need to add;

$config['nginx'] = '1';
$config['nginx_key'] = 'mysecret';
$config['nginx_prefix'] = '/media/';

mysecret random word also must exactly match the line from securelinks_avs.conf.

 

Now you need to get the video player in AVS to understand what it's doing.

 

Open /media/player/config.php.

 

(I don't use standard conversions, paths or use FLV files so this is how I would think you can change AVS default player config)

 

find in /media/player/config.php;

   $SD_URL = $config['FLVDO_URL'].'/' .$video_id. '.mp4';
   $HD_URL = $config['HD_URL'].'/'.$hd_filename;

replace it with;

$sdjailpath = '/media/videos/iphone/'.$sd_filename.'';
$hdjailpath = '/media/videos/hd/'.$hd_filename.'';

$expire = time()+3600; //links return error 410 expired... links expire after 3600 seconds/1 hour.
$sdmd5 = str_replace('=','',strtr(base64_encode(md5($config['nginx_key'].$sdjailpath.$expire, true)),'+/','-_'));
$hdmd5 = str_replace('=','',strtr(base64_encode(md5($config['nginx_key'].$hdjailpath.$expire, true)),'+/','-_'));
         
  $SD_URL = $config['BASE_URL'].'/media/videos/iphone/'.$sd_filename.'?st='.$sdmd5.'&e='.$expire; 
  $HD_URL = $config['BASE_URL'].'/media/videos/hd/'.$hd_filename.'?st='.$hdmd5.'&e='.$expire; 

You'd need to do the same in /mobile_src.php probably.

 

adding;

$sdjailpath = '/media/videos/iphone/'.$mobile_filename.'';
$expire = time()+30;
$sdmd5 = str_replace('=','',strtr(base64_encode(md5($config['nginx_key'].$sdjailpath.$expire, true)),'+/','-_'));

and changing;

if ($mobile_filename) {
	if ($config['multi_server'] == '1' && $server != '')
		 $MOBILE_URL = $config['BASE_URL'].'/media/videos/iphone/'.$mobile_filename.'?st='.$sdmd5.'&e='.$expire; 
	else
		
        // $MOBILE_URL = $config['BASE_URL'].'/media/videos/iphone/'.$mobile_filename;
        $MOBILE_URL = $config['BASE_URL'].'/media/videos/iphone/'.$mobile_filename.'?st='.$sdmd5.'&e='.$expire; 
  
}

There are maybe more paths in files to do with FLV files or multiple server mods and stuff like that.

 

Also the admin video player and blog videos paths need to be located and edited if you want to still use them.

 

ps: You could probably put 

$sdjailpath = '/media/videos/iphone/'.$sd_filename.'';
$hdjailpath = '/media/videos/hd/'.$hd_filename.'';
$expire = time()+3600; //links return error 410 expired... links expire after 3600 seconds/1 hour.
$sdmd5 = str_replace('=','',strtr(base64_encode(md5($config['nginx_key'].$sdjailpath.$expire, true)),'+/','-_'));
$hdmd5 = str_replace('=','',strtr(base64_encode(md5($config['nginx_key'].$hdjailpath.$expire, true)),'+/','-_'));

in config.php and call it globally if you feel like not repeating code, just make sure you do it in files that include config.php. Then just edit the paths from there, eg;

$MOBILE_URL = $config['BASE_URL'].'/media/videos/iphone/'.$filename.'?st='.$sdmd5.'&e='.$expire;
?st='.$sdmd5.'&e='.$expire;

That's the magic part.

 

Good luck! :)



#2 sextube

sextube

    Senior Member

  • Members
  • PipPipPipPip
  • 242 posts

Posted 13 April 2016 - 05:54 PM

nice one! going to try it soon, Thanks!



#3 Damien

Damien

    Junior Member

  • Members
  • PipPipPip
  • 81 posts

Posted 14 April 2016 - 07:24 AM

just reading this again, you can remove autoindex from the rewrite area it's not required, it's a file browser function of sorts for directory listing I used, but the nginx config section for folder security still overrides any issues.

try_files $uri $uri/ /loader.php?$args; # this handles all rewrites
# autoindex on;
}

also my typos not removed from test install;

 Another global include - the security conf 
        include global/ggvideoprotect.conf;

should just be videoprotect.conf. Just read the code and error logs much as you can if something seems wrong.



#4 sextube

sextube

    Senior Member

  • Members
  • PipPipPipPip
  • 242 posts

Posted 08 September 2016 - 03:25 PM

how about config_embed.php?



#5 Damien

Damien

    Junior Member

  • Members
  • PipPipPip
  • 81 posts

Posted 27 December 2016 - 03:11 PM

use this for avs4, slight changes from above guide;

 

1) required in local config avs:

$config['nginx'] = '1';
$config['nginx_key'] = 'mysecret';

2) global nginx include: (change the alias! make sure "mysecret" passwords match here above and below when you change it to something else random)

        location ^~ /media/videos {
        alias /full/server/path/EXAMPLE/public_html/media/videos;
        secure_link $arg_st,$arg_e;
        # change 'mysecret' password below & in avs config
        secure_link_md5 mysecret$uri$arg_e;
 
        if ($secure_link = "") {
             return 403; # invalid hash or direct link
        }
        if ($secure_link = "0") {
             return 410; # link expired
        }
        mp4; # pseudo-streaming support
        flv;
        expires max;
        gzip off;
        gzip_static off;
        directio 100m; # useful for serving large files:
        output_buffers 2 512k;
        open_file_cache off;
        }

3) in AVS4 player config.php

 

find;

$sd_filename    = $rs->fields['flvdoname'];
		$hd_filename    = $rs->fields['hd_filename'];
		$hd    			= $rs->fields['hd'];
		$SD_URL			= $config['FLVDO_URL'].'/'.$sd_filename;
		$HD_URL			= $config['HD_URL'].'/'.$hd_filename;
		
		if ($sd_filename == '') {
			$sd_filename    = $rs->fields['ipod_filename'];
			$SD_URL			= $config['IPHONE_URL'].'/'.$sd_filename;
			$sd_mobile = true;
		} else {
			$sd_mobile = false;
		}

replace with

if ($config['nginx'] == '1') {
	$expire = time() + 3600; //links return error 410 expired... links expire after 3600 seconds/1 hour.

	// HD

	$hd_filename = $rs->fields['hd_filename'];
	$hd = $rs->fields['hd'];
	$hdjailpath = '/media/videos/hd/' . $hd_filename . '';
	$hdmd5 = str_replace('=', '', strtr(base64_encode(md5($config['nginx_key'] . $hdjailpath . $expire, true)) , '+/', '-_'));
	$HD_URL = $config['BASE_URL'] . '/media/videos/hd/' . $hd_filename . '?st=' . $hdmd5 . '&e=' . $expire;

	// POTATO

	$sd_filename = $rs->fields['flvdoname'];
	$flvjailpath = '/media/videos/flv/' . $sd_filename . '';
	$flmd5 = str_replace('=', '', strtr(base64_encode(md5($config['nginx_key'] . $flvjailpath . $expire, true)) , '+/', '-_'));
	$SD_URL = $config['BASE_URL'] . '/media/videos/flv/' . $sd_filename . '?st=' . $flmd5 . '&e=' . $expire;

	// MOBILE

	if ($sd_filename == '') {
		$mobile_filename = $rs->fields['ipod_filename'];
		$sdjailpath = '/media/videos/iphone/' . $mobile_filename . '';
		$sdmd5 = str_replace('=', '', strtr(base64_encode(md5($config['nginx_key'] . $sdjailpath . $expire, true)) , '+/', '-_'));
		$SD_URL = $config['BASE_URL'] . '/media/videos/iphone/' . $mobile_filename . '?st=' . $sdmd5 . '&e=' . $expire;
		$sd_mobile = true;
	}
	else {
		$sd_mobile = false;
	}
}
else {

	// no nginx

	$sd_filename = $rs->fields['flvdoname'];
	$hd_filename = $rs->fields['hd_filename'];
	$hd = $rs->fields['hd'];
	$SD_URL = $config['FLVDO_URL'] . '/' . $sd_filename;
	$HD_URL = $config['HD_URL'] . '/' . $hd_filename;
	if ($sd_filename == '') {
		$sd_filename = $rs->fields['ipod_filename'];
		$SD_URL = $config['IPHONE_URL'] . '/' . $sd_filename;
		$sd_mobile = true;
	}
	else {
		$sd_mobile = false;
	}
}

repeat above for config.embed.php and config.admin.php, blog etc.

 

4) Open mobile_src.php

 

Find;

if ($mobile_filename) {
	if ($config['multi_server'] == '1' && $server != '')
		$MOBILE_URL = $server.'/iphone/'.$mobile_filename;
	else
		$MOBILE_URL = $config['BASE_URL'].'/media/videos/iphone/'.$mobile_filename;
}
else {
	$MOBILE_URL = $config['BASE_URL'].'/media/videos/iphone/no-video.mp4';
}

replace with this;


if ($mobile_filename) {
	$expire = time() + 50; //links return error 410 expired... links expire after 3600 seconds/1 hour.
	$sdjailpath = '/media/videos/iphone/' . $mobile_filename . '';
	$sdmd5 = str_replace('=', '', strtr(base64_encode(md5($config['nginx_key'] . $sdjailpath . $expire, true)) , '+/', '-_'));
	if ($config['multi_server'] == '1' && $server != '') $MOBILE_URL = $config['BASE_URL'] . '/media/videos/iphone/' . $mobile_filename . '?st=' . $sdmd5 . '&e=' . $expire;
	else $MOBILE_URL = $config['BASE_URL'] . '/media/videos/iphone/' . $mobile_filename . '?st=' . $sdmd5 . '&e=' . $expire;
}
else {
	$MOBILE_URL = $config['BASE_URL'] . '/someplace/outside/media/no-video.mp4';
}

Make sure you change path to no-video.mp4. Nothing put under /media/ folders (except thumbnail images) will be able to be linked to directly without nginx hash, it's a 403 error. That's why we give images only specific permissions from main config example.

 

eg;

    location /media/videos/slides {
        # secure links WILL 403 your slides under /videos
        allow all;
    }
    location /media/videos/tmb {
        # secure links WILL 403 your thumbs under /videos 
        allow all;
    }

That should do it. :)


Edited by Damien, 29 December 2016 - 10:42 AM.


#6 Damien

Damien

    Junior Member

  • Members
  • PipPipPip
  • 81 posts

Posted 27 December 2016 - 03:19 PM

If some shitty browsers, validation or such give you entities errors here in the video URL;
 

<src>http://example.com/media/videos/flv/4.flv?st=22F4mLhpLl0Ekj4ksRCFJA&e=1482851947</src>
...$sdmd5.'&amp;e='.$expire;

it's because &e= is not working for you. So the video won't work (rarely).
 
you can try

...$sdmd5.htmlspecialchars_decode('&amp;e=').$expire;

or just

...$sdmd5.'&e='.$expire;

Edited by Damien, 27 December 2016 - 03:21 PM.


#7 sextube

sextube

    Senior Member

  • Members
  • PipPipPipPip
  • 242 posts

Posted 23 August 2017 - 08:02 PM

Works :)

 

but

 

1. "$config['nginx_prefix'] = '/video/'; " does not change url it's still /media

 

2. despite of "mysecret" not being the same it loads video

 

3. 404 error pages is broken, shows the browsers 404


Edited by sextube, 25 August 2017 - 07:13 AM.


#8 Damien

Damien

    Junior Member

  • Members
  • PipPipPip
  • 81 posts

Posted 11 September 2017 - 03:28 PM

Works :)

 

but

 

1. "$config['nginx_prefix'] = '/video/'; " does not change url it's still /media

 

2. despite of "mysecret" not being the same it loads video

 

3. 404 error pages is broken, shows the browsers 404

 

1) it's now the $sdjailpath replacement etc. That can't change URL paths either it's not its function. You won't find any other usage of nginx_prefix in revised config, it's old code I forgot to remove.

2) check your config files again

3) check your config files again

 

Those 2), 3) errors are module related, it's all related. (did you compile nginx source with ngx_sec modules etc?)

https://nginx.org/en...secure_link_md5

 

It's all working fine here still.


Edited by Damien, 11 September 2017 - 03:39 PM.






Also tagged with one or more of these keywords: nginx, secure streaming, nginx config