diff --git a/package/secubox/luci-app-tor-shield/htdocs/luci-static/resources/tor-shield/api.js b/package/secubox/luci-app-tor-shield/htdocs/luci-static/resources/tor-shield/api.js index be2fe776..2f4b6a1d 100644 --- a/package/secubox/luci-app-tor-shield/htdocs/luci-static/resources/tor-shield/api.js +++ b/package/secubox/luci-app-tor-shield/htdocs/luci-static/resources/tor-shield/api.js @@ -188,9 +188,13 @@ return baseclass.extend({ callPresets(), callBandwidth() ]).then(function(results) { + // Handle RPC expect unwrapping - results may be array or object + var presetsData = results[1] || []; + var presets = Array.isArray(presetsData) ? presetsData : (presetsData.presets || []); + return { status: results[0] || {}, - presets: (results[1] || {}).presets || [], + presets: presets, bandwidth: results[2] || {} }; }); @@ -203,9 +207,13 @@ return baseclass.extend({ callCircuits(), callBandwidth() ]).then(function(results) { + // Handle RPC expect unwrapping - results[1] may be array or object + var circuitsData = results[1] || []; + var circuits = Array.isArray(circuitsData) ? circuitsData : (circuitsData.circuits || []); + return { status: results[0] || {}, - circuits: (results[1] || {}).circuits || [], + circuits: circuits, bandwidth: results[2] || {} }; }); diff --git a/package/secubox/luci-app-tor-shield/htdocs/luci-static/resources/view/tor-shield/hidden-services.js b/package/secubox/luci-app-tor-shield/htdocs/luci-static/resources/view/tor-shield/hidden-services.js index 27dcb654..630dd026 100644 --- a/package/secubox/luci-app-tor-shield/htdocs/luci-static/resources/view/tor-shield/hidden-services.js +++ b/package/secubox/luci-app-tor-shield/htdocs/luci-static/resources/view/tor-shield/hidden-services.js @@ -176,7 +176,8 @@ return view.extend({ render: function(data) { var self = this; - var services = data.services || []; + // Handle RPC expect unwrapping - data may be array or object + var services = Array.isArray(data) ? data : (data.services || []); var view = E('div', { 'class': 'tor-dashboard' }, [ E('link', { 'rel': 'stylesheet', 'href': L.resource('tor-shield/dashboard.css') }), diff --git a/package/secubox/luci-app-tor-shield/root/usr/libexec/rpcd/luci.tor-shield b/package/secubox/luci-app-tor-shield/root/usr/libexec/rpcd/luci.tor-shield index 2960ae7d..2c49bbd3 100644 --- a/package/secubox/luci-app-tor-shield/root/usr/libexec/rpcd/luci.tor-shield +++ b/package/secubox/luci-app-tor-shield/root/usr/libexec/rpcd/luci.tor-shield @@ -7,20 +7,40 @@ . /usr/share/libubox/jshn.sh CONFIG="tor-shield" -TOR_CONTROL="/var/run/tor/control" +TOR_RUN="/var/run/tor" +TOR_CONTROL="$TOR_RUN/control" TOR_DATA="/var/lib/tor" -# Send command to Tor control socket +# Send command to Tor control socket with cookie auth tor_control() { if [ ! -S "$TOR_CONTROL" ]; then return 1 fi - echo -e "$1" | nc -U "$TOR_CONTROL" 2>/dev/null + + # Read cookie for authentication + local cookie="" + local cookie_file="$TOR_RUN/control_auth_cookie" + if [ -f "$cookie_file" ]; then + cookie=$(hexdump -e '32/1 "%02x"' "$cookie_file" 2>/dev/null) + fi + + # Use socat for Unix socket (BusyBox nc doesn't support -U) + # Send AUTHENTICATE first, then the actual command + { + [ -n "$cookie" ] && echo "AUTHENTICATE $cookie" + echo "$1" + } | socat - UNIX-CONNECT:"$TOR_CONTROL" 2>/dev/null } # Check if Tor is running is_running() { - pgrep tor >/dev/null 2>&1 + # Check for tor process (procd manages the process, no pid file) + pgrep -f "/usr/sbin/tor" >/dev/null 2>&1 +} + +# Check if tor-shield control socket is available +has_control() { + [ -S "$TOR_CONTROL" ] } # Get bootstrap percentage @@ -49,45 +69,55 @@ get_status() { # Running state if is_running; then json_add_boolean "running" 1 + json_add_boolean "has_control" "$(has_control && echo 1 || echo 0)" - # Bootstrap percentage - local bootstrap=$(get_bootstrap) + # Bootstrap percentage (only if control socket available) + local bootstrap=0 + if has_control; then + bootstrap=$(get_bootstrap) + fi json_add_int "bootstrap" "${bootstrap:-0}" # Get exit IP if bootstrapped if [ "$bootstrap" -ge 100 ]; then local socks_port config_get socks_port socks port '9050' - local exit_ip=$(curl -s --max-time 10 --socks5-hostname 127.0.0.1:$socks_port https://check.torproject.org/api/ip 2>/dev/null | jsonfilter -e '@.IP' 2>/dev/null) + # Single curl call for both IP and IsTor + local tor_check=$(curl -s --max-time 10 --socks5-hostname 127.0.0.1:$socks_port https://check.torproject.org/api/ip 2>/dev/null) + local exit_ip=$(echo "$tor_check" | jsonfilter -e '@.IP' 2>/dev/null) json_add_string "exit_ip" "${exit_ip:-unknown}" # Check if using Tor - local is_tor=$(curl -s --max-time 10 --socks5-hostname 127.0.0.1:$socks_port https://check.torproject.org/api/ip 2>/dev/null | jsonfilter -e '@.IsTor' 2>/dev/null) + local is_tor=$(echo "$tor_check" | jsonfilter -e '@.IsTor' 2>/dev/null) json_add_boolean "is_tor" "$([ "$is_tor" = "true" ] && echo 1 || echo 0)" - # Get circuit count - local circuits=$(tor_control "GETINFO circuit-status" | grep -c "BUILT" 2>/dev/null) - json_add_int "circuit_count" "${circuits:-0}" + # Get circuit count (only if control available) + if has_control; then + local circuits=$(tor_control "GETINFO circuit-status" | grep -c "BUILT" 2>/dev/null) + json_add_int "circuit_count" "${circuits:-0}" - # Get bandwidth - local bw_read=$(tor_control "GETINFO traffic/read" | grep "250" | awk '{print $2}') - local bw_written=$(tor_control "GETINFO traffic/written" | grep "250" | awk '{print $2}') - json_add_int "bytes_read" "${bw_read:-0}" - json_add_int "bytes_written" "${bw_written:-0}" + # Get bandwidth + local bw_read=$(tor_control "GETINFO traffic/read" | grep "250" | awk '{print $2}') + local bw_written=$(tor_control "GETINFO traffic/written" | grep "250" | awk '{print $2}') + json_add_int "bytes_read" "${bw_read:-0}" + json_add_int "bytes_written" "${bw_written:-0}" + else + json_add_int "circuit_count" 0 + json_add_int "bytes_read" 0 + json_add_int "bytes_written" 0 + fi fi - # Uptime from pid file - local pidfile="/var/run/tor/tor.pid" - if [ -f "$pidfile" ]; then - local pid=$(cat "$pidfile") - if [ -d "/proc/$pid" ]; then - local start_time=$(stat -c %Y "/proc/$pid" 2>/dev/null) - local now=$(date +%s) - json_add_int "uptime" "$((now - start_time))" - fi + # Uptime from process start time + local pid=$(pgrep -f "/usr/sbin/tor" | head -1) + if [ -n "$pid" ] && [ -d "/proc/$pid" ]; then + local start_time=$(stat -c %Y "/proc/$pid" 2>/dev/null) + local now=$(date +%s) + json_add_int "uptime" "$((now - start_time))" fi else json_add_boolean "running" 0 + json_add_boolean "has_control" 0 json_add_int "bootstrap" 0 fi @@ -98,9 +128,11 @@ get_status() { json_add_boolean "bridges_enabled" "$bridges_enabled" json_add_string "bridge_type" "$bridge_type" - # Get real IP - local real_ip=$(curl -s --max-time 5 https://ipinfo.io/ip 2>/dev/null) - json_add_string "real_ip" "${real_ip:-unknown}" + # Get real IP (try multiple services as fallback) + local real_ip=$(curl -s --max-time 5 https://api.ipify.org 2>/dev/null) + [ -z "$real_ip" ] && real_ip=$(curl -s --max-time 5 https://ifconfig.me/ip 2>/dev/null) + [ -z "$real_ip" ] && real_ip="unknown" + json_add_string "real_ip" "$real_ip" json_dump } @@ -109,12 +141,15 @@ get_status() { do_enable() { read input json_load "$input" + + # Get values from input BEFORE json_init + local preset json_get_var preset preset - - json_init - [ -z "$preset" ] && preset="anonymous" + # Now initialize output JSON + json_init + # Load preset configuration config_load "$CONFIG" @@ -172,9 +207,18 @@ get_circuits() { return fi - local circuits=$(tor_control "GETINFO circuit-status") + # Check if control socket exists + if [ ! -S "$TOR_CONTROL" ]; then + json_close_array + json_dump + return + fi - echo "$circuits" | grep "BUILT" | while read line; do + # Use temp file to avoid subshell issue with pipe + local TMP_CIRCUITS="/tmp/tor_circuits_$$" + tor_control "GETINFO circuit-status" | grep "BUILT" > "$TMP_CIRCUITS" 2>/dev/null + + while read line; do local id=$(echo "$line" | awk '{print $1}') local status=$(echo "$line" | awk '{print $2}') local path=$(echo "$line" | awk '{print $3}') @@ -189,7 +233,8 @@ get_circuits() { # Parse path into nodes json_add_array "nodes" - local IFS=',' + local OLD_IFS="$IFS" + IFS=',' for node in $path; do local fingerprint=$(echo "$node" | cut -d'~' -f1 | tr -d '$') local name=$(echo "$node" | cut -d'~' -f2) @@ -199,12 +244,14 @@ get_circuits() { json_add_string "name" "${name:-$fingerprint}" json_close_object done + IFS="$OLD_IFS" json_close_array json_close_object fi - done + done < "$TMP_CIRCUITS" + rm -f "$TMP_CIRCUITS" json_close_array json_dump } @@ -331,10 +378,14 @@ add_hidden_service_json() { add_hidden_service() { read input json_load "$input" + + # Get values from input BEFORE json_init + local name local_port virtual_port json_get_var name name json_get_var local_port local_port json_get_var virtual_port virtual_port + # Now initialize output JSON json_init if [ -z "$name" ]; then @@ -368,8 +419,12 @@ add_hidden_service() { remove_hidden_service() { read input json_load "$input" + + # Get values from input BEFORE json_init + local name json_get_var name name + # Now initialize output JSON json_init if [ -z "$name" ]; then @@ -535,9 +590,13 @@ add_bridge_json() { set_bridges() { read input json_load "$input" + + # Get values from input BEFORE json_init + local enabled type json_get_var enabled enabled json_get_var type type + # Now initialize output JSON json_init [ -n "$enabled" ] && uci set tor-shield.bridges.enabled="$enabled" @@ -612,9 +671,9 @@ save_settings() { read input json_load "$input" - json_init - - # Get values from input + # Get values from input BEFORE json_init (which wipes loaded JSON) + local mode dns_over_tor kill_switch socks_port trans_port dns_port + local exit_nodes exclude_exit strict_nodes json_get_var mode mode json_get_var dns_over_tor dns_over_tor json_get_var kill_switch kill_switch @@ -625,6 +684,9 @@ save_settings() { json_get_var exclude_exit exclude_exit_nodes json_get_var strict_nodes strict_nodes + # Now initialize output JSON + json_init + # Apply settings [ -n "$mode" ] && uci set tor-shield.main.mode="$mode" [ -n "$dns_over_tor" ] && uci set tor-shield.main.dns_over_tor="$dns_over_tor" diff --git a/package/secubox/luci-app-wireguard-dashboard/htdocs/luci-static/resources/view/wireguard-dashboard/overview.js b/package/secubox/luci-app-wireguard-dashboard/htdocs/luci-static/resources/view/wireguard-dashboard/overview.js index 1242ef91..df9f4c0a 100644 --- a/package/secubox/luci-app-wireguard-dashboard/htdocs/luci-static/resources/view/wireguard-dashboard/overview.js +++ b/package/secubox/luci-app-wireguard-dashboard/htdocs/luci-static/resources/view/wireguard-dashboard/overview.js @@ -222,8 +222,11 @@ return view.extend({ return api.getAllData().then(L.bind(function(data) { var status = data.status || {}; - var interfaces = (data.interfaces || {}).interfaces || []; - var peers = (data.peers || {}).peers || []; + // Handle RPC expect unwrapping - may be array or object + var interfacesData = data.interfaces || []; + var peersData = data.peers || []; + var interfaces = Array.isArray(interfacesData) ? interfacesData : (interfacesData.interfaces || []); + var peers = Array.isArray(peersData) ? peersData : (peersData.peers || []); this.updateStats(status); this.updatePeers(peers); @@ -240,8 +243,11 @@ return view.extend({ render: function(data) { var self = this; var status = data.status || {}; - var interfaces = (data.interfaces || {}).interfaces || []; - var peers = (data.peers || {}).peers || []; + // Handle RPC expect unwrapping - may be array or object + var interfacesData = data.interfaces || []; + var peersData = data.peers || []; + var interfaces = Array.isArray(interfacesData) ? interfacesData : (interfacesData.interfaces || []); + var peers = Array.isArray(peersData) ? peersData : (peersData.peers || []); // Store peer descriptions this.peerDescriptions = data.descriptions || {}; diff --git a/package/secubox/luci-app-wireguard-dashboard/htdocs/luci-static/resources/wireguard-dashboard/api.js b/package/secubox/luci-app-wireguard-dashboard/htdocs/luci-static/resources/wireguard-dashboard/api.js index 8b00d2d2..2fa4d950 100644 --- a/package/secubox/luci-app-wireguard-dashboard/htdocs/luci-static/resources/wireguard-dashboard/api.js +++ b/package/secubox/luci-app-wireguard-dashboard/htdocs/luci-static/resources/wireguard-dashboard/api.js @@ -178,10 +178,14 @@ return baseclass.extend({ callGetTraffic(), callPeerDescriptions() ]).then(function(results) { + // Handle RPC expect unwrapping - results may be array or object + var peersData = results[1] || []; + var interfacesData = results[2] || []; + return { status: results[0] || {}, - peers: results[1] || { peers: [] }, - interfaces: results[2] || { interfaces: [] }, + peers: Array.isArray(peersData) ? peersData : (peersData.peers || []), + interfaces: Array.isArray(interfacesData) ? interfacesData : (interfacesData.interfaces || []), traffic: results[3] || {}, descriptions: (results[4] || {}).descriptions || {} }; @@ -196,10 +200,14 @@ return baseclass.extend({ callBandwidthRates(), callPeerDescriptions() ]).then(function(results) { + // Handle RPC expect unwrapping - results may be array or object + var peersData = results[1] || []; + var ratesData = results[2] || []; + return { status: results[0] || {}, - peers: results[1] || { peers: [] }, - rates: (results[2] || {}).rates || [], + peers: Array.isArray(peersData) ? peersData : (peersData.peers || []), + rates: Array.isArray(ratesData) ? ratesData : (ratesData.rates || []), descriptions: (results[3] || {}).descriptions || {} }; }); diff --git a/package/secubox/secubox-app-haproxy/Makefile b/package/secubox/secubox-app-haproxy/Makefile index 6c3b2045..78a65596 100644 --- a/package/secubox/secubox-app-haproxy/Makefile +++ b/package/secubox/secubox-app-haproxy/Makefile @@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=secubox-app-haproxy PKG_VERSION:=1.0.0 -PKG_RELEASE:=13 +PKG_RELEASE:=14 PKG_MAINTAINER:=CyberMind PKG_LICENSE:=MIT @@ -50,11 +50,28 @@ define Package/secubox-app-haproxy/install $(INSTALL_DIR) $(1)/usr/sbin $(INSTALL_BIN) ./files/usr/sbin/haproxyctl $(1)/usr/sbin/haproxyctl + $(INSTALL_BIN) ./files/usr/sbin/haproxy-sync-certs $(1)/usr/sbin/haproxy-sync-certs + + $(INSTALL_DIR) $(1)/usr/lib/acme/deploy + $(INSTALL_BIN) ./files/usr/lib/acme/deploy/haproxy.sh $(1)/usr/lib/acme/deploy/haproxy.sh $(INSTALL_DIR) $(1)/usr/share/haproxy/templates $(INSTALL_DATA) ./files/usr/share/haproxy/templates/* $(1)/usr/share/haproxy/templates/ $(INSTALL_DIR) $(1)/usr/share/haproxy/certs + + # Add cron job for certificate sync after ACME renewals + $(INSTALL_DIR) $(1)/etc/cron.d + echo "# Sync ACME certs to HAProxy after renewals" > $(1)/etc/cron.d/haproxy-certs + echo "15 3 * * * root /usr/sbin/haproxy-sync-certs >/dev/null 2>&1" >> $(1)/etc/cron.d/haproxy-certs +endef + +define Package/secubox-app-haproxy/postinst +#!/bin/sh +[ -n "$${IPKG_INSTROOT}" ] && exit 0 +# Sync existing ACME certificates on install +/usr/sbin/haproxy-sync-certs 2>/dev/null || true +exit 0 endef $(eval $(call BuildPackage,secubox-app-haproxy)) diff --git a/package/secubox/secubox-app-haproxy/files/etc/init.d/haproxy b/package/secubox/secubox-app-haproxy/files/etc/init.d/haproxy index 94cd476c..6bed2b38 100644 --- a/package/secubox/secubox-app-haproxy/files/etc/init.d/haproxy +++ b/package/secubox/secubox-app-haproxy/files/etc/init.d/haproxy @@ -16,6 +16,9 @@ start_service() { [ "$enabled" = "1" ] || return 0 + # Sync ACME certificates to HAProxy format before starting + /usr/sbin/haproxy-sync-certs 2>/dev/null || true + procd_open_instance procd_set_param command "$PROG" service-run procd_set_param respawn 3600 5 0 diff --git a/package/secubox/secubox-app-haproxy/files/usr/lib/acme/deploy/haproxy.sh b/package/secubox/secubox-app-haproxy/files/usr/lib/acme/deploy/haproxy.sh new file mode 100644 index 00000000..eba5b5b2 --- /dev/null +++ b/package/secubox/secubox-app-haproxy/files/usr/lib/acme/deploy/haproxy.sh @@ -0,0 +1,59 @@ +#!/bin/sh +# ACME deploy hook for HAProxy +# Combines fullchain + private key into single .pem file +# Usage: Called by acme.sh after certificate issuance/renewal + +HAPROXY_CERTS_DIR="/srv/haproxy/certs" + +# acme.sh passes these environment variables: +# DOMAIN - the domain name +# CERT_PATH - path to the domain certificate +# KEY_PATH - path to the domain private key +# CA_PATH - path to the intermediate CA certificate +# FULLCHAIN_PATH - path to the full chain certificate +# CERT_KEY_PATH - same as KEY_PATH + +deploy() { + local domain="$1" + local key_path="$2" + local cert_path="$3" + local ca_path="$4" + local fullchain_path="$5" + + [ -z "$domain" ] && { echo "Error: domain required"; return 1; } + + mkdir -p "$HAPROXY_CERTS_DIR" + + # Use fullchain if available, otherwise use cert + ca + local combined_cert="" + if [ -n "$fullchain_path" ] && [ -f "$fullchain_path" ]; then + combined_cert="$fullchain_path" + elif [ -n "$cert_path" ] && [ -f "$cert_path" ]; then + combined_cert="$cert_path" + else + echo "Error: No certificate file found for $domain" + return 1 + fi + + if [ -z "$key_path" ] || [ ! -f "$key_path" ]; then + echo "Error: No key file found for $domain" + return 1 + fi + + # Combine fullchain + private key for HAProxy + echo "Deploying certificate for $domain to HAProxy..." + cat "$combined_cert" "$key_path" > "$HAPROXY_CERTS_DIR/$domain.pem" + chmod 600 "$HAPROXY_CERTS_DIR/$domain.pem" + + echo "Certificate deployed: $HAPROXY_CERTS_DIR/$domain.pem" + + # Reload HAProxy if running + if [ -x /etc/init.d/haproxy ]; then + /etc/init.d/haproxy reload 2>/dev/null || true + fi + + return 0 +} + +# Entry point for acme.sh deploy hook +deploy "$Le_Domain" "$CERT_KEY_PATH" "$CERT_PATH" "$CA_CERT_PATH" "$CERT_FULLCHAIN_PATH" diff --git a/package/secubox/secubox-app-haproxy/files/usr/sbin/haproxy-sync-certs b/package/secubox/secubox-app-haproxy/files/usr/sbin/haproxy-sync-certs new file mode 100644 index 00000000..994321a5 --- /dev/null +++ b/package/secubox/secubox-app-haproxy/files/usr/sbin/haproxy-sync-certs @@ -0,0 +1,47 @@ +#!/bin/sh +# Sync ACME certificates to HAProxy format +# Combines fullchain + private key into .pem files +# Called by ACME renewal or manually via haproxyctl + +ACME_DIR="/etc/acme" +HAPROXY_CERTS_DIR="/srv/haproxy/certs" + +log_info() { echo "[haproxy-sync-certs] $*"; logger -t haproxy-sync-certs "$*"; } +log_error() { echo "[haproxy-sync-certs] ERROR: $*" >&2; logger -t haproxy-sync-certs -p err "$*"; } + +mkdir -p "$HAPROXY_CERTS_DIR" + +# Find all ACME certificates and deploy them +for domain_dir in "$ACME_DIR"/*/; do + [ -d "$domain_dir" ] || continue + + # Skip non-domain directories + case "$(basename "$domain_dir")" in + ca|*.ecc) continue ;; + esac + + domain=$(basename "$domain_dir") + fullchain="$domain_dir/fullchain.cer" + key="$domain_dir/${domain}.key" + + # Try alternate paths + [ -f "$fullchain" ] || fullchain="$domain_dir/fullchain.pem" + [ -f "$key" ] || key="$domain_dir/privkey.pem" + [ -f "$key" ] || key="$domain_dir/${domain}.key" + + if [ -f "$fullchain" ] && [ -f "$key" ]; then + log_info "Syncing certificate for $domain" + cat "$fullchain" "$key" > "$HAPROXY_CERTS_DIR/$domain.pem" + chmod 600 "$HAPROXY_CERTS_DIR/$domain.pem" + else + log_error "Missing cert or key for $domain (fullchain=$fullchain, key=$key)" + fi +done + +log_info "Certificate sync complete" + +# Reload HAProxy if running +if pgrep -x haproxy >/dev/null 2>&1 || lxc-info -n haproxy -s 2>/dev/null | grep -q RUNNING; then + log_info "Reloading HAProxy..." + /etc/init.d/haproxy reload 2>/dev/null || true +fi diff --git a/package/secubox/secubox-app-haproxy/files/usr/sbin/haproxyctl b/package/secubox/secubox-app-haproxy/files/usr/sbin/haproxyctl index c72ce7dd..a94ee7b6 100644 --- a/package/secubox/secubox-app-haproxy/files/usr/sbin/haproxyctl +++ b/package/secubox/secubox-app-haproxy/files/usr/sbin/haproxyctl @@ -630,8 +630,13 @@ cmd_cert_add() { --home "$LE_WORKING_DIR" \ --cert-file "$CERTS_PATH/$domain.crt" \ --key-file "$CERTS_PATH/$domain.key" \ - --fullchain-file "$CERTS_PATH/$domain.pem" \ + --fullchain-file "$CERTS_PATH/$domain.fullchain.pem" \ --reloadcmd "/etc/init.d/haproxy reload" 2>/dev/null || true + + # HAProxy needs combined file: fullchain + private key + log_info "Creating combined PEM for HAProxy..." + cat "$CERTS_PATH/$domain.fullchain.pem" "$CERTS_PATH/$domain.key" > "$CERTS_PATH/$domain.pem" + chmod 600 "$CERTS_PATH/$domain.pem" fi # Restart HAProxy if it was running diff --git a/package/secubox/secubox-app-tor/Makefile b/package/secubox/secubox-app-tor/Makefile index 96e437ad..f801dc72 100644 --- a/package/secubox/secubox-app-tor/Makefile +++ b/package/secubox/secubox-app-tor/Makefile @@ -22,7 +22,7 @@ define Package/secubox-app-tor PKGARCH:=all SUBMENU:=SecuBox Apps TITLE:=SecuBox Tor Shield - DEPENDS:=+tor +tor-geoip +iptables +curl +jsonfilter + DEPENDS:=+tor +tor-geoip +iptables +curl +jsonfilter +socat endef define Package/secubox-app-tor/description diff --git a/package/secubox/secubox-app-tor/files/etc/init.d/tor-shield b/package/secubox/secubox-app-tor/files/etc/init.d/tor-shield index 48b1a99c..a7e112b0 100644 --- a/package/secubox/secubox-app-tor/files/etc/init.d/tor-shield +++ b/package/secubox/secubox-app-tor/files/etc/init.d/tor-shield @@ -37,7 +37,13 @@ generate_torrc() { config_get strict_nodes security strict_nodes '0' mkdir -p "$TOR_RUN" "$TOR_DATA" - chmod 700 "$TOR_DATA" + + # Clean up stale files that may have wrong ownership + rm -f "$TOR_RUN/tor.pid" "$TOR_RUN/control" "$TOR_RUN/control_auth_cookie" 2>/dev/null + rm -f "$TOR_DATA/lock" 2>/dev/null + + chown tor:tor "$TOR_RUN" "$TOR_DATA" + chmod 700 "$TOR_RUN" "$TOR_DATA" cat > "$TORRC" << EOF # SecuBox Tor Shield - Auto-generated config @@ -45,10 +51,12 @@ generate_torrc() { User tor DataDirectory $TOR_DATA -PidFile $TOR_RUN/tor.pid -Log notice file /var/log/tor.log +Log notice syslog ControlSocket $TOR_RUN/control ControlSocketsGroupWritable 1 +CookieAuthentication 1 +CookieAuthFile $TOR_RUN/control_auth_cookie +CookieAuthFileGroupReadable 1 # SOCKS proxy SocksPort $socks_addr:$socks_port @@ -79,15 +87,23 @@ VirtualAddrNetworkIPv4 10.192.0.0/10 EOF fi - # Bridge configuration + # Bridge configuration - only enable if bridges are configured if [ "$bridges_enabled" = "1" ]; then - cat >> "$TORRC" << EOF + # Count bridge lines first + BRIDGE_COUNT=0 + count_bridge() { BRIDGE_COUNT=$((BRIDGE_COUNT + 1)); } + config_list_foreach bridges bridge_lines count_bridge + + # Only add UseBridges if there are actual bridges configured + if [ "$BRIDGE_COUNT" -gt 0 ]; then + cat >> "$TORRC" << EOF # Bridge mode UseBridges 1 EOF - # Add bridge lines from config - config_list_foreach bridges bridge_lines add_bridge_line + # Add bridge lines from config + config_list_foreach bridges bridge_lines add_bridge_line + fi fi # Exit node restrictions @@ -111,6 +127,9 @@ EOF if [ -f /usr/share/tor/geoip6 ]; then echo "GeoIPv6File /usr/share/tor/geoip6" >> "$TORRC" fi + + # Ensure torrc is readable by tor user + chown tor:tor "$TORRC" } add_bridge_line() { @@ -130,6 +149,7 @@ add_hidden_service() { local hs_dir="$TOR_DATA/hidden_service_$name" mkdir -p "$hs_dir" + chown tor:tor "$hs_dir" chmod 700 "$hs_dir" cat >> "$TORRC" << EOF @@ -153,6 +173,10 @@ setup_iptables() { # Get Tor user ID local tor_uid=$(id -u tor 2>/dev/null || echo "tor") + # Remove from OUTPUT chain first (to allow chain deletion) + iptables -t nat -D OUTPUT -j TOR_SHIELD 2>/dev/null + iptables -t filter -D OUTPUT -j TOR_SHIELD 2>/dev/null + # Clear existing Tor rules iptables -t nat -F TOR_SHIELD 2>/dev/null iptables -t nat -X TOR_SHIELD 2>/dev/null @@ -161,9 +185,9 @@ setup_iptables() { [ "$mode" = "transparent" ] || return 0 - # Create chains - iptables -t nat -N TOR_SHIELD - iptables -t filter -N TOR_SHIELD + # Create chains (ignore "already exists" errors) + iptables -t nat -N TOR_SHIELD 2>/dev/null || true + iptables -t filter -N TOR_SHIELD 2>/dev/null || true # Exclude Tor traffic iptables -t nat -A TOR_SHIELD -m owner --uid-owner $tor_uid -j RETURN