Skip to content

Conversation

townsend2010
Copy link
Contributor

Fixes #885


This was tricky to test. I had to create an Ubuntu VM using Hyper-V and then in the VM, install squid and set it up. Then I would set the http_proxy environment variable before running multipassd.

Also, after trying this and manually testing various failure scenarios, I have found the URLDownloader class, CommonVMImageHost and its derived classes, and the daemon need some pretty major refactoring to better handle long running network operations like when a host is unreachable and to also better getting these issues back to the user.

That said, this PR is only for getting the proxy values, but does nothing for failure scenarios. That will come with a follow up PR.

@multipass-ci-bot

This comment has been minimized.

@codecov
Copy link

codecov bot commented Feb 10, 2020

Codecov Report

Merging #1348 into master will increase coverage by 0.05%.
The diff coverage is 95.65%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #1348      +/-   ##
==========================================
+ Coverage   73.16%   73.21%   +0.05%     
==========================================
  Files         208      208              
  Lines        7531     7550      +19     
==========================================
+ Hits         5510     5528      +18     
- Misses       2021     2022       +1
Impacted Files Coverage Δ
src/daemon/daemon_config.h 100% <ø> (ø) ⬆️
src/daemon/daemon_config.cpp 59.45% <100%> (+12.09%) ⬆️
src/network/url_downloader.cpp 55.17% <50%> (-0.1%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 9125a51...a4883b6. Read the comment docs.

Copy link
Collaborator

@ricab ricab left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @townsend2010, proxy support will be crucial for a lot of people, so this is very useful. I have some questions and concerns though. Some of them inline, general ones here:

  • Shouldn't multipass look at other variables affecting this, like https_proxy, no_proxy, or all_proxy?
  • How do instances get to go through the proxy? Does that somehow happen transparently? Would the user have to set the proxy manually inside the instances, or should multipass be responsible for "forwarding" that configuration? I am not say multipass should do it, just raising the question.
    • There is also ftp_proxy, but that could only be needed by the instances, so that is ok if we don't forward anything.
  • do we have any local connections that could be inadvertently affected by application-level proxy?

{
if (!http_proxy.startsWith("http://"))
{
http_proxy.prepend("http://");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if it is socks5://?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SOCKS support can come later. If a system level SOCKS proxy is set, Qt will automatically pick it up anyways.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My point is that passing http://socks://blah to Qt doesn't seem right, even if we don't have specific support for SOCKS. Perhaps this could be checked for a "://" sub-string instead. Otherwise, maybe it is preferable to require the protocol to be part of the env var.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An env var defined as http_proxy=socks://blah is not a valid proxy and would break things regardless of how we are parsing this. This is for doing something like the following:

http_proxy=192.168.1.3:3128 and then adding http:// to the beginning of the IP address (or host name if it's given) so we can then pass a valid URL to QUrl.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure I follow, http_proxy=socks5://something is normally correct, does Qt not like that?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, ok, I see what you mean. Sure, I should just check to make sure like you mentioned previously.

return reply->readAll();
}

std::unique_ptr<QNetworkProxy> discover_http_proxy()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't this unit deserve tests?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I gave this quite a bit of thought and we would basically have to get into the business of mocking a proxy somehow. And that I don't think is worth the effort for something like this.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking something much more superficial, like just checking whether or not the application had a QNetworkProxy proxy registered with the right url and data, depending on whether/how http_proxy was defined. No proxy mocking should be required for that (?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I added a unit test. Even after implementing the test, it still seems it's mainly testing QNetworkProxy, but it was easy enough to add, so it should be good.

@townsend2010
Copy link
Contributor Author

Hey @ricab,

Shouldn't multipass look at other variables affecting this, like https_proxy, no_proxy, or all_proxy?

No, it's not necessary for Qt when setting a proxy. You're basically telling Qt the address, port, username, and password of a proxy, the protocol is not important for that.

How do instances get to go through the proxy? Does that somehow happen transparently? Would the user have to set the proxy manually inside the instances, or should multipass be responsible for "forwarding" that configuration? I am not say multipass should do it, just raising the question.

This is not intended for instances at all. It's only for allowing multipassd itself to reach the network resources it needs such as SimpleStreams manifests, images, multipass version info on github, etc. Poking it through to instances can be an enhancement we add later, but definitely not now. The user will still need to provision proxy support for their instances, but cloud-init makes that easy.

do we have any local connections that could be inadvertently affected by application-level proxy?

This is only for Qt network access. We don't use Qt for local connections.

@townsend2010
Copy link
Contributor Author

I will also add, this PR is very focused on addressing basically two things. First, this is the only way (besides popping up a window to ask for credentials) for Qt to add proxy authorization. Qt will not pick up credentials automatically via a system proxy, so the http_proxy env var is the defacto way of doing this.

The second thing it addresses is when a user sets a local http_proxy env var for a per application proxy set up.

Based on review feedback, it makes more sense to put the proxy discovery into the DaemonConfig
code.
@multipass-ci-bot

This comment has been minimized.

@ricab
Copy link
Collaborator

ricab commented Feb 11, 2020

Hi @townsend2010, thank you for the explanations.

No, it's not necessary for Qt when setting a proxy.

Sure, it is not needed, but a user that sees multipass understanding one of those may expect it to react to the others too. For instance, if /etc/environment defines both http_proxy and no_proxy, multipass will honor the first but not the second. I guess we can live with that, but I'd prefer if it was documented. For extra clarity, perhaps even a warning saying they're ignored, WDYT?

This is not intended for instances at all.

OK, I was wondering if our proxy support would feel coherent without that. But yeah, I understand it is workable without that and any such addition can be separate.

This is only for Qt network access. We don't use Qt for local connections.

Ack.

@multipass-ci-bot

This comment has been minimized.

@townsend2010 townsend2010 changed the title url_downloader: Detect proxy env var and use it if found daemon_config: Detect proxy env var and use it if found Feb 11, 2020
@multipass-ci-bot
Copy link
Collaborator

Snap build available: snap refresh multipass --channel edge/pr1348

Copy link
Collaborator

@ricab ricab left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bors r+

bors bot added a commit that referenced this pull request Feb 11, 2020
1348: daemon_config: Detect proxy env var and use it if found r=ricab a=townsend2010

Fixes #885



Co-authored-by: Chris Townsend <[email protected]>
@bors
Copy link
Contributor

bors bot commented Feb 11, 2020

Build failed

@townsend2010
Copy link
Contributor Author

Ugh

bors r=ricab

bors bot added a commit that referenced this pull request Feb 11, 2020
1348: daemon_config: Detect proxy env var and use it if found r=ricab a=townsend2010

Fixes #885



Co-authored-by: Chris Townsend <[email protected]>
@bors
Copy link
Contributor

bors bot commented Feb 11, 2020

Build succeeded

@bors bors bot merged commit a4883b6 into master Feb 11, 2020
@bors bors bot deleted the detect-and-use-proxy branch February 11, 2020 20:10
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

Successfully merging this pull request may close these issues.

Multipass on windows does not use system proxy and no option to manually configure proxy
3 participants