mirror of
https://github.com/smittix/intercept.git
synced 2026-04-24 22:59:59 -07:00
The bkerler fork still uses SWIG. The velichkov fork has a dedicated maint-3.10 branch with proper GNU Radio 3.10 support. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
864 lines
25 KiB
Bash
Executable File
864 lines
25 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# INTERCEPT Setup Script (best-effort installs, hard-fail verification)
|
|
|
|
# ---- Force bash even if launched with sh ----
|
|
if [ -z "${BASH_VERSION:-}" ]; then
|
|
echo "[x] This script must be run with bash (not sh)."
|
|
echo " Run: bash $0"
|
|
exec bash "$0" "$@"
|
|
fi
|
|
|
|
set -Eeuo pipefail
|
|
|
|
# Ensure admin paths are searchable (many tools live here)
|
|
export PATH="/usr/local/sbin:/usr/sbin:/sbin:/opt/homebrew/sbin:/opt/homebrew/bin:$PATH"
|
|
|
|
# ----------------------------
|
|
# Pretty output
|
|
# ----------------------------
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m'
|
|
|
|
info() { echo -e "${BLUE}[*]${NC} $*"; }
|
|
ok() { echo -e "${GREEN}[✓]${NC} $*"; }
|
|
warn() { echo -e "${YELLOW}[!]${NC} $*"; }
|
|
fail() { echo -e "${RED}[x]${NC} $*"; }
|
|
|
|
# ----------------------------
|
|
# Progress tracking
|
|
# ----------------------------
|
|
CURRENT_STEP=0
|
|
TOTAL_STEPS=0
|
|
|
|
progress() {
|
|
local msg="$1"
|
|
((CURRENT_STEP++)) || true
|
|
local pct=$((CURRENT_STEP * 100 / TOTAL_STEPS))
|
|
local filled=$((pct / 5))
|
|
local empty=$((20 - filled))
|
|
local bar=$(printf '█%.0s' $(seq 1 $filled 2>/dev/null) || true)
|
|
bar+=$(printf '░%.0s' $(seq 1 $empty 2>/dev/null) || true)
|
|
echo -e "${BLUE}[${CURRENT_STEP}/${TOTAL_STEPS}]${NC} ${bar} ${pct}% - ${msg}"
|
|
}
|
|
|
|
on_error() {
|
|
local line="$1"
|
|
local cmd="${2:-unknown}"
|
|
fail "Setup failed at line ${line}: ${cmd}"
|
|
exit 1
|
|
}
|
|
trap 'on_error $LINENO "$BASH_COMMAND"' ERR
|
|
|
|
# ----------------------------
|
|
# Banner
|
|
# ----------------------------
|
|
echo -e "${BLUE}"
|
|
echo " ___ _ _ _____ _____ ____ ____ _____ ____ _____ "
|
|
echo " |_ _| \\ | |_ _| ____| _ \\ / ___| ____| _ \\_ _|"
|
|
echo " | || \\| | | | | _| | |_) | | | _| | |_) || | "
|
|
echo " | || |\\ | | | | |___| _ <| |___| |___| __/ | | "
|
|
echo " |___|_| \\_| |_| |_____|_| \\_\\\\____|_____|_| |_| "
|
|
echo -e "${NC}"
|
|
echo "INTERCEPT - Setup Script"
|
|
echo "============================================"
|
|
echo
|
|
|
|
# ----------------------------
|
|
# Helpers
|
|
# ----------------------------
|
|
cmd_exists() {
|
|
local c="$1"
|
|
command -v "$c" >/dev/null 2>&1 && return 0
|
|
[[ -x "/usr/sbin/$c" || -x "/sbin/$c" || -x "/usr/local/sbin/$c" || -x "/opt/homebrew/sbin/$c" ]] && return 0
|
|
return 1
|
|
}
|
|
|
|
have_any() {
|
|
local c
|
|
for c in "$@"; do
|
|
cmd_exists "$c" && return 0
|
|
done
|
|
return 1
|
|
}
|
|
|
|
need_sudo() {
|
|
if [[ "$(id -u)" -eq 0 ]]; then
|
|
SUDO=""
|
|
ok "Running as root"
|
|
else
|
|
if cmd_exists sudo; then
|
|
SUDO="sudo"
|
|
else
|
|
fail "sudo is not installed and you're not root."
|
|
echo "Either run as root or install sudo first."
|
|
exit 1
|
|
fi
|
|
fi
|
|
}
|
|
|
|
detect_os() {
|
|
if [[ "${OSTYPE:-}" == "darwin"* ]]; then
|
|
OS="macos"
|
|
elif [[ -f /etc/debian_version ]]; then
|
|
OS="debian"
|
|
else
|
|
OS="unknown"
|
|
fi
|
|
info "Detected OS: ${OS}"
|
|
[[ "$OS" != "unknown" ]] || { fail "Unsupported OS (macOS + Debian/Ubuntu only)."; exit 1; }
|
|
}
|
|
|
|
# ----------------------------
|
|
# Required tool checks (with alternates)
|
|
# ----------------------------
|
|
missing_required=()
|
|
|
|
check_required() {
|
|
local label="$1"; shift
|
|
local desc="$1"; shift
|
|
|
|
if have_any "$@"; then
|
|
ok "${label} - ${desc}"
|
|
else
|
|
warn "${label} - ${desc} (missing, required)"
|
|
missing_required+=("$label")
|
|
fi
|
|
}
|
|
|
|
check_tools() {
|
|
info "Checking required tools..."
|
|
missing_required=()
|
|
|
|
echo
|
|
info "Core SDR:"
|
|
check_required "rtl_fm" "RTL-SDR FM demodulator" rtl_fm
|
|
check_required "rtl_test" "RTL-SDR device detection" rtl_test
|
|
check_required "multimon-ng" "Pager decoder" multimon-ng
|
|
check_required "rtl_433" "433MHz sensor decoder" rtl_433 rtl433
|
|
check_required "dump1090" "ADS-B decoder" dump1090
|
|
check_required "acarsdec" "ACARS decoder" acarsdec
|
|
|
|
echo
|
|
info "GPS:"
|
|
check_required "gpsd" "GPS daemon" gpsd
|
|
|
|
echo
|
|
info "Audio:"
|
|
check_required "ffmpeg" "Audio encoder/decoder" ffmpeg
|
|
|
|
echo
|
|
info "WiFi:"
|
|
check_required "airmon-ng" "Monitor mode helper" airmon-ng
|
|
check_required "airodump-ng" "WiFi scanner" airodump-ng
|
|
check_required "aireplay-ng" "Injection/deauth" aireplay-ng
|
|
check_required "hcxdumptool" "PMKID capture" hcxdumptool
|
|
check_required "hcxpcapngtool" "PMKID/pcapng conversion" hcxpcapngtool
|
|
|
|
echo
|
|
info "Bluetooth:"
|
|
check_required "bluetoothctl" "Bluetooth controller CLI" bluetoothctl
|
|
check_required "hcitool" "Bluetooth scan utility" hcitool
|
|
check_required "hciconfig" "Bluetooth adapter config" hciconfig
|
|
|
|
echo
|
|
info "SoapySDR:"
|
|
check_required "SoapySDRUtil" "SoapySDR CLI utility" SoapySDRUtil
|
|
|
|
echo
|
|
info "GSM (optional):"
|
|
if have_any grgsm_scanner; then
|
|
ok "grgsm_scanner - GSM cell scanner"
|
|
else
|
|
warn "grgsm_scanner - GSM cell scanner (optional, for ISMS GSM detection)"
|
|
fi
|
|
echo
|
|
}
|
|
|
|
# ----------------------------
|
|
# Python venv + deps
|
|
# ----------------------------
|
|
check_python_version() {
|
|
if ! cmd_exists python3; then
|
|
fail "python3 not found."
|
|
[[ "$OS" == "macos" ]] && echo "Install with: brew install python"
|
|
[[ "$OS" == "debian" ]] && echo "Install with: sudo apt-get install python3"
|
|
exit 1
|
|
fi
|
|
|
|
local ver
|
|
ver="$(python3 -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")')"
|
|
info "Python version: ${ver}"
|
|
|
|
python3 - <<'PY'
|
|
import sys
|
|
raise SystemExit(0 if sys.version_info >= (3,9) else 1)
|
|
PY
|
|
ok "Python version OK (>= 3.9)"
|
|
}
|
|
|
|
install_python_deps() {
|
|
progress "Setting up Python environment"
|
|
check_python_version
|
|
|
|
if [[ ! -f requirements.txt ]]; then
|
|
warn "requirements.txt not found; skipping Python dependency install."
|
|
return 0
|
|
fi
|
|
|
|
# On Debian/Ubuntu, try apt packages first as they're more reliable
|
|
if [[ "$OS" == "debian" ]]; then
|
|
info "Installing Python packages via apt (more reliable on Debian/Ubuntu)..."
|
|
$SUDO apt-get install -y python3-flask python3-requests python3-serial >/dev/null 2>&1 || true
|
|
|
|
# skyfield may not be available in all distros, try apt first then pip
|
|
if ! $SUDO apt-get install -y python3-skyfield >/dev/null 2>&1; then
|
|
warn "python3-skyfield not in apt, will try pip later"
|
|
fi
|
|
ok "Installed available Python packages via apt"
|
|
fi
|
|
|
|
if [[ ! -d venv ]]; then
|
|
python3 -m venv --system-site-packages venv
|
|
ok "Created venv/ (with system site-packages)"
|
|
else
|
|
ok "Using existing venv/"
|
|
fi
|
|
|
|
# shellcheck disable=SC1091
|
|
source venv/bin/activate
|
|
|
|
python -m pip install --upgrade pip setuptools wheel >/dev/null 2>&1 || true
|
|
ok "Upgraded pip tooling"
|
|
|
|
progress "Installing Python dependencies"
|
|
# Try pip install, but don't fail if apt packages already satisfied deps
|
|
if ! python -m pip install -r requirements.txt 2>/dev/null; then
|
|
warn "Some pip packages failed - checking if apt packages cover them..."
|
|
# Verify critical packages are available
|
|
python -c "import flask; import requests" 2>/dev/null || {
|
|
fail "Critical Python packages (flask, requests) not installed"
|
|
echo "Try: sudo apt install python3-flask python3-requests"
|
|
exit 1
|
|
}
|
|
ok "Core Python dependencies available"
|
|
else
|
|
ok "Python dependencies installed"
|
|
fi
|
|
echo
|
|
}
|
|
|
|
# ----------------------------
|
|
# macOS install (Homebrew)
|
|
# ----------------------------
|
|
ensure_brew() {
|
|
cmd_exists brew && return 0
|
|
warn "Homebrew not found. Installing Homebrew..."
|
|
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
|
|
|
if [[ -x /opt/homebrew/bin/brew ]]; then
|
|
eval "$(/opt/homebrew/bin/brew shellenv)"
|
|
elif [[ -x /usr/local/bin/brew ]]; then
|
|
eval "$(/usr/local/bin/brew shellenv)"
|
|
fi
|
|
|
|
cmd_exists brew || { fail "Homebrew install failed. Install manually then re-run."; exit 1; }
|
|
}
|
|
|
|
brew_install() {
|
|
local pkg="$1"
|
|
if brew list --formula "$pkg" >/dev/null 2>&1; then
|
|
ok "brew: ${pkg} already installed"
|
|
return 0
|
|
fi
|
|
info "brew: installing ${pkg}..."
|
|
if brew install "$pkg" 2>&1; then
|
|
ok "brew: installed ${pkg}"
|
|
return 0
|
|
else
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
install_multimon_ng_from_source_macos() {
|
|
info "multimon-ng not available via Homebrew. Building from source..."
|
|
|
|
# Ensure build dependencies are installed
|
|
brew_install cmake
|
|
brew_install libsndfile
|
|
|
|
(
|
|
tmp_dir="$(mktemp -d)"
|
|
trap 'rm -rf "$tmp_dir"' EXIT
|
|
|
|
info "Cloning multimon-ng..."
|
|
git clone --depth 1 https://github.com/EliasOenal/multimon-ng.git "$tmp_dir/multimon-ng" >/dev/null 2>&1 \
|
|
|| { fail "Failed to clone multimon-ng"; exit 1; }
|
|
|
|
cd "$tmp_dir/multimon-ng"
|
|
info "Compiling multimon-ng..."
|
|
mkdir -p build && cd build
|
|
cmake .. >/dev/null 2>&1 || { fail "cmake failed for multimon-ng"; exit 1; }
|
|
make >/dev/null 2>&1 || { fail "make failed for multimon-ng"; exit 1; }
|
|
|
|
# Install to /usr/local/bin (no sudo needed on Homebrew systems typically)
|
|
if [[ -w /usr/local/bin ]]; then
|
|
install -m 0755 multimon-ng /usr/local/bin/multimon-ng
|
|
else
|
|
sudo install -m 0755 multimon-ng /usr/local/bin/multimon-ng
|
|
fi
|
|
ok "multimon-ng installed successfully from source"
|
|
)
|
|
}
|
|
|
|
install_macos_packages() {
|
|
TOTAL_STEPS=13
|
|
CURRENT_STEP=0
|
|
|
|
progress "Checking Homebrew"
|
|
ensure_brew
|
|
|
|
progress "Installing RTL-SDR libraries"
|
|
brew_install librtlsdr
|
|
|
|
progress "Installing multimon-ng"
|
|
# multimon-ng is not in Homebrew core, so build from source
|
|
if ! cmd_exists multimon-ng; then
|
|
install_multimon_ng_from_source_macos
|
|
else
|
|
ok "multimon-ng already installed"
|
|
fi
|
|
|
|
progress "Installing direwolf (APRS decoder)"
|
|
(brew_install direwolf) || warn "direwolf not available via Homebrew"
|
|
|
|
progress "Installing ffmpeg"
|
|
brew_install ffmpeg
|
|
|
|
progress "Installing rtl_433"
|
|
brew_install rtl_433
|
|
|
|
progress "Installing dump1090"
|
|
(brew_install dump1090-mutability) || warn "dump1090 not available via Homebrew"
|
|
|
|
progress "Installing acarsdec"
|
|
(brew_install acarsdec) || warn "acarsdec not available via Homebrew"
|
|
|
|
progress "Installing aircrack-ng"
|
|
brew_install aircrack-ng
|
|
|
|
progress "Installing hcxtools"
|
|
brew_install hcxtools
|
|
|
|
progress "Installing SoapySDR"
|
|
brew_install soapysdr
|
|
|
|
progress "Installing gpsd"
|
|
brew_install gpsd
|
|
|
|
warn "macOS note: hcitool/hciconfig are Linux (BlueZ) utilities and often unavailable on macOS."
|
|
info "TSCM BLE scanning uses bleak library (installed via pip) for manufacturer data detection."
|
|
warn "macOS note: gr-gsm (for GSM cell scanning) is not easily available on macOS."
|
|
info "GSM cell detection in ISMS mode requires Linux with GNU Radio."
|
|
echo
|
|
}
|
|
|
|
# ----------------------------
|
|
# Debian/Ubuntu install (APT)
|
|
# ----------------------------
|
|
apt_install() {
|
|
local pkgs="$*"
|
|
local output
|
|
local ret=0
|
|
output=$($SUDO apt-get install -y --no-install-recommends "$@" 2>&1) || ret=$?
|
|
if [[ $ret -ne 0 ]]; then
|
|
fail "Failed to install: $pkgs"
|
|
echo "$output" | tail -10
|
|
fail "Try running: sudo apt-get update && sudo apt-get install -y $pkgs"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
apt_try_install_any() {
|
|
local p
|
|
for p in "$@"; do
|
|
if $SUDO apt-get install -y --no-install-recommends "$p" >/dev/null 2>&1; then
|
|
ok "apt: installed ${p}"
|
|
return 0
|
|
fi
|
|
done
|
|
return 1
|
|
}
|
|
|
|
install_dump1090_from_source_debian() {
|
|
info "dump1090 not available via APT. Building from source (required)..."
|
|
|
|
apt_install build-essential git pkg-config \
|
|
librtlsdr-dev libusb-1.0-0-dev \
|
|
libncurses-dev tcl-dev python3-dev
|
|
|
|
# Run in subshell to isolate EXIT trap
|
|
(
|
|
tmp_dir="$(mktemp -d)"
|
|
trap 'rm -rf "$tmp_dir"' EXIT
|
|
|
|
info "Cloning FlightAware dump1090..."
|
|
git clone --depth 1 https://github.com/flightaware/dump1090.git "$tmp_dir/dump1090" >/dev/null 2>&1 \
|
|
|| { fail "Failed to clone FlightAware dump1090"; exit 1; }
|
|
|
|
cd "$tmp_dir/dump1090"
|
|
info "Compiling FlightAware dump1090..."
|
|
if make BLADERF=no RTLSDR=yes >/dev/null 2>&1; then
|
|
$SUDO install -m 0755 dump1090 /usr/local/bin/dump1090
|
|
ok "dump1090 installed successfully (FlightAware)."
|
|
exit 0
|
|
fi
|
|
|
|
warn "FlightAware build failed. Falling back to antirez/dump1090..."
|
|
rm -rf "$tmp_dir/dump1090"
|
|
git clone --depth 1 https://github.com/antirez/dump1090.git "$tmp_dir/dump1090" >/dev/null 2>&1 \
|
|
|| { fail "Failed to clone antirez dump1090"; exit 1; }
|
|
|
|
cd "$tmp_dir/dump1090"
|
|
info "Compiling antirez dump1090..."
|
|
make >/dev/null 2>&1 || { fail "Failed to build dump1090 from source (required)."; exit 1; }
|
|
|
|
$SUDO install -m 0755 dump1090 /usr/local/bin/dump1090
|
|
ok "dump1090 installed successfully (antirez)."
|
|
)
|
|
}
|
|
|
|
install_acarsdec_from_source_debian() {
|
|
info "acarsdec not available via APT. Building from source..."
|
|
|
|
apt_install build-essential git cmake \
|
|
librtlsdr-dev libusb-1.0-0-dev libsndfile1-dev
|
|
|
|
# Run in subshell to isolate EXIT trap
|
|
(
|
|
tmp_dir="$(mktemp -d)"
|
|
trap 'rm -rf "$tmp_dir"' EXIT
|
|
|
|
info "Cloning acarsdec..."
|
|
git clone --depth 1 https://github.com/TLeconte/acarsdec.git "$tmp_dir/acarsdec" >/dev/null 2>&1 \
|
|
|| { warn "Failed to clone acarsdec"; exit 1; }
|
|
|
|
cd "$tmp_dir/acarsdec"
|
|
mkdir -p build && cd build
|
|
|
|
info "Compiling acarsdec..."
|
|
if cmake .. -Drtl=ON >/dev/null 2>&1 && make >/dev/null 2>&1; then
|
|
$SUDO install -m 0755 acarsdec /usr/local/bin/acarsdec
|
|
ok "acarsdec installed successfully."
|
|
else
|
|
warn "Failed to build acarsdec from source. ACARS decoding will not be available."
|
|
fi
|
|
)
|
|
}
|
|
|
|
install_grgsm_from_source_debian() {
|
|
info "Installing gr-gsm for GSM cell scanning (optional)..."
|
|
|
|
# Check if GNU Radio is available
|
|
if ! cmd_exists gnuradio-config-info; then
|
|
info "GNU Radio not found. Installing GNU Radio first..."
|
|
if ! $SUDO apt-get install -y gnuradio gnuradio-dev; then
|
|
warn "Failed to install GNU Radio. gr-gsm requires GNU Radio 3.8+."
|
|
warn "GSM scanning will not be available."
|
|
return 1
|
|
fi
|
|
fi
|
|
|
|
# Check GNU Radio version (need 3.8+)
|
|
local gr_version
|
|
gr_version=$(gnuradio-config-info --version 2>/dev/null || echo "0.0.0")
|
|
info "GNU Radio version: $gr_version"
|
|
|
|
# Install basic build dependencies first
|
|
info "Installing gr-gsm build dependencies..."
|
|
$SUDO apt-get install -y \
|
|
cmake \
|
|
autoconf \
|
|
automake \
|
|
libtool \
|
|
pkg-config \
|
|
build-essential \
|
|
python3-docutils \
|
|
libcppunit-dev \
|
|
swig \
|
|
doxygen \
|
|
liblog4cpp5-dev \
|
|
python3-scipy \
|
|
python3-numpy \
|
|
gnuradio-dev \
|
|
gr-osmosdr \
|
|
libtalloc-dev \
|
|
libpcsclite-dev \
|
|
libusb-1.0-0-dev \
|
|
libgnutls28-dev \
|
|
libmnl-dev \
|
|
libsctp-dev \
|
|
pybind11-dev \
|
|
python3-pybind11 \
|
|
|| warn "Some build dependencies failed to install."
|
|
|
|
# Check if libosmocore is available via apt
|
|
info "Checking for libosmocore packages..."
|
|
if ! $SUDO apt-get install -y libosmocore-dev 2>/dev/null; then
|
|
info "libosmocore not available in repos, building from source..."
|
|
|
|
# Build libosmocore from source
|
|
local osmo_tmp
|
|
osmo_tmp="$(mktemp -d)"
|
|
|
|
info "Cloning libosmocore..."
|
|
if git clone --depth 1 https://gitea.osmocom.org/osmocom/libosmocore.git "$osmo_tmp/libosmocore"; then
|
|
cd "$osmo_tmp/libosmocore"
|
|
|
|
info "Building libosmocore (this may take a few minutes)..."
|
|
autoreconf -fi
|
|
./configure --prefix=/usr/local
|
|
if make -j$(nproc) && $SUDO make install && $SUDO ldconfig; then
|
|
ok "libosmocore built and installed successfully"
|
|
else
|
|
warn "Failed to build libosmocore from source"
|
|
cd /
|
|
rm -rf "$osmo_tmp"
|
|
return 1
|
|
fi
|
|
|
|
cd /
|
|
rm -rf "$osmo_tmp"
|
|
else
|
|
warn "Failed to clone libosmocore"
|
|
rm -rf "$osmo_tmp"
|
|
return 1
|
|
fi
|
|
else
|
|
ok "libosmocore installed from packages"
|
|
# Also try to install the other osmo packages
|
|
$SUDO apt-get install -y \
|
|
libosmocoding-dev \
|
|
libosmoctrl-dev \
|
|
libosmogsm-dev \
|
|
libosmovty-dev \
|
|
libosmocodec-dev \
|
|
2>/dev/null || true
|
|
fi
|
|
|
|
# Build gr-gsm
|
|
local tmp_dir
|
|
tmp_dir="$(mktemp -d)"
|
|
|
|
# Check GNU Radio version to select correct gr-gsm fork
|
|
local gr_major gr_minor
|
|
gr_major=$(gnuradio-config-info --version 2>/dev/null | cut -d. -f1 || echo "3")
|
|
gr_minor=$(gnuradio-config-info --version 2>/dev/null | cut -d. -f2 || echo "8")
|
|
|
|
local grgsm_repo grgsm_branch
|
|
if [[ "$gr_major" -ge 3 && "$gr_minor" -ge 10 ]]; then
|
|
# GNU Radio 3.10+ needs velichkov fork with maint-3.10 branch
|
|
info "GNU Radio 3.10+ detected, using velichkov fork (maint-3.10 branch)..."
|
|
grgsm_repo="https://github.com/velichkov/gr-gsm.git"
|
|
grgsm_branch="maint-3.10"
|
|
|
|
# Install pybind11 for GNU Radio 3.10+
|
|
$SUDO apt-get install -y pybind11-dev python3-pybind11 || true
|
|
else
|
|
# Older GNU Radio versions use original repo with SWIG
|
|
info "GNU Radio < 3.10 detected, using original gr-gsm..."
|
|
grgsm_repo="https://github.com/ptrkrysik/gr-gsm.git"
|
|
grgsm_branch="master"
|
|
fi
|
|
|
|
info "Cloning gr-gsm from $grgsm_repo..."
|
|
if ! git clone --depth 1 -b "$grgsm_branch" "$grgsm_repo" "$tmp_dir/gr-gsm"; then
|
|
warn "Failed to clone gr-gsm repository"
|
|
rm -rf "$tmp_dir"
|
|
return 1
|
|
fi
|
|
|
|
cd "$tmp_dir/gr-gsm"
|
|
mkdir -p build && cd build
|
|
|
|
info "Configuring gr-gsm..."
|
|
# Include /usr/local in CMAKE_PREFIX_PATH for source-built libosmocore
|
|
if ! cmake -DCMAKE_PREFIX_PATH="/usr/local;/usr" -DCMAKE_INSTALL_PREFIX=/usr/local ..; then
|
|
warn "Failed to configure gr-gsm (cmake failed)"
|
|
warn "Check that all dependencies are installed"
|
|
cd /
|
|
rm -rf "$tmp_dir"
|
|
return 1
|
|
fi
|
|
|
|
info "Compiling gr-gsm (this may take a few minutes)..."
|
|
if ! make -j$(nproc); then
|
|
warn "Failed to compile gr-gsm"
|
|
warn "Check the build output above for errors"
|
|
cd /
|
|
rm -rf "$tmp_dir"
|
|
return 1
|
|
fi
|
|
|
|
info "Installing gr-gsm..."
|
|
if $SUDO make install && $SUDO ldconfig; then
|
|
ok "gr-gsm installed successfully."
|
|
info "grgsm_scanner should now be available for GSM cell detection."
|
|
else
|
|
warn "Failed to install gr-gsm"
|
|
cd /
|
|
rm -rf "$tmp_dir"
|
|
return 1
|
|
fi
|
|
|
|
# Cleanup
|
|
cd /
|
|
rm -rf "$tmp_dir"
|
|
return 0
|
|
}
|
|
|
|
install_rtlsdr_blog_drivers_debian() {
|
|
# The RTL-SDR Blog drivers provide better support for:
|
|
# - RTL-SDR Blog V4 (R828D tuner)
|
|
# - RTL-SDR Blog V3 with bias-t improvements
|
|
# - Better overall compatibility with all RTL-SDR devices
|
|
# These drivers are backward compatible with standard RTL-SDR devices.
|
|
|
|
info "Installing RTL-SDR Blog drivers (improved V4 support)..."
|
|
|
|
# Install build dependencies
|
|
apt_install build-essential git cmake libusb-1.0-0-dev pkg-config
|
|
|
|
# Run in subshell to isolate EXIT trap
|
|
(
|
|
tmp_dir="$(mktemp -d)"
|
|
trap 'rm -rf "$tmp_dir"' EXIT
|
|
|
|
info "Cloning RTL-SDR Blog driver fork..."
|
|
git clone https://github.com/rtlsdrblog/rtl-sdr-blog.git "$tmp_dir/rtl-sdr-blog" >/dev/null 2>&1 \
|
|
|| { warn "Failed to clone RTL-SDR Blog drivers"; exit 1; }
|
|
|
|
cd "$tmp_dir/rtl-sdr-blog"
|
|
mkdir -p build && cd build
|
|
|
|
info "Compiling RTL-SDR Blog drivers..."
|
|
if cmake .. -DINSTALL_UDEV_RULES=ON -DDETACH_KERNEL_DRIVER=ON >/dev/null 2>&1 && make >/dev/null 2>&1; then
|
|
$SUDO make install >/dev/null 2>&1
|
|
$SUDO ldconfig
|
|
|
|
# Copy udev rules if they exist
|
|
if [[ -f ../rtl-sdr.rules ]]; then
|
|
$SUDO cp ../rtl-sdr.rules /etc/udev/rules.d/20-rtlsdr-blog.rules
|
|
$SUDO udevadm control --reload-rules || true
|
|
$SUDO udevadm trigger || true
|
|
fi
|
|
|
|
ok "RTL-SDR Blog drivers installed successfully."
|
|
info "These drivers provide improved support for RTL-SDR Blog V4 and other devices."
|
|
warn "Unplug and replug your RTL-SDR devices for the new drivers to take effect."
|
|
else
|
|
warn "Failed to build RTL-SDR Blog drivers. Using stock drivers."
|
|
warn "If you have an RTL-SDR Blog V4, you may need to install drivers manually."
|
|
warn "See: https://github.com/rtlsdrblog/rtl-sdr-blog"
|
|
fi
|
|
)
|
|
}
|
|
|
|
setup_udev_rules_debian() {
|
|
[[ -d /etc/udev/rules.d ]] || { warn "udev not found; skipping RTL-SDR udev rules."; return 0; }
|
|
|
|
local rules_file="/etc/udev/rules.d/20-rtlsdr.rules"
|
|
[[ -f "$rules_file" ]] && { ok "RTL-SDR udev rules already present: $rules_file"; return 0; }
|
|
|
|
info "Installing RTL-SDR udev rules..."
|
|
$SUDO tee "$rules_file" >/dev/null <<'EOF'
|
|
SUBSYSTEM=="usb", ATTRS{idVendor}=="0bda", ATTRS{idProduct}=="2838", MODE="0666"
|
|
SUBSYSTEM=="usb", ATTRS{idVendor}=="0bda", ATTRS{idProduct}=="2832", MODE="0666"
|
|
EOF
|
|
$SUDO udevadm control --reload-rules || true
|
|
$SUDO udevadm trigger || true
|
|
ok "udev rules installed. Unplug/replug your RTL-SDR if connected."
|
|
echo
|
|
}
|
|
|
|
blacklist_kernel_drivers_debian() {
|
|
local blacklist_file="/etc/modprobe.d/blacklist-rtlsdr.conf"
|
|
|
|
if [[ -f "$blacklist_file" ]]; then
|
|
ok "RTL-SDR kernel driver blacklist already present"
|
|
return 0
|
|
fi
|
|
|
|
info "Blacklisting conflicting DVB kernel drivers..."
|
|
$SUDO tee "$blacklist_file" >/dev/null <<'EOF'
|
|
# Blacklist DVB-T drivers to allow rtl-sdr to access RTL2832U devices
|
|
blacklist dvb_usb_rtl28xxu
|
|
blacklist rtl2832
|
|
blacklist rtl2830
|
|
blacklist r820t
|
|
EOF
|
|
|
|
# Unload modules if currently loaded
|
|
for mod in dvb_usb_rtl28xxu rtl2832 rtl2830 r820t; do
|
|
if lsmod | grep -q "^$mod"; then
|
|
$SUDO modprobe -r "$mod" 2>/dev/null || true
|
|
fi
|
|
done
|
|
|
|
ok "Kernel drivers blacklisted. Unplug/replug your RTL-SDR if connected."
|
|
echo
|
|
}
|
|
|
|
install_debian_packages() {
|
|
need_sudo
|
|
|
|
# Suppress needrestart prompts (Ubuntu Server 22.04+)
|
|
export DEBIAN_FRONTEND=noninteractive
|
|
export NEEDRESTART_MODE=a
|
|
|
|
TOTAL_STEPS=19
|
|
CURRENT_STEP=0
|
|
|
|
progress "Updating APT package lists"
|
|
$SUDO apt-get update -y >/dev/null
|
|
|
|
# Fix any broken RTL-SDR packages first (common issue with Blog drivers vs stock)
|
|
info "Fixing RTL-SDR package conflicts..."
|
|
# Force remove broken packages
|
|
$SUDO dpkg --remove --force-remove-reinstreq librtlsdr0 librtlsdr2 librtlsdr-dev rtl-sdr 2>/dev/null || true
|
|
$SUDO apt-get -f install -y 2>/dev/null || true
|
|
$SUDO dpkg --configure -a 2>/dev/null || true
|
|
$SUDO apt-get autoremove -y --purge 2>/dev/null || true
|
|
|
|
progress "Installing RTL-SDR"
|
|
# Skip apt rtl-sdr package - we'll use RTL-SDR Blog drivers instead which are better
|
|
# The stock packages often conflict with the Blog drivers
|
|
info "Skipping stock rtl-sdr package (RTL-SDR Blog drivers will be used instead)"
|
|
|
|
progress "Installing RTL-SDR Blog drivers (V4 support)"
|
|
install_rtlsdr_blog_drivers_debian
|
|
|
|
progress "Installing multimon-ng"
|
|
apt_install multimon-ng
|
|
|
|
progress "Installing direwolf (APRS decoder)"
|
|
apt_install direwolf || true
|
|
|
|
progress "Installing ffmpeg"
|
|
apt_install ffmpeg
|
|
|
|
progress "Installing rtl_433"
|
|
apt_try_install_any rtl-433 rtl433 || warn "rtl-433 not available"
|
|
|
|
progress "Installing aircrack-ng"
|
|
apt_install aircrack-ng || true
|
|
|
|
progress "Installing hcxdumptool"
|
|
apt_install hcxdumptool || true
|
|
|
|
progress "Installing hcxtools"
|
|
apt_install hcxtools || true
|
|
|
|
progress "Installing Bluetooth tools"
|
|
apt_install bluez bluetooth || true
|
|
|
|
progress "Installing SoapySDR"
|
|
# Exclude xtrx-dkms - its kernel module fails to build on newer kernels (6.14+)
|
|
# and causes apt to hang. Most users don't have XTRX hardware anyway.
|
|
apt_install soapysdr-tools xtrx-dkms- || true
|
|
|
|
progress "Installing gpsd"
|
|
apt_install gpsd gpsd-clients || true
|
|
|
|
progress "Installing Python packages"
|
|
apt_install python3-venv python3-pip || true
|
|
# Install Python packages via apt (more reliable than pip on modern Debian/Ubuntu)
|
|
$SUDO apt-get install -y python3-flask python3-requests python3-serial >/dev/null 2>&1 || true
|
|
$SUDO apt-get install -y python3-skyfield >/dev/null 2>&1 || true
|
|
# bleak for BLE scanning with manufacturer data (TSCM mode)
|
|
$SUDO apt-get install -y python3-bleak >/dev/null 2>&1 || true
|
|
|
|
progress "Installing dump1090"
|
|
if ! cmd_exists dump1090 && ! cmd_exists dump1090-mutability; then
|
|
#export DEBIAN_FRONTEND=noninteractive
|
|
apt_try_install_any dump1090-fa dump1090-mutability dump1090 || true
|
|
fi
|
|
if ! cmd_exists dump1090; then
|
|
if cmd_exists dump1090-mutability; then
|
|
$SUDO ln -s $(which dump1090-mutability) /usr/local/sbin/dump1090
|
|
fi
|
|
fi
|
|
cmd_exists dump1090 || install_dump1090_from_source_debian
|
|
|
|
progress "Installing acarsdec"
|
|
if ! cmd_exists acarsdec; then
|
|
apt_install acarsdec || true
|
|
fi
|
|
cmd_exists acarsdec || install_acarsdec_from_source_debian
|
|
|
|
progress "Installing gr-gsm (optional, for GSM cell detection)"
|
|
if ! cmd_exists grgsm_scanner; then
|
|
install_grgsm_from_source_debian || true
|
|
else
|
|
ok "grgsm_scanner already installed"
|
|
fi
|
|
|
|
progress "Configuring udev rules"
|
|
setup_udev_rules_debian
|
|
|
|
progress "Blacklisting conflicting kernel drivers"
|
|
blacklist_kernel_drivers_debian
|
|
}
|
|
|
|
# ----------------------------
|
|
# Final summary / hard fail
|
|
# ----------------------------
|
|
final_summary_and_hard_fail() {
|
|
check_tools
|
|
|
|
echo "============================================"
|
|
echo
|
|
echo "To start INTERCEPT:"
|
|
echo " sudo -E venv/bin/python intercept.py"
|
|
echo
|
|
echo "Then open http://localhost:5050 in your browser"
|
|
echo
|
|
echo "============================================"
|
|
|
|
if [[ "${#missing_required[@]}" -eq 0 ]]; then
|
|
ok "All REQUIRED tools are installed."
|
|
else
|
|
fail "Missing REQUIRED tools:"
|
|
for t in "${missing_required[@]}"; do echo " - $t"; done
|
|
echo
|
|
if [[ "$OS" == "macos" ]]; then
|
|
warn "macOS note: bluetoothctl/hcitool/hciconfig are Linux (BlueZ) tools and unavailable on macOS."
|
|
warn "Bluetooth functionality will be limited. Other features should work."
|
|
else
|
|
fail "Exiting because required tools are missing."
|
|
exit 1
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# ----------------------------
|
|
# MAIN
|
|
# ----------------------------
|
|
main() {
|
|
detect_os
|
|
|
|
if [[ "$OS" == "macos" ]]; then
|
|
install_macos_packages
|
|
else
|
|
install_debian_packages
|
|
fi
|
|
|
|
install_python_deps
|
|
final_summary_and_hard_fail
|
|
}
|
|
|
|
main "$@"
|
|
|