mirror of
https://github.com/SignTools/SignTools.git
synced 2026-04-27 10:55:49 +03:00
[GH-ISSUE #401] "Unable to install *.ipa" when done through reverse proxy #99
Labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
starred/SignTools#99
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @TJWeiten on GitHub (Mar 17, 2024).
Original GitHub issue: https://github.com/SignTools/SignTools/issues/401
!! Please fill in this template, DO NOT ignore or delete it. !!
I tried basic troubleshooting first
Describe the bug
I just spent the last few days shifting my setup for SignTools from using the trial Cloudflare Tunnel with GitHub Actions to self-hosting the SignTools service and SignTools-Builder on my internal network.
There was a lot of trial and error getting everything to work, and I am almost all of the way there, but am running into a strange issue where the correctly signed IPA is not able to be installed using the web portal when connected via the reverse proxy.
When I attempt to install a signed app, it prompts me to open in "iTunes" as it normally does, but immediately fails with "Unable To Install *.ipa".
If I switch to connecting to the SignTools web portal directly over HTTP instead of through the reverse proxy over HTTPS, it seems to work as intended. The application is installed correctly. Additionally, I can download the signed app and verify it has been signed appropriately. The app can be installed manually through the
ideviceinstaller -i app.ipacommand.The issue is purely in the OTA installation procedure.
Logs
SignTools output for when connecting directly:
SignTools output for when connecting via reverse proxy:
SignTools does not make any more logs after getting a 200 on the manifest endpoint.
System configuration
Additional context
I believe I should have the correct declarations for reverse proxying in
lighttpd, but perhaps there is something I am not understanding about reverse proxying when doing the OTA procedure.@ViRb3 commented on GitHub (Mar 17, 2024):
This is happening because SignTools is telling your phone to download the IPA from an internal IP address (10.0.0.6) which is valid inside your server but not outside of it.
SignTools uses the URL you visit in your browser to construct the download URL. If SignTools sees the internal IP (10.0.0.6) instead of your domain name, then your reverse proxy didn't pass through the original hostname properly. Unfortunately I've never used lightppd, but for nginx, you need the following:
@ViRb3 commented on GitHub (Mar 17, 2024):
I think the problem is you're setting
X-Forwarded-Hostheader, but SignTools does not support it currently. You need to set theHostheader directly. I will take this as a feature request though.@TJWeiten commented on GitHub (Mar 17, 2024):
Perhaps I am being dumb, but as far as I can tell, my Host header is being set properly?
We do want it to be set to the domain name and not the IP, correct?
The logs seem to be backing that up. When accessed through the reverse proxy, the only visible IP address is that of my iPhone (10.0.2.4). I removed some of the empty/not important parts of the log to make it a bit easier to parse. But the key part seems to be the host is showing up as shisui.ryuu, which is where the reverse proxy is listening.
I will toy with some of the lighttpd reverse proxy settings though, see if that can't make some difference.
@ViRb3 commented on GitHub (Mar 17, 2024):
Your first screenshot is from a browser. Remember that browsers always talk to the reverse proxy and never to SignTools directly. I suspect the
Hostheader is being changed in the next step of the request chain, between the reverse proxy and SignTools.Can you try querying
/apps/d50afb8b-569b-4cfc-86cb-2ec90f5fe6f6/manifestin your browser and seeing what it returns? To be honest I'm very surprised that thehostfield is correct in the logs.@TJWeiten commented on GitHub (Mar 18, 2024):
Yeah, good point. I don't totally understand how the OTA procedure works, but SignTools mostly just serves up the /manifest and /signed endpoints, right? Not sure what happens after both of those are accessed, but is it handled mostly on the iPhone's end at that point? If so, I would assume that so long as the /manifest and /signed endpoints are directly accessible through the browser on the phone, it should work? Or maybe I am totally misunderstanding the OTA installation procedure.
But as for the logs in SignTools, I checked again and it is most definitely parsing the host correctly as my internal domain name.
I am able to probe and access all of these endpoints on my phone and receive their contents. For example, I can visit https://shisui.ryuu/apps/d50afb8b-569b-4cfc-86cb-2ec90f5fe6f6/signed directly and download the App.ipa.zip file, extract it on the iPhone's file system, etc.
In so far as it is meaningful to access them on my MacBook's browser, the host appears to be set correctly.
So I am definitely flummoxed.
Come to think of it, I think this happened while I was still using the Cloudflare Tunnel, too. If I recall correctly, I tried to sideload something a week ago and got the same error message before I switched to self-hosting/reverse proxying. I just didn't think much of it at the time. I'll see if I can't troubleshoot to see if it's a opnSense/firewall issue, though don't have the slightest idea what there could be causing the issue.
@ViRb3 commented on GitHub (Mar 18, 2024):
SIgnTools produces a manifest file which contains a URL to your
/signedendpoint, which is the actual IPA file. The manifest is read from your iPhone and then it fetches the IPA.Come to think of it, if you're seeing
using OTA manifest proxyin the logs, that means the protocol forward header didn't work either. Manifests cannot be served over HTTP (Apple policy), so if SignTools doesn't detect HTTPS (either via request url directly or protocol forward header), it will relay the manifest creation to a Cloudflare worker that is HTTPS. So, your proxy headers don't seem to be working.Also, what did the
/manifestendpoint say? Does it show your domain name as expected?@TJWeiten commented on GitHub (Mar 18, 2024):
Yep! Shows the domain name as expected in the Host header and the manifest file. See below:
Wait, is the install button not supposed to work if you're connecting to the SignTools server over HTTP and not HTTPS? Because, uhm, it totally works on my end, haha.Edit: I understand what you are saying now. See update below.Visiting the /manifest endpoint for this app shows that on the 'direct-to-SignTools' link, the /signed endpoint is served over HTTP.
Edit:
I noticed that when SignTools is run from the local IP address, the pop-up says
"ota.signtools.workers.dev" would like to install app.ipavs."shisui.ryuu" would like to install app.ipa. Now I understand what you meant by:That answers why it would be able to work over HTTP.
So that gave me an idea for another experiment. I disabled the https directive for SignTools and forced it to connect with only http. When I attempted an install on http://shisui.ryuu, the prompt stated
"ota.signtools.workers.dev" would like to install app.ipa, however the installation still failed.Maybe I'll test using nginx as the reverse proxy later. Maybe it is as simple as lighttpd handling proxying differently than SignTools was designed to handle.
@TJWeiten commented on GitHub (Mar 18, 2024):
Well, I can now confirm that a very simple nginx reverse proxy configuration also exhibits the same issue:
I also attempted slightly changing my self-signed cert to remove the wildcards, and tried a 'valid' TLD on my internal network to make sure the fake .ryuu TLD wasn't having an unintended consequence—neither appear to have done anything.
Edit: Just had an idea. Since Apple doesn't allow for manifests to be served over HTTP, do they also not allow them to be served over HTTPS with self-signed certificates? When I was setting up the builder, I ran into an issue where I needed to set
NODE_TLS_REJECT_UNAUTHORIZEDto 0 to get it to function.@ViRb3 commented on GitHub (Mar 18, 2024):
Oh, yes, it's very likely that Apple doesn't allow self-signed certificates for OTA install. I've never tested this, but I would not be surprised at all. Maybe you need to add your self-signed CA to the trust chain of your phone (if you haven't already), but even that may not work. FWIW, I personally use the nginx setup described in docs with a real domain and letsencrypt certificate, and there are no issues.
@ViRb3 commented on GitHub (Mar 19, 2024):
Released an update with support for
X-Forwarded-Host, just in case.@TJWeiten commented on GitHub (Mar 19, 2024):
Well, I did a bit more experimentation and confirmed that the issue relates to Apple disallowing manifests to be served over self-signed certificates via https.
Here were some of the experiments:
I am unclear why (1) works but not (3) given that they both are handed off to the ota.signtools.workers.dev and are both technically direct connections to SignTools—just one is the internal IP address the the other is an internal domain resolving to the same internal IP address.
Anyway, the good news? All you have to do to bypass the issue is to add the self-signed certificate to your iPhone's trust store and 'Enable full trust for root certificates' on it.
It might be worth mentioning this in SignTools documentation.
The rough sequence of steps includes:
@TJWeiten commented on GitHub (Mar 20, 2024):
Oh and one last thing, I can confirm that my lighttpd configuration as posted in https://github.com/SignTools/SignTools/issues/401#issue-2190897944 does not have any issue with forwarding the host in SignTools 3.0.1, making
github.com/SignTools/SignTools@356d5ff317probably unnecessary in most cases, but I guess maybe it could be triggered at some point in someone else's setup if they're rocking old versions of lighttpd or some other reverse proxy. As far as I can tell though, lighttpd now uses the Forwarded request header, as that supersedes X-Forwarded-Host.@ViRb3 commented on GitHub (Mar 20, 2024):
Glad to hear you got it working. I suspect very few people are using self-signed certificates, so I'm wary of overloading the docs with information. But anyone can search the issues and find this one if they are having the same problem. I think
github.com/SignTools/SignTools@356d5ff317still makes sense, as you can't always override theHostheader directly. Regarding the newForwardedheader, this is the first time I'm encountering it, and I don't want to provide multiple ways to do the same thing. If need be, will revise later.