Securing URLs with the Secure Link Module in NGINX

Andrew Andonopoulos andre8525 at
Sat Jun 8 14:44:22 UTC 2019

Hi Francis,

Thanks for the clarification, so all requests will be like this:

http://<domain>/hls/<content folder name>/<content filename>

can i include in the map the domain, the folder /hls/ and ignore all the rest?

any guidance/help with the map will be very helpfull because i am not very familiar with regex

map $uri $hls_uri {
        ~^(?<base_uri>.*).m3u8$ $base_uri;
        ~^(?<base_uri>.*).ts$   $base_uri;
        default                 $uri;


From: nginx <nginx-bounces at> on behalf of Francis Daly <francis at>
Sent: Friday, June 7, 2019 10:34 PM
To: nginx at
Subject: Re: Securing URLs with the Secure Link Module in NGINX

On Fri, Jun 07, 2019 at 09:51:49PM +0000, Andrew Andonopoulos wrote:

Hi there,

thanks for the fuller details. I think it makes it clear what is

> and this command to generate the md5:
>  echo -n 'enigma/hls/justin-timberlake/playlist1560033000' | openssl md5 -binary | openssl base64 | tr '+/' '-_' | tr -d '='
> DWHdyTKR5vTqw10wNtnlIg
> The request for the main manifest was ok:
> Request URL: http://<domain>/hls/justin-timberlake/playlist.m3u8?md5=DWHdyTKR5vTqw10wNtnlIg&expires=1560033000
> Request Method: GET
> Status Code: 200 OK
> But the content of the manifest doesn't have the md5

The content of the manifest file must be, in this case, "the relative
urls for the individual pieces".

> Justin_Timberlake_416_234_200.m3u8
> Justin_Timberlake_480_270_300.m3u8

Justin_Timberlake_416_234_200.m3u8 is probably the filename; but you
have configured your nginx such that Justin_Timberlake_416_234_200.m3u8
is not a valid url for that file.

The url with your current nginx configuration is something more like


(from: $ echo -n 'enigma/hls/justin-timberlake/Justin_Timberlake_416_234_2001560033000' | openssl md5 -binary | openssl base64 | tr '+/' '-_' | tr -d '='

so *that* is the string that must appear in the playlist.m3u8 file.

And the file Justin_Timberlake_480_270_300.m3u8 will have a different
"md5" part of the url, because your nginx config ignores the .m3u8 but
uses everything before it when checking the md5sum.

Whatever creates the playlist.m3u8 file that ends up being served by your
nginx, will need to be modified to create the correct urls for the files,
if they are to be served by your nginx.

You could, if you chose, change your nginx config (the map) to ignore the
final digits-and-underscores as well as the .m3u8 part; if you did that,
then the query-string part of all of these entries in the manifest would
be the same (and you would only need to calculate it once).

> As well as the other m3u8 manifest, so only the playlist have the md5 and expire:

You must decide how you want your files to be accessed, and then configure
things appropriately.

If you want every .m3u8 and .ts file below /hls/ to only be accessed via
the secure_link, then you must make sure that you advertise the correct
secure_link urls for those files.

If you want only the playlist.m3u8 files to be accessed via the
secure_link, while the other .m38u and .ts files are not restricted and
expiring, then you must configure your nginx to do the secure_link check
on playlist.m3u8 and not on the others.

> Request URL:
> Request Method: GET
> Status Code: 403 Forbidden

That is what you configured your nginx to do, so it looks like it is
worked as implemented -- but presumably not as desired.

Good luck with it,

Francis Daly        francis at
nginx mailing list
nginx at
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the nginx mailing list