CzADSB-Mapa: Porovnání verzí
(→debug-file.lua) |
(→sso_auth.lua) |
||
| Řádka 185: | Řádka 185: | ||
=== sso_auth.lua === | === sso_auth.lua === | ||
| + | |||
| + | -- Konfigurace | ||
| + | local secret = "vase_velmi_tajne_heslo_123456" | ||
| + | local login_url = "https://user.czadsb.cz/index.php?page=login&return=mapy&mapa=tar" | ||
| + | local cookie_name = "czadsb_sso" | ||
| + | |||
| + | -- Lokalni IP (whitelist) | ||
| + | local trusted_ips = { | ||
| + | ["127.0.0.1"] = true, | ||
| + | ["::1"] = true, | ||
| + | ["10.129.99.145"] = true, | ||
| + | } | ||
| + | |||
| + | -- Opustit statiku (bleskove) | ||
| + | local uri = lighty.env["uri.path"] or "" | ||
| + | if uri:match("%.%w%w%w?$") and not uri:match("%.php") and not uri:match("%.html") then | ||
| + | return 0 | ||
| + | end | ||
| + | |||
| + | -- Zjisteni IP adresy a opustit pokud je v whitelist IP (bleskove) | ||
| + | local final_ip = lighty.request["X-Forwarded-For"] or lighty.env["request.remote-ip"] or lighty.env["remote_addr"] | ||
| + | if final_ip then | ||
| + | final_ip = final_ip:match("([^, ]+)") | ||
| + | if trusted_ips[final_ip] then return 0 end | ||
| + | end | ||
| + | |||
| + | -- Funkce pro logovani | ||
| + | local function debug_log(msg) | ||
| + | print("[SSO-DEBUG] " .. tostring(msg)) | ||
| + | end | ||
| + | |||
| + | -- Funkce pro Base64 dekodovani | ||
| + | local function base64_decode(data) | ||
| + | local b = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' | ||
| + | data = string.gsub(data, '[^'..b..'=]', '') | ||
| + | return (data:gsub('.', function(x) | ||
| + | if (x == '=') then return '' end | ||
| + | local r,f='',(b:find(x)-1) | ||
| + | for i=6,1,-1 do r=r..(f%2^i-f%2^(i-1)>0 and '1' or '0') end | ||
| + | return r; | ||
| + | end):gsub('%d%d%d%d%d%d%d%d', function(x) | ||
| + | local r=0 | ||
| + | for i=1,8 do r=r+(x:sub(i,i)=='1' and 2^(8-i) or 0) end | ||
| + | return string.char(r) | ||
| + | end)) | ||
| + | end | ||
| + | |||
| + | -- Funkce pro URL dekodovani | ||
| + | local function url_decode(str) | ||
| + | str = string.gsub(str, "+", " ") | ||
| + | str = string.gsub(str, "%%(%x%x)", function(h) return string.char(tonumber(h, 16)) end) | ||
| + | return str | ||
| + | end | ||
| + | |||
| + | -- Nacteni HMAC knihovny (lua-ossl) | ||
| + | local status_hmac, openssl_hmac = pcall(require, "openssl.hmac") | ||
| + | if not status_hmac then | ||
| + | debug_log("CHYBA: Knihovna openssl.hmac nenalezena!") | ||
| + | return 500 | ||
| + | end | ||
| + | |||
| + | -- Nacteni a zpracovani Cookie | ||
| + | local cookie_header = lighty.request["Cookie"] or lighty.request["cookie"] | ||
| + | |||
| + | if cookie_header then | ||
| + | local sso_cookie_raw = cookie_header:match(cookie_name .. "=([^;]+)") | ||
| + | |||
| + | if sso_cookie_raw then | ||
| + | local sso_cookie = url_decode(sso_cookie_raw) | ||
| + | local status_b64, decoded = pcall(base64_decode, sso_cookie) | ||
| + | |||
| + | if status_b64 and decoded then | ||
| + | local sep_pos = decoded:find("||") | ||
| + | if sep_pos then | ||
| + | local payload = decoded:sub(1, sep_pos - 1) | ||
| + | local signature_raw = decoded:sub(sep_pos + 2) | ||
| + | |||
| + | -- RESENI: SHA256 HEX ma vzdy 64 znaku. Orizneme pripadne nuly z dekoderu. | ||
| + | local signature = signature_raw:sub(1, 64) | ||
| + | |||
| + | -- HMAC SHA256 vypocet | ||
| + | local h = openssl_hmac.new(secret, "SHA256") | ||
| + | h:update(payload) | ||
| + | local bin_sig = h:final() | ||
| + | |||
| + | local hex_sig = "" | ||
| + | for i = 1, #bin_sig do | ||
| + | hex_sig = hex_sig .. string.format("%02x", string.byte(bin_sig, i)) | ||
| + | end | ||
| + | |||
| + | if hex_sig == signature then | ||
| + | -- Rozdeleni payloadu (user_id|username|time) | ||
| + | local parts = {} | ||
| + | for part in (payload .. "|"):gmatch("([^|]*)|") do | ||
| + | table.insert(parts, part) | ||
| + | end | ||
| + | |||
| + | local u_time = tonumber(parts[3]) | ||
| + | if u_time then | ||
| + | local diff = os.time() - u_time | ||
| + | if diff >= 0 and diff < 7200 then | ||
| + | -- debug_log("Autentizace OK pro: " .. tostring(parts[2])) | ||
| + | return 0 | ||
| + | else | ||
| + | debug_log("Cookie vyprsela, rozdil: " .. diff) | ||
| + | end | ||
| + | end | ||
| + | else | ||
| + | debug_log("Podpis nesouhlasi! (" .. final_ip .. ")") | ||
| + | debug_log("Vypocteno: " .. hex_sig) | ||
| + | debug_log("Prijato (upraveno): " .. signature) | ||
| + | debug_log("Prijato (raw): " .. signature_raw) | ||
| + | end | ||
| + | end | ||
| + | end | ||
| + | end | ||
| + | end | ||
| + | |||
| + | -- Pridani hlavicek proti cachovani pro jistotu | ||
| + | lighty.header["Cache-Control"] = "no-cache, no-store, must-revalidate" | ||
| + | lighty.header["Connection"] = "close" | ||
| + | lighty.header["Pragma"] = "no-cache" | ||
| + | lighty.header["Expires"] = "0" | ||
| + | |||
| + | -- Pokud nic neproslo, presmerujeme | ||
| + | debug_log("Pristup odmitnut, presmerovani (" .. final_ip .. " | " .. uri .. ").") | ||
| + | lighty.header["Location"] = login_url | ||
| + | return 302 | ||
Verze z 15. 2. 2026, 13:00
Obsah
Uvod
Predpokladany postup instalace
- Pripravit si distribuci
- Zkompilovat ReADSB (nepotrebujeme zadne sdr ovladace)
- Nastavit ReADSB
- Nainstalovat Tar1090
- Zkonfigurovat Tar1090
Distribuce
Nebojime se niceho, takze jdeme do nejnovejsiho operacniho systemu, at mame na dlouho klid. Priparvime si komplet distribuci vcetne aktualizaci a ovladaci pro virtual ( Linux & Aplikace ).
WebServer
Pro provoz potrebujeme jeden ze dvou nize uvedenych web serveru. Volba je v podstate na vas, ale Tar1090 ma primo integrovanou podporu pro Lighttpd.
Lighttpd
# prvne nainstalujeme WebServer. Doporu4uje se nginx, nebo lighttpd sudo apt install -y lighttpd sudo apt install -y lighttpd-mod-authn-pam sudo apt install -y lighttpd-modules-lua lua-luaossl
Nginx
# prvne nainstalujeme WebServer. Doporu4uje se nginx, nebo lighttpd sudo apt install nginx
ReADSB
Kompilace
sudo apt update && sudo apt upgrade -y sudo apt install --no-install-recommends --no-install-suggests -y \ git build-essential debhelper libusb-1.0-0-dev pkg-config fakeroot libncurses-dev zlib1g-dev libzstd-dev librtlsdr-dev help2man git clone --depth 20 https://github.com/wiedehopf/readsb.git cd readsb rm -f ../readsb_*.deb export DEB_BUILD_OPTIONS=noddebs dpkg-buildpackage -b -ui -uc -us
Pokud již máme potřebný balíček, tak jej nainstalujeme:
cd rm -f /tmp/readsb_*.deb cp ./readsb_*.deb /tmp/ sudo apt install /tmp/readsb_*.deb rm -f /tmp/readsb_*.deb
Dale vytvorime pravidlo pro Lighttpd (pokud jsme jej instalovali
sudo wget -q https://rxw.cz/adsb/install/web/64-readsb.conf -O /etc/lighttpd/conf-available/64-readsb.conf sudo ln -s ../conf-available/64-readsb.conf /etc/lighttpd/conf-enabled/64-readsb.conf sudo wget -q https://rxw.cz/adsb/install/web/system.cgi -O /var/www/html/system.cgi sudo systemctl reload lighttpd.service
Nastaveni ReADSB
sudo mcedit /etc/default/readsb
# readsb configuration # This is sourced by /etc/systemd/system/default.target.wants/readsb.service as # daemon startup configuration. RECEIVER_OPTIONS="--net --net-only --net-ingest --net-connector 10.0.0.74,30005,beast_in,silent_fail --net-connector 10.129.99.147,30005,beast_in,silent_fail --net-connector 10.0.0.73,30005,beast_in,silent_fail" DECODER_OPTIONS="--write-json-every 1 --net-beast-reduce-interval 0.5 --net-heartbeat 60 --net-ro-size 1280 --net-ro-interval=0.05 --net-ro-interval-beast-reduce=0.12" NET_OPTIONS="--net-ro-port 0 --net-sbs-port 0 --net-bi-port 0 --net-bo-port 0 --net-ri-port 0 --net-api-port unix:/run/readsb/api.sock --api-shutdown-delay 10 --tar1090-use-api" JSON_OPTIONS="--write-receiver-id-json --write-json-every 1 --json-location-accuracy 2 --range-outline-hours 24"
sudo systemctl restart readsb.service
Tar1090
POZOR: Pokud neni funkcni ReADSB, tak nam nebude fungovat ani Tar. Ve skriptu si zjistuje kde ma data letadel a pokud je nema, tak se nespusti.
Instalace
# Nainstalujeme vlastni Tar1090 sudo bash -c "$(wget -nv -O - https://github.com/wiedehopf/tar1090/raw/master/install.sh)" sudo wget -O /usr/local/share/tar1090/aircraft.csv.gz https://github.com/wiedehopf/tar1090-db/raw/csv/aircraft.csv.gz
Nastaveni Tar1090
sudo sed -i "s/\/\/PlaneCountInTitle = false.*/PlaneCountInTitle = true;/g" /usr/local/share/tar1090/html/config.js sudo sed -i "/^\/\/shareBaseUrl = 'https:\/\/adsb\.lol\/'[^;]*/i shareBaseUrl = 'https://aircrafts.rxw.cz/'" /usr/local/share/tar1090/html/config.js sudo sed -i "s/\/\/ imageConfigLink = .*/imageConfigLink = 'https:\/\/user.czadsb.cz';/g" /usr/local/share/tar1090/html/config.js sudo sed -i "s/\/\/ imageConfigText = .*/imageConfigText = 'CzADSB';/g" /usr/local/share/tar1090/html/config.js
Autorizace
Za účelem přihlášení a přesměrování při neplatnem přihlášení vztvoříme skript:
sudo nano /etc/pam.d/lighttpd-auth
auth required pam_exec.so expose_authtok /usr/local/bin/lighttpd_auth.sh account required pam_permit.so
sudo mcedit /usr/local/bin/lighttpd_auth.sh
#!/bin/bash
# PAM předává jméno v proměnné prostředí $PAM_USER
# Heslo (token) čteme ze standardního vstupu
read -r TOKEN
USERNAME="$PAM_USER"
# Zjištění IP adresy (zůstává stejné)
if [ -n "$HTTP_X_FORWARDED_FOR" ]; then
CLIENT_IP=$(echo "$HTTP_X_FORWARDED_FOR" | cut -d',' -f1 | tr -d ' ')
else
CLIENT_IP="$REMOTE_ADDR"
fi
# Dotaz na váš PHP portál
RESPONSE=$(curl -s --max-time 5 -X POST \
-d "username=$USERNAME" \
-d "token=$TOKEN" \
-d "ip=$CLIENT_IP" \
"https://user.czadsb.cz/service/autentizace.php")
if [ "$RESPONSE" == "OK" ]; then
exit 0
else
exit 1
fi
sudo mcedit /var/www/html/redirect_login.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="refresh" content="0;url=https://user.czadsb.cz/index.php?page=login&return=mapa">
<script type="text/javascript">
window.location.href = "https://user.czadsb.cz/index.php?page=login&return=mapa"
</script>
</head>
<body>
Požadováno přihlášení. Přesměrovávám na <a href="https://user.czadsb.cz/login.php">user.czadsb.cz</a>...
</body>
</html>
Následně upravíme konfiguraci pro lighttpd a tar1090:
LUA
Jde o velmi ořezaný skript jazyk uřečeny pro web servery ke zpracování, vyhodnocení nasměrovaní URL požadavků. Proto ani neumí pak zpracovat POST požadavky. U GET požadavku se musí pak dotaz parsovat jako celek. To ale nevadí pro zpracování cookie, IP adres a podobně. Přikládám pár užitečných pomocných skriptu.
debug-log.lua
-- Funkce pro logovani
local function debug_log(msg)
print("[SSO-DEBUG] " .. tostring(msg))
end
-- Funkce pro ziskani hodnoty z GET (uri.query)
local function get_get_param(param_name)
local query = lighty.env["uri.query"]
if not query then return nil end
-- Hleda v retezci vzor: param=hodnota
return query:match(param_name .. "=([^&]+)")
end
-- Nacti promenne a hodnotu lighty.env
debug_log("-------------------------------------------------")
for k, v in pairs(lighty.env) do
debug_log("env - [" .. k .. "]='" .. tostring(v) .. "'")
end
-- Nacti promenne a hodnotu lighty.request
for k, v in pairs(lighty.request) do
debug_log("request - [" .. k .. "]='" .. tostring(v) .. "'")
end
-- Pouziti funkce ziskani hodnoty z GET:
-- local page = get_get_param("page") -- vrati "login"
debug-file.lua
local ts = os.date("%Y%m%d-%H%M%S")
local fname = "/tmp/magnet_env-" .. ts .. ".log"
local f = io.open(fname, "w")
if f then
for k, v in pairs(lighty.env) do
f:write("env: " .. k .. "=" .. tostring(v) .. "\n")
end
forr k, v in pairs(lighty.request) do
f:write("request: " .. k .. "=" .. tostring(v) .. "\n")
end
f:close()
end
return lighty.RESTART_REQUEST
sso_auth.lua
-- Konfigurace local secret = "vase_velmi_tajne_heslo_123456" local login_url = "https://user.czadsb.cz/index.php?page=login&return=mapy&mapa=tar" local cookie_name = "czadsb_sso" -- Lokalni IP (whitelist) local trusted_ips = { ["127.0.0.1"] = true, ["::1"] = true, ["10.129.99.145"] = true, } -- Opustit statiku (bleskove) local uri = lighty.env["uri.path"] or "" if uri:match("%.%w%w%w?$") and not uri:match("%.php") and not uri:match("%.html") then return 0 end -- Zjisteni IP adresy a opustit pokud je v whitelist IP (bleskove) local final_ip = lighty.request["X-Forwarded-For"] or lighty.env["request.remote-ip"] or lighty.env["remote_addr"] if final_ip then final_ip = final_ip:match("([^, ]+)") if trusted_ips[final_ip] then return 0 end end -- Funkce pro logovani local function debug_log(msg) print("[SSO-DEBUG] " .. tostring(msg)) end -- Funkce pro Base64 dekodovani local function base64_decode(data) local b = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' data = string.gsub(data, '[^'..b..'=]', ) return (data:gsub('.', function(x) if (x == '=') then return end local r,f=,(b:find(x)-1) for i=6,1,-1 do r=r..(f%2^i-f%2^(i-1)>0 and '1' or '0') end return r; end):gsub('%d%d%d%d%d%d%d%d', function(x) local r=0 for i=1,8 do r=r+(x:sub(i,i)=='1' and 2^(8-i) or 0) end return string.char(r) end)) end -- Funkce pro URL dekodovani local function url_decode(str) str = string.gsub(str, "+", " ") str = string.gsub(str, "%%(%x%x)", function(h) return string.char(tonumber(h, 16)) end) return str end -- Nacteni HMAC knihovny (lua-ossl) local status_hmac, openssl_hmac = pcall(require, "openssl.hmac") if not status_hmac then debug_log("CHYBA: Knihovna openssl.hmac nenalezena!") return 500 end -- Nacteni a zpracovani Cookie local cookie_header = lighty.request["Cookie"] or lighty.request["cookie"] if cookie_header then local sso_cookie_raw = cookie_header:match(cookie_name .. "=([^;]+)") if sso_cookie_raw then local sso_cookie = url_decode(sso_cookie_raw) local status_b64, decoded = pcall(base64_decode, sso_cookie) if status_b64 and decoded then local sep_pos = decoded:find("||") if sep_pos then local payload = decoded:sub(1, sep_pos - 1) local signature_raw = decoded:sub(sep_pos + 2) -- RESENI: SHA256 HEX ma vzdy 64 znaku. Orizneme pripadne nuly z dekoderu. local signature = signature_raw:sub(1, 64) -- HMAC SHA256 vypocet local h = openssl_hmac.new(secret, "SHA256") h:update(payload) local bin_sig = h:final() local hex_sig = "" for i = 1, #bin_sig do hex_sig = hex_sig .. string.format("%02x", string.byte(bin_sig, i)) end if hex_sig == signature then -- Rozdeleni payloadu (user_id|username|time) local parts = {} for part in (payload .. "|"):gmatch("([^|]*)|") do table.insert(parts, part) end local u_time = tonumber(parts[3]) if u_time then local diff = os.time() - u_time if diff >= 0 and diff < 7200 then -- debug_log("Autentizace OK pro: " .. tostring(parts[2])) return 0 else debug_log("Cookie vyprsela, rozdil: " .. diff) end end else debug_log("Podpis nesouhlasi! (" .. final_ip .. ")") debug_log("Vypocteno: " .. hex_sig) debug_log("Prijato (upraveno): " .. signature) debug_log("Prijato (raw): " .. signature_raw) end end end end end -- Pridani hlavicek proti cachovani pro jistotu lighty.header["Cache-Control"] = "no-cache, no-store, must-revalidate" lighty.header["Connection"] = "close" lighty.header["Pragma"] = "no-cache" lighty.header["Expires"] = "0" -- Pokud nic neproslo, presmerujeme debug_log("Pristup odmitnut, presmerovani (" .. final_ip .. " | " .. uri .. ").") lighty.header["Location"] = login_url return 302