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

electrum_client: disrepancies w/ certificate verification between use-rustls & use-openssl #1598

Open
pythcoiner opened this issue Sep 9, 2024 · 2 comments
Labels
bug Something isn't working
Milestone

Comments

@pythcoiner
Copy link

Describe the bug
trying to connect to an electrum server w/ a self-signed certificate using use-rustls fails but succeed w/ use-openssl

To Reproduce
code snippet:

use electrum_client::{ConfigBuilder, ElectrumApi};

fn main() {
    let config = ConfigBuilder::new()
        .retry(1)
        .timeout(Some(1))
        .validate_domain(false)
        .socks5(None)
        .build();
    let client =
        electrum_client::Client::from_config("ssl://testnet.aranguren.org:51002", config).unwrap();

    match client.ping() {
        Ok(_) => println!("Pong"),
        Err(e) => {
            println!("{:?}", e);
        }
    }
}

Expected behavior
should succeed w/ both features, use-rusttls fails w/:

AllAttemptsErrored([IOError(Kind(UnexpectedEof))])

trying w/ a local electrs + nginx + self-sign certificate i got this in nginx error log w/ use-rustls:

2024/09/09 10:31:50 [info] 493372#493372: *16 client 192.168.1.6:56774 connected to 0.0.0.0:60002
2024/09/09 10:31:50 [debug] 493372#493372: *16 posix_memalign: 00005583228C41D0:256 @16
2024/09/09 10:31:50 [debug] 493372#493372: *16 posix_memalign: 00005583227FA5D0:256 @16
2024/09/09 10:31:50 [debug] 493372#493372: *16 generic phase: 0
2024/09/09 10:31:50 [debug] 493372#493372: *16 generic phase: 1
2024/09/09 10:31:50 [debug] 493372#493372: *16 generic phase: 2
2024/09/09 10:31:50 [debug] 493372#493372: *16 generic phase: 3
2024/09/09 10:31:50 [debug] 493372#493372: *16 generic phase: 4
2024/09/09 10:31:50 [debug] 493372#493372: *16 tcp_nodelay
2024/09/09 10:31:50 [debug] 493372#493372: *16 posix_memalign: 00005583227FAC90:256 @16
2024/09/09 10:31:50 [debug] 493372#493372: *16 SSL_do_handshake: -1
2024/09/09 10:31:50 [debug] 493372#493372: *16 SSL_get_error: 1
2024/09/09 10:31:50 [crit] 493372#493372: *16 SSL_do_handshake() failed (SSL: error:0A00006E:SSL routines::bad extension) while SSL handshaking, client: 192.168.1.6, server: 0.0.0.0:60002
2024/09/09 10:31:50 [debug] 493372#493372: *16 finalize stream session: 500
2024/09/09 10:31:50 [debug] 493372#493372: *16 stream log handler
2024/09/09 10:31:50 [debug] 493372#493372: *16 geoip2 stream log handler
2024/09/09 10:31:50 [debug] 493372#493372: *16 close stream connection: 18
2024/09/09 10:31:50 [debug] 493372#493372: *16 reusable connection: 0
2024/09/09 10:31:50 [debug] 493372#493372: *16 free: 00005583228C3B50, unused: 19
2024/09/09 10:31:50 [debug] 493372#493372: *16 free: 00005583228C43F0, unused: 16
2024/09/09 10:31:50 [debug] 493372#493372: *16 free: 00005583228C41D0, unused: 64
2024/09/09 10:31:50 [debug] 493372#493372: *16 free: 00005583227FA5D0, unused: 48
2024/09/09 10:31:50 [debug] 493372#493372: *16 free: 00005583227FAC90, unused: 53

and this w/ use-openssl:

2024/09/09 10:34:20 [debug] 493372#493372: *17 accept: 192.168.1.6:60776 fd:18
2024/09/09 10:34:20 [debug] 493372#493372: posix_memalign: 00005583227FA5D0:256 @16
2024/09/09 10:34:20 [info] 493372#493372: *17 client 192.168.1.6:60776 connected to 0.0.0.0:60002
2024/09/09 10:34:20 [debug] 493372#493372: *17 posix_memalign: 00005583228C41D0:256 @16
2024/09/09 10:34:20 [debug] 493372#493372: *17 posix_memalign: 00005583228C43F0:256 @16
2024/09/09 10:34:20 [debug] 493372#493372: *17 generic phase: 0
2024/09/09 10:34:20 [debug] 493372#493372: *17 generic phase: 1
2024/09/09 10:34:20 [debug] 493372#493372: *17 generic phase: 2
2024/09/09 10:34:20 [debug] 493372#493372: *17 generic phase: 3
2024/09/09 10:34:20 [debug] 493372#493372: *17 generic phase: 4
2024/09/09 10:34:20 [debug] 493372#493372: *17 tcp_nodelay
2024/09/09 10:34:20 [debug] 493372#493372: *17 posix_memalign: 00005583228C3B50:256 @16
2024/09/09 10:34:20 [debug] 493372#493372: *17 SSL_do_handshake: -1
2024/09/09 10:34:20 [debug] 493372#493372: *17 SSL_get_error: 2
2024/09/09 10:34:20 [debug] 493372#493372: *17 epoll add event: fd:18 op:1 ev:80002001
2024/09/09 10:34:20 [debug] 493372#493372: *17 event timer add: 18: 60000:439665879
2024/09/09 10:34:20 [debug] 493372#493372: *17 SSL handshake handler: 0
2024/09/09 10:34:20 [debug] 493372#493372: *17 SSL_do_handshake: -1
2024/09/09 10:34:20 [debug] 493372#493372: *17 SSL_get_error: 2
2024/09/09 10:34:20 [debug] 493372#493372: *17 SSL handshake handler: 0
2024/09/09 10:34:20 [debug] 493372#493372: *17 ssl new session: 101DC0F1:32:149
2024/09/09 10:34:20 [debug] 493372#493372: *17 ssl new session: 4BBE0F2A:32:150
2024/09/09 10:34:20 [debug] 493372#493372: *17 SSL_do_handshake: 1
2024/09/09 10:34:20 [debug] 493372#493372: *17 SSL: TLSv1.3, cipher: "TLS_AES_256_GCM_SHA384 TLSv1.3 Kx=any Au=any Enc=AESGCM(256) Mac=AEAD"
2024/09/09 10:34:20 [debug] 493372#493372: *17 event timer del: 18: 439665879
2024/09/09 10:34:20 [debug] 493372#493372: *17 generic phase: 4
2024/09/09 10:34:20 [debug] 493372#493372: *17 ssl preread handler
2024/09/09 10:34:20 [debug] 493372#493372: *17 proxy connection handler
2024/09/09 10:34:20 [debug] 493372#493372: *17 malloc: 00005583228C4BB0:448
2024/09/09 10:34:20 [debug] 493372#493372: *17 malloc: 00005583228BAC70:16384
2024/09/09 10:34:20 [debug] 493372#493372: *17 post event 0000558322896D10
2024/09/09 10:34:20 [debug] 493372#493372: *17 get rr peer, try: 1
2024/09/09 10:34:20 [debug] 493372#493372: *17 stream socket 19
2024/09/09 10:34:20 [debug] 493372#493372: *17 epoll add connection: fd:19 ev:80002005
2024/09/09 10:34:20 [debug] 493372#493372: *17 connect to 192.168.1.21:50003, fd:19 #18
2024/09/09 10:34:20 [debug] 493372#493372: *17 proxy connect: -2
2024/09/09 10:34:20 [debug] 493372#493372: *17 event timer add: 19: 60000:439665925
2024/09/09 10:34:20 [debug] 493372#493372: *17 delete posted event 0000558322896D10
2024/09/09 10:34:20 [debug] 493372#493372: *17 SSL_read: -1
2024/09/09 10:34:20 [debug] 493372#493372: *17 SSL_get_error: 2
2024/09/09 10:34:20 [debug] 493372#493372: *17 event timer del: 19: 439665925
2024/09/09 10:34:20 [debug] 493372#493372: *17 stream proxy connect upstream
2024/09/09 10:34:20 [debug] 493372#493372: *17 tcp_nodelay
2024/09/09 10:34:20 [info] 493372#493372: *17 proxy 192.168.1.21:57420 connected to 192.168.1.21:50003
2024/09/09 10:34:20 [debug] 493372#493372: *17 malloc: 00005583228C5030:16384
2024/09/09 10:34:20 [debug] 493372#493372: *17 event timer add: 18: 600000:440205926
2024/09/09 10:34:20 [debug] 493372#493372: *17 SSL_read: 60
2024/09/09 10:34:20 [debug] 493372#493372: *17 SSL_read: -1
2024/09/09 10:34:20 [debug] 493372#493372: *17 SSL_get_error: 2
2024/09/09 10:34:20 [debug] 493372#493372: *17 write new buf t:1 f:0 0000000000000000, pos 00005583228BAC70, size: 60 file: 0, size: 0
2024/09/09 10:34:20 [debug] 493372#493372: *17 stream write filter: l:0 f:1 s:60
2024/09/09 10:34:20 [debug] 493372#493372: *17 writev: 60 of 60
2024/09/09 10:34:20 [debug] 493372#493372: *17 stream write filter 0000000000000000
2024/09/09 10:34:20 [debug] 493372#493372: *17 event timer: 18, old: 440205926, new: 440205931
2024/09/09 10:34:20 [debug] 493372#493372: *17 recv: eof:0, avail:-1
2024/09/09 10:34:20 [debug] 493372#493372: *17 recv: fd:19 39 of 16384
2024/09/09 10:34:20 [debug] 493372#493372: *17 write new buf t:1 f:0 0000000000000000, pos 00005583228C5030, size: 39 file: 0, size: 0
2024/09/09 10:34:20 [debug] 493372#493372: *17 stream write filter: l:0 f:1 s:39
2024/09/09 10:34:20 [debug] 493372#493372: *17 SSL to write: 39
2024/09/09 10:34:20 [debug] 493372#493372: *17 SSL_write: 39
2024/09/09 10:34:20 [debug] 493372#493372: *17 stream write filter 0000000000000000
2024/09/09 10:34:20 [debug] 493372#493372: *17 event timer: 18, old: 440205926, new: 440205931
2024/09/09 10:34:20 [debug] 493372#493372: *17 event timer: 18, old: 440205926, new: 440205931
2024/09/09 10:34:20 [debug] 493372#493372: *17 SSL_read: 0
2024/09/09 10:34:20 [debug] 493372#493372: *17 SSL_get_error: 6
2024/09/09 10:34:20 [debug] 493372#493372: *17 peer shutdown SSL cleanly
2024/09/09 10:34:20 [debug] 493372#493372: *17 write new buf t:0 f:0 0000000000000000, pos 00005583228BAC70, size: 0 file: 0, size: 0
2024/09/09 10:34:20 [debug] 493372#493372: *17 stream write filter: l:1 f:1 s:0
2024/09/09 10:34:20 [info] 493372#493372: *17 client disconnected, bytes from/to client:60/39, bytes from/to upstream:39/60
2024/09/09 10:34:20 [debug] 493372#493372: *17 finalize stream proxy: 200
2024/09/09 10:34:20 [debug] 493372#493372: *17 free rr peer 1 0
2024/09/09 10:34:20 [debug] 493372#493372: *17 close stream proxy upstream connection: 19
2024/09/09 10:34:20 [debug] 493372#493372: *17 reusable connection: 0
2024/09/09 10:34:20 [debug] 493372#493372: *17 finalize stream session: 200
2024/09/09 10:34:20 [debug] 493372#493372: *17 stream log handler
2024/09/09 10:34:20 [debug] 493372#493372: *17 posix_memalign: 00005583228C35A0:256 @16
2024/09/09 10:34:20 [debug] 493372#493372: *17 posix_memalign: 00005583228C3820:256 @16
2024/09/09 10:34:20 [debug] 493372#493372: *17 geoip2 stream log handler
2024/09/09 10:34:20 [debug] 493372#493372: *17 close stream connection: 18
2024/09/09 10:34:20 [debug] 493372#493372: *17 SSL_shutdown: 1
2024/09/09 10:34:20 [debug] 493372#493372: *17 event timer del: 18: 440205926
2024/09/09 10:34:20 [debug] 493372#493372: *17 reusable connection: 0
2024/09/09 10:34:20 [debug] 493372#493372: *17 free: 00005583228C5030
2024/09/09 10:34:20 [debug] 493372#493372: *17 free: 00005583228BAC70
2024/09/09 10:34:20 [debug] 493372#493372: *17 free: 00005583228C4BB0
2024/09/09 10:34:20 [debug] 493372#493372: *17 free: 00005583227FAC90, unused: 8
2024/09/09 10:34:20 [debug] 493372#493372: *17 free: 00005583227FA5D0, unused: 0
2024/09/09 10:34:20 [debug] 493372#493372: *17 free: 00005583228C41D0, unused: 8
2024/09/09 10:34:20 [debug] 493372#493372: *17 free: 00005583228C43F0, unused: 0
2024/09/09 10:34:20 [debug] 493372#493372: *17 free: 00005583228C3B50, unused: 2
2024/09/09 10:34:20 [debug] 493372#493372: *17 free: 00005583228C35A0, unused: 70
2024/09/09 10:34:20 [debug] 493372#493372: *17 free: 00005583228C3820, unused: 124

Build environment

  • BDK tag/commit: 0.21.0
  • OS+version: arch linux
  • Rust/Cargo version: cargo 1.78.0 (54d8815d0 2024-03-26)
  • Rust/Cargo target: x86_64-unknown-linux-gnu
@oleonardolima
Copy link
Contributor

oleonardolima commented Sep 9, 2024

Thanks for debugging and collecting the related info. Although I didn't delve into this yet and reproduced the problem, I think it's somewhat related to a problem I faced in the past with LND, reference: lightningnetwork/lnd#5450.

It requires further investigation, but if it's not a problem downstream with how rustls and how webpki handle self-signed certificates, it's related to how we are building the client here.

There's also the issue that we don't expose the use-openssl feature on bdk_electrum, right ?

@notmandatory @thunderbiscuit, have there been any previous discussions on why it's not exposed ?

@pythcoiner
Copy link
Author

pythcoiner commented Sep 9, 2024

Thanks for debugging and collecting the related info. Although I didn't delve into this yet and reproduced the problem, I think it's somewhat related to a problem I faced in the past with LND, reference: lightningnetwork/lnd#5450.

looks have the same root cause

It requires further investigation, but if it's not a problem downstream with how rustls and how webpki handle self-signed certificates, it's related to how we are building the client here.

Yes, it looks to me the intended logic is to NOT check the certificate if validate_domain = false :

but ends up not as intended for rustls

There's also the issue that we don't expose the use-openssl feature on bdk_electrum, right ?

right this make it uneasy to fallback to openssl

@notmandatory @thunderbiscuit, have there been any previous discussions on why it's not exposed ?

@notmandatory notmandatory added this to the 1.0.0-beta milestone Sep 17, 2024
notmandatory added a commit that referenced this issue Oct 2, 2024
f602d1b feat(bdk_electrum): add `use-openssl` as a feature (Leonardo Lima)

Pull request description:

  partially addresses #1598

  <!-- You can erase any parts of this template not applicable to your Pull Request. -->

  ### Description

  It's a simple PR to expose the `use-openssl` from `electrum-client` to `bdk_electrum`. It partially addresses #1598, allowing the user to use `openssl` as an alternative to `rustls`, as there are some problems with it when handling some types of TLS certificates.

  Do we need to add some sort of `bdk_electrum` tests using the new exposed `use-openssl` feature ?

  <!-- Describe the purpose of this PR, what's being adding and/or fixed -->

  ### Notes to the reviewers

  <!-- In this section you can include notes directed to the reviewers, like explaining why some parts
  of the PR were done in a specific way -->

  ### Changelog notice

  - Adds `use-openssl` as feature to `bdk_electrum`, exposing `electrum-client` `use-openssl` feature.

  <!-- Notice the release manager should include in the release tag message changelog -->
  <!-- See https://keepachangelog.com/en/1.0.0/ for examples -->

  ### Checklists

  #### All Submissions:

  * [x] I've signed all my commits
  * [x] I followed the [contribution guidelines](https://github.com/bitcoindevkit/bdk/blob/master/CONTRIBUTING.md)
  * [x] I ran `cargo fmt` and `cargo clippy` before committing

  #### New Features:

  * [ ] I've added tests for the new feature
  * [ ] I've added docs for the new feature

  #### Bugfixes:

  * [ ] This pull request breaks the existing API
  * [ ] I've added tests to reproduce the issue which are now passing
  * [ ] I'm linking the issue being fixed by this PR

Top commit has no ACKs.

Tree-SHA512: 86e0fdeaa0b6a48e0c7ddde6e3890ce86510b86ad727adf05cde5e8c311a8c6b7614ae57bae0cff9e7b8443478a324e5ce9e5180023d501453a5c1e9e45920e1
ValuedMammal added a commit to bitcoindevkit/rust-electrum-client that referenced this issue Oct 23, 2024
…tion

05771a8 fix: `NoCertificateVerification` implementation (Leonardo Lima)

Pull request description:

  fixes #149 bitcoindevkit/bdk#1598
  <!-- You can erase any parts of this template not applicable to your Pull Request. -->

  ### Description

  <!-- Describe the purpose of this PR, what's being adding and/or fixed -->

  It has been noticed some issues by both users and developers, as reported in #149, bitcoindevkit/bdk#1598 and wizardsardine/liana#1300, when using the library with `use-rustls-{ring}` feature to connect to electrum servers that use self-signed certificates, there are even some issues when trying to connect to `ssl://electrum.blockstream.info:50002` server.

  To connect in an insecure manner either with `rustls` or `openssl` features, the user can set the `validate_domain` field in the `Config` to false, this will either set the `SslVerifyMode::NONE` when using `openssl`, or use the custom `NoCertificateVerification` for the
  `rustls::client::danger::ServerCertVerifier` trait when using `rustls`, that said it should ignore the certificate verification when used.

  At the current library state, it's failing because we didn't set up the supported `rustls::SignatureScheme` properly, returning an empty vector at the moment. This PR focuses on fixing this issue by relying on the `CryptoProvider` in usage to get the correct and supported signature schemes.

  As part of the research to understand the problem, I've noticed that ideally, we should still use both the `rustls::webpki::verify_tls12_signature` and `rustls::webpki::verify_tls12_signature` and only rely on `rustls::client::danger::ServerCertVerified::assertion()` to ignore the certificate verification, however, it would still fail in scenarios such as bitcoindevkit/bdk#1598 which uses X.509 certificates with any version other than 3 (it uses version 1), see [here](https://github.com/rustls/webpki/blob/1a0d1646d0bb1b7851bf81c6244cab09c352d8ef/src/cert.rs#L202-L218).

  I kept the current behavior to also ignore the TLS signature, but I still would like to bring this to the discussion, should we validate it properly and update the documentation to mention the `webpki` limitation instead ?

  ### Notes to the reviewers

  I kept the current behavior to also ignore the TLS signature, but I still would like to bring this to the discussion, should we validate it properly and update the documentation to mention the `webpki` limitation instead ?

  <!-- In this section you can include notes directed to the reviewers, like explaining why some parts
  of the PR were done in a specific way -->

  ### Changelog notice

  - Updates the `NoCertificateVerification` implementation for the
  `rustls::client::danger::ServerCertVerifier` to use the `rustls::SignatureScheme` from `CryptoProvider` in use.

  <!-- Notice the release manager should include in the release tag message changelog -->
  <!-- See https://keepachangelog.com/en/1.0.0/ for examples -->

  ### Checklists

  #### All Submissions:

  * [x] I've signed all my commits
  * [x] I followed the [contribution guidelines](https://github.com/bitcoindevkit/bdk/blob/master/CONTRIBUTING.md)
  * [x] I ran `cargo fmt` and `cargo clippy` before committing

  #### New Features:

  * [ ] I've added tests for the new feature
  * [ ] I've added docs for the new feature

  #### Bugfixes:

  * [ ] This pull request breaks the existing API
  * [ ] I've added tests to reproduce the issue which are now passing
  * [ ] I'm linking the issue being fixed by this PR

ACKs for top commit:
  LLFourn:
    ACK 05771a8
  ValuedMammal:
    ACK 05771a8
  notmandatory:
    ACK 05771a8

Tree-SHA512: f74dedf458853fb19cd21dedb5b92158acd865ee0ab0fd6bbb2b3e267bac22edc7cf004d2dc0068f66d2665d87e6dd419231710a02317e3b2bfaa9f408b30759
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
Status: Discussion
Development

No branches or pull requests

3 participants