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

BrowserStack configuration behind a proxy is not clear #16

Closed
lbod opened this issue Nov 5, 2014 · 24 comments
Closed

BrowserStack configuration behind a proxy is not clear #16

lbod opened this issue Nov 5, 2014 · 24 comments

Comments

@lbod
Copy link
Contributor

lbod commented Nov 5, 2014

I've asked on StackOverflow http://stackoverflow.com/questions/26681808/intern-2-configuration-for-browserstack-behind-a-proxy and on IRC.
Current documentation is not sufficient to understand what configuration to use when behind a proxy using BrowserStack. It's a common problem with proxies and IMO, is documented better in other libraries. If this isn't a bug a constructive criticism would be your documentation is incomplete.

Repeating the StackOverflow question:


I'm unsure what the configuration should be running intern 2 tests against BrowserStack when running behind a proxy/firewall and currently seeing errors/timeouts.

My Current configuration is:

proxyPort : 9000,
proxyUrl : 'http://localhost:9000',
tunnel : 'BrowserStackLocal',
tunnelOptions : {
username : 'myusername',
accessKey : 'myaccesskey',
hostname : '<myproxyip>',
proxy : 'http://<myproxyip>:<myproxyport>'
}
``` I don't think I need `hostname` however if I remove that I immediately see the error `getaddrinfo ENOTFOUND`. 

If use the above configuration it seems to get further, waits for a while then see: 

Listening on 0.0.0.0:9000
Starting tunnel...
BrowserStackLocal v3.3
Connecting to BrowserStack using WebSocket protocol...
Connected.
Ready
Error: [POST http://(redacted)@:4444/wd/hub/session] connect ETIMEDOUT
Error: connect ETIMEDOUT
at errnoException net.js:904:11
at Object.afterConnect [as oncomplete] net.js:895:19
FATAL ERROR
Error: [POST http://(redacted)@:4444/wd/hub/session] connect ETIMEDOUT
Error: connect ETIMEDOUT
at errnoException net.js:904:11
``` The [POST http://(redacted)@<myproxyip>:4444/wd/hub/session] url doesn't seem right. Obviously I have this misconfigured & would appreciate any advice. I do struggle to understand intern's documentation when running behind a proxy.

@lbod lbod changed the title BrowserStack behind a proxy BrowserStack configuration behind a proxy is not clear Nov 5, 2014
@lbod
Copy link
Contributor Author

lbod commented Nov 27, 2014

It'd be nice if someone acknowledged this issue. I aim to spend time next week debugging in that environment to identify if it is a config issue or a library issue

@neonstalwart
Copy link
Member

@lbod i might guess that nobody else has tried using using browserstack behind a proxy and may not be in a position to spend the time to setup an environment to try this so we are not able to acknowledge the issue. it looks like you may be breaking new ground so forge ahead and let us know what you find.

@lbod
Copy link
Contributor Author

lbod commented Dec 1, 2014

@neonstalwart I figured as much as no one else has reported this & there's been no meaningful replies on SO; it's fair to say there are no corporate users using intern against browserstack.

However, does that configuration above look correct?
I spent most of the day debugging this comparing against a standard wd.js test which works (https://www.browserstack.com/automate/node) and not made much headway. I suppose dojo/request/node is another layer in the way too; digdug may not be the place this issue belongs

I'll setup privoxy on my home laptop to try reproduce as I can't justify spending time on this at work

@neonstalwart
Copy link
Member

@lbod it doesn't quite look correct to me since i would assume that your proxy might need a username and password. all the proxy config is extracted from proxy : 'http://<myproxyip>:<myproxyport>' (see

if (this.proxy) {
var proxy = urlUtil.parse(this.proxy);
proxy.hostname && args.push('-proxyHost', proxy.hostname);
proxy.port && args.push('-proxyPort', proxy.port);
if (proxy.auth) {
var auth = proxy.auth.split(':');
args.push('-proxyUser', auth[0], '-proxyPass', auth[1]);
}
else {
proxy.username && args.push('-proxyUser', proxy.username);
proxy.password && args.push('-proxyPass', proxy.password);
}
}
for the relevant code) which means you are missing your username and password in that url (assuming they're needed).

my suggestion would be to initially cut out intern/digdug completely and just download the browserstack local executable yourself, figure out which arguments need to be passed to that executable in order for everything to work with the proxy, and then work backwards from there to figure out what you need in your tunnel config in order for _makeArgs to produce the same arguments to the executable. at that point, it still may not work but then you will have eliminated your config as the cause of the issue.

@lbod
Copy link
Contributor Author

lbod commented Dec 1, 2014

@neonstalwart thanks, at the moment we're whitelisting ip's, so no usr/pwd needed but I can add a dummy usr/pwd to make sure there's no funky logic relying on this.

I did see generated urls of the form http://"browserstack user name":"browserstack auth key"@hub.browserstack.com:4444/wd/hub/session in Server.createHttpRequest() which didn't look right., also tried adding the proxy to the kwArgs object in there.
I'll keep digging

@lbod
Copy link
Contributor Author

lbod commented Dec 2, 2014

I undid any hacks I'd made and checked makeArgs which is producing the correct arguments to start BrowserStackLocal (sniffing tcp traffic I see successful communication to and from hub.browserstack.com) however from somewhere I'm getting dns resolution issues for hub.browserstack.com. We can't resolve external DNS from our company PC's, however I'd expect those requests to be using the proxy. e.g. :

Error: [POST http://(redacted)@hub.browserstack.com:4444/wd/hub/session] getaddrinfo ENOTFOUND
Error: getaddrinfo ENOTFOUND
  at errnoException  <dns.js:37:11>
  at Object.onanswer [as oncomplete]  <dns.js:124:16>
FATAL ERROR

Error: [POST http://(redacted)@hub.browserstack.com:4444/wd/hub/session] getaddrinfo ENOTFOUND
Error: getaddrinfo ENOTFOUND
  at errnoException  <dns.js:37:11>
  at Object.onanswer [as oncomplete]  <dns.js:124:16>

@lbod
Copy link
Contributor Author

lbod commented Dec 4, 2014

@neonstalwart any advice on where I can stick some breakpoints to see where these requests are coming from to trace it back?
e.g. I found pathname: '/wd/hub/' but could only see a reference to that in https://github.com/theintern/digdug/blob/master/SauceLabsTunnel.js#L313

@lbod
Copy link
Contributor Author

lbod commented Jan 14, 2015

Just to note I believe dojo/request is the cause, I raised this https://bugs.dojotoolkit.org/ticket/18424 but not had any feedback.
I was able to get that example change working from home using my own proxy but haven't been able to do correctly with my corporate work proxy.

This is also relevant to #17

You could consider this as an upstream bug but seeing intern is part of the Dojo foundation it seems wise to keep both these issues open

@jason0x43
Copy link
Member

Any updates on this issue? Still relevant?

@lbod
Copy link
Contributor Author

lbod commented May 8, 2016

I suspect it's still relevant to others, not to me or the company I work for as we switched to other various testing libraries which didn't have this issue.
Thanks for the ping though it's way too late and just a cleanup of old issues.

@Rrrapture
Copy link

+1

It's an issue for me, unless there is something else interfering that I'm not aware of.

browser-stack-proxy-settings-external-link

@lbod
Copy link
Contributor Author

lbod commented Sep 18, 2018

Hi @jason0x43 ! Crazy I opened this 4 years ago, sorry if this is a long one..
I had a try again through our proxies the last week as we're evaluating some testing libraries for a new project.

I tried out the typescript/backbone example, upgraded to the latest to make sure and as I suspected it still didn't support CONNECT tunnelling proxies. Intern/dojo's changed a lot since I last looked so there was a bit of digging around first and getting support from the network team in work. dojo's node.js provider just doesn't support it.

Eventually I hacked something working and wanted your thoughts the best way to do this. I used https://www.npmjs.com/package/global-tunnel-ng and loaded it as a plugin to see if I could bootstrap the process. Something like :

    "browser": {
        "loader": "systemjs",
        "plugins": { "script": "src/config.js", "useLoader": true }
    },
    "node": {
        "plugins": {"script" : "src_node/global-tunnel.js"}
    }

In that plugin I added the initialise script, something like:

var tunnel = require('global-tunnel-ng');
tunnel.initialize({
    host: 'xxx.xxx.xxx.xxx',
    port: xxxx,
    connect: "both",
    protocol: "http:"
});
module.exports = tunnel;

It got further, (can't remember if it was a 4xx or a 5xx and if it was the BS local binary trying to download) but I still had the proxy config in the tunnel config in intern.json.

Removed that and the next error was the browserstack local tunnel binary args (because I'd removed the tunnel proxy property). So I hacked node_modules and just hardcoded the proxy at https://github.com/theintern/digdug/blob/master/src/BrowserStackTunnel.ts#L174

Hey presto, connectivity and the full local unit/functional suite ran. I didn't have time to debug and will look tomorrow why the difference.

Any thoughts on how I could inject that proxy config just for the BS local binary? I was sure there's another issue about the same thing.
I still think there's mileage in it before I discount it as something we use, I also realise I need to understand the new architecture more and maybe loaders but it seems we're not far from it working.


I could try and contribute something back on this as I've learned a bit more about how the hop-by-hop goes. I wouldn't want to be just copying code from that global-tunnel-ng library though but this is an upstream dependency issue with dojo. It might be nice to be able to swap out that request provider dependency to another.

@jason0x43
Copy link
Member

Hi! Wow, yeah, this one's been around for a while. :)

What did your working BS tunnel end up looking like? If we can figure out specifically what handles the problem, we can see about making it a general option for tunnels.

Also, have you tried the newest Dig Dug yet? We removed all the @dojo dependencies from Intern and its projects because they were causing frequent typing issues with Dojo itself (which uses Intern for testing). The current release uses request from @theintern/common, which uses axios behind the scenes. We haven't really exercised its proxying capabilities much yet, but it may behave a bit better.

@lbod
Copy link
Contributor Author

lbod commented Sep 18, 2018

Quick reply thanks!

What did your working BS tunnel end up looking like?

It was just removing the proxy property

configs : {
  "bsproxy" : {
    "tunnel" : "browserstack",
     "environments" : {
           "browserName" : "chrome"            
      }
  }

Also, have you tried the newest Dig Dug yet?

Maybe I'm not understanding, I had seen the references to axios and seen the TS docs that say it mirrors dojo's request API. At first look it it also seemed to have the same lack of support.

But.. Dig Dug is a dependency of intern and I'm using 4.2.4, so Dig Dug is 2.1.2.

@lbod
Copy link
Contributor Author

lbod commented Sep 19, 2018

Hi @jason0x43 I wasn't sure if I was to get back to you with more info?

https://github.com/theintern/digdug/blob/master/src/Tunnel.ts#L441 the "bsproxy" config I have above won't have that proxy config as it's removed. The binary binary process is spawned with the tunnel args and obviously not going to be bootstrapped with the node.js http/https API global either (from global-tunnel-ng).

So at the moment I need to be able to separately set the binary proxy arguments. The browserstack binary client can obviously work with CONNECT proxies.

Me hardcoding the proxy args into the node_modules package JS (BrowserStackTunnel.js) looked like

    if (this.proxy) {
      const proxy = parseUrl(this.proxy);

      proxy.hostname && args.push('-proxyHost', proxy.hostname);
      proxy.port && args.push('-proxyPort', proxy.port);

      if (proxy.auth) {
        const auth = proxy.auth.split(':');
        args.push('-proxyUser', auth[0], '-proxyPass', auth[1]);
      }
      /*else {
				proxy.username && args.push('-proxyUser', proxy.username);
				proxy.password && args.push('-proxyPass', proxy.password);
			}*/
    }
    // ME HARDCODING
    args.push('-proxyHost', "http://xxx.xxx.xxx.xxx");
    args.push('-proxyPort', 8080)

Does that make sense?

@jason0x43
Copy link
Member

Hmmm..I'm not sure I understand the core issue.

There are at least two network connections involved with Dig Dug tunnels -- Dig Dug has to connect to a server to download the tunnel binary, and the tunnel binary needs to connect to a remote server. Dig Dug assumes that if a proxy is required, both of these connections will use it for outgoing connections.

In your fix above, it looks like you're overriding the proxy config that's passed to the BS executable. Is the issue that the BS executable needs to use a different proxy than the one Dig Dug uses to download the executable (maybe Dig Dug doesn't need one but BS does?), or that the existing proxy config isn't being passed properly to the BS executable, or something else entirely?

@lbod
Copy link
Contributor Author

lbod commented Oct 12, 2018

Yes, sorry it looks like I'm not explaining this well at all.

Effectively I want to separately configure proxy args for the BS executable.

Because I'm bootstrapping in this global-tunnel-ng module (and setting proxy configuration there) I don't need any Tunnel configuration set for proxy. However I do still need those arguments to be set on the BS executable.


I have no idea if global-tunnel-ng is even a good idea, I want to drive a large suite of tests through it to see if there's any weird stuff, latency etc. However it is the only option we have behind a CONNECT tunneling proxy server because dojo's request/node or axios doesn't support it.

@jason0x43
Copy link
Member

Ok. What if we add a a tunnelProxy option to the tunnel options that will apply to the tunnel executable specifically. So, from intern you'd end up doing something like:

{
  "tunnelOptions": {
    "tunnelProxy": "http://xxx.xxx.xxx.xxx:8080"
  }
}

The tunnel classes can then use tunnelProxy if it exists and fallback to proxy by default. Setting tunnelProxy to null could disable the proxy for the tunnel while allowing it to be used by dig dug, if necessary.

@lbod
Copy link
Contributor Author

lbod commented Oct 12, 2018

Yes that's perfect. Thanks!

Do you want me to PR it if it saves you time? You said you were busy and I completely understand that

@jason0x43
Copy link
Member

Go ahead and PR it.

@lbod
Copy link
Contributor Author

lbod commented Oct 18, 2018

Hi @jason0x43 I've been away from work the last week but made the change locally. Will be able to test when I get back, however..
I'm uncomfortable adding this for all tunnels because I won't be able to test them and also because the other tunnels are very much different.

It makes sense to only add a property to the BrowserStackTunnel? (though I do understand that's not ideal).
#65 is possibly asking a similar thing for the selenium tunnel, if they could confirm it's a connect proxy in use then maybe this workaround will work for them if they were willing to commit/test too.

@jason0x43
Copy link
Member

I'm not sure #65 is related to this issue; in that case, Dig Dug is unable to download files through a proxy, implying the base proxy property isn't working at all. In your case you need the regular tunnel downloads and the BrowserStack tunnel executable to use different proxy settings.

Regarding adding the setting for all tunnels, the idea would be to add the tunnelProxy setting to Tunnel.ts, and update tunnels to actually use it separately. So for now, only BrowserStackTunnel would actually use the setting; the other tunnel classes would simply ignore it.

@lbod
Copy link
Contributor Author

lbod commented Nov 1, 2018

@jason0x43 apologies for my delay. It's a tiny commit but had to keep back and forth testing at work and then was lazy.
Originally I thought the doc should remain in the browserstack api properties as it would seem misleading to others but I've added as you asked.

jason0x43 pushed a commit that referenced this issue Nov 12, 2018
@jason0x43
Copy link
Member

Closing this as resolved by f504f84

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

4 participants