SDP Origin attribute ('o') - is this the IP of the client, or the RTP server? - sdp

In an SDP message, the "Origin" ('o') attribute is defined as:
o=<username> <sess-id> <sess-version> <nettype> <addrtype> <unicast-address>
Where <unicast-address> has the following definition:
is the address of the machine from which the session was created.
However, I'm unclear on whether this should be the IP of the client, or the RTP server. For example, if the client is running VLC on IP 1.1.1.1, and the RTP server is serving media from 2.2.2.2, should the <unicast-address> be set to 1.1.1.1, or 2.2.2.2?

I take it to mean the machine which creates the session and actually generates the SDP message, i.e. not the RTP server (the address of the RTP endpoints are defined elsewhere in the message). That's how I've always implemented it in the past.

The unicast address is of the server thats creating the RTP session. Usually it carries the IP address but for reasons of obfuscation the IP can be switched to FQDN or even something relatively obscure that for purposes of debugging can only be understood by the application developers.
It doesn't have any significance w.r.t to SDP / RTP processing.

Related

How tunneling services like 'Localtunnel' works without SSH?

I want to understand how my local IP address (localhost) can be exposed to Internet. For that I've read [here] a method of port forwarding using SSH. Which basically does routing from publicly available server to our localhost using SSH.
But I wonder how the service like 'LocalTunnel' works? In above article it's written as following:
There services (localtunnel for example) creates a tunnel from their server back to port 3000 on your dev box. It functions pretty much exactly like an SSH tunnel, but doesn’t require that you have a server.
I've tried reading code from it's github repository and what I understood is:
These services have a server which is publicly available, which generates different URLs, and when we hit that URL, It forward the request to localhost corresponding to that URL.
So basically it's works like a proxy server.
Is these understanding correct? If yes then what I don't understand is that how these server has access to some localhost running on my computer? How it perform request to it? What I'm missing here? Here is the code which I referred.
The Short Answer (TL;DR)
The Remote (i.e. the localtunnel software on your computer) initializes the connection to the Relay (i.e. localtunnel.me) acts as a multiplexing proxy and when Clients (i.e. web browsers) connect, the relay multiplexes the connections between remotes and clients by appending special headers with network information.
Browser <--\ /--> Device
Browser <---- M-PROXY Service ----> Device
Browser <--/ \--> Device
Video Presentation
If you prefer a video preso, I just gave a talk on this at UtahJS Conf 2018, in which I talk a little about all of the other potential solutions as well: SSH Socksv5 proxies (which you mentioned), VPN, UPnP, DHT, Relays, etc:
Access Ability: Access your Devices, Share your Stuff
Slides: http://telebit.cloud/utahjs2018
How localtunnel, ngrok, and Telebit work (Long Answer)
I'm the author of Telebit, which provides service with similar features to what ngrok, localtunnel, and libp2p provide (as well as open source code for both the remote/client and relay/server to run it yourself).
Although I don't know the exact internals of how localtunnel is implemented, I can give you an explanation of how it's generally done (and how we do it), and it's most likely nearly identical to how they do it.
The magic that you're curious about happens in two places: the remote socket and the multiplexer.
How does a remote client access the server on my localhost?
1. The Remote Socket
This is pretty simple. When you run a "remote" (telebit, ngrok, and localtunnel all work nearly the same in this regard), it's actually your computer that initiates the request.
So imagine that the relay (the localtunnel proxy in your case) uses port 7777 to receive traffic from "remotes" (like your computer) and your socket number (randomly chosen source address on your computer) is 1234:
Devices: [Your Computer] (tcp 1234:7777) [Proxy Server]
Software: [Remote] -----------------------> [Relay]
(auth & request 5678)
However, the clients (such as browsers, netcat, or other user agents) that connect to you actually also initiate requests with the relay.
Devices: [Proxy Service] (tcp 5678) [Client Computer]
Software: [Relay] <------------------------ [netcat]
If you're using tcp ports, then the relay service keeps an internal mapping, much like NAT
Internal Relay "Routing Table"
Rule:
Socket remote[src:1234] --- Captures ------> ALL_INCOMING[dst:5678]
Condition:
Incoming client[dst:5678] --- MATCHES -------> ALL_INCOMING[dst:5678]
Therefore:
Incoming client[dst:5678] --- Forwards To ---> remote[src:1234]
Both connections are "incoming" connections, but the remote connection on the "south end" is authorized to receive traffic coming from another incoming source (without some form of authorized session anyone could claim use of that port or address and hijack your traffic).
[Client Computer] (tcp 5678) [Proxy Service] (tcp 1234) [Your Computer]
[netcat] --------------> <--[Relay]--> <------------ [remote]
2. The Multiplexer
You may have noticed that there's a critical flaw in the description above. If you just route the traffic as-is, your computer (the remote) could only handle one connection at a time. If another client (browser, netcat, etc) hopped on the connection, your computer wouldn't be able to tell which packets came from where.
Browser <--\ /--> Device
Browser <---- M-PROXY Service ----> Device
Browser <--/ \--> Device
Essentially what the relay (i.e. localtunnel proxy) and the remote (i.e. your computer) do is place a header in front of all data that is to be received by the client. It needs to be something very similar to HAProxy's The PROXY Protocol, but works for non-local traffic as well. It could look like this:
<src-address>,<src-port>,<sni>,<dst-port>,<protocol-guess>,<datalen>
For example
172.2.3.4,1234,example.com,443,https,1024
That info could be sent exactly before or append to each data packet that's routed.
Likewise, when the remote responds to the relay, it has to include that information so that the relay knows which client the data packet is responding to.
See https://www.npmjs.com/package/proxy-packer for long details
Sidenote/Rant: Ports vs TLS SNI
The initial explanation I gave using tcp ports, because it's easy to understand. However, localtunnel, ngrok, and telebit all have the ability to use tls servername indicator (SNI) instead of relying on port numbers.
[Client Computer] (https 443) [Proxy Service] (wss 443) [Your Computer]
[netcat+openssl] --------------------> <--[Relay]--> <------------ [remote]
(or web browser) (sni:xyz.somerelay.com) (sni:somerelay.com)
MITM vs p2p
There are still a few different ways you can go about this (and this is where I want to give a shameless plug for telebit because if you're into decentralization and peer-to-peer, this is where we shine!)
If you only use the tls sni for routing (which is how localtunnel and ngrok both work by default last time I checked) all of the traffic is decrypted at the relay.
Anther way requires ACME/Let's Encrypt integration (i.e. Greenlock.js) so that the traffic remains encrypted, end-to-end, routing the tls traffic to the client without decrypting it. This method functions as peer-to-peer channel for all practical purposes (the relay acts as just another opaque "switch" on the network of the Internet, unaware of the contents of the traffic).
Furthermore, if https is used both for remotes (for example, via Secure WebSockets) and the clients, then the clients look just like any other type of https request and won't be hindered by poorly configured firewalls or other harsh / unfavorable network conditions.
Now, solutions built on libp2p also give you a virtualized peer connection, but it's far more indirect and requires routing through untrusted parties. I'm not a fan of that because it's typically slower and I see it as more risky. I'm a big believer than network federation will win out over anonymization (like libp2p) in the long. (for our use case we needed something that could be federated - run by independently trusted parties- which is why we built our solution the way that we did)

Set interleaving in RTSP with Ip camera (Onvif standard)

I am working with an IP camera based on onvif standards. The scenario is the following one:
The RTP port and HTTP port are 22554 and 22280 respectively. I have no problem with this, I reroute the traffic from A to B in those ports to reach the camera. In fact, the RTP session is correctly established.
The problem comes in the SETUP message. Here A (which starts the session), establishes a new port (client port) for the UDP connection for video interchange. The same way, the camera also sets a new port (server port). As the server ports are not redirected in B, I am not able to receive anything.
I read that there is a possibility to used interleaved mode in order to use the same port used for RTSP messages (22554 in this case) for the video packets. But I do not know how to do this. For example, VLC tries the first option (new client-server ports) and as it does not work it successfuly setups another rtsp session with interleave mode.
I started working with this code (http://bit.ly/1Xvwqx9), which is based on Onvif libraries. But I cannot find anything regarding this aspect of interleaving.
Anyone can give me a hint?
Thanks and kind regards.
Finally I found the solution. It is important to set these aspects:
protocol = TransportProtocol.rtsp
MediaStreamInfo.Transport transp = MediaStreamInfo.Transport.Tcp;

Accuracy of remote IP address retrieved from packet

If it were possible to retrieve the remote IP from a packet received by my Apache2 server (through a custom plugin perhaps), would it always be guaranteed to be accurate? Or is this value as easy to spoof as the referrer header?
My intended use case is to rate-limit unauthenticated API calls.
If it's a TCP packet, then it'll be accurate as to the sending host. IPs in TCP packets cannot be spoofed unless you've got control of the routers involved. With spoofed source packets, only the initial SYN packet will come back, and then the SYN+ACK response from the server will go to the spoofed address, not wherever the forgery came from - e.g. you cannot do the full 3-way handshake unless you can control packet routing from the targetted machine.
UDP packets, on the other hand, can be trivially forged and you cannot trust anything about them.
As well, even simple things like proxy servers and NAT gateways can cloak the 'real' ip from where the packet originated. You'll get an IP, but it'll be the IP of the gateway/proxy, not the original machine.
It is not reliable. Not only because it can be spoofed, but also because a network element can make your server see a different IP address.
For example, it is very typical in a company to access the Internet through a proxy. Depending on the configuration, from your server point of view, all the different users come from the same IP address.
In any case is a filter you can use in many scenarios. For example, show a captcha when you detect too many login requests from the same IP address.
If your intention is to rate-limit invalid API calls you might want to consider using a service like spamhaus. They list IP's that are likely bots and probes. There are other companies and lists as well. But if your intention is to ever ID the 'bad guy' the source IP is very unlikely to be correct.

Regarding RTSP setup request

We are trying to build a SIP2RTSP gateway for one of our solutions, Where in one of SIP invite is converted to RTSP SETUP request to wowza media Server and then a PlayBack is played from the mediaServer to SipClient.
But when the setup request is sent the wowza is always binding to rtsp client address even though the destination is set in transport of SETUP request header. Here we want to tell the wowza rtsp server to bind to sip UA IP and not the rtsp client ip for the flow of RTP traffic.
RFC 2326 says
destination:
The address to which a stream will be sent. The client may
specify the multicast address with the destination parameter.
To avoid becoming the unwitting perpetrator of a remote-
controlled denial-of-service attack, a server SHOULD
authenticate the client and SHOULD log such attempts before
allowing the client to direct a media stream to an address not
chosen by the server. This is particularly important if RTSP
commands are issued via UDP, but implementations cannot rely
on TCP as reliable means of client identification by itself. A
server SHOULD not allow a client to direct media streams to an
address that differs from the address commands are coming
from.
here it also tells A
server SHOULD not allow a client to direct media streams to an
address that differs from the address commands are coming
from.
What is the use of destination field and how we can direct the media streams other than the RTSP client?
The point is that client MAY request the stream to be sent at client-chosen location. Still server should be doing this carefully, and take decision whether to allow an address which is different from RTSP client address or not using security consideration such as authentication availability etc. Because sending stream blindly to any given address, esp. via UDP, is unsafe: a malicious client might easily bring server down.
All in all, destination is where to send stream to. Servers do not guarantee that streams will be sent to locations other than RTSP client's.

remote dial using SIP client

I want to remote dial from my pc using a simple non SIP client program which I wrote and wchich sends commands to a proprietary SIP client that accepts remote commands via a TCP connection. The proprietary SIP client will then dial the remote party using my PC's IP and port number in SDP for RTP. Is this possible in principle? Are there any opensource clients available that use this concept? Is there any documentation (IETF RFCs, blogs etc) that is available.
Appreciate any help in this matter.
Check out pjsip, it's an open-source cross-platform SIP client for all major platforms and with API in C and an API wrapper for python, whichever you prefer. There are also examples on their site. Link your TCP parsing code to pjsip and call its functions to initiate a call, you can find how to do it on their site
If I understand correctly, here is what you want to do:
TCP SIP/SDP/RTP
PC <===> SIP client <===========> softswitch
Actually, TCP between PC and SIP client will probably be accurate for signalling but not for media as RTP media stream is often sent over UDP.
In my opinion, the first step is to make sure that your softswitch will accept sending RTP packets to an IP address which is not the same as SIP client (I think most of them refuse for security reasons). If it accepts and if you have no NAT between your SIP client and your PC, you should be able to send RTP stream directly to your PC. In this case, you have to retrieve RTP packets, eventually rearrange them, decompress their payload and feed them to your speakers.
If your softswitch does not want to send RTP packets to an IP address different from SIP IP address, then you have to forward your RTP packets from your SIP client to your PC. But if you can't modify your SIP client to do this (and it's probably the case as it's a proprietary software), you're probably stuck.
To test whether your softswitch accepts sending RTP packets to an unintended IP address, you can use sipp and specify a remote media ip address different from SIP signalling IP address.

Resources