Add serverip= config option to pin the domain to a LAN IP
The "unsupported protocol" failure was never about HTTPS: the Vita resolved the public domain to the WAN IP, the router (no NAT loopback) answered with its own admin page, and curl reported the resulting HTTP/0.9 garbage as CURLE_UNSUPPORTED_PROTOCOL. serverip= pins the hostname to the LAN IP via CURLOPT_RESOLVE, keeping Host/SNI intact for the reverse proxy. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+2
-1
@@ -11,7 +11,7 @@ endif()
|
|||||||
project(vitaImmich C)
|
project(vitaImmich C)
|
||||||
include("${VITASDK}/share/vita.cmake" REQUIRED)
|
include("${VITASDK}/share/vita.cmake" REQUIRED)
|
||||||
|
|
||||||
set(VITA_APP_NAME "Vita Immich")
|
set(VITA_APP_NAME "Immich")
|
||||||
set(VITA_TITLEID "VIMM00001")
|
set(VITA_TITLEID "VIMM00001")
|
||||||
set(VITA_VERSION "01.00")
|
set(VITA_VERSION "01.00")
|
||||||
|
|
||||||
@@ -47,4 +47,5 @@ vita_create_self(${PROJECT_NAME}.self ${PROJECT_NAME})
|
|||||||
vita_create_vpk(${PROJECT_NAME}.vpk ${VITA_TITLEID} ${PROJECT_NAME}.self
|
vita_create_vpk(${PROJECT_NAME}.vpk ${VITA_TITLEID} ${PROJECT_NAME}.self
|
||||||
VERSION ${VITA_VERSION}
|
VERSION ${VITA_VERSION}
|
||||||
NAME ${VITA_APP_NAME}
|
NAME ${VITA_APP_NAME}
|
||||||
|
FILE ${CMAKE_SOURCE_DIR}/assets/sce_sys/icon0.png sce_sys/icon0.png
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -37,6 +37,19 @@ This produces `build/vitaImmich.vpk`.
|
|||||||
apikey=your-immich-api-key
|
apikey=your-immich-api-key
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If your server sits behind a public domain (reverse proxy) and your
|
||||||
|
router does not support NAT loopback, add the server's LAN IP so the
|
||||||
|
domain is pinned to it while on your home network:
|
||||||
|
|
||||||
|
```
|
||||||
|
server=https://immich.example.com
|
||||||
|
apikey=your-immich-api-key
|
||||||
|
serverip=192.168.1.100
|
||||||
|
```
|
||||||
|
|
||||||
|
This keeps the Host header and TLS SNI on the domain (so the reverse
|
||||||
|
proxy still routes correctly) but connects to the LAN IP directly.
|
||||||
|
|
||||||
4. Relaunch the app.
|
4. Relaunch the app.
|
||||||
|
|
||||||
## Controls
|
## Controls
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
+36
-1
@@ -51,6 +51,9 @@ int _newlib_heap_size_user = 192 * 1024 * 1024;
|
|||||||
|
|
||||||
static char g_server[512];
|
static char g_server[512];
|
||||||
static char g_apikey[256];
|
static char g_apikey[256];
|
||||||
|
static char g_serverip[64];
|
||||||
|
/* optional DNS pin ("host:port:ip") for routers without NAT loopback */
|
||||||
|
static struct curl_slist *g_resolve_list;
|
||||||
|
|
||||||
static vita2d_pgf *g_font;
|
static vita2d_pgf *g_font;
|
||||||
|
|
||||||
@@ -167,7 +170,9 @@ static int load_config(void)
|
|||||||
f = fopen(CONFIG_PATH, "w");
|
f = fopen(CONFIG_PATH, "w");
|
||||||
if (f) {
|
if (f) {
|
||||||
fputs("server=http://192.168.1.100:2283\n"
|
fputs("server=http://192.168.1.100:2283\n"
|
||||||
"apikey=PASTE_YOUR_IMMICH_API_KEY_HERE\n", f);
|
"apikey=PASTE_YOUR_IMMICH_API_KEY_HERE\n"
|
||||||
|
"# serverip=192.168.1.100 (optional: LAN IP of the\n"
|
||||||
|
"# server, for routers without NAT loopback)\n", f);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
@@ -180,6 +185,8 @@ static int load_config(void)
|
|||||||
snprintf(g_server, sizeof(g_server), "%s", clean_line(s + 7));
|
snprintf(g_server, sizeof(g_server), "%s", clean_line(s + 7));
|
||||||
else if (!strncmp(s, "apikey=", 7))
|
else if (!strncmp(s, "apikey=", 7))
|
||||||
snprintf(g_apikey, sizeof(g_apikey), "%s", clean_line(s + 7));
|
snprintf(g_apikey, sizeof(g_apikey), "%s", clean_line(s + 7));
|
||||||
|
else if (!strncmp(s, "serverip=", 9))
|
||||||
|
snprintf(g_serverip, sizeof(g_serverip), "%s", clean_line(s + 9));
|
||||||
}
|
}
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
@@ -200,6 +207,30 @@ static int load_config(void)
|
|||||||
if (strncasecmp(g_server, "http://", 7) && strncasecmp(g_server, "https://", 8))
|
if (strncasecmp(g_server, "http://", 7) && strncasecmp(g_server, "https://", 8))
|
||||||
fatal_error(g_server,
|
fatal_error(g_server,
|
||||||
"Bad server URL in config (must start with http:// or https://):");
|
"Bad server URL in config (must start with http:// or https://):");
|
||||||
|
|
||||||
|
/* serverip= pins the hostname to a fixed IP (keeps Host header and
|
||||||
|
* TLS SNI intact, unlike putting the IP in the URL) */
|
||||||
|
if (g_serverip[0]) {
|
||||||
|
int https = !strncasecmp(g_server, "https://", 8);
|
||||||
|
const char *host = strstr(g_server, "://") + 3;
|
||||||
|
char hostname[256];
|
||||||
|
size_t i = 0;
|
||||||
|
while (host[i] && host[i] != '/' && host[i] != ':' &&
|
||||||
|
i < sizeof(hostname) - 1) {
|
||||||
|
hostname[i] = host[i];
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
hostname[i] = '\0';
|
||||||
|
int port = https ? 443 : 80;
|
||||||
|
if (host[i] == ':')
|
||||||
|
port = atoi(host + i + 1);
|
||||||
|
|
||||||
|
char resolve[400];
|
||||||
|
snprintf(resolve, sizeof(resolve), "%s:%d:%s",
|
||||||
|
hostname, port, g_serverip);
|
||||||
|
g_resolve_list = curl_slist_append(NULL, resolve);
|
||||||
|
log_line("resolve pin: %s", resolve);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -296,6 +327,8 @@ static CURLcode http_request(const char *url, const char *body,
|
|||||||
/* PoC: no CA bundle on the Vita, skip TLS verification */
|
/* PoC: no CA bundle on the Vita, skip TLS verification */
|
||||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
|
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
|
||||||
|
if (g_resolve_list)
|
||||||
|
curl_easy_setopt(curl, CURLOPT_RESOLVE, g_resolve_list);
|
||||||
if (body)
|
if (body)
|
||||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body);
|
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body);
|
||||||
if (g_verbose_request) {
|
if (g_verbose_request) {
|
||||||
@@ -725,6 +758,8 @@ static int worker_thread(SceSize args, void *argp)
|
|||||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, "vitaImmich/0.1 (PS Vita)");
|
curl_easy_setopt(curl, CURLOPT_USERAGENT, "vitaImmich/0.1 (PS Vita)");
|
||||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
|
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
|
||||||
|
if (g_resolve_list)
|
||||||
|
curl_easy_setopt(curl, CURLOPT_RESOLVE, g_resolve_list);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (g_req_state != REQ_PENDING) {
|
if (g_req_state != REQ_PENDING) {
|
||||||
|
|||||||
Reference in New Issue
Block a user