fix(tor-shield): Multiple bug fixes for control socket and startup
- Fix subshell bug in get_circuits (pipe loses JSON state) - Add has_control flag to status for frontend awareness - Fix UseBridges without bridge lines causing Tor to fail - Fix hidden service directory ownership (tor:tor) - Change log output from file to syslog - Fix run directory ownership and permissions (700) - Add CookieAuthentication for control socket auth - Use socat instead of nc (BusyBox lacks Unix socket support) - Add socat as package dependency - Optimize duplicate curl calls in status check - Use fallback IP services for real_ip detection Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
cc86aa7f84
commit
0c54940010
@ -7,22 +7,47 @@
|
|||||||
. /usr/share/libubox/jshn.sh
|
. /usr/share/libubox/jshn.sh
|
||||||
|
|
||||||
CONFIG="tor-shield"
|
CONFIG="tor-shield"
|
||||||
TOR_CONTROL="/var/run/tor/control"
|
TOR_RUN="/var/run/tor"
|
||||||
|
TOR_CONTROL="$TOR_RUN/control"
|
||||||
TOR_DATA="/var/lib/tor"
|
TOR_DATA="/var/lib/tor"
|
||||||
|
|
||||||
# Send command to Tor control socket
|
# Send command to Tor control socket with cookie auth
|
||||||
tor_control() {
|
tor_control() {
|
||||||
if [ ! -S "$TOR_CONTROL" ]; then
|
if [ ! -S "$TOR_CONTROL" ]; then
|
||||||
return 1
|
return 1
|
||||||
fi
|
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
|
# Check if Tor is running (via tor-shield, not just any tor process)
|
||||||
is_running() {
|
is_running() {
|
||||||
|
# Check for tor-shield's pid file first
|
||||||
|
if [ -f "$TOR_RUN/tor.pid" ]; then
|
||||||
|
local pid=$(cat "$TOR_RUN/tor.pid" 2>/dev/null)
|
||||||
|
[ -n "$pid" ] && [ -d "/proc/$pid" ] && return 0
|
||||||
|
fi
|
||||||
|
# Fallback to checking any tor process
|
||||||
pgrep tor >/dev/null 2>&1
|
pgrep tor >/dev/null 2>&1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Check if tor-shield control socket is available
|
||||||
|
has_control() {
|
||||||
|
[ -S "$TOR_CONTROL" ]
|
||||||
|
}
|
||||||
|
|
||||||
# Get bootstrap percentage
|
# Get bootstrap percentage
|
||||||
get_bootstrap() {
|
get_bootstrap() {
|
||||||
local status=$(tor_control "GETINFO status/bootstrap-phase")
|
local status=$(tor_control "GETINFO status/bootstrap-phase")
|
||||||
@ -49,35 +74,47 @@ get_status() {
|
|||||||
# Running state
|
# Running state
|
||||||
if is_running; then
|
if is_running; then
|
||||||
json_add_boolean "running" 1
|
json_add_boolean "running" 1
|
||||||
|
json_add_boolean "has_control" "$(has_control && echo 1 || echo 0)"
|
||||||
|
|
||||||
# Bootstrap percentage
|
# Bootstrap percentage (only if control socket available)
|
||||||
local bootstrap=$(get_bootstrap)
|
local bootstrap=0
|
||||||
|
if has_control; then
|
||||||
|
bootstrap=$(get_bootstrap)
|
||||||
|
fi
|
||||||
json_add_int "bootstrap" "${bootstrap:-0}"
|
json_add_int "bootstrap" "${bootstrap:-0}"
|
||||||
|
|
||||||
# Get exit IP if bootstrapped
|
# Get exit IP if bootstrapped
|
||||||
if [ "$bootstrap" -ge 100 ]; then
|
if [ "$bootstrap" -ge 100 ]; then
|
||||||
local socks_port
|
local socks_port
|
||||||
config_get socks_port socks port '9050'
|
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}"
|
json_add_string "exit_ip" "${exit_ip:-unknown}"
|
||||||
|
|
||||||
# Check if using Tor
|
# 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)"
|
json_add_boolean "is_tor" "$([ "$is_tor" = "true" ] && echo 1 || echo 0)"
|
||||||
|
|
||||||
# Get circuit count
|
# Get circuit count (only if control available)
|
||||||
local circuits=$(tor_control "GETINFO circuit-status" | grep -c "BUILT" 2>/dev/null)
|
if has_control; then
|
||||||
json_add_int "circuit_count" "${circuits:-0}"
|
local circuits=$(tor_control "GETINFO circuit-status" | grep -c "BUILT" 2>/dev/null)
|
||||||
|
json_add_int "circuit_count" "${circuits:-0}"
|
||||||
|
|
||||||
# Get bandwidth
|
# Get bandwidth
|
||||||
local bw_read=$(tor_control "GETINFO traffic/read" | grep "250" | awk '{print $2}')
|
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}')
|
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_read" "${bw_read:-0}"
|
||||||
json_add_int "bytes_written" "${bw_written:-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
|
fi
|
||||||
|
|
||||||
# Uptime from pid file
|
# Uptime from pid file
|
||||||
local pidfile="/var/run/tor/tor.pid"
|
local pidfile="$TOR_RUN/tor.pid"
|
||||||
if [ -f "$pidfile" ]; then
|
if [ -f "$pidfile" ]; then
|
||||||
local pid=$(cat "$pidfile")
|
local pid=$(cat "$pidfile")
|
||||||
if [ -d "/proc/$pid" ]; then
|
if [ -d "/proc/$pid" ]; then
|
||||||
@ -88,6 +125,7 @@ get_status() {
|
|||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
json_add_boolean "running" 0
|
json_add_boolean "running" 0
|
||||||
|
json_add_boolean "has_control" 0
|
||||||
json_add_int "bootstrap" 0
|
json_add_int "bootstrap" 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -98,9 +136,11 @@ get_status() {
|
|||||||
json_add_boolean "bridges_enabled" "$bridges_enabled"
|
json_add_boolean "bridges_enabled" "$bridges_enabled"
|
||||||
json_add_string "bridge_type" "$bridge_type"
|
json_add_string "bridge_type" "$bridge_type"
|
||||||
|
|
||||||
# Get real IP
|
# Get real IP (try multiple services as fallback)
|
||||||
local real_ip=$(curl -s --max-time 5 https://ipinfo.io/ip 2>/dev/null)
|
local real_ip=$(curl -s --max-time 5 https://api.ipify.org 2>/dev/null)
|
||||||
json_add_string "real_ip" "${real_ip:-unknown}"
|
[ -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
|
json_dump
|
||||||
}
|
}
|
||||||
@ -172,9 +212,18 @@ get_circuits() {
|
|||||||
return
|
return
|
||||||
fi
|
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 id=$(echo "$line" | awk '{print $1}')
|
||||||
local status=$(echo "$line" | awk '{print $2}')
|
local status=$(echo "$line" | awk '{print $2}')
|
||||||
local path=$(echo "$line" | awk '{print $3}')
|
local path=$(echo "$line" | awk '{print $3}')
|
||||||
@ -189,7 +238,8 @@ get_circuits() {
|
|||||||
|
|
||||||
# Parse path into nodes
|
# Parse path into nodes
|
||||||
json_add_array "nodes"
|
json_add_array "nodes"
|
||||||
local IFS=','
|
local OLD_IFS="$IFS"
|
||||||
|
IFS=','
|
||||||
for node in $path; do
|
for node in $path; do
|
||||||
local fingerprint=$(echo "$node" | cut -d'~' -f1 | tr -d '$')
|
local fingerprint=$(echo "$node" | cut -d'~' -f1 | tr -d '$')
|
||||||
local name=$(echo "$node" | cut -d'~' -f2)
|
local name=$(echo "$node" | cut -d'~' -f2)
|
||||||
@ -199,12 +249,14 @@ get_circuits() {
|
|||||||
json_add_string "name" "${name:-$fingerprint}"
|
json_add_string "name" "${name:-$fingerprint}"
|
||||||
json_close_object
|
json_close_object
|
||||||
done
|
done
|
||||||
|
IFS="$OLD_IFS"
|
||||||
json_close_array
|
json_close_array
|
||||||
|
|
||||||
json_close_object
|
json_close_object
|
||||||
fi
|
fi
|
||||||
done
|
done < "$TMP_CIRCUITS"
|
||||||
|
|
||||||
|
rm -f "$TMP_CIRCUITS"
|
||||||
json_close_array
|
json_close_array
|
||||||
json_dump
|
json_dump
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,7 +22,7 @@ define Package/secubox-app-tor
|
|||||||
PKGARCH:=all
|
PKGARCH:=all
|
||||||
SUBMENU:=SecuBox Apps
|
SUBMENU:=SecuBox Apps
|
||||||
TITLE:=SecuBox Tor Shield
|
TITLE:=SecuBox Tor Shield
|
||||||
DEPENDS:=+tor +tor-geoip +iptables +curl +jsonfilter
|
DEPENDS:=+tor +tor-geoip +iptables +curl +jsonfilter +socat
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define Package/secubox-app-tor/description
|
define Package/secubox-app-tor/description
|
||||||
|
|||||||
@ -37,7 +37,8 @@ generate_torrc() {
|
|||||||
config_get strict_nodes security strict_nodes '0'
|
config_get strict_nodes security strict_nodes '0'
|
||||||
|
|
||||||
mkdir -p "$TOR_RUN" "$TOR_DATA"
|
mkdir -p "$TOR_RUN" "$TOR_DATA"
|
||||||
chmod 700 "$TOR_DATA"
|
chown tor:tor "$TOR_RUN" "$TOR_DATA"
|
||||||
|
chmod 700 "$TOR_RUN" "$TOR_DATA"
|
||||||
|
|
||||||
cat > "$TORRC" << EOF
|
cat > "$TORRC" << EOF
|
||||||
# SecuBox Tor Shield - Auto-generated config
|
# SecuBox Tor Shield - Auto-generated config
|
||||||
@ -46,9 +47,12 @@ generate_torrc() {
|
|||||||
User tor
|
User tor
|
||||||
DataDirectory $TOR_DATA
|
DataDirectory $TOR_DATA
|
||||||
PidFile $TOR_RUN/tor.pid
|
PidFile $TOR_RUN/tor.pid
|
||||||
Log notice file /var/log/tor.log
|
Log notice syslog
|
||||||
ControlSocket $TOR_RUN/control
|
ControlSocket $TOR_RUN/control
|
||||||
ControlSocketsGroupWritable 1
|
ControlSocketsGroupWritable 1
|
||||||
|
CookieAuthentication 1
|
||||||
|
CookieAuthFile $TOR_RUN/control_auth_cookie
|
||||||
|
CookieAuthFileGroupReadable 1
|
||||||
|
|
||||||
# SOCKS proxy
|
# SOCKS proxy
|
||||||
SocksPort $socks_addr:$socks_port
|
SocksPort $socks_addr:$socks_port
|
||||||
@ -79,15 +83,23 @@ VirtualAddrNetworkIPv4 10.192.0.0/10
|
|||||||
EOF
|
EOF
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Bridge configuration
|
# Bridge configuration - only enable if bridges are configured
|
||||||
if [ "$bridges_enabled" = "1" ]; then
|
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
|
# Bridge mode
|
||||||
UseBridges 1
|
UseBridges 1
|
||||||
EOF
|
EOF
|
||||||
# Add bridge lines from config
|
# Add bridge lines from config
|
||||||
config_list_foreach bridges bridge_lines add_bridge_line
|
config_list_foreach bridges bridge_lines add_bridge_line
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Exit node restrictions
|
# Exit node restrictions
|
||||||
@ -130,6 +142,7 @@ add_hidden_service() {
|
|||||||
|
|
||||||
local hs_dir="$TOR_DATA/hidden_service_$name"
|
local hs_dir="$TOR_DATA/hidden_service_$name"
|
||||||
mkdir -p "$hs_dir"
|
mkdir -p "$hs_dir"
|
||||||
|
chown tor:tor "$hs_dir"
|
||||||
chmod 700 "$hs_dir"
|
chmod 700 "$hs_dir"
|
||||||
|
|
||||||
cat >> "$TORRC" << EOF
|
cat >> "$TORRC" << EOF
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user