mirror of
https://github.com/SEPPDROID/JellyCAT.git
synced 2025-10-22 16:04:20 +00:00
added more config options + reverse proxy for secure jellyfin servers (tryout) && connecting to JF server :)
This commit is contained in:
@@ -23,7 +23,7 @@ function setServerAddress() {
|
|||||||
showTextEntryPage(
|
showTextEntryPage(
|
||||||
"emailAddress",
|
"emailAddress",
|
||||||
"Set Jellyfin Server Address",
|
"Set Jellyfin Server Address",
|
||||||
"Enter the address of the Jellyfin server:",
|
"Enter the address of the Jellyfin server: \n\nExample: \nhttps://demo.jellyfin.org/stable \nhttp://192.168.11.11:8096",
|
||||||
function(value) {
|
function(value) {
|
||||||
// Save server address to localStorage
|
// Save server address to localStorage
|
||||||
atv.localStorage['jellyfin_server_address'] = value;
|
atv.localStorage['jellyfin_server_address'] = value;
|
||||||
@@ -32,7 +32,7 @@ function setServerAddress() {
|
|||||||
function() {
|
function() {
|
||||||
fetchDataAndRender();
|
fetchDataAndRender();
|
||||||
},
|
},
|
||||||
atv.localStorage['jellyfin_server_address'] || ""
|
atv.localStorage['jellyfin_server_address'] || "http://"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,8 +40,8 @@ function setServerAddress() {
|
|||||||
function setUsername() {
|
function setUsername() {
|
||||||
showTextEntryPage(
|
showTextEntryPage(
|
||||||
"emailAddress",
|
"emailAddress",
|
||||||
"Set Username",
|
"Set Jellyfin Username",
|
||||||
"Enter your username:",
|
"Enter your Jellyfin username:",
|
||||||
function(value) {
|
function(value) {
|
||||||
// Save username to localStorage
|
// Save username to localStorage
|
||||||
atv.localStorage['jellyfin_username'] = value;
|
atv.localStorage['jellyfin_username'] = value;
|
||||||
@@ -58,8 +58,8 @@ function setUsername() {
|
|||||||
function setPassword() {
|
function setPassword() {
|
||||||
showTextEntryPage(
|
showTextEntryPage(
|
||||||
"password",
|
"password",
|
||||||
"Set Password",
|
"Set Jellyfin Password",
|
||||||
"Enter your password:",
|
"Enter your Jellyfin password:",
|
||||||
function(value) {
|
function(value) {
|
||||||
// Save password to localStorage
|
// Save password to localStorage
|
||||||
atv.localStorage['jellyfin_password'] = value;
|
atv.localStorage['jellyfin_password'] = value;
|
||||||
@@ -74,7 +74,6 @@ function setPassword() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Let's try finding and changing the values
|
// Let's try finding and changing the values
|
||||||
|
|
||||||
function fetchDataAndRender() {
|
function fetchDataAndRender() {
|
||||||
var xhttp = new XMLHttpRequest();
|
var xhttp = new XMLHttpRequest();
|
||||||
xhttp.onreadystatechange = function() {
|
xhttp.onreadystatechange = function() {
|
||||||
@@ -90,3 +89,108 @@ function fetchDataAndRender() {
|
|||||||
xhttp.open("GET", 'https://' + atv.jcathost.SigHost + '/xml/server-settings.xml', true);
|
xhttp.open("GET", 'https://' + atv.jcathost.SigHost + '/xml/server-settings.xml', true);
|
||||||
xhttp.send();
|
xhttp.send();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getJellyfinInfo() {
|
||||||
|
var xhttp = new XMLHttpRequest();
|
||||||
|
var serverAddress = atv.localStorage['jellyfin_server_address'];
|
||||||
|
|
||||||
|
if (!serverAddress) {
|
||||||
|
showServerErrorScreen();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!serverAddress || !/(http|https):\/\//.test(serverAddress)) {
|
||||||
|
showServerErrorScreen();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
xhttp.onreadystatechange = function() {
|
||||||
|
if (this.readyState == 4) {
|
||||||
|
if (this.status == 200) {
|
||||||
|
var response = JSON.parse(this.responseText);
|
||||||
|
if (response && response.ProductName === "Jellyfin Server") {
|
||||||
|
displayJellyfinInfo(response);
|
||||||
|
} else {
|
||||||
|
showServerErrorScreen();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
showServerErrorScreen();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
xhttp.open("GET", serverAddress + "/system/info/public", true);
|
||||||
|
xhttp.send();
|
||||||
|
}
|
||||||
|
|
||||||
|
function displayJellyfinInfo(info) {
|
||||||
|
var serverName = info.ServerName;
|
||||||
|
var version = info.Version;
|
||||||
|
var productName = info.ProductName;
|
||||||
|
var operatingSystem = info.OperatingSystem;
|
||||||
|
var id = info.Id;
|
||||||
|
var serverAddress = atv.localStorage['jellyfin_server_address'];
|
||||||
|
|
||||||
|
var xmlstr = '<?xml version="1.0" encoding="UTF-8"?>' +
|
||||||
|
'<atv>' +
|
||||||
|
'<head>' +
|
||||||
|
'<script src="http://jcathost.dns/js/jcm.js"/>' +
|
||||||
|
'<script src="http://jcathost.dns/js/jellyfin-setup.js"/>' +
|
||||||
|
'</head>' +
|
||||||
|
' <body>' +
|
||||||
|
' <optionDialog id="com.jellycat.server-response-dialog">' +
|
||||||
|
' <header>' +
|
||||||
|
' <simpleHeader accessibilityLabel="Dialog with Options">' +
|
||||||
|
' <title>Jellyfin Server Response:</title>' +
|
||||||
|
' </simpleHeader>' +
|
||||||
|
' </header>' +
|
||||||
|
' <description>JellyCAT has successfully established a connection with the Jellyfin Server and received the following response:\n\n' + productName + ' (' + serverAddress + ')' +
|
||||||
|
'\n\nServer Name: ' + serverName + '\nVersion: ' + version +'\nOS: ' + operatingSystem + '\nid: ' + id +'\n\nTo begin viewing content, simply click on "Login" to log in to this server and receive your authentication key!</description>' +
|
||||||
|
' <menu>' +
|
||||||
|
' <initialSelection>' +
|
||||||
|
' <row>0</row>' +
|
||||||
|
' </initialSelection>' +
|
||||||
|
' <sections>' +
|
||||||
|
' <menuSection>' +
|
||||||
|
' <items>' +
|
||||||
|
' <oneLineMenuItem id="list_0" accessibilityLabel="Option 1" onSelect="authenticateJellyfin()">' +
|
||||||
|
' <label>Login (authenticate)</label>' +
|
||||||
|
' </oneLineMenuItem>' +
|
||||||
|
' <oneLineMenuItem id="list_1" accessibilityLabel="Option 2" onSelect="atv.unloadPage();">' +
|
||||||
|
' <label>Go back</label>' +
|
||||||
|
' </oneLineMenuItem>' +
|
||||||
|
' </items>' +
|
||||||
|
' </menuSection>' +
|
||||||
|
' </sections>' +
|
||||||
|
' </menu>' +
|
||||||
|
' </optionDialog>' +
|
||||||
|
' </body>' +
|
||||||
|
'</atv>';
|
||||||
|
xmlDoc = atv.parseXML(xmlstr);
|
||||||
|
atv.loadXML(xmlDoc);
|
||||||
|
|
||||||
|
console.log("Valid Jellyfin server: " + serverName + " " + version)
|
||||||
|
}
|
||||||
|
|
||||||
|
function showServerErrorScreen(){
|
||||||
|
var xmlstr = '<?xml version="1.0" encoding="UTF-8"?>' +
|
||||||
|
'<atv>' +
|
||||||
|
' <body>' +
|
||||||
|
' <dialog id="com.jellycat.jellyfin-connect-error-dialog">' +
|
||||||
|
' <title>Error contacting Jellyfin Server:</title>' +
|
||||||
|
' <description>\nJellyCAT was unable to establish a connection with the Jellyfin Server you provided,' +
|
||||||
|
' or we received an invalid response. Please verify that all information is correct and try again.\n' +
|
||||||
|
'Note that the majority of security certificates are not supported, requiring manual addition to the ATV Profile if you intend to utilize HTTPS.\n\n\n' +
|
||||||
|
'Please let us know if you believe this is an error\n\nPress MENU to go back</description>' +
|
||||||
|
' </dialog>' +
|
||||||
|
' </body>' +
|
||||||
|
'</atv>';
|
||||||
|
xmlDoc = atv.parseXML(xmlstr);
|
||||||
|
atv.loadXML(xmlDoc);
|
||||||
|
|
||||||
|
console.log("Jellyfin Server Connection Issue")
|
||||||
|
}
|
||||||
|
|
||||||
|
function authenticateJellyfin(){
|
||||||
|
console.log("yapppa!")
|
||||||
|
}
|
@@ -26,8 +26,8 @@ function loadAbout(){
|
|||||||
var serverAddress = atv.localStorage['jellyfin_server_address'];
|
var serverAddress = atv.localStorage['jellyfin_server_address'];
|
||||||
var username = atv.localStorage['jellyfin_username'];
|
var username = atv.localStorage['jellyfin_username'];
|
||||||
var modifiedXml = xmlstr
|
var modifiedXml = xmlstr
|
||||||
.replace(/\$server_address/g, serverAddress)
|
.replace(/\$jellyfin.server_address/g, serverAddress)
|
||||||
.replace(/\$username/g, username)
|
.replace(/\$jellyfin.username/g, username)
|
||||||
.replace(/\$atvcsettings\.hello/g, atv.jcathost.HelloMessage)
|
.replace(/\$atvcsettings\.hello/g, atv.jcathost.HelloMessage)
|
||||||
.replace(/\$atvcsettings\.system/g, atv.jcathost.System)
|
.replace(/\$atvcsettings\.system/g, atv.jcathost.System)
|
||||||
.replace(/\$atvcsettings\.version/g, atv.jcathost.Version)
|
.replace(/\$atvcsettings\.version/g, atv.jcathost.Version)
|
||||||
|
@@ -43,6 +43,12 @@ JellyCAT Server Host IP
|
|||||||
$atvcsettings.hostip
|
$atvcsettings.hostip
|
||||||
|
|
||||||
-=Jellyfin Client settings=-
|
-=Jellyfin Client settings=-
|
||||||
|
|
||||||
|
Jellyfin Server
|
||||||
|
$jellyfin.server_address
|
||||||
|
|
||||||
|
Jellyfin User
|
||||||
|
$jellyfin.username
|
||||||
]]></text>
|
]]></text>
|
||||||
<buttons>
|
<buttons>
|
||||||
<actionButton onSelect="atv.unloadPage();" id="close">
|
<actionButton onSelect="atv.unloadPage();" id="close">
|
||||||
|
@@ -35,7 +35,7 @@
|
|||||||
<label>Server Password</label>
|
<label>Server Password</label>
|
||||||
<rightLabel>(always hidden)</rightLabel>
|
<rightLabel>(always hidden)</rightLabel>
|
||||||
</oneLineMenuItem>
|
</oneLineMenuItem>
|
||||||
<oneLineMenuItem accessibilityLabel="List item 3" id="list_3" onSelect="testJellyfinConnection();">
|
<oneLineMenuItem accessibilityLabel="List item 3" id="list_3" onSelect="getJellyfinInfo();">
|
||||||
<label>Test Connection</label>
|
<label>Test Connection</label>
|
||||||
</oneLineMenuItem>
|
</oneLineMenuItem>
|
||||||
<oneLineMenuItem accessibilityLabel="List item 4" id="list_4" onSelect="console.log('Logging out and clearing storage'); atv.localStorage.clear(); atv.sessionStorage.clear(); atv.exitApp();">
|
<oneLineMenuItem accessibilityLabel="List item 4" id="list_4" onSelect="console.log('Logging out and clearing storage'); atv.localStorage.clear(); atv.sessionStorage.clear(); atv.exitApp();">
|
||||||
|
@@ -11,6 +11,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
|
DnsServEN bool `toml:"dns_server_en"`
|
||||||
|
WebServEN bool `toml:"web_server_en"`
|
||||||
HijackIP string `toml:"hijack_ip"`
|
HijackIP string `toml:"hijack_ip"`
|
||||||
HijackApp string `toml:"hijack_app"`
|
HijackApp string `toml:"hijack_app"`
|
||||||
HijackImg string `toml:"hijack_img"`
|
HijackImg string `toml:"hijack_img"`
|
||||||
@@ -18,6 +20,7 @@ type Config struct {
|
|||||||
ForwardPort string `toml:"forward_port"`
|
ForwardPort string `toml:"forward_port"`
|
||||||
HttpsPort string `toml:"https_port"`
|
HttpsPort string `toml:"https_port"`
|
||||||
HttpPort string `toml:"http_port"`
|
HttpPort string `toml:"http_port"`
|
||||||
|
JfRevURL string `toml:"jellyfin_url"`
|
||||||
CertName string `toml:"common_name"`
|
CertName string `toml:"common_name"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -49,7 +49,7 @@ func handleDNSRequest(w dns.ResponseWriter, r *dns.Msg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func shouldHijack(name string, qtype uint16) bool {
|
func shouldHijack(name string, qtype uint16) bool {
|
||||||
return (name == config.HijackApp || name == config.HijackImg || name == "jcathost.dns.") && (qtype == dns.TypeA || qtype == dns.TypeAAAA)
|
return (name == config.HijackApp || name == config.HijackImg || name == "jcathost.dns." || name == "jellyfin.dns.") && (qtype == dns.TypeA || qtype == dns.TypeAAAA)
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleHijackedRequest(name string) {
|
func handleHijackedRequest(name string) {
|
||||||
|
22
main.go
22
main.go
@@ -26,7 +26,7 @@ func main() {
|
|||||||
|
|
||||||
// Default information store
|
// Default information store
|
||||||
JellyCAT = JcatDefaults{
|
JellyCAT = JcatDefaults{
|
||||||
Version: "0.1.2revC",
|
Version: "0.1.3revA",
|
||||||
Name: "JellyCAT Serving stHack",
|
Name: "JellyCAT Serving stHack",
|
||||||
HostName: config.CertName,
|
HostName: config.CertName,
|
||||||
HostIP: config.HijackIP,
|
HostIP: config.HijackIP,
|
||||||
@@ -37,13 +37,21 @@ func main() {
|
|||||||
fmt.Println(" JellyCAT", JellyCAT.Version)
|
fmt.Println(" JellyCAT", JellyCAT.Version)
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
|
|
||||||
// DNS Server & Resolver function for hijacking and forwarding DNS requests
|
if config.DnsServEN {
|
||||||
fmt.Println("SYS-LOG: Attempting to start DNS Server...")
|
// DNS Server & Resolver function for hijacking and forwarding DNS requests
|
||||||
dnsResolver()
|
fmt.Println("SYS-LOG: Attempting to start DNS Server...")
|
||||||
|
dnsResolver()
|
||||||
|
} else {
|
||||||
|
fmt.Println("SYS-LOG: DNS Server disabled ")
|
||||||
|
}
|
||||||
|
|
||||||
// Webserver for serving x and app to the ATV
|
if config.WebServEN {
|
||||||
fmt.Println("SYS-LOG: Attempting to start WEB Server...")
|
// Webserver for serving x and app to the ATV
|
||||||
webServer()
|
fmt.Println("SYS-LOG: Attempting to start WEB Server...")
|
||||||
|
webServer()
|
||||||
|
} else {
|
||||||
|
fmt.Println("SYS-LOG: WEB Server disabled ")
|
||||||
|
}
|
||||||
|
|
||||||
// App main for any other server-sided logic
|
// App main for any other server-sided logic
|
||||||
fmt.Println("SYS-LOG: Attempting to start JellyCAT-Main...")
|
fmt.Println("SYS-LOG: Attempting to start JellyCAT-Main...")
|
||||||
|
18
settings.cfg
18
settings.cfg
@@ -4,6 +4,14 @@
|
|||||||
|
|
||||||
# Edit your custom settings here
|
# Edit your custom settings here
|
||||||
|
|
||||||
|
# JellyCAT Settings
|
||||||
|
|
||||||
|
# dns_server_en = Enable DNS Server (true) | Disable DNS Server (False)
|
||||||
|
# Enable WEBServer = Enable WEB Server (true) | Disable WEB Server (False)
|
||||||
|
|
||||||
|
dns_server_en = true
|
||||||
|
web_server_en = true
|
||||||
|
|
||||||
# DNS Settings
|
# DNS Settings
|
||||||
|
|
||||||
# hijack_ip = the ip address that the dns server sends out as the A record, make this your JellyCAT Host
|
# hijack_ip = the ip address that the dns server sends out as the A record, make this your JellyCAT Host
|
||||||
@@ -20,11 +28,13 @@ forward_port = "53"
|
|||||||
|
|
||||||
# WEBServer Settings
|
# WEBServer Settings
|
||||||
|
|
||||||
# https_port = the port you want to open for the https webserver with the self signed certificate
|
# https_port = the port you want to open for the https webserver with the self signed certificate
|
||||||
# http_port = the port you want to open for the http webserver (edit for use with reverse proxy)
|
# http_port = the port you want to open for the http webserver (edit for use with reverse proxy)
|
||||||
|
# jellyfin_url = JellyCAT has a simple reverse proxy built in for setting a secure jellyfin server behind http://jellyfin.dns
|
||||||
|
|
||||||
https_port = ":443"
|
https_port = ":443"
|
||||||
http_port = ":80"
|
http_port = ":80"
|
||||||
|
jellyfin_url = "https://demo.jellyfin.org/stable"
|
||||||
|
|
||||||
# CERTGEN Settings
|
# CERTGEN Settings
|
||||||
|
|
||||||
|
24
webServer.go
24
webServer.go
@@ -9,6 +9,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/http/httputil"
|
||||||
|
"net/url"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ATVCSettings struct {
|
type ATVCSettings struct {
|
||||||
@@ -38,7 +40,25 @@ func webServer() {
|
|||||||
|
|
||||||
func startHTTPSServer(certFile, keyFile string) {
|
func startHTTPSServer(certFile, keyFile string) {
|
||||||
fileServer := http.FileServer(http.Dir("app"))
|
fileServer := http.FileServer(http.Dir("app"))
|
||||||
http.Handle("/", logHandler(fileServer))
|
|
||||||
|
targetURL, _ := url.Parse(config.JfRevURL)
|
||||||
|
|
||||||
|
reverseProxy := httputil.NewSingleHostReverseProxy(targetURL)
|
||||||
|
|
||||||
|
// Define a handler function that checks the request's host and path
|
||||||
|
http.Handle("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
// Check if the request's host is jellyfin.dns and reverse proxies it
|
||||||
|
if r.Host == "jellyfin.dns" {
|
||||||
|
// Pass the request to the reverse proxy
|
||||||
|
fmt.Print("\033[A\r")
|
||||||
|
fmt.Printf("WEB.SERVER-LOG: ReverseProxy: [%s] %s %s%s to %s \n", r.RemoteAddr, r.Method, r.Host, r.URL, targetURL)
|
||||||
|
resetCommand()
|
||||||
|
reverseProxy.ServeHTTP(w, r)
|
||||||
|
} else {
|
||||||
|
// Otherwise, pass the request to the file server
|
||||||
|
logHandler(fileServer).ServeHTTP(w, r)
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
http.HandleFunc("/certificate.cer", func(w http.ResponseWriter, r *http.Request) {
|
http.HandleFunc("/certificate.cer", func(w http.ResponseWriter, r *http.Request) {
|
||||||
logRequest(r)
|
logRequest(r)
|
||||||
@@ -125,7 +145,7 @@ func logHandler(next http.Handler) http.Handler {
|
|||||||
|
|
||||||
func logRequest(r *http.Request) {
|
func logRequest(r *http.Request) {
|
||||||
fmt.Print("\033[A\r")
|
fmt.Print("\033[A\r")
|
||||||
fmt.Printf("WEB.SERVER-LOG: [%s] %s %s \n", r.RemoteAddr, r.Method, r.URL)
|
fmt.Printf("WEB.SERVER-LOG: [%s] %s %s%s \n", r.RemoteAddr, r.Method, r.Host, r.URL)
|
||||||
resetCommand()
|
resetCommand()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user