Skip to content

Commit

Permalink
detect multicast IP addresses and set IP_MULTICAST_TTL to 0 as a secu…
Browse files Browse the repository at this point in the history
…rity precaution
  • Loading branch information
Michael Franzl committed Jan 13, 2018
1 parent 5b761da commit 3a21ee6
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 11 deletions.
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Janus rtpforward plugin

This plugin for the [Janus WebRTC gateway](https://github.com/meetecho/janus-gateway) takes RTP and RTCP packets from a WebRTC connection (Janus Session) and forwards/sends them to UDP ports for further processing or display by an external receiver/decoder (e.g. a GStreamer pipeline). UDP broadcast and multicast is implicitly supported by setting the `sendipv4` to broadcast or multicast IP addresses.
This plugin for the [Janus WebRTC gateway](https://github.com/meetecho/janus-gateway) takes RTP and RTCP packets from a WebRTC connection (Janus Session) and forwards/sends them to UDP ports for further processing or display by an external receiver/decoder (e.g. a GStreamer pipeline).

Four destination UDP addresses/ports are used:

Expand Down Expand Up @@ -56,10 +56,14 @@ These packet loss simulations are perhaps too simple. They are no replacement fo

This plugin only accepts VP8 and OPUS in RECVONLY mode. This is hardcoded via arguments to the `janus_sdp_generate_answer()` function, but can be changed easily (see comments there).

# UDP broadcast/multicast

UDP broadcast and multicast is implicitly supported by configuring the `sendipv4` to broadcast or multicast IP addresses (strictly speaking, this is just a feature of the socket or OS, not a feature of this plugin). If a multicast IP address is detected, as a security precaution, the plugin will set the `IP_MULTICAST_TTL` option of the sending socket to 0 (zero) which SHOULD cause at least the first router (the Linux kernel) to NOT forward the UDP packets to any other network (the packets SHOULD be accessible only on the same machine). This behavior is however OS-specific. **When configuring a multicast IP address, you SHOULD verify that the UDP packets are not inadvertenly forwarded into networks where the security/privacy of the packets could be compromised, or into networks where congestion or bandwidth need to be observed. If in doubt, do NOT configure this plugin with multicast IP addresses!**


# Use cases

Note: The following two use cases use the UDP multicast IP address 225.0.0.37 (which is in a group of multicast addresses not routed, i.e. only working on the same machine). This enables multiple subscribers to the same RTP stream, for maximum flexibility.
Note: The following two use cases use the UDP multicast IP address 225.0.0.37. This enables multiple subscribers to the same RTP stream, for maximum flexibility.

## GStreamer display

Expand Down
40 changes: 31 additions & 9 deletions janus_rtpforward.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
#include <plugins/plugin.h>
#include <debug.h>

#include <netinet/in.h>
#include <sys/socket.h>

#include <poll.h>

#include "debug.h"
Expand All @@ -39,7 +42,7 @@
#include "utils.h"

#define RTPFORWARD_VERSION 1
#define RTPFORWARD_VERSION_STRING "0.2.1"
#define RTPFORWARD_VERSION_STRING "0.2.2"
#define RTPFORWARD_DESCRIPTION "Forwards RTP and RTCP to an external UDP receiver/decoder"
#define RTPFORWARD_NAME "rtpforward"
#define RTPFORWARD_AUTHOR "Michael Karl Franzl"
Expand Down Expand Up @@ -504,14 +507,33 @@ struct janus_plugin_result *rtpforward_handle_message(janus_plugin_session *hand
}

// create the SEND socket
if (session->sendsockfd < 0) {
session->sendsockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (session->sendsockfd < 0) { // still?
if (session->sendsockfd < 0) { // only once
session->sendsockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (session->sendsockfd < 0) { // error
JANUS_LOG(LOG_ERR, "%s Could not create sending socket\n", RTPFORWARD_NAME);
error_code = 99; // TODO define
error_code = 99; // TODO: define this
g_snprintf(error_cause, 512, "Could not create sending socket");
goto respond;
}

if (IN_MULTICAST(ntohl(inet_addr(sendipv4)))) {
u_int ttl = 0; // do not route UDP packets outside of local host
setsockopt(session->sendsockfd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));

struct in_addr mcast_iface_addr;
mcast_iface_addr.s_addr = htonl(INADDR_LOOPBACK); // same as inet_addr("127.0.0.1");

JANUS_LOG(LOG_WARN, "%s: This rtpforward session will multicast to IP multicast address %s "
"because you specified it. The IP_MULTICAST_TTL option has been set to 0 (zero), which "
"SHOULD cause at least the first router (the Linux kernel) to NOT forward the UDP packets. "
"The behavior is is however OS-specific. You SHOULD verify that the UDP packets "
"are not inadvertenly forwarded into network zones where the security/privacy of the packets "
"could be compromised.\n", RTPFORWARD_NAME, inet_ntoa(session->sendsockaddr.sin_addr));

JANUS_LOG(LOG_WARN, "%s: Will multicast from network interface with IP %s\n", RTPFORWARD_NAME, inet_ntoa(mcast_iface_addr));

setsockopt(session->sendsockfd, IPPROTO_IP, IP_MULTICAST_IF, &mcast_iface_addr, sizeof(mcast_iface_addr));
}
}

#ifdef FORWARD_FEEDBACK
Expand Down Expand Up @@ -539,7 +561,7 @@ struct janus_plugin_result *rtpforward_handle_message(janus_plugin_session *hand

// create the RECEIVE socket for audio RTCP
if (session->recvsockfd_audio_rtcp < 0) {
session->recvsockfd_audio_rtcp = socket(AF_INET, SOCK_DGRAM, 0); // TODO: IPPROTO_UDP???
session->recvsockfd_audio_rtcp = socket(AF_INET, SOCK_DGRAM, 0);
if(session->recvsockfd_audio_rtcp < 0) { // still?
JANUS_LOG(LOG_ERR, "%s Could create listening socket for audio RTCP...\n", RTPFORWARD_NAME);
error_code = 99; // TODO define
Expand All @@ -550,7 +572,7 @@ struct janus_plugin_result *rtpforward_handle_message(janus_plugin_session *hand

// create the RECEIVE socket for video RTCP
if (session->recvsockfd_video_rtcp < 0) {
session->recvsockfd_video_rtcp = socket(AF_INET, SOCK_DGRAM, 0); // TODO: IPPROTO_UDP???
session->recvsockfd_video_rtcp = socket(AF_INET, SOCK_DGRAM, 0);
if(session->recvsockfd_video_rtcp < 0) { // still?
JANUS_LOG(LOG_ERR, "%s Could create listening socket for video RTCP...\n", RTPFORWARD_NAME);
error_code = 99; // TODO define
Expand All @@ -559,10 +581,10 @@ struct janus_plugin_result *rtpforward_handle_message(janus_plugin_session *hand
}
}

session->recvsockaddr_audio_rtcp.sin_addr.s_addr = INADDR_ANY; // inet_addr("127.0.0.1"); // htonl(INADDR_ANY)
session->recvsockaddr_audio_rtcp.sin_addr.s_addr = INADDR_ANY;
session->recvsockaddr_audio_rtcp.sin_port = htons(session->recvport_audio_rtcp);

session->recvsockaddr_video_rtcp.sin_addr.s_addr = INADDR_ANY; //inet_addr("127.0.0.1");
session->recvsockaddr_video_rtcp.sin_addr.s_addr = INADDR_ANY;
session->recvsockaddr_video_rtcp.sin_port = htons(session->recvport_video_rtcp);

// TODO: protect against multiple runs of configure
Expand Down

0 comments on commit 3a21ee6

Please sign in to comment.