python-3.xrtspgstreamer-1.0python-gstreamer

Can we restrict client port range for GStreamer rtspsrc element?


We're working in a heavily-controlled network environment (in production) where we need to lock down ports used for certain things.

We currently have a need to open an RTSP stream to some camera and we route return traffic based on the ports being used (since the IP addresses of each instance of production can vary wildly).

The router rules work fine currently but the final rule is to route all traffic (not already caught by earlier rules) to a default box A. The router appears too care little about IP addresses, it instead routes packets to specific connectors that the machines are attached to. So, when I say A or B, that's really the physical connector on the back of the router.

We, however, want to be able to route the GStreamer camera feeds initiated from a different box B, back to that box.

Currently, when I do netstat -na on B (in a non-locked-down development environment), I can see the that the RTSP streams use various client ports from 35100 through 58712. This gels with the contents of /proc/sys/net/ipv4/ip_local_port_range which shows 32768 60999.

For example (with .20.20 being machine B and .30.30 being the camera:

tcp   0   0   172.24.20.20:36250   172.24.30.30:8091   ESTABLISHED

I thought it would be enough to set the port-range in the props structure used when creating the rtspsrc element. However, setting this to 4500-4999 still results in the netstat output showing use of client ports above 30000.

Is port-range supposed to control these ports used for camera streaming back or is it for something else?

If the latter, how can we restrict the ports used for the streaming?


As extra information if needed, this is the properties dictionary and code used to set the properties of the rtspsrc element:

props = {
    "protocols": "tcp",
    "drop-on-latency": True,
    "do-retransmission": False,
    "latency": 100,
    "port-range": "4500-4999",
    "buffer-mode": 1,
}

elem = self.gstreamer.ElementFactory.make("rtspsrc", "source")
for name, prop in props.items():
    elem.set_property(name, prop)

Solution

  • Okay, many hours of thoroughly looking through the source code for RTSP and RTP elements, along with a better education on how it all works under the covers, has turned up the fact that port restriction only works for when you use the UDP protocol, not TCP as I have.

    I noticed that, when I used Wireshark to monitor VLC connecting to the camera, it contained a client_port=58100-58101 clause in the SETUP string passed to the camera. That clause, which specifies the RTP and RTCP ports to be used by the server, was not there when my application ran.

    The port restriction is stored in the element regardless of protocol but, when it comes time to form the SETUP message, the gst_rtspsrc_create_transports_string() function constructs it as follows (reformatted for readability):

    if (protocols & GST_RTSP_LOWER_TRANS_UDP) {
        GST_DEBUG_OBJECT(src, "adding UDP unicast");
        if (add_udp_str) {
            g_string_append(result, "/UDP");
        }
        g_string_append(result, ";unicast;client_port=%%u1-%%u2");       // HERE.
    } else if (protocols & GST_RTSP_LOWER_TRANS_UDP_MCAST) {
        GST_DEBUG_OBJECT(src, "adding UDP multicast");
        if (add_udp_str) {
            g_string_append(result, "/UDP");
        }
        g_string_append(result, ";multicast");
        if (src->next_port_num != 0) {
            if ((src->client_port_range.max > 0)
            && (src->next_port_num >= src->client_port_range.max)) {
                goto no_ports;
            }
    
            g_string_append_printf(result, ";client_port=%d-%d",         // HERE.
                src->next_port_num, src->next_port_num + 1);
        }
    } else if (protocols & GST_RTSP_LOWER_TRANS_TCP) {
        GST_DEBUG_OBJECT(src, "adding TCP");
    
        g_string_append(result, "/TCP;unicast;interleaved=%%i1-%%i2");   // NOT HERE.
    }
    

    You can see there that the all-important client_port=<low>-<high> clause is only added for UDP unicast and multicast, not TCP.

    It's that clause that controls what ports the RTSP server should connect to for return traffic.

    And, indeed, changing the protocols property to be udp solves the issue, ensuring that only the desired ports are used.