Skip to main content

RTSP streaming over dual nat with RTSP Interleaved mode

I have an IP Camera that supports RTSP streaming (most IP cameras seem to support it - Axis, Edimax, etc). This allows you to view mpeg4 or h264 live streams either by using a proprietary ActiveX control (via their web interface) or via a RTSP client.

If you are in the same LAN as the camera, you can easily connect to it by using VLC or even ffmpeg (to save or transcode the stream):

vlc rtsp://192.168.1.10/ipcamera_h264.sdp
ffmpeg -i rtsp://192.168.1.10/ipcamera_h264.sdp test.ts
ffmpeg -i rtsp://192.168.1.10/ipcamera_h264.sdp -f mpegts | vlc -



The problem is if you want to access that camera over the Internet. RTSP usually transports the data over UDP and negotiates the UDP ports over a control session on port 554 TCP. This gets difficult if you use NAT at either end or if you have firewalls you need to get through.

Let's consider this typical scenario:



The packets need to go through 2 NATs to travel between the source and destination. To make this happen, you have 3 possible solutions:

1. Using a session management protocol like ICE, but it needs to be supported by the client and server. Cheap IP cameras don't usually support it
2. Using a Layer 3 or Layer 2 VPN between RouterA and RouterB. With a VPN set in place (and with the appropriate firewall permits), the client can connect via RTSP to the server and it would communicate the same way it does in a LAN environment (no more NAT!). However, your routers need to be configured for site-to-site VPN - which might be challenging (especially if you don't have management access on either router)
3. Using RTSP Interleaved mode - a method I will describe next

According to Wikipedia:
Certain firewall designs and other circumstances may force a server to interleave RTSP methods and stream data. This interleaving should generally be avoided unless necessary since it complicates client and server operation and imposes additional overhead. Interleaved binary data SHOULD only be used if RTSP is carried over TCP.

So, instead of using UDP to transfer data, it uses TCP, and furthermore, it piggybacks the video data on top of the control session that is established on port 554. It may be less efficient in payload size and processing power, but it works with NAT and firewalls - which is what we want.

So, for the example above we have the following prerequisites for this to work:
  1.  The ability to port forward on RouterB
  2.  The IP Camera must have a fixed IP address (in order for port forwarding to work). This can be done either by assigning a static IP manually, or through DHCP.
  3.  Client and server must support RTSP Interleaved mode


Port forwarding setup

Depending on your router's firmware this can be done in different ways. I will not show a specific way to do it, just the concept. On RouterB you need to allow incoming TCP packets from source IP 11.11.11.11 (the NATed IP of the client) to go to your IP camera's IP (192.168.1.10) on the RTSP port (554 by default).

Since this is port forwarding you are actually forwarding a TCP port on your router (e.g. 22.22.22.22:1234) to an internal server in your network (192.168.1.10:554), so you will need to decide which external port you will be using (I used 1234 in my example).

If you have multiple IP Cameras behind RouterB, you can add multiple port forwarding rules - like this:

allow TCP from 11.11.11.11 to 192.168.1.10:554 on external port 1234
allow TCP from 11.11.11.11 to 192.168.1.11:554 on external port 5678
The port forwarding rule does not necessarily have to specify the source address - if it is missing it will allow access from any source address - but this is a security risk, so I advise against it.

RTSP Interleaved mode
Right now, you should be able to connect to the camera from the client computer, but if you try to use RTSP, you will notice that the control session is established, but the data never arrives because the NAT and firewall prevent the communication on the negotiated UDP ports.

You must convince the client software to try connecting in interleaved mode (this is why you came here for, right?).

VLC: Well, according to http://www.wowza.com/forums/content.php?64 you need to do the following configuration in VLC:

  1. Open VLC
  2. Select menu item Tools: Preferences
  3. Select the Input & Codecs section
  4. Select the Live555 stream transport option RTP over RTSP (TCP)
  5. Click Save button
You can now connect to your stream using the command:

vlc rtsp://22.22.22.22:1234/ipcamera_h264.sdp
For other cameras, change the destination port (e.g. 1234 -> 5678) in your command

FFMPEG: Their documentation states that you need to use the rtsp_transport flag:

ffmpeg -rtsp_transport tcp -i rtsp://22.22.22.22:1234/ipcamera_h264.sdp test.ts
ffmpeg -rtsp_transport tcp -i rtsp://22.22.22.22:1234/ipcamera_h264.sdp -f mpegts | vlc -
In case of problems, you should analyse a packet capture and see if Interleaved mode is supported by both end systems (it is negotiated in a RTSP OPTIONS request) - capture example below:


Have fun streaming!

Comments

Deniel nash said…
This comment has been removed by a blog administrator.

Popular posts from this blog

Home Assistant + Android TV = fun

Here's a quick setup guide for controlling your Android TV from within Home Assistant. I've used it to control a genuine Android TV (Philips 7304) and an Odroid N2 running Android TV. For this to work you need ADB access. It can usually be enabled from within Developer Settings. The great part is - you don't need root access! The most important things are described in the androidtv component for Home Assistant: https://www.home-assistant.io/integrations/androidtv/ Make sure you go through the adb setup. My configuration is simple (inside configuration.yaml): media_player:   - platform: androidtv     name: TV Bedroom ATV     host: 192.168.1.61     device_class: androidtv Once Home Assistant restarts, your TV might require you to accept the connection (adb authentication). This happens only once (or until you reset your ATV to factory settings). Once running the integration will show you the current ATV state (on or off) and allows you to turn it on or off.

SmokePing + InfluxDB export + docker + slaves + Grafana = fun

I've been working for a while on this project - with the purpose of getting SmokePing measurements from different hosts (slaves) into InfluxDB so that we can better graph them with Grafana. The slaves run multiple Smokeping instances inside Docker so that they have separate networking (measure through different uplinks, independently). This will not be a comprehensive configuration guide, but a quick "how to" to handle setup and basic troubleshooting. It assumes you already know how to set up and operate a regular Smokeping install with or without slaves and that you are fluent in Smokeping configuration syntax, know your way around Docker and aren't a stranger from InfluxDB and Grafana (sorry, there's a lot of information to take in). 1. Getting Smokeping with InfluxDB support - you can get it either from the official page (most changes have been merged) - https://github.com/oetiker/SmokePing (PR discussion here: https://github.com/oetiker/SmokePing/issues/

Installing Home Assistant Supervised on an old 32bit HP laptop

 I've received a challenge from my former boss: an old HP laptop that was born in 2005:  an HP-Compaq NC6220 ( https://www.pocket-lint.com/laptops/reviews/hp/68181-hp-compaq-nc6220-notebook-laptop/ ). The specs are abysmal: So, i386, 1.7GHz single-core CPU (remember those?), 1G of DDR2 RAM (2x512M) and a 40GB ATA (not SATA!) drive. But hey, at least it has a serial port!  The challenge is to install HomeAssistant ( https://www.home-assistant.io/ ) on it so that he can monitor some Zigbee temperature sensors and relays (via a gateway). The first hurdle was to remove the BIOS password - following this nice guide: https://www.youtube.com/watch?v=ZaGKyb0ntSg Next-up - install HASSOS. Unfortunately, it doesn't support i386, but only x86_64... So, I went the Home Assistant Supervised route, and installed Debian 11 i386 edition from a netinstall USB ( https://cdimage.debian.org/debian-cd/current/i386/iso-cd/debian-11.6.0-i386-netinst.iso ).   Once Debian was up and running (didn't