[GH-ISSUE #401] "Unable to install *.ipa" when done through reverse proxy #99

Closed
opened 2026-03-04 00:23:52 +03:00 by kerem · 13 comments
Owner

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.ipa command.

The issue is purely in the OTA installation procedure.

Logs

SignTools output for when connecting directly:

Mar 17 22:16:24 azim SignTools[390828]: 10:16PM INF bytes_in=0 bytes_out=49961 host=10.0.0.6:7895 latency=2.904642 latency_human=2.904642ms method=GET referer= remote_ip=10.0.2.4 status=200 uri=/ user_agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1"
Mar 17 22:18:19 azim SignTools[390828]: 10:18PM WRN using OTA manifest proxy, installation may not work base_url=http://10.0.0.6:7895
Mar 17 22:18:19 azim SignTools[390828]: 10:18PM INF bytes_in=0 bytes_out=1388 host=10.0.0.6:7895 latency=0.321805 latency_human="321.805µs" method=GET referer=http://10.0.0.6:7895/ remote_ip=10.0.2.4 status=200 uri=/apps/d50afb8b-569b-4cfc-86cb-2ec90f5fe6f6/install user_agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1"
Mar 17 22:18:23 azim SignTools[390828]: 10:18PM INF bytes_in=0 bytes_out=0 host=10.0.0.6:7895 latency=0.122165 latency_human="122.165µs" method=HEAD referer= remote_ip=10.0.2.4 status=200 uri=/apps/d50afb8b-569b-4cfc-86cb-2ec90f5fe6f6/signed user_agent="com.apple.appstored/1.0 iOS/17.4 model/iPhone16,2 hwp/t8130 build/21E219 (6; dt:311) AMS/1"
Mar 17 22:18:23 azim SignTools[390828]: 10:18PM INF bytes_in=0 bytes_out=3260512 host=10.0.0.6:7895 latency=48.224842 latency_human=48.224842ms method=GET referer= remote_ip=10.0.2.4 status=200 uri=/apps/d50afb8b-569b-4cfc-86cb-2ec90f5fe6f6/signed user_agent="com.apple.appstored/1.0 iOS/17.4 model/iPhone16,2 hwp/t8130 build/21E219 (6; dt:311) AMS/1"

SignTools output for when connecting via reverse proxy:

Mar 17 22:16:28 azim SignTools[390828]: 10:16PM INF bytes_in=0 bytes_out=49961 host=signtools.ryuu latency=2.465585 latency_human=2.465585ms method=GET referer= remote_ip=10.0.2.4 status=200 uri=/ user_agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1"
Mar 17 22:17:31 azim SignTools[390828]: 10:17PM INF bytes_in=0 bytes_out=1274 host=signtools.ryuu latency=0.237079 latency_human="237.079µs" method=GET referer=https://signtools.ryuu/ remote_ip=10.0.2.4 status=200 uri=/apps/d50afb8b-569b-4cfc-86cb-2ec90f5fe6f6/install user_agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1"
Mar 17 22:17:32 azim SignTools[390828]: 10:17PM INF bytes_in=0 bytes_out=1118 host=signtools.ryuu latency=0.189832 latency_human="189.832µs" method=GET referer= remote_ip=10.0.2.4 status=200 uri=/apps/d50afb8b-569b-4cfc-86cb-2ec90f5fe6f6/manifest user_agent="com.apple.appstored/1.0 iOS/17.4 model/iPhone16,2 hwp/t8130 build/21E219 (6; dt:311) AMS/1"

SignTools does not make any more logs after getting a 200 on the manifest endpoint.

System configuration

  • SignTools version: 3.0.1
  • Installation type: personal server; lighttpd for reverse proxy
  • Operating System: Linux
  • Builder type: SignTools-Builder
  • Builder version: 1.1.12; 13250eb

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.

$SERVER["socket"] == "10.0.0.6:443" {
    ssl.engine  = "enable"
    ssl.pemfile = "/etc/lighttpd/ryuu.pem"
    ssl.openssl.ssl-conf-cmd = ("MinProtocol" => "TLSv1.3", "Options" => "-ServerPreference")
    $HTTP["host"] == "signtools.ryuu" {
        proxy.server = ( "" => ( ( "host" => "10.0.0.6", "port" => "7895" ) ) )
        proxy.forwarded = ( "host" => 1, "proto" => 1, "for" => 1, "remote_user" => 1 )
        proxy.header = ( "upgrade" => "enable" )
    }
}

# All connections to http should redirect to https
$SERVER["socket"] == "10.0.0.6:80" {
    $HTTP["scheme"] == "http" {
        $HTTP["host"] == "signtools.ryuu" {
            url.redirect := (".*" => "https://%0$0")
        }
    }
}
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** - [X] Updated **both** [SignTools](https://github.com/SignTools/SignTools) **and** the builder ([SignTools-CI](https://github.com/SignTools/SignTools-CI) or [SignTools-Builder](https://github.com/SignTools/SignTools-Builder)) to the latest version - [X] Read through the [FAQ page](https://github.com/SignTools/SignTools/blob/master/FAQ.md) **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.ipa` command. The issue is purely in the OTA installation procedure. **Logs** SignTools output for when connecting directly: ``` Mar 17 22:16:24 azim SignTools[390828]: 10:16PM INF bytes_in=0 bytes_out=49961 host=10.0.0.6:7895 latency=2.904642 latency_human=2.904642ms method=GET referer= remote_ip=10.0.2.4 status=200 uri=/ user_agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1" Mar 17 22:18:19 azim SignTools[390828]: 10:18PM WRN using OTA manifest proxy, installation may not work base_url=http://10.0.0.6:7895 Mar 17 22:18:19 azim SignTools[390828]: 10:18PM INF bytes_in=0 bytes_out=1388 host=10.0.0.6:7895 latency=0.321805 latency_human="321.805µs" method=GET referer=http://10.0.0.6:7895/ remote_ip=10.0.2.4 status=200 uri=/apps/d50afb8b-569b-4cfc-86cb-2ec90f5fe6f6/install user_agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1" Mar 17 22:18:23 azim SignTools[390828]: 10:18PM INF bytes_in=0 bytes_out=0 host=10.0.0.6:7895 latency=0.122165 latency_human="122.165µs" method=HEAD referer= remote_ip=10.0.2.4 status=200 uri=/apps/d50afb8b-569b-4cfc-86cb-2ec90f5fe6f6/signed user_agent="com.apple.appstored/1.0 iOS/17.4 model/iPhone16,2 hwp/t8130 build/21E219 (6; dt:311) AMS/1" Mar 17 22:18:23 azim SignTools[390828]: 10:18PM INF bytes_in=0 bytes_out=3260512 host=10.0.0.6:7895 latency=48.224842 latency_human=48.224842ms method=GET referer= remote_ip=10.0.2.4 status=200 uri=/apps/d50afb8b-569b-4cfc-86cb-2ec90f5fe6f6/signed user_agent="com.apple.appstored/1.0 iOS/17.4 model/iPhone16,2 hwp/t8130 build/21E219 (6; dt:311) AMS/1" ``` SignTools output for when connecting via reverse proxy: ``` Mar 17 22:16:28 azim SignTools[390828]: 10:16PM INF bytes_in=0 bytes_out=49961 host=signtools.ryuu latency=2.465585 latency_human=2.465585ms method=GET referer= remote_ip=10.0.2.4 status=200 uri=/ user_agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1" Mar 17 22:17:31 azim SignTools[390828]: 10:17PM INF bytes_in=0 bytes_out=1274 host=signtools.ryuu latency=0.237079 latency_human="237.079µs" method=GET referer=https://signtools.ryuu/ remote_ip=10.0.2.4 status=200 uri=/apps/d50afb8b-569b-4cfc-86cb-2ec90f5fe6f6/install user_agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Mobile/15E148 Safari/604.1" Mar 17 22:17:32 azim SignTools[390828]: 10:17PM INF bytes_in=0 bytes_out=1118 host=signtools.ryuu latency=0.189832 latency_human="189.832µs" method=GET referer= remote_ip=10.0.2.4 status=200 uri=/apps/d50afb8b-569b-4cfc-86cb-2ec90f5fe6f6/manifest user_agent="com.apple.appstored/1.0 iOS/17.4 model/iPhone16,2 hwp/t8130 build/21E219 (6; dt:311) AMS/1" ``` SignTools does not make any more logs after getting a 200 on the manifest endpoint. **System configuration** - SignTools version: 3.0.1 - Installation type: personal server; lighttpd for reverse proxy - Operating System: Linux - Builder type: SignTools-Builder - Builder version: 1.1.12; 13250eb **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. ``` $SERVER["socket"] == "10.0.0.6:443" { ssl.engine = "enable" ssl.pemfile = "/etc/lighttpd/ryuu.pem" ssl.openssl.ssl-conf-cmd = ("MinProtocol" => "TLSv1.3", "Options" => "-ServerPreference") $HTTP["host"] == "signtools.ryuu" { proxy.server = ( "" => ( ( "host" => "10.0.0.6", "port" => "7895" ) ) ) proxy.forwarded = ( "host" => 1, "proto" => 1, "for" => 1, "remote_user" => 1 ) proxy.header = ( "upgrade" => "enable" ) } } # All connections to http should redirect to https $SERVER["socket"] == "10.0.0.6:80" { $HTTP["scheme"] == "http" { $HTTP["host"] == "signtools.ryuu" { url.redirect := (".*" => "https://%0$0") } } } ```
kerem 2026-03-04 00:23:52 +03:00
  • closed this issue
  • added the
    bug
    label
Author
Owner

@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:

<!-- gh-comment-id:2002641646 --> @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: - https://github.com/SignTools/SignTools/blob/master/INSTALL.md#4a-reverse-proxy
Author
Owner

@ViRb3 commented on GitHub (Mar 17, 2024):

I think the problem is you're setting X-Forwarded-Host header, but SignTools does not support it currently. You need to set the Host header directly. I will take this as a feature request though.

<!-- gh-comment-id:2002643836 --> @ViRb3 commented on GitHub (Mar 17, 2024): I think the problem is you're setting `X-Forwarded-Host` header, but SignTools does not support it currently. You need to set the `Host` header directly. I will take this as a feature request though.
Author
Owner

@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?

SCR-20240317-mf4

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.

INF bytes_out=49961 host=shisui.ryuu remote_ip=10.0.2.4 status=200 uri=/
INF bytes_out=1274 host=shisui.ryuu referer=https://shisui.ryuu/ remote_ip=10.0.2.4 status=200 uri=/apps/d50afb8b-569b-4cfc-86cb-2ec90f5fe6f6/install
INF bytes_out=1118 host=shisui.ryuu remote_ip=10.0.2.4 status=200 uri=/apps/d50afb8b-569b-4cfc-86cb-2ec90f5fe6f6/manifest

I will toy with some of the lighttpd reverse proxy settings though, see if that can't make some difference.

<!-- gh-comment-id:2002652647 --> @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? ![SCR-20240317-mf4](https://github.com/SignTools/SignTools/assets/4565829/13285e42-9f1e-429b-b64c-71182277a74e) 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. ``` INF bytes_out=49961 host=shisui.ryuu remote_ip=10.0.2.4 status=200 uri=/ INF bytes_out=1274 host=shisui.ryuu referer=https://shisui.ryuu/ remote_ip=10.0.2.4 status=200 uri=/apps/d50afb8b-569b-4cfc-86cb-2ec90f5fe6f6/install INF bytes_out=1118 host=shisui.ryuu remote_ip=10.0.2.4 status=200 uri=/apps/d50afb8b-569b-4cfc-86cb-2ec90f5fe6f6/manifest ``` I will toy with some of the lighttpd reverse proxy settings though, see if that can't make some difference.
Author
Owner

@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 Host header 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/manifest in your browser and seeing what it returns? To be honest I'm very surprised that the host field is correct in the logs.

<!-- gh-comment-id:2002655379 --> @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 `Host` header 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/manifest` in your browser and seeing what it returns? To be honest I'm very surprised that the `host` field is correct in the logs.
Author
Owner

@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.

SignTools[390828]: 11:40PM INF bytes_in=0 bytes_out=1274 host=shisui.ryuu latency=0.223361 latency_human="223.361µs" method=GET referer= remote_ip=10.0.2.4 status=200 uri=/apps/d50afb8b-569b-4cfc-86cb-2ec90f5fe6f6/install
SignTools[390828]: 11:40PM INF bytes_in=0 bytes_out=1274 host=shisui.ryuu latency=0.201726 latency_human="201.726µs" method=GET referer= remote_ip=10.0.2.4 status=200 uri=/apps/d50afb8b-569b-4cfc-86cb-2ec90f5fe6f6/install
SignTools[390828]: 11:40PM INF bytes_in=0 bytes_out=1118 host=shisui.ryuu latency=0.12472 latency_human="124.72µs" method=GET referer= remote_ip=10.0.2.4 status=200 uri=/apps/d50afb8b-569b-4cfc-86cb-2ec90f5fe6f6/manifest
SignTools[390828]: 11:40PM ERR error="code=404, message=Not Found" bytes_in=0 bytes_out=24 host=shisui.ryuu latency=0.031409 latency_human="31.409µs" method=GET referer=https://shisui.ryuu/apps/d50afb8b-569b-4cfc-86cb-2ec90f5fe6f6/manifest remote_ip=10.0.2.4 status=404 uri=/favicon.ico
SignTools[390828]: 11:41PM INF bytes_in=0 bytes_out=3260512 host=shisui.ryuu latency=2.196766 latency_human=2.196766ms method=GET referer= remote_ip=10.0.2.4 status=200 uri=/apps/d50afb8b-569b-4cfc-86cb-2ec90f5fe6f6/signed

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.

SCR-20240317-n8i

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.

<!-- gh-comment-id:2002669175 --> @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. ``` SignTools[390828]: 11:40PM INF bytes_in=0 bytes_out=1274 host=shisui.ryuu latency=0.223361 latency_human="223.361µs" method=GET referer= remote_ip=10.0.2.4 status=200 uri=/apps/d50afb8b-569b-4cfc-86cb-2ec90f5fe6f6/install SignTools[390828]: 11:40PM INF bytes_in=0 bytes_out=1274 host=shisui.ryuu latency=0.201726 latency_human="201.726µs" method=GET referer= remote_ip=10.0.2.4 status=200 uri=/apps/d50afb8b-569b-4cfc-86cb-2ec90f5fe6f6/install SignTools[390828]: 11:40PM INF bytes_in=0 bytes_out=1118 host=shisui.ryuu latency=0.12472 latency_human="124.72µs" method=GET referer= remote_ip=10.0.2.4 status=200 uri=/apps/d50afb8b-569b-4cfc-86cb-2ec90f5fe6f6/manifest SignTools[390828]: 11:40PM ERR error="code=404, message=Not Found" bytes_in=0 bytes_out=24 host=shisui.ryuu latency=0.031409 latency_human="31.409µs" method=GET referer=https://shisui.ryuu/apps/d50afb8b-569b-4cfc-86cb-2ec90f5fe6f6/manifest remote_ip=10.0.2.4 status=404 uri=/favicon.ico SignTools[390828]: 11:41PM INF bytes_in=0 bytes_out=3260512 host=shisui.ryuu latency=2.196766 latency_human=2.196766ms method=GET referer= remote_ip=10.0.2.4 status=200 uri=/apps/d50afb8b-569b-4cfc-86cb-2ec90f5fe6f6/signed ``` 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. ![SCR-20240317-n8i](https://github.com/SignTools/SignTools/assets/4565829/3deec025-fc03-431a-bdc0-60bf1af3c682) 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.
Author
Owner

@ViRb3 commented on GitHub (Mar 18, 2024):

SIgnTools produces a manifest file which contains a URL to your /signed endpoint, 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 proxy in 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 /manifest endpoint say? Does it show your domain name as expected?

<!-- gh-comment-id:2002674944 --> @ViRb3 commented on GitHub (Mar 18, 2024): SIgnTools produces a manifest file which contains a URL to your `/signed` endpoint, 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 proxy` in 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 `/manifest` endpoint say? Does it show your domain name as expected?
Author
Owner

@TJWeiten commented on GitHub (Mar 18, 2024):

Also, what did the /manifest endpoint say? Does it show your domain name as expected?

Yep! Shows the domain name as expected in the Host header and the manifest file. See below:

SCR-20240317-pyr

Come to think of it, if you're seeing using OTA manifest proxy in 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.

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.ipa vs. "shisui.ryuu" would like to install app.ipa. Now I understand what you meant by:

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

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.

<!-- gh-comment-id:2002737380 --> @TJWeiten commented on GitHub (Mar 18, 2024): > Also, what did the /manifest endpoint say? Does it show your domain name as expected? Yep! Shows the domain name as expected in the Host header and the manifest file. See below: ![SCR-20240317-pyr](https://github.com/SignTools/SignTools/assets/4565829/bb88a101-d940-4645-b83a-b5863d62326a) > Come to think of it, if you're seeing using OTA manifest proxy in 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. ~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. <img src="https://github.com/SignTools/SignTools/assets/4565829/3a090ac3-9f86-43b8-968d-e7634835210f" width="400px"/> **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.ipa` vs. `"shisui.ryuu" would like to install app.ipa`. Now I understand what you meant by: > 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 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.
Author
Owner

@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:

server {
    listen 10.0.0.6:443 ssl;
    server_name shisui.ryuu;

    ssl_certificate /etc/lighttpd/ryuu.pem;
    ssl_certificate_key /etc/lighttpd/ryuu.pem;

    location / {
        proxy_pass http://10.0.0.6:7895;
        proxy_set_header Host $http_host;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

server {
    listen 10.0.0.6:80;
    server_name shisui.ryuu;

    location / {
        return 301 https://$host$request_uri;
    }
}

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_UNAUTHORIZED to 0 to get it to function.

<!-- gh-comment-id:2003061426 --> @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: ``` server { listen 10.0.0.6:443 ssl; server_name shisui.ryuu; ssl_certificate /etc/lighttpd/ryuu.pem; ssl_certificate_key /etc/lighttpd/ryuu.pem; location / { proxy_pass http://10.0.0.6:7895; proxy_set_header Host $http_host; proxy_set_header X-Forwarded-Proto $scheme; } } server { listen 10.0.0.6:80; server_name shisui.ryuu; location / { return 301 https://$host$request_uri; } } ``` 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_UNAUTHORIZED` to 0 to get it to function.
Author
Owner

@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.

<!-- gh-comment-id:2005181559 --> @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.
Author
Owner

@ViRb3 commented on GitHub (Mar 19, 2024):

Released an update with support for X-Forwarded-Host, just in case.

<!-- gh-comment-id:2005390383 --> @ViRb3 commented on GitHub (Mar 19, 2024): Released an update with support for `X-Forwarded-Host`, just in case.
Author
Owner

@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:

1. http://10.0.0.6:7895 [SignTools Direct Connection] => "ota.signtools.workers.dev" would like to install => WORKS
2. https://10.0.0.6 [Reverse Proxy -> SignTools] => "10.0.0.6" would like to install => FAILS
3. http://shisui.ryuu:7895 [Pi-Hole DNS -> SignTools Direct Connection] => "ota.signtools.workers.dev" would like to install => FAILS
4. https://shisui.ryuu [Reverse Proxy -> SignTools] => "shisui.ryuu" would like to install => FAILS
5. https://signtools.tjweiten.com [Cloudflare Hosted Domain -> WAN IP -> Port Forwarding to Reverse Proxy -> SignTools] => "signtools.tjweiten.com" would like to install => WORKS

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:

  1. Assuming you already have a self-signed certificate set up, download it in .crt form to your iPhone (I e-mailed the public certificate to myself and saved it to Files)
  2. Open the public certificate from Files
  3. A popup will tell you to "Review the profile in the Settings app if you want to install it."
  4. On the home page of Settings, you should see a "Profile Downloaded" near the top—click it and hit "Install" and follow the prompts
  5. Once installed, in Settings go to General -> About -> scroll to the bottom -> Click 'Certificate Trust Settings'
  6. Under 'Enable full trust for root certificates', flip the switch on your public certificate
  7. SignTools OTA installation should now work with your self-signed certificate
<!-- gh-comment-id:2008300008 --> @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: ``` 1. http://10.0.0.6:7895 [SignTools Direct Connection] => "ota.signtools.workers.dev" would like to install => WORKS 2. https://10.0.0.6 [Reverse Proxy -> SignTools] => "10.0.0.6" would like to install => FAILS 3. http://shisui.ryuu:7895 [Pi-Hole DNS -> SignTools Direct Connection] => "ota.signtools.workers.dev" would like to install => FAILS 4. https://shisui.ryuu [Reverse Proxy -> SignTools] => "shisui.ryuu" would like to install => FAILS 5. https://signtools.tjweiten.com [Cloudflare Hosted Domain -> WAN IP -> Port Forwarding to Reverse Proxy -> SignTools] => "signtools.tjweiten.com" would like to install => WORKS ``` 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: 1. Assuming you already have a self-signed certificate set up, download it in .crt form to your iPhone (I e-mailed the public certificate to myself and saved it to Files) 2. Open the public certificate from Files 3. A popup will tell you to "Review the profile in the Settings app if you want to install it." 4. On the home page of Settings, you should see a "Profile Downloaded" near the top—click it and hit "Install" and follow the prompts 6. Once installed, in Settings go to General -> About -> scroll to the bottom -> Click 'Certificate Trust Settings' 7. Under 'Enable full trust for root certificates', flip the switch on your public certificate 8. SignTools OTA installation should now work with your self-signed certificate
Author
Owner

@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@356d5ff317 probably 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.

<!-- gh-comment-id:2008724881 --> @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 https://github.com/SignTools/SignTools/commit/356d5ff31751273f17b4ddb930bdb2ef976d1bcc _probably_ 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](https://http.dev/forwarded), as [that supersedes X-Forwarded-Host](https://http.dev/x-forwarded-host).
Author
Owner

@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@356d5ff317 still makes sense, as you can't always override the Host header directly. Regarding the new Forwarded header, 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.

<!-- gh-comment-id:2010827353 --> @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 https://github.com/SignTools/SignTools/commit/356d5ff31751273f17b4ddb930bdb2ef976d1bcc still makes sense, as you can't always override the `Host` header directly. Regarding the new `Forwarded` header, 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.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/SignTools#99
No description provided.