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

[BUG]: Self Signed TLS certificate is no longer trusted for AnkiDroid after new update (works well with 2.16.5) #14686

Closed
3 of 4 tasks
Cloufish opened this issue Nov 8, 2023 · 17 comments · Fixed by #16481
Closed
3 of 4 tasks

Comments

@Cloufish
Copy link

Cloufish commented Nov 8, 2023

Checked for duplicates?

  • This issue is not a duplicate

What are the steps to reproduce this bug?

  1. Make a self hosted instance of anki-server
  2. Have it on https and create your own TLS Certificate
  3. Set both Desktop Anki and AnkiDroid to point to the self-hosted instance
  4. Notice, that on Desktop Anki the upload goes without a problem, but on AnkiDroid it gives:
**Error**

A network error occured.

Error details: error sending request for url (): error trying to connect: invalid peer certificate: UnknownIssuer

Expected behaviour

  • Because I have installed tls self-signed certificate before, which worked on the previous version of AnkiDroid it shouldn't output any error
  • The certificate rootCA.pem is installed under "User's certificates".

Actual behaviour

  • It gives the error, and I can't sync to the self-hosted instance

Debug info

AnkiDroid Version = 2.17alpha3 (42a8c8c55c200f372b0bd0b462e4b58554b72fe5)

Android Version = 12

ProductFlavor = play

Manufacturer = samsung

Model = SM-M215F

Hardware = exynos9611

Webview User Agent = Mozilla/5.0 (Linux; Android 12; SM-M215F Build/SP1A.210812.016; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/[118.0.0.0](http://118.0.0.0/) Mobile Safari/537.36

ACRA UUID = 2ce4e882-5792-4ef3-a912-0720e9478533

Crash Reports Enabled = true

DatabaseV2 Enabled = true

(Optional) Anything else you want to share?

No response

Research

  • I am reporting a bug specific to AnkiDroid (Android app)
  • I have checked the manual and the FAQ and could not find a solution to my issue
  • (Optional) I have confirmed the issue is not resolved in the latest alpha release (instructions)
Copy link

welcome bot commented Nov 8, 2023

Hello! 👋 Thanks for logging this issue. Please remember we are all volunteers here, so some patience may be required before we can get to the issue. Also remember that the fastest way to get resolution on an issue is to propose a change directly, https://github.com/ankidroid/Anki-Android/wiki/Contributing

@mikehardy
Copy link
Member

Interesting.
I'm not aware of any change in this area, and in fact our network security config is still specifically set up to allow the potentially insecure settings that should work for you:

https://github.com/ankidroid/Anki-Android/blob/main/AnkiDroid/src/main/res/xml/network_security_config.xml

<trust-anchors>
<!-- Trust preinstalled CAs -->
<certificates src="system" />
<!-- Additionally trust user added CAs -->
<certificates src="user" />
</trust-anchors>

Indeed the Play Console is adamant that this is a terrible idea and reminds me of same every time we publish a release:

image

I suspect something else may be going on here, but I don't know exactly what

@dae
Copy link
Contributor

dae commented Nov 8, 2023

The backend uses https://github.com/rustls/rustls-native-certs. It doesn't currently support self-signed certs on the mobile platforms. This will hopefully change in the future when https://github.com/rustls/rustls-platform-verifier matures. In the mean time, you should use something like let's encrypt or a VPN instead.

@Cloufish
Copy link
Author

Cloufish commented Nov 9, 2023

The backend uses https://github.com/rustls/rustls-native-certs. It doesn't currently support self-signed certs on the mobile platforms. This will hopefully change in the future when https://github.com/rustls/rustls-platform-verifier matures. In the mean time, you should use something like let's encrypt or a VPN instead.

It makes me wonder why it suddenly stopped working (previous version of AnkiDroid worked fine)
But thanks for response dae :)

@Cloufish Cloufish closed this as completed Nov 9, 2023
@Cloufish
Copy link
Author

Cloufish commented Nov 9, 2023

(previous version of AnkiDroid worked fine)

Just to confirm I tested the released versions:

  • 2.16.3 - works
  • 2.16.4 - works
  • 2.16.5 - works

So this seems like a alpha release issue
I'll reopen the ticket. I'd be happy to provide more logs (tell me which one)
An app in a newer version shouldn't lose the functionality

@Cloufish Cloufish reopened this Nov 9, 2023
@Cloufish Cloufish changed the title [BUG]: Self Signed TLS certificate is no longer trusted for AnkiDroid after new update [BUG]: Self Signed TLS certificate is no longer trusted for AnkiDroid after new update (works well with 2.16.5) Nov 9, 2023
@mikehardy
Copy link
Member

The alpha releases just switched to "the new backend" as the default, 2.16.x releases only use the new backend as an experimental option. So I guess you were on 2.16 without the new backend option in advanced settings, but now in 2.17 you get the new backend no matter what

And the new backend uses the Rust code for synchronization, which goes into the problem @dae mentioned (which I wasn't aware of myself!)

That's why it changed all of the sudden

An app in a newer version may suffer regressions, that is inevitable, even if not desired. Additionally, any app that has been around for 10 years may decide to no longer support features that are not used by enough people - which AnkiDroid frequently does. The users this affects are of course not happy but you must understand we have approximately 2 million users. The number that use self-signed certificates is probably about 100. The other 1,999,900 (using my made up numbers that are nevertheless still likely close) are benefiting from getting up to date Anki Desktop features like v3 scheduler + FSRS now and they really appreciate it.

Feature development, and feature retirement math is unfortunately pitiless when there are tradeoffs to be made.

That said, I hope Rust starts accepting self-signed certs soon. It seems like a basic feature for a TLS library, to me.

@mikehardy
Copy link
Member

So I'm going to re-close this, it is not actionable here unfortunately. That said, this issue is the one to follow + vote on I think: rustls/rustls-native-certs#3 - once rustls-platform-verifier is "ready for primetime" (according to the rustls-native-certs maintainers) it will hopefully be included in the rustls-native-certs crate, at which point the anki backend can ingest it, and we'll get support again here in the new backend

@Cloufish
Copy link
Author

Cloufish commented Jan 27, 2024

Hey @mikehardy

The rustls-platform verifier has been released, but in the independent crate
Is there a chance to implement it in the Anki backend?

image

@acht
Copy link

acht commented Mar 8, 2024

Hi,
Thanks for your work!
I do not want to blame you or the work of the project. I only want to add the view of the user.
The problem is very annoying. The only workaround is to remove AnkiDroid and reinstall an older version. A downgrade is not possible. So, all settings have to be redone. A warning in the release notes (f-droid) would be very helpful.

Certificates in Android are a very annoying issue. In principle, a certificate pinning is the best solution. (In my opinion.) It does not make sense to trust all Android certificates if you want to connect to the original Anki service. If a custom server is used, it makes sense to present the certificate to the user. I think DavDroid is a good example. To not trust certificates installed by the user is one of the most annoying habits of Android applications.

Sorry, Anki is not a project about certificate handling. Nevertheless, it would be nice to have the user in mind how try to avoid the big service providers.

A question, can you estimate any timeframe when user-installed certificates are working again?

@RedPine404
Copy link

I can also confirm AnkiDroid 2.17.5 no longer allows me to use my server with self signed certificates

@AH12A
Copy link

AH12A commented Mar 18, 2024

Hello, I'd also like to add my view on this matter as a user.
While I understand this issue might be created by some third party library that AnkiDroid does not have a direct influence on, I'm sure some of us will greatly appreciate a workaround in the meantime, until user provided system-wide certificates can be trusted again.
While the workaround of using a Let's Encrypt issued certificate as suggested by @dae could alleviate the issue in some cases, there are other cases where this is not possible.
For instance, in the cases where the user uses domains with pseudo-TLD, such as .lan, .home or .alt, it's not possible to get a certificate from a well known CA.
Another case would be for users who on a corporate network/proxy where all TLS connections are inspected by a firewall, thus stripped of their original certificate and issued a corporate certificate (in this case, even using the official ankiweb server is not possible).

I humbly suggest what @acht suggested: Allow the user to select a custom certificate file when using a custom sync server. This way, even those who wish to use ankiweb sync servers, can define ankiweb's url as their custom sync server with their own trusted certificate authority.
If this solution is too difficult to implement, then at least an option to override the certificate verification process and establish the connection (same as with any major browser) could be considered as a stop-gap measure as well.

Thank you for all your hard work and making AnkiDroid better

@voczi
Copy link
Contributor

voczi commented Mar 21, 2024

For anyone compiling from source, you can pin a root CA in Anki-Android-Backend/anki/rslib/src/backend/mod.rs by changing from this:

fn web_client(&self) -> &Client {
        // currently limited to http1, as nginx doesn't support http2 proxies
        self.web_client
            .get_or_init(|| Client::builder().http1_only().build().unwrap())
}

to this:

fn web_client(&self) -> &Client {
  let cert = reqwest::tls::Certificate::from_pem(
"-----BEGIN CERTIFICATE-----
<contents>
-----END CERTIFICATE-----

".as_bytes()).unwrap();
  // currently limited to http1, as nginx doesn't support http2 proxies
  return self.web_client
  .get_or_init(|| Client::builder()
  .use_rustls_tls()
  .add_root_certificate(cert)
  .http1_only().build().unwrap());
}

Probably ugly because I'm a newbie to Rust, and also just tedious in general to compile everything.

I did try adding rustls-platform-verifier and that was a lot of work. I think I got so far as to have the library inject itself into the Android Context, but I ran into annoying dependency conflicts so I just gave up.

@voczi
Copy link
Contributor

voczi commented Mar 22, 2024

So, rustls-platform-verifier can actually work with the project. At least after a bunch of adjustments, most of which from this PR. Only part that didn't quite work was the revocation checking. Otherwise it uses the phone's CA store perfectly fine.
I'll fork the relevant repos and commit all the changes I did, most likely later on in the weekend. But so far, the biggest issue I can see right now are all of the changes I had to do for rustls-platform-verifier to work with Ankidroid..

EDIT: I think the above is as good as it gets for now. Still haven't spent enough time learning about the Ankidroid architecture to release a good solution. But hopefully I can help again, maybe around my finals, that is if this issue is still open.

@voczi
Copy link
Contributor

voczi commented Mar 29, 2024

For anyone who doesn't have time to wait for the upstream repo to fix this, you can use the version here: https://github.com/voczi/Anki-Android/releases/tag/latest
Just make sure you read all of the information on the release carefully before installing.

@ROOMBON
Copy link

ROOMBON commented Apr 30, 2024

It's a shame that you can't integrate it into the regular version of Android.
But thanks for what you did.
If there is a possibility to combine in the future it will be better.

@voczi
Copy link
Contributor

voczi commented May 22, 2024

Added a new PR to the backend code (ankitects/anki#3203). Should be able to get this working after it is merged.

@voczi
Copy link
Contributor

voczi commented Jun 19, 2024

devs can test #16481 until it is merged and an alpha/stable version is released.

@github-actions github-actions bot added this to the 2.19 release milestone Jun 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
9 participants