Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Investigation about SocketRocket Proxy support #346

Closed
madlymad opened this issue Apr 12, 2016 · 1 comment
Closed

Investigation about SocketRocket Proxy support #346

madlymad opened this issue Apr 12, 2016 · 1 comment

Comments

@madlymad
Copy link

I've done some investigation regarding the support of the WebSocket connection behind proxies. As I haven't managed to make it work and I run out of time I feel that sharing my findings will help someone else to take over with better results.

1: SOCKS proxy "easily" applied when available.

I have managed to connect the socket successfully by using the following code in the _initializeStreams

CFDictionaryRef proxyDict = CFNetworkCopySystemProxySettings();
CFMutableDictionaryRef socksConfig = CFDictionaryCreateMutableCopy(NULL, 0, proxyDict);
CFDictionarySetValue(socksConfig, kCFStreamPropertySOCKSVersion, kCFStreamSocketSOCKSVersion5);
CFDictionarySetValue(socksConfig, kCFStreamPropertySOCKSProxyHost, (CFStringRef)@"172.0.0.1");
CFDictionarySetValue(socksConfig, kCFStreamPropertySOCKSProxyPort, (__bridge CFNumberRef)[NSNumber numberWithInteger:8889]);
CFDictionarySetValue(socksConfig, NSStreamSOCKSProxyUserKey, (CFStringRef)@"proxy-username");
CFDictionarySetValue(socksConfig, NSStreamSOCKSProxyPasswordKey, (CFStringRef)@"proxy-password");

Sadly this method can only work if there is a SOCKS proxy available and not apply for the HTTP proxies.
Trying to use kCFStreamPropertyHTTPProxyHost, kCFStreamPropertyHTTPProxyHost, kCFStreamPropertyHTTPProxy the same way they seem to be ignored by the CFReadStreamRef and CFWriteStreamRef.

2: Regarding HTTP Proxy, there seem to be a workaround to tunnel the socket connection after the proxy handshake.

According to SO post and a java library that works for proxy connections.
The logic that should be used in this case is:

-open a socket to the proxy (host, port)
-send text to the proxy with basic header 
  ....CONNECT remote.internethost.com:1494 HTTP/1.0
  ....User-Agent: Java Proxy Socket version 1.0a
  ....Host: remote.internethost.com
  ....Proxy-Authorization: Basic YourBase64usernamePasswordIfRequired
-then, the proxy will return a http status code (multiline text string) and the actual socket (if successful)
-this is this socket that needs to be returned to the connection object

In order to try this approach I changed the

  1. CFStreamCreatePairWithSocketToHost to performed on the proxy address, and not to the WebSocket url, port.
  2. Then in safeHandleEvent case of NSStreamEventOpenCompleted I added my code (snippet bellow).
  3. The code is equivalent to didConnect with only the request change to CONNECT and the missing headers as bellow.
// safeHandleEvent @ case NSStreamEventOpenCompleted
if (proxy_exists && aStream == _outputStream) {
    CFHTTPMessageRef request = CFHTTPMessageCreateRequest(NULL, CFSTR("CONNECT"), (__bridge CFURLRef)_url, kCFHTTPVersion1_1);

    // Set host first so it defaults
    CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Host"), (__bridge CFStringRef)(_url.port ? [NSString stringWithFormat:@"%@:%@", _url.host, _url.port] : _url.host));
    CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Proxy-Connection"), CFSTR("Keep-Alive"));
    // ...
    // everything else is the same as didConnect method simply copy them...
    // ...
}

Here the problem is that I get a CFNetwork SSLHandshake failed (-9847) which imply that I am missing some logic in the SSL handling but I cannot what. The fact that I copied the code of didConnect made me believe that this should not happen.

I created this new issue because it is more concerned about the actual implementation than the feature requests of #344 and #114 . Please share any ideas or questions in order to workaround the problem.

Sorry, for the long post.

@Cloudef
Copy link

Cloudef commented Nov 28, 2016

acmacalister/jetfire#49 Here is something dirty I did to include basic proxy support in JFRWebSocket, it does support TLS/SSL handover, as long as it's made sure stream contains no more incoming or outgoing data when applying the new TLS/SSL settings to socket.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants