Secure RTSP and HLS/HTTP streaming

Hello,

We are live streaming couple of TV channels. We were able to secure RTMP (flash player) streaming with modules and some PHP scripting, so it cannot be hot-linked.

Now the problem is that RTSP and HTTP/HLS streaming links are totally unsecured. People can simple copy the link and play on any device they want.

We want the user to visit our website and then only the RTSP or HTTP/HLS link should work.

Any great mind have any idea !

We were thinking of using random URL but dont know how Wowza will understand it.

-Mamoor

Just a little idea:

Write a Wowza module in conjunction with some code on your webserver. When the client clicks your video link on your webserver, send their IP and streamname to your module, to be recorded along with a timeout value. Override the play() method, if they’re not on your list reject them.

This way only clients who authenticated on your webserver can play streams.

Actually, the play command does not run for non-Flash RTMP clients. And you don’t have to send IP to Wowza in either case. Take a look at these methods

https://www.wowza.com/docs/how-to-control-access-to-http-streams-cupertinostreaming-sanjosestreaming-smoothstreaming-mpegdashstreaming

https://www.wowza.com/docs/how-to-control-access-to-rtsp-rtp-streams

Richard

You can get the IP like this:

HTTP:

String ipAddressClient = httpSession.getIpAddress();

RTSP:

String ipAddress = rtpSession.getIp();

You don’t want referrer I don’t think, and it might not be reliably populated in some cases, iOS for one, because it does not send that data.

Richard

Good idea but need more clarifications.

How about random links that keep alive for a minute. Anyone if try to hotlink the temporary URL it would not work and he should be required a new working link.

I think its easy to implement on webserver under PHP but how Wowza will understand it.

-Mamoor

Going through the code it looks like if the referrer is populated with 123.com and only this domain is allowed then all other will be denied.

But could u please tell me how the referrer will be populated ?

Do u have any working example code which i can mimic?, Say the code only allow wowza.com referrer when someone click on an RTSP link.

-Mamoor

Richard,

But we cannot block or allow according to IP address.

Domain locking is more appropriate. Say, if the link is coming from www.123.com it should allow. Similar like in https://www.wowza.com/docs/how-to-combat-hotlinking-your-adobe-flash-swf-file

Is similar technique can be implemented in RTSP and HTTP streaming ?

I used the following code but it deny everything:

package com.wowza.wms.example.module;

// com.wowza.wms.example.module.ModuleAccessControlHTTPStreaming

import com.wowza.wms.httpstreamer.model.IHTTPStreamerSession;

import com.wowza.wms.module.*;

import com.wowza.wms.application.*;

public class ModuleAccessControlHTTPStreaming extends ModuleBase

{

public void onHTTPSessionCreate(IHTTPStreamerSession httpSession)

{

boolean isGood = true;

String ipAddressClient = httpSession.getIpAddress();

String ipAddressServer = httpSession.getServerIp();

String uri = httpSession.getUri();

String queryStr = httpSession.getQueryStr();

String referrer = httpSession.getReferrer();

String cookieStr = httpSession.getCookieStr();

String userAgent = httpSession.getUserAgent();

IApplicationInstance appInstance = httpSession.getAppInstance();

String streamName = httpSession.getStreamName();

// Here you can use the request and session information above to determine

// if you want to reject the connection

// isGood = true/false;

getLogger().info(“ModuleAccessControlHTTPStreaming.onHTTPSessionCreate[”+appInstance.getContextStr()+“:”+streamName+“]: accept:”+isGood);

// boolean reject = true;

String domainLocks = null;

String domainUrl = null;;

try

{

domainLocks = httpSession.getAppInstance().getProperties().getPropertyStr(“domainLock”).toLowerCase().split(“,”);

//String pageUrl = httpSession.getProperties().getPropertyStr(“connectpageUrl”).toLowerCase();

// domainUrl = pageUrl.split(“/”);

getLogger().info("domainLock: " + httpSession.getAppInstance().getProperties().getPropertyStr(“domainLock”).toLowerCase());

getLogger().info("pageUrl: " + ipAddressClient);

for (int i = 0; i < domainLocks.length; i++)

{

if (domainLocks_.trim().startsWith(“*”))_

{

String lock = domainLocks*.trim().substring(1);*

if (ipAddressClient.endsWith(lock))

{

isGood = true;

}

}

else if (ipAddressClient.equalsIgnoreCase(domainLocks*.trim()))*

{

isGood = true;

}

}

}

catch(Exception ex)

{

isGood = false;

}

if (isGood)

{

getLogger().info("Client Rejected. IP: " + httpSession.getIpAddress());

httpSession.rejectSession();

}

if (!isGood)

httpSession.rejectSession();

}

}

-Mamoor

Hell Randall,

Its not that ur idea is not good but any example coding is appreciated.

-Mamoor

Use a query string instead of a stream name to do your authentication. A user posted an example: Application exists for RTMP but not RTSP?

On your webserver md5 encode your random salt and their IP and then add the current unix timestamp to the result. On the Wowza module, recalculate hash from their IP + salt, then subtract from key leaving unix time. This will accomplish two things:

  1. Ensure the person who requested the URI is the same IP as the one playing it.

  2. Provide a time, that you can check/reject.

What, you guys don’t like my ideas? :stuck_out_tongue: Disclaimer: I haven’t tried it.

“We want the user to visit our website and only then the RTSP or HTTP/HLS link should work.”

“If Anyone try to hotlink the temporary URL it would not work and he should be required a new working link.”

My suggestion accomplishes this. It functions as hotlink denial too. To start with just append the IP and timestamp to the URI you present to the client, then check the values in the module on connect. Worry about the hash/encryption algorithm later. You could put the code in the OverridePlay script which has code for RTMP, HTTP, and RTSP. The getReferer method might not work for all clients, but this should.

I mentioned keeping track of IPs at first. That’s one way. This second way doesn’t track IPs. It just makes sure that the URI being played is being played by the correct IP.

Eventually, you will want to generate the cipher on the server (cgi-bin), as opposed to javascript, then present the encoded URI to the client.

Hello all,

residing on the same position, example coding will be appreciated. The idea is great !