I'm trying to have WebRTC media over TCP with a gateway in between but I'm having some interesting issues on the ICE connection phase. Before further advances, it's important to know that I have the same setup for UDP and everything works correctly.
In the gateway we modify the remote answer SDP to include a single TCP candidate (the media port is also modified to include the same port):
a=candidate:1 1 tcp 1 <gw_ip> <gw_port> typ host tcptype passive generation 0
Also I'm sending the attribute setup as passive:
a=setup:passive
Seconds after applying the remote description on Chrome, I'm receiving a STUN BIND request on the gateway which I'm answering with a Bind Success response (I've checked both Transaction ID and Message Integrity and they seem fine).
After this chrome simple doesn't continue the ICE checking (neither DTLS messages). I've enabled chrome logs to see if some error was happening and I've found an interesting output:
"Ignoring STUN binding response message on shared socket"
I've taken a look at chromium source code and it seems this is being shown because chrome is using a shared socket but I cannot understand it's reason.
Any ideas? Thanks!
After a deep investigation I've found out that the TCP stream wasn't being parsed correctly on the gateway side.
This stream in specific, uses a length framing mechanism that wasn't being applied on the inbound/outbound data, therefore provoking several issues on the process pipeline.
Refer to rfc5389 for more information regarding the framing mechanism:
https://www.rfc-editor.org/rfc/rfc5389
Related
Error:
The client needs a new connection for this request as the requested host name does not match the Server Name Indication (SNI) in use for this connection.
I recently purchased a EV SSL certificate from Comodo, installed it on my VPS (cPanel/WHM) and everything worked great. I then upgraded to http2 and am now receiving the error when switching between each website on the certificate. The 3 websites share the same IP address. From what I can tell, this may be the issue. I do not want to reissue a SSL cert for each domain as I paid for the EV multi domain cert. Is the answer to purchase 2 additional IPs and make sure each domain has its own IP? Or is there a way I can edit the virtual hosts so that I can maintain the same setup I have now?
I should mention, this is only happening on Safari, not chrome.
SSL Labs Report
https://www.ssllabs.com/ssltest/analyze.html?d=www.deschutesdesigngroup.com&s=142.4.0.142&hideResults=on
EasyApache HTTP vhost configuration
https://pastebin.com/dNeFRGWJ
EasyApache HTTPS vhost configuration
https://pastebin.com/vgWAD5mg
You have enabled HTTP/2 on only two of the three sites.
HTTP/2 will try to reuse the connection for multiple domains if both the IP address matches and the certificate covers all the necessary domains. This is the case here and so HTTP/2 is reused.
However if you run SSLLabs on all three domains you see a slight difference in the protocol used for Chrome (for example):
Chrome 70 / Win 10 RSA 2048 (SHA256) TLS 1.2 > h2
Chrome 70 / Win 10 RSA 2048 (SHA256) TLS 1.2 > http/1.1
Chrome 70 / Win 10 RSA 2048 (SHA256) TLS 1.2 > h2
And similarly further down in the ALPN setting:
ALPN Yes h2 http/1.1
ALPN Yes http/1.1
ALPN Yes h2 http/1.1
So going to the middle domain first will work as it will connect via HTTP/1.1 and so not reuse the connection. However going to the middle domain after initiating a request to either the first or last domain will attempt to reuse the HTTP/2 connection and fail as the middle domain doesn't support HTTP/2.
Web servers should return a 421 Misdirected Request status code for any requests when the browser attempts to reuse the connection when it shouldn't, to say "Yeah you really shouldn't be attempting to reuse the connection here! Can you try again on another connection please?". The same thing happens if there are different SSL/TLS setup (e.g. the cipher suite used for the connection is not accepted on the other domain).
Chrome and Firefox correctly handle the 421 response and transparently resend the requests over a new connection, which in this case then uses HTTP/1.1 (check out developer tools in the browser and you'll see this is true). Other browsers, including Safari used by iOS, have not implemented support of the relatively new 421 status code yet and so fail with an error like below:
Misdirected Request
The client needs a new connection for this request as the requested
host name does not match the Server Name Indication (SNI) in use for
this connection.
I presume there is no reason not to enable HTTP/2 on all domains and this was a misconfiguration error? If so enable HTTP/2 in all domains and your issue should be sorted.
If you do not want HTTP/2 on all domains, then you ensure the browser doesn't think it can reuse the connection. That means either using a separate IP address for that domain, or getting the certificate reissued for only two domains, and a separate certificate for the other than shouldn't share connections.
WebRTC comes essentially in 3 flavors depending on the network situation:
No NAT - session is peer to peer
NAT - session uses STUN but is eventually peer to peer for the media
NAT+Firewall: in which case session is not peer to peer and media goes through a TURN server.
Is there a way/tool to figure out for an existing live session if it is using a TURN server or if it's peer to peer?
I am using chrome. If a tool exists for other browsers I am happy to know about it as well.
Thx
this pull request for the webrtc samples makes the constraints/getStats sample show the ip address. Instead of the local and remote ip around here you want the candidateType property.
If either of them is "relay" you are using a turn server. If both are "host" this is a direct connection without NAT. For all other cases NAT is used.
Note that this sample is currently a bit of a mess since the getStats API changed a bit.
I'm a bit confused about HTML5 Websockets. I've looked at numerous tutorials out there and a lot of them have different variations of connecting using different ports. What do these ports mean?
Adobe for instance, uses this:
new WebSocket('ws://localhost:1740');
Then another tutorial has this where no ports are required:
new WebSocket("ws://www.websockets.org");
And finally a third tutorial has a port, but it's completely different:
new WebSocket("ws://localhost:8080/echo");
My question would be, why do these vary? How do I know which ports to connect to? Also, I've attempted to do my own connection:
var ws = new WebSocket("ws://test.ontarget-network.com/");
But I get the following error: Unexpected response code: 200
I've tested around and tried connecting to various other "ports" (not knowing what I'm doing obviously, typing in random numbers) and this error would disappear, however, my code
ws.onopen = function(){
alert("Connection Established");
};
would not execute.
I'm trying to fully understand HTML5's Websockets API so I can experiment and create more dynamic applications. Thanks for the help.
The server should have an endpoint that accepts WebSocket connections. So, if that endpoint is /echo you would want to connect to:
ws://localhost:8080/echo/websocket
You will get the Unexpected response code: 200 error if you exclude the /websocket suffix after the endpoint. I was having the same confusion and this link cleared things up a bit for me.
The following comes from the latest WebSocket draft:
By default the WebSocket protocol uses port 80 for regular WebSocket
connections and port 443 for WebSocket connections tunneled over TLS
[RFC2818].
Really though, you should be able to use any valid port not in use. As long as clients are trying to connect to the same port that the server-side script opens for the socket connection, you should be fine.
A quick note on ports:
Port 80 is the HTTP port.
Port 8080 is the alternate HTTP port.
Port 443 is the HTTPS (i.e., HTTP with TLS) port.
Port 1740 in the Adobe code seems like some random port not already in use by other services.
For a full list of preset ports, please see the following:
http://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers
As for your "Unexpected response code: 200" error, I'm guessing that the WebSocket URL you're using on the client side is not pointing to a valid server-side script, but that's hard to comment on without more info.
I had the same issue, But to survive with
Unexpected response code: 200
You need to have either server-side script to handle the web socket, or you can use Node.js to build a you server script.
for the sake of education you can try to biuld your own websocket sever script.
Actually there is something else... You can not open a connection to every port since there is a list of blocked ports in every browser. I remember seeing the full list of ports in 'The tangled Web' from Michal Zalewski; however, I think a quick google will show this also.
I already have a server with port and want to write a web app to get the information form the port. Will this be possible with WebPorts?
The Client doesn't even need to talk back to the server, which is the whole point of websockets I would imagine, but since I already have the ports setup, I might be easier and cleaner to just connect and get the info without having to refresh.
WebSockets are not intended as clear TCP channels over which other existing protocols can be implemented.
WebSockets are designed to allow messages to be sent between a client and server, where an event is raised each time a message is received.
Hence a WebSocket client cannot simply connect to an existing TCP server - that server also has to speak the WebSocket protocol.
You could of course write a WebSocket-based server that does nothing but act as a proxy to existing network services.
I think you want websockify which is a WebSocket to plain TCP socket bridge/proxy. It also allows sending and receiving of binary data with the older version of the WebSocket protocol which hadn't yet added direct binary data support.
Disclaimer: I created websockify.
I have a testapp consisting of an HTML5/WebSocket client and an HTTP/WS server. Both servers are in C#; the HTTP server is my own simple thing and the WS server is also homebrew based on concepts from http://nugget.codeplex.com/. HTTP server is listening on 0.0.0.0:5959 and WS server on 0.0.0.0:5960 (accept connections from any client, but on different ports).
My index.html includes some JavaScript that opens a WebSocket to 'ws://'+document.location.hostname+':5960/' (that is, to the same IP address that the webpage came from, but on port 5960). The WS server sends sample data every 100ms. All in all, it's a pretty straightforward demo.
I'm using Chrome 12.0 on Windows7.
I've found that the HTTP server works from any client, either a browser on my machine pointed to 127.0.0.1:5959 or localhost:5959, AND it works when any machine (mine or a remote machine... "remote" being a different PC on my desk :) hits my server machine's work-internal 10-net address 10.122.0.159:5959. Everything works as expected in HTTP land.
However, the WebSocket only works on 127.0.0.1 and localhost; remote machines can successfully fetch HTML from 10.122.0.159:5959 but the WebSocket will NOT connect to 10.122.0.159:5960. In fact, when I point my local browser to it's own 10-net address (10.122.0.159:5959) I get the same result - HTML loads but WebSocket does not connect.
Any ideas as to why this might be happening?
Does CORS require that the WS be using the same port as the HTTP request originated from? If so, is there a special exception to the rule for 127.0.0.1?
Many thanks,
-Dave
Update
It seems to be caused by a proxy server blocking ws:// requests. Our company employs a proxy server for content filtering and all the usual stuff, and our browsers are configured to use it.Chrome uses IE's proxy settings, and IE's default settings are for localhost to not use a proxy server. When I check the box to have local connections also use the proxy server, my ws:// requests to localhost get blocked. Conversely, when I uncheck the "use proxy server" box my server does rx the WS request. Similarly with the remote machine, if I turn off the proxy on the remote machine my server does rx the ws:// request.
So it's a proxy thing, not a CORS or socket thing, and now I'm off to explore proxy settings with our IT folks.
There is no WebSocket limitation on cross-origin except what is governed by the CORS security in the handshake.
It sounds like something is wrong with your WebSocket server and it is only listening on localhost for connections. I would add some debug output to the OnClientConnect routine in Nugget (WebSocketServer.cs) so you can see when socket connections happen. If you really think it isn't a problem with the server then I would suggest using wireshark and comparing the localhost connection to the remote connection.
Also, if you are using the SilverLight WebSocket prototype (README) in IE 9, then you are restricted to ports 4502-4534 for WebSocket connections. It's possible that for localhost this restriction is lifted.
It is/was indeed a proxy thing.
Rather than asking our IT folks to make changes (good luck with that, eh?) I simply turned off proxy for 10.122.0.159 ([Howto for IE/Chrome][1]). I briefly experimented with turning it off for the ws:// protocol but couldn't get it to work, so for now just opening that one IP address does the trick.