views:

460

answers:

2

I've got a simple Flash client connecting to a Flash Media Server, and I'd like to be able to simulate the client doing the following:

  • Attempting to connect to an RTMP stream on port 1935 and failing,
  • Falling back to RTMP on port 443 and failing,
  • Falling back to RTMP on port 80 and failing, and ultimately
  • Falling back to RTMPT (HTTP) over port 80 and succeeding.

This is supposed to be the default behavior of the Flash player, for example as described here:

In many cases, this is all you need to get past many firewalls without even using HTTP tunneling. This works because of a feature built into the NetConnection object. When you do not specify a port number in an RTMP address, Macromedia Flash will attempt to connect to port 1935. If it fails it will then try to connect to port 443; if that fails, it will try port 80. So no coding is required to access ports 1935, 443, or port 80 if you do not specify a port in the RTMP address.

And here:

When connecting to FMS you'll use a netConnection object on the client side, within the parameters of the connect method you can set what protocol you want to use: nc.connect("rtmp://whatever"). If you do that it should be noted that the flash player will cycle through different ports and protocols trying to connect up automatically. Of course you can set which protocol you want to use by changing the rtmp part. The Flash player will try connecting to rtmp over port 1935, then port 80, then it'll try rtmpt (covered below) over port 80.

I'm on a Windows 7 machine, and essentially I'm looking for tips as to how I can simulate an environment in which Flash fails to connect to an RTMP stream on any port and falls back to RTMPT. Windows Firewall seems to allow for setting a "protocol number" (in addition to the usual port number -- e.g., TCP is 6, UDP 17, etc.), but I can't seem to find a protocol number for RTMP.

If anyone has any suggestions as to how I can simulate this behavior simply, I'd hugely appreciate it. Many thanks in advance.

A: 

RTMP is built on top of TCP, so you should be able to pick TCP and the corresponding port to use your firewall to test.

You'll want to create one custom rule for each port.

name: RTMP Default (1935)
protocol: TCP
local port: any
remote port: 1935
local ip: any
remote ip: any

name: RTMP over 443
protocol: TCP
local port: any
remote port: 443
local ip: any
remote ip: any

name: RTMP over 80
protocol: TCP
local port: any
remote port: 80
local ip: any
remote ip: any

Then set the RTMP Default rule to block all traffic, but set the others to allow. Then test and ensure it fails over to port 443. Then set the RTMP over 443 rule to block, and ensure it fails over to port 80.

Marcus Adams
Ah, sorry, yes that's true -- but I want to allow TCP, since I want the RTMPT fallback to succeed.
Christian Nunciato
@Christian, I updated my answer with more details. You don't block all of TCP, just for specific ports.
Marcus Adams
Hey Marcus -- thanks. I'm not sure that'll work (correct me if I'm wrong); what I want to set up is essentially this: disable tcp to remote port 1935, disable tcp to remote port 443, and disable tcp to remote port 80 *unless the request is HTTP or RTMPT*. That last clause is really what I need to figure out, ideally with Windows Firewall (or some other software firewall, such that this is doable easily on a single Windows machine).
Christian Nunciato
@Christian, I thought this was just for testing. You can put the port in whatever state you want at any time you want. You shouldn't need to do packet inspection.
Marcus Adams
@Marcus It is for testing, yeah. The trouble here is that the port I want to block (for RTMP) is port 80 -- but I need simultaneously to enable traffic to port 80 for RTMPT. Windows Firewall only provides control at the protocol:port level, which is "tcp:80" in both cases. Hopefully that makes sense.
Christian Nunciato
A: 

You will have to use an HTTP proxy server intermediary which will throw an HTTP error for invalid requests. I'm not sure how the RTMP protocol does this, but I suspect you may be erroneous in claiming that it tries RTMP over port 80 and then falls back to RTMPT on the same port. That really wouldn't make a whole lot of sense. BUT - IF this is actually the case, which personally I find highly unlikely and I personally would never design a protocol to use two different formats on the same port, THEN you would need to have an intermediary such as an HTTP proxy server which is the only realistic way I could see this happening in practice.

Drew
Ok I went ahead and looked up the RTMP spechttp://kb2.adobe.com/cps/166/tn_16631.htmlI was right of course. The flash client does NOT in fact do what you claim. It does not attempt to connect via RTMP over port 80 then fallback to RTMPT over the same port. In fact, it does not even try three connection attempts as you claim, it only makes up to two attempts. It first attempts to connect via RTMP over port 1935, and if that fails, then it attempts RTMPT over port 80.
Drew
My tests in practice confirm this behaviour, though common sense dictates it as well.
Drew
Actually an HTTP proxy (Apache, in this case) proxies RTMP without a problem -- try it yourself and you'll see. Using Apache as a *reverse* proxy, though, does fail to proxy RTMP. Maybe that's what you meant.The article you cite is almost six years old, and in fact the current player does precisely what I describe, as our tests have revealed. If you're on Windows, a simple way to simulate the first three fallbacks is simply to block outbound ports 1935 and 443 over TCP. That's a no-brainer, and works every time. The problem, as I describe, is testing the fallback to RTMPT/80. [...]
Christian Nunciato
I'd like to know what your "tests in practice" were, if you wouldn't mind sharing. (Mine are encapsulated in a Wireshark dump obtained after simply blocking all outbound TCP traffic, which I'd be happy to send along if you like.) As for common sense, I'm not sure why it's so difficult to comprehend two methods of servicing requests over a single port; FMS simply listens on port 80, and when it gets an RTMP header, it responds accordingly; for HTTP, it responds in HTTP. Again, our tests confirm this, and it's in keeping with the Adobe documentation I cite in my post.
Christian Nunciato
In the end, we decided not to rely on the player's automatic-fallback functionality (after confirming it), since when it does fall back, it does so silently, and we decided it's more useful to know which port/protocol combinations succeed for our users, rather than relying on the fallback path for every request.
Christian Nunciato