kaltura / nginx-secure-token-module

GNU Affero General Public License v3.0
116 stars 42 forks source link

Configure URI encryption #78

Closed andygr closed 5 years ago

andygr commented 5 years ago

Hello,

I would like to ask, how can I encrypt the URI. Is enough to just add the following in the config by generating the key and IV?

URI encryption
    location ~ ^/hls/p/\d+/(sp/\d+/)?serveFlavor/entryId/([^/]+)/(.*) {
        vod hls;
        vod_secret_key "password$2";

        secure_token_encrypt_uri on;
        secure_token_encrypt_uri_key 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f;
        secure_token_encrypt_uri_iv 00000000000000000000000000000000;
        secure_token_encrypt_uri_part $3;
        secure_token_types application/vnd.apple.mpegurl;

        add_header Last-Modified "Sun, 19 Nov 2000 08:52:00 GMT";
        expires 100d;
    }

I already have the appropriate modules compiled with Nginx

Thanks Andrew

erankor commented 5 years ago

You pasted the sample from the readme... so yes, that is what is needed.

andygr commented 5 years ago

@erankor , thanks for the confirmation.

In my case the location is "/". What shall I use for the uri part? Also which are the specs for the key and IV, I am thinking to use this for the Key/IV generation: https://devops.datenkollektiv.de/using-aes-with-openssl-to-encrypt-files.html

Location / secure_token_encrypt_uri on; secure_token_encrypt_uri_key 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f; secure_token_encrypt_uri_iv 00000000000000000000000000000000; secure_token_encrypt_uri_part $3; secure_token_types application/vnd.apple.mpegurl;

erankor commented 5 years ago

You have to use regex location, you can use location ~ ^/(.*) if you want to catch everything, and then use $1 for uri_part. The key is 256 bit hex, the iv is 128 bit hex, you can just read some bytes from /dev/urandom -

# dd if=/dev/urandom bs=1 count=32 2> /dev/null | xxd -p -c32
6f924323bf82b14e0d633ff7fdec9140494e4125e6f99c4294cf1b81df9c3648
# dd if=/dev/urandom bs=1 count=16 2> /dev/null | xxd -p -c32
0b04618b0e67bc5aef49b0d81f3a4762
andygr commented 5 years ago

Hi @erankor

I did the following changes:

location ~ ^/(.*) 
   proxy_pass     https://s3/;

With regex in location I got this error: nginx: [emerg] "proxy_pass" cannot have URI part in location given by regular expression, or inside named location, or inside "if" statement, or inside "limit_except" block

Then I changed it to this to fix the error:

location ~ ^/(.*) 
    proxy_pass     https://s3/$1;

and this is the secure URI config:

secure_token_encrypt_uri on;
secure_token_encrypt_uri_key 5D467F403D02F12B8FA083D6058A3FEE886F373F8FCED8E0572A7A0DA2BDB712;
secure_token_encrypt_uri_iv 251A64BFA516D12453B64F30AEC40B12;
secure_token_encrypt_uri_part $1;

By using the script I created this URL:

Usage:
    php encryptUrl.php <base url> <encrypted part> <encryption key> <encryption iv>

php encryptUrl.php https://example.com/hls/nickelback/playlist.m3u8 ? token=exp=1595955371~acl=/hls/*~hmac=0fe555c1c5fa14f0a653ee829baa358e74bfab53bdd229a8d3f1d5570bd94a0b 5D467F403D02F12B8FA083D6058A3FEE886F373F8FCED8E0572A7A0DA2BDB712 251A64BFA516D12453B64F30AEC40B12

https://example.com/hls/nickelback/playlist.m3u87MvSvj4AuLIsYDTjLqDKW2Nu8hp5A0JlW6Wx07b-mambBKuEmRxnQAyRFi5JvF3i_DMAG0RHnRuThSegZ2wTR5QQYaYGmXqwrcxAkDsthKD18MzpSuc3YsW4fdo1PtUsNQ_w15YqGtRLG72DLEoJIA

but I got an error: HTTP/1.1 400 Bad Request Server: nginx/1.17.0 Date: Tue, 30 Jul 2019 22:04:58 GMT Content-Type: text/html Content-Length: 157 Connection: close

2019/07/30 23:04:58 [error] 1342#100241: *1 ngx_http_secure_token_decrypt_uri: ngx_decode_base64url failed -1, client: 86.180.185.234, server: example.com, request: "HEAD /hls/nickelback/playlist.m3u87MvSvj4AuLIsYDTjLqDKW2Nu8hp5A0JlW6Wx07b-mambBKuEmRxnQAyRFi5JvF3i_DMAG0RHnRuThSegZ2wTR5QQYaYGmXqwrcxAkDsthKD18MzpSuc3YsW4fdo1PtUsNQ_w15YqGtRLG72DLEoJIA HTTP/1.1"

Do you think the above steps are correct? Do I need to change something?

Thanks Andrew

erankor commented 5 years ago

You configured nginx to encrypt the entire URI, but the URL you tested with is encrypted only after playlist.m3u8.

andygr commented 5 years ago

Hi @erankor ,

I was checking the uri_part:

secure_token_encrypt_uri_part
syntax: secure_token_encrypt_uri_part expression
default: none
context: http, server, location

An expression that calculates the part of the URL that should be encrypted in regular expression locations. For non-regular expression locations, the encrypted part is everything following the path defined on the location block.

Example 1:

  location /secret_param/([^/]+)/some_other_param/.* {
    secure_token_encrypt_uri_part $1;
    ...
  }
In this configuration, only the value of secret_param will be encrypted/decrypted.

Example 2:

  location /base/ {
    ...
  }
In this configuration, everything following /base/ will be encrypted/decrypted.

and I decided to use example 2 which is with non-regular expression. So I changed the config to this (didn't use uri part):

location /hls/ {
.
.
.
secure_token_encrypt_uri on;
secure_token_encrypt_uri_key 5D467F403D02F12B8FA083D6058A3FEE886F373F8FCED8E0572A7A0DA2BDB712;
secure_token_encrypt_uri_iv 251A64BFA516D12453B64F30AEC40B12;
#secure_token_encrypt_uri_part $1;

then I generated the encrypted URL:

php encryptUrl.php https://example.com/hls/ nickelback/playlist.m3u8?token=exp=1595955371~acl=/hls/*~hmac=0fe555c1c5fa14f0a653ee829baa358e74bfab53bdd229a8d3f1d5570bd94a0b 5D467F403D02F12B8FA083D6058A3FEE886F373F8FCED8E0572A7A0DA2BDB712 251A64BFA516D12453B64F30AEC40B12

but I am getting 403:

curl -I https://cdnuser2.cosmocdn.com/hls/vcEUVhBvmtZVzmfJblPy4jQsIx-m3u-6A8XtLaic8Pj9kSncnqBSdllKGOcRnQyhKZDygFeY6MZQx3rsD3pTkulsheR-Xw_8kBOjEJDHgfXVwBjyCgnPO766KkwsxR4qRb9JROkluHaldKuFnpiRbzdMMBq27VDcZwfn284bh116Q3ndYwsr3KNMF1jVqBuV

HTTP/1.1 403 Forbidden
Server: nginx/1.17.0
Date: Thu, 01 Aug 2019 20:56:38 GMT
Content-Type: text/html
Content-Length: 153
Connection: keep-alive

Am I doing something wrong?

andygr commented 5 years ago

Hello,

any suggestion on the last comment?

Thanks

erankor commented 5 years ago

"everything following /base/ will be encrypted/decrypted." - everything = on the URL path. A location in nginx is matched against the path, you should not encrypt the query params. In general, URI encryption + query params is not fully supported - $request_uri will get stripped out of the query params after decryption. But it may still work ok for you, since $args will still point to the original query params.

andygr commented 5 years ago

thanks will close this issue