In the process of testing my WebSocket proposal I discovered the CONNECT method has a major restriction. Most proxies disable CONNECT to anything but port 443.

The following is from "Squid and the Blowfish":
------------------
It is very important that you stop CONNECT type requests to non-SSL ports. The CONNECT method allows data transfer in any direction at any time, regardless of the transport protocol used. As a consequence, a malicious user could telnet(1) to a (very) badly configured proxy, enter something like:
... snip example ...
and end up connected to the remote server, as if the connection was originated by the proxy.
-------------------

I verified that Squid and all public proxies I tried disable CONNECT by default to non-SSL ports. It's unlikely many internet hosts will have 443 available for WebSockets if they also run a webserver. It could be done with virtual IPs or dedicated hosts but this imposes complex requirements and costs over alternatives like CGI.

The availability and capabilities of the OPTIONS and GET protocols also varied from proxy to proxy. The IETF draft related to TLS (http://tools.ietf.org/html/draft-ietf-tls-http-upgrade-05) has this to say:

-------------------
3.2 Mandatory Upgrade

  If an unsecured response would be unacceptable, a client MUST send
  an OPTIONS request first to complete the switch to TLS/1.0 (if
  possible).

         OPTIONS * HTTP/1.1
         Host: example.bank.com
         Upgrade: TLS/1.0
         Connection: Upgrade
-------------------

So according to this draft spec OPTIONS is the only way to do a *mandatory* upgrade of our connection. Once again this failed in testing

-------------------
=> OPTIONS * HTTP/1.1
=> Proxy-Connection: keep-alive
=> Connection: Upgrade
=> Upgrade: WebSocket/1.0
=> Host: warriorhut.org:8000
=>
<= HTTP/1.0 400 Bad Request
<= Server: squid/3.0.STABLE8
--------------------

Other proxies gave different errors or simply returned nothing. The problem may be related to the Upgrade and Connection headers rather than OPTIONS, since I had similar issues using Connection: Upgrade with GET.

I had the most success using GET without a Connection: Upgrade header. It seems that the proxy thinks the header is directed at it so it does not pass it on to the remote host. In many cases it will abort the connection. Using the Upgrade: header without Connection allows the Upgrade header through to the actual websocket service.

It seems to me that whatever we try in many cases the connection will be silently dropped by the proxy and the reasons will be unclear due to the lack of error handling. There seems to be a wide variation in proxy behaviour for uncommon operations. I suppose proxy developers could fix these issues but whether a significant rollout could be achieved before HTML5 is released is questionable.

Given that an asynchronous connection cannot be cached the only reasons remaining for going through a proxy are anonymity and firewall traversal. Automatically bypassing the users proxy configuration to solve the issues above has the potential to break both of these. It would be a significant breach of trust for a UA to bypass the users proxy and some networks only allow connections via a proxy (for security and monitoring).

It seems that we're stuck between a rock and hard place here. In light of this I reiterate my earlier suggestion that the time could be better spent providing guidelines for communication via an asynchronous CGI interface. This would allow reuse of existing port 80 and 443 web services which would resolve the cross-domain issues (the CGI can relay the actual service via a backend connection) and most of the proxy issues above (since proxy GET and CONNECT are more reliable on these ports).

Shannon

Reply via email to