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

Use behind a corporate proxy #314

Closed
XiaofengXie16 opened this issue Oct 31, 2020 · 15 comments
Closed

Use behind a corporate proxy #314

XiaofengXie16 opened this issue Oct 31, 2020 · 15 comments
Labels
bug Something isn't working

Comments

@XiaofengXie16
Copy link

Is there an option where I could add a certificate to use this tool given that I want to use this tool behind a corporate proxy?

Currently, I am seeing this error.
HttpError: error sending request for url (https://nodejs.org/dist/index.json): error trying to connect: invalid certificate: UnknownIssuer

@Schniz
Copy link
Owner

Schniz commented Nov 5, 2020

Hi, I'm going to need to know more details. What OS are you using? what version of fnm?
Thanks

@XiaofengXie16
Copy link
Author

XiaofengXie16 commented Nov 6, 2020

OS: 10.15 - Catalina
fnm version: 1.22.6
Note: NVM works fine behind the proxy

@Schniz
Copy link
Owner

Schniz commented Nov 9, 2020

Can you try building fnm on your machine and tell me if it is working well?
I wonder if I should not use rustls on Mac 🤔 maybe use it only on ARM

@zicklag
Copy link

zicklag commented Nov 23, 2020

I'm getting a possibly related issue when running behind a corporate proxy with authentication and a custom certificate ( which I have trusted on my machine and which works will most other apps such as curl ). I'm on Pop!_OS ( Ubuntu ) 20.04 and I get the following error:

[2020-11-23T21:20:16Z TRACE reqwest::blocking::wait] (ThreadId(1)) park without timeout
[2020-11-23T21:20:16Z TRACE mio::poll] registering with poller
[2020-11-23T21:20:16Z TRACE reqwest::blocking::client] (ThreadId(2)) start runtime::block_on
[2020-11-23T21:20:16Z TRACE reqwest::blocking::wait] wait at most 30s
[2020-11-23T21:20:16Z TRACE reqwest::blocking::wait] (ThreadId(1)) park timeout 29.999986819s
[2020-11-23T21:20:16Z TRACE hyper::client::pool] checkout waiting for idle connection: ("https", nodejs.org) 
[2020-11-23T21:20:16Z DEBUG reqwest::connect] starting new connection: https://nodejs.org/
[2020-11-23T21:20:16Z DEBUG reqwest::connect] proxy(http://123.456.789.10:3128) intercepts 'https://nodejs.org/'
[2020-11-23T21:20:16Z TRACE hyper::client::connect::http] Http::connect; scheme=Some("http"), host=Some("123.456.789.10"), port=Some(Port(3128)) 
[2020-11-23T21:20:16Z DEBUG hyper::client::connect::http] connecting to 123.456.789.10:3128 
[2020-11-23T21:20:16Z TRACE mio::poll] registering with poller
[2020-11-23T21:20:16Z DEBUG hyper::client::connect::http] connected to 123.456.789.10:3128 
[2020-11-23T21:20:16Z TRACE reqwest::connect] tunneling HTTPS over proxy
[2020-11-23T21:20:16Z DEBUG reqwest::connect] tunnel to nodejs.org:443 using basic auth
[2020-11-23T21:20:16Z DEBUG rustls::client::hs] No cached session for DNSNameRef("nodejs.org")
[2020-11-23T21:20:16Z DEBUG rustls::client::hs] Not resuming any session
[2020-11-23T21:20:16Z TRACE rustls::client::hs] Sending ClientHello Message { ... }
[2020-11-23T21:20:16Z ERROR rustls::session] TLS alert received: Message {
        typ: Alert,
        version: TLSv1_2,
        payload: Alert(
            AlertMessagePayload {
                level: Fatal,
                description: HandshakeFailure,
            },
        ),
    }
[2020-11-23T21:20:16Z TRACE mio::poll] deregistering handle with poller
[2020-11-23T21:20:16Z TRACE hyper::client::pool] checkout dropped for ("https", nodejs.org) 
[2020-11-23T21:20:16Z TRACE reqwest::blocking::client] closing runtime thread (ThreadId(2))
[2020-11-23T21:20:16Z TRACE reqwest::blocking::client] signaled close for runtime thread (ThreadId(2))
[2020-11-23T21:20:16Z TRACE reqwest::blocking::client] (ThreadId(2)) Receiver is shutdown
[2020-11-23T21:20:16Z TRACE reqwest::blocking::client] (ThreadId(2)) end runtime::block_on
[2020-11-23T21:20:16Z TRACE reqwest::blocking::client] (ThreadId(2)) finished
[2020-11-23T21:20:16Z TRACE reqwest::blocking::client] closed runtime thread (ThreadId(2))
error: HttpError: error sending request for url (https://nodejs.org/dist/index.json): error trying to connect: received fatal alert: HandshakeFailure

I get the same issue when installing fnm from source using cargo install fnm. When building it locally without request/rust-tls feature I get a different error:

[2020-11-23T21:17:14Z TRACE reqwest::blocking::wait] (ThreadId(1)) park without timeout
[2020-11-23T21:17:14Z TRACE mio::poll] registering with poller
[2020-11-23T21:17:14Z TRACE reqwest::blocking::client] (ThreadId(2)) start runtime::block_on
[2020-11-23T21:17:14Z TRACE reqwest::blocking::wait] wait at most 30s
[2020-11-23T21:17:14Z TRACE reqwest::blocking::wait] (ThreadId(1)) park timeout 29.999980526s
[2020-11-23T21:17:14Z TRACE hyper::client::pool] checkout waiting for idle connection: ("https", nodejs.org) 
[2020-11-23T21:17:14Z DEBUG reqwest::connect] starting new connection: https://nodejs.org/
[2020-11-23T21:17:14Z DEBUG reqwest::connect] proxy(http://123.456.789.10:3128) intercepts 'https://nodejs.org/'
[2020-11-23T21:17:14Z TRACE hyper::client::connect::http] Http::connect; scheme=Some("http"), host=Some("123.456.789.10"), port=Some(Port(3128)) 
[2020-11-23T21:17:14Z DEBUG hyper::client::connect::http] connecting to 123.456.789.10:3128 
[2020-11-23T21:17:14Z TRACE mio::poll] registering with poller
[2020-11-23T21:17:14Z DEBUG hyper::client::connect::http] connected to 123.456.789.10:3128 
[2020-11-23T21:17:14Z TRACE hyper::client::conn] client handshake HTTP/1 
[2020-11-23T21:17:14Z TRACE hyper::client] handshake complete, spawning background dispatcher task 
[2020-11-23T21:17:14Z TRACE want] signal: Want
[2020-11-23T21:17:14Z TRACE want] signal found waiting giver, notifying
[2020-11-23T21:17:14Z TRACE hyper::proto::h1::conn] flushed({role=client}): State { reading: Init, writing: Init, keep_alive: Busy } 
[2020-11-23T21:17:14Z TRACE want] poll_want: taker wants!
[2020-11-23T21:17:14Z TRACE hyper::client::pool] checkout dropped for ("https", nodejs.org) 
[2020-11-23T21:17:14Z TRACE hyper::proto::h1::role] encode_headers
[2020-11-23T21:17:14Z TRACE hyper::proto::h1::role] -> encode_headers
[2020-11-23T21:17:14Z TRACE hyper::proto::h1::role] Client::encode method=GET, body=None 
[2020-11-23T21:17:14Z TRACE hyper::proto::h1::role] <- encode_headers
[2020-11-23T21:17:14Z TRACE hyper::proto::h1::role] -- encode_headers
[2020-11-23T21:17:14Z TRACE hyper::proto::h1::io] detected no usage of vectored write, flattening 
[2020-11-23T21:17:14Z DEBUG hyper::proto::h1::io] flushed 85 bytes 
[2020-11-23T21:17:14Z TRACE hyper::proto::h1::conn] flushed({role=client}): State { reading: Init, writing: KeepAlive, keep_alive: Busy } 
[2020-11-23T21:17:14Z TRACE hyper::proto::h1::conn] Conn::read_head 
[2020-11-23T21:17:14Z DEBUG hyper::proto::h1::io] read 3969 bytes 
[2020-11-23T21:17:14Z TRACE hyper::proto::h1::role] parse_headers
[2020-11-23T21:17:14Z TRACE hyper::proto::h1::role] -> parse_headers
[2020-11-23T21:17:14Z TRACE hyper::proto::h1::role] Response.parse([Header; 100], [u8; 3969]) 
[2020-11-23T21:17:14Z TRACE hyper::proto::h1::role] Response.parse Complete(396) 
[2020-11-23T21:17:14Z TRACE hyper::proto::h1::role] <- parse_headers
[2020-11-23T21:17:14Z TRACE hyper::proto::h1::role] -- parse_headers
[2020-11-23T21:17:14Z DEBUG hyper::proto::h1::io] parsed 12 headers 
[2020-11-23T21:17:14Z DEBUG hyper::proto::h1::conn] incoming body is content-length (3573 bytes) 
[2020-11-23T21:17:14Z TRACE hyper::proto::h1::conn] remote disabling keep-alive 
[2020-11-23T21:17:14Z TRACE hyper::proto::h1::decode] decode; state=Length(3573) 
[2020-11-23T21:17:14Z DEBUG hyper::proto::h1::conn] incoming body completed 
[2020-11-23T21:17:14Z TRACE hyper::proto::h1::conn] try_keep_alive({role=client}): could keep-alive, but status = Disabled 
[2020-11-23T21:17:14Z TRACE hyper::proto::h1::conn] State::close() 
[2020-11-23T21:17:14Z TRACE hyper::proto::h1::conn] flushed({role=client}): State { reading: Closed, writing: Closed, keep_alive: Disabled } 
[2020-11-23T21:17:14Z TRACE hyper::proto::h1::conn] shut down IO complete 
[2020-11-23T21:17:14Z TRACE mio::poll] deregistering handle with poller
[2020-11-23T21:17:14Z TRACE want] signal: Closed
[2020-11-23T21:17:14Z DEBUG reqwest::async_impl::client] response '400 Bad Request' for https://nodejs.org/dist/index.json
[2020-11-23T21:17:14Z TRACE want] poll_want: closed
[2020-11-23T21:17:14Z TRACE reqwest::blocking::wait] wait at most 30s
[2020-11-23T21:17:14Z TRACE reqwest::blocking::client] closing runtime thread (ThreadId(2))
[2020-11-23T21:17:14Z TRACE reqwest::blocking::client] signaled close for runtime thread (ThreadId(2))
[2020-11-23T21:17:14Z TRACE reqwest::blocking::client] (ThreadId(2)) Receiver is shutdown
[2020-11-23T21:17:14Z TRACE reqwest::blocking::client] (ThreadId(2)) end runtime::block_on
[2020-11-23T21:17:14Z TRACE reqwest::blocking::client] (ThreadId(2)) finished
[2020-11-23T21:17:14Z TRACE reqwest::blocking::client] closed runtime thread (ThreadId(2))
error: HttpError: error decoding response body: expected value at line 1 column 1

@zicklag
Copy link

zicklag commented Nov 24, 2020

Ah, I was able to fix it by disabling the rustls-tls feature in reqwests and by re-enabling the default features ( which just enables the default-tls feature ). It's probably due to RusTLS failing to trust the system certificate.

Coincidentally this is exactly the same problem I ran into with Deno today.

@Schniz
Copy link
Owner

Schniz commented Nov 24, 2020

Oh cool, thanks for checking it out!
we probably need to use rustls-tls only on ARM 😄

@Schniz Schniz added the bug Something isn't working label Nov 24, 2020
@pfiaux
Copy link
Contributor

pfiaux commented May 30, 2021

I ran into a similar issue, I'll need to retest with the latest release which has the newest reqwests version to make sure it still happens.

Looking at their doc tho it seems rustls-tls is equivalent to rustls-tls-webpki-roots (https://docs.rs/reqwest/0.11.3/reqwest/#optional-features). Can it be combined with native-tls or perhaps rustls-tls-native-roots? If they're not exclusive that might allow using the configured certificates on the host as well.

@pfiaux
Copy link
Contributor

pfiaux commented Jun 5, 2021

I've tested with rustls-tls-native-roots (keeping rustls-tls as well):

reqwest = { version = "0.11.3", features = ["blocking", "json", "rustls-tls", "rustls-tls-native-roots", "brotli"], default-features = false }

It worked without proxy and with proxy (if someone wants to try it before it lands cargo install --path ./ worked out for me).

I didn't look at the difference between rustls-tls-native-roots and native-tls.

pfiaux added a commit to pfiaux/fnm that referenced this issue Jun 5, 2021
Addresses Schniz#314 allowing use of fnm when behind a proxy with certificates.

This adds the `"rustls-tls-native-roots"` [cargo feature](https://docs.rs/reqwest/0.11.3/reqwest/#optional-features) to reqwest. That uses [rustls-native-certs](https://github.com/rustls/rustls-native-certs):
> rustls-native-certs allows rustls to use the platform's native certificate store when operating as a TLS client.

I tested on macOS both with and without proxy mainly doing `cargo run -- list-remote`, and installing node 16, this worked behind proxy. Without proxy I only tested list-remote. Perhaps other commands need to be retested as well.

The [`native-tls`](https://docs.rs/native-tls/0.2.7/native_tls/) feature might also work, I didn't test. They seem to cover similar functionality but maybe it works better on Linux ARM systems.
@michahell
Copy link

michahell commented Dec 9, 2021

I am getting a similar error on Windows 10 20H2 while having installed via chocolatey: choco install fnm

error: Can't download the requested binary: HttpError: error sending request for url (https://nodejs.org/dist/v16.13.1/node-v16.13.1-win-x64.zip): error trying to connect: invalid certificate: UnknownIssuer

A possible workaround is to disable one's company VPN / proxies and then download node versions

@zicklag
Copy link

zicklag commented Dec 13, 2021

I use fnm on Linux behind a proxy with a custom SSL certificate, but I have to use the default-tls feature for the requests crate ( which might be default in fnm by now, I can't remember ), and I have to trust the proxy certificate in my system certificate store.

I'm not if it works on Windows, but have you trusted your proxy certificate in your Windows network settings. If I remember correctly, it's kind of in the internet explorer / edge settings ( even if you don't use internet explorer ).

@cko-jimmy-wong
Copy link

cko-jimmy-wong commented Dec 13, 2021

I'm on macOS and I'm getting UnknownIssuer on 1.28.2. #468 was removed but there's no equivalent replacement. How should I bypass this problem? The corporate proxy on my machine MITM the TLS connection and rewrites the cert, how do I accept the cert, even on TOFU manner?

@zicklag
Copy link

zicklag commented Dec 13, 2021

@cko-jimmy-wong worst case scenario you can just apply these changes and build it from source to use it behind a proxy.

@Schniz will have to decide what the best way to support all platforms is being that it seems like some platforms work better with different features enabled, but if you are find building from source, then that should work for you for now.

@Schniz
Copy link
Owner

Schniz commented Dec 13, 2021

I probably forgot to apply the feature when I reverted. We can do this again

@pfiaux
Copy link
Contributor

pfiaux commented Dec 16, 2021

Indeed looks like https://github.com/Schniz/fnm/pull/586/files doesn't include "rustls-tls-native-roots". I'll open a PR when I can to re-introduce it (and maybe then close this issue since there was no comments while it was in place =] )

The revert mentions testing, the proxy might be testable in a container given that there's a small proxy that can run in the container too. Maybe something like https://dev.to/andre/docker-restricting-in--and-outbound-network-traffic-67p could be used to drop the non proxy traffic, so that the test fails if it doesn't use the proxy. Then there would be the tls part... sounds like it would make for one big e2e test to check all that!

pfiaux added a commit to pfiaux/fnm that referenced this issue Dec 16, 2021
Addresses Schniz#314 allowing use of fnm when behind a proxy with certificates by reapplying Schniz#468 after the revert from ureq to reqwest.

This adds the `"rustls-tls-native-roots"` [cargo feature](https://docs.rs/reqwest/0.11.3/reqwest/#optional-features) to reqwest. That uses [rustls-native-certs](https://github.com/rustls/rustls-native-certs):
> rustls-native-certs allows rustls to use the platform's native certificate store when operating as a TLS client.

I tested on macOS both with and without proxy mainly doing `cargo run -- list-remote`, and installing node 16, this worked behind proxy. Without proxy I only tested list-remote. Perhaps other commands need to be retested as well.

The [`native-tls`](https://docs.rs/native-tls/0.2.7/native_tls/) feature might also work, I didn't test. They seem to cover similar functionality but maybe it works better on Linux ARM systems.
Schniz pushed a commit that referenced this issue Dec 28, 2021
Addresses #314 allowing use of fnm when behind a proxy with certificates by reapplying #468 after the revert from ureq to reqwest.

This adds the `"rustls-tls-native-roots"` [cargo feature](https://docs.rs/reqwest/0.11.3/reqwest/#optional-features) to reqwest. That uses [rustls-native-certs](https://github.com/rustls/rustls-native-certs):
> rustls-native-certs allows rustls to use the platform's native certificate store when operating as a TLS client.

I tested on macOS both with and without proxy mainly doing `cargo run -- list-remote`, and installing node 16, this worked behind proxy. Without proxy I only tested list-remote. Perhaps other commands need to be retested as well.

The [`native-tls`](https://docs.rs/native-tls/0.2.7/native_tls/) feature might also work, I didn't test. They seem to cover similar functionality but maybe it works better on Linux ARM systems.
@Schniz
Copy link
Owner

Schniz commented Feb 15, 2022

This should be fixed already! Thanks @pfiaux! 🙌

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

6 participants