feat(tor-shield): Add excluded destinations for direct/CDN access
- Add get_excluded_destinations() method to list bypassed destinations - Add add_excluded_destination() to exclude IPs/CIDRs/domains from Tor - Add remove_excluded_destination() to remove exclusions - Add apply_exclusions() to restart tor-shield with new rules - Domain resolution attempts to get IP for iptables compatibility - Existing private network CIDRs (192.168/10/172.16/127) are default excluded Also includes metablogizer fixes: - reload_haproxy() helper function - Server address uses 127.0.0.1 for uhttpd backends - fix_permissions() on file uploads PKG_RELEASE: tor-shield=3, metablogizer=3 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
e079014dfb
commit
70187a7c45
@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
|
|||||||
|
|
||||||
PKG_NAME:=luci-app-tor-shield
|
PKG_NAME:=luci-app-tor-shield
|
||||||
PKG_VERSION:=1.0.0
|
PKG_VERSION:=1.0.0
|
||||||
PKG_RELEASE:=2
|
PKG_RELEASE:=3
|
||||||
PKG_ARCH:=all
|
PKG_ARCH:=all
|
||||||
|
|
||||||
PKG_LICENSE:=MIT
|
PKG_LICENSE:=MIT
|
||||||
|
|||||||
@ -696,6 +696,128 @@ add_excluded_ip_json() {
|
|||||||
json_add_string "" "$1"
|
json_add_string "" "$1"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Get excluded destinations (bypasses Tor, served directly or via CDN)
|
||||||
|
get_excluded_destinations() {
|
||||||
|
json_init
|
||||||
|
json_add_array "destinations"
|
||||||
|
|
||||||
|
config_load "$CONFIG"
|
||||||
|
|
||||||
|
# Get excluded IPs/CIDRs
|
||||||
|
local idx=0
|
||||||
|
add_excluded_dest_json() {
|
||||||
|
local dest="$1"
|
||||||
|
json_add_object
|
||||||
|
json_add_int "id" "$idx"
|
||||||
|
json_add_string "destination" "$dest"
|
||||||
|
# Detect type
|
||||||
|
if echo "$dest" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/[0-9]+$'; then
|
||||||
|
json_add_string "type" "cidr"
|
||||||
|
elif echo "$dest" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$'; then
|
||||||
|
json_add_string "type" "ip"
|
||||||
|
else
|
||||||
|
json_add_string "type" "domain"
|
||||||
|
fi
|
||||||
|
json_close_object
|
||||||
|
idx=$((idx + 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
config_list_foreach trans excluded_ips add_excluded_dest_json
|
||||||
|
|
||||||
|
json_close_array
|
||||||
|
json_dump
|
||||||
|
}
|
||||||
|
|
||||||
|
# Add excluded destination
|
||||||
|
add_excluded_destination() {
|
||||||
|
read input
|
||||||
|
json_load "$input"
|
||||||
|
|
||||||
|
local destination
|
||||||
|
json_get_var destination destination
|
||||||
|
|
||||||
|
json_init
|
||||||
|
|
||||||
|
if [ -z "$destination" ]; then
|
||||||
|
json_add_boolean "success" 0
|
||||||
|
json_add_string "error" "Destination is required"
|
||||||
|
json_dump
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Ensure trans section exists
|
||||||
|
uci -q get tor-shield.trans >/dev/null 2>&1 || {
|
||||||
|
uci set tor-shield.trans=transparent
|
||||||
|
uci set tor-shield.trans.port='9040'
|
||||||
|
uci set tor-shield.trans.dns_port='9053'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Resolve domain to IP if it's a domain (not an IP or CIDR)
|
||||||
|
local resolved=""
|
||||||
|
if ! echo "$destination" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+'; then
|
||||||
|
# It's a domain, try to resolve it to IP for better iptables compatibility
|
||||||
|
# nslookup output varies, try multiple patterns
|
||||||
|
local nslookup_out=$(nslookup "$destination" 2>/dev/null)
|
||||||
|
resolved=$(echo "$nslookup_out" | grep -E "^Address.*[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" | grep -v "127.0.0.1" | grep -v "#53" | head -1 | grep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+')
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Add to excluded list
|
||||||
|
uci add_list tor-shield.trans.excluded_ips="$destination"
|
||||||
|
|
||||||
|
# Also add resolved IP if domain was given and valid IP was resolved
|
||||||
|
if [ -n "$resolved" ] && echo "$resolved" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$'; then
|
||||||
|
uci add_list tor-shield.trans.excluded_ips="$resolved"
|
||||||
|
fi
|
||||||
|
|
||||||
|
uci commit tor-shield
|
||||||
|
|
||||||
|
json_add_boolean "success" 1
|
||||||
|
json_add_string "destination" "$destination"
|
||||||
|
[ -n "$resolved" ] && json_add_string "resolved_ip" "$resolved"
|
||||||
|
json_add_string "message" "Destination excluded from Tor"
|
||||||
|
|
||||||
|
json_dump
|
||||||
|
}
|
||||||
|
|
||||||
|
# Remove excluded destination
|
||||||
|
remove_excluded_destination() {
|
||||||
|
read input
|
||||||
|
json_load "$input"
|
||||||
|
|
||||||
|
local destination
|
||||||
|
json_get_var destination destination
|
||||||
|
|
||||||
|
json_init
|
||||||
|
|
||||||
|
if [ -z "$destination" ]; then
|
||||||
|
json_add_boolean "success" 0
|
||||||
|
json_add_string "error" "Destination is required"
|
||||||
|
json_dump
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
uci del_list tor-shield.trans.excluded_ips="$destination" 2>/dev/null
|
||||||
|
uci commit tor-shield
|
||||||
|
|
||||||
|
json_add_boolean "success" 1
|
||||||
|
json_add_string "message" "Destination removed from exclusion list"
|
||||||
|
|
||||||
|
json_dump
|
||||||
|
}
|
||||||
|
|
||||||
|
# Apply exclusions (restart iptables rules)
|
||||||
|
apply_exclusions() {
|
||||||
|
json_init
|
||||||
|
|
||||||
|
# Restart tor-shield to apply new iptables rules
|
||||||
|
/etc/init.d/tor-shield restart >/dev/null 2>&1 &
|
||||||
|
|
||||||
|
json_add_boolean "success" 1
|
||||||
|
json_add_string "message" "Exclusions applied, Tor Shield restarting"
|
||||||
|
|
||||||
|
json_dump
|
||||||
|
}
|
||||||
|
|
||||||
# Save settings
|
# Save settings
|
||||||
save_settings() {
|
save_settings() {
|
||||||
read input
|
read input
|
||||||
@ -773,7 +895,7 @@ do_restart() {
|
|||||||
|
|
||||||
case "$1" in
|
case "$1" in
|
||||||
list)
|
list)
|
||||||
echo '{"status":{},"enable":{"preset":"str"},"disable":{},"restart":{},"circuits":{},"new_identity":{},"check_leaks":{},"hidden_services":{},"add_hidden_service":{"name":"str","local_port":"int","virtual_port":"int"},"remove_hidden_service":{"name":"str"},"exit_ip":{},"refresh_ips":{},"bandwidth":{},"presets":{},"bridges":{},"set_bridges":{"enabled":"bool","type":"str"},"settings":{},"save_settings":{"mode":"str","dns_over_tor":"bool","kill_switch":"bool","socks_port":"int","trans_port":"int","dns_port":"int","exit_nodes":"str","exclude_exit_nodes":"str","strict_nodes":"bool"}}'
|
echo '{"status":{},"enable":{"preset":"str"},"disable":{},"restart":{},"circuits":{},"new_identity":{},"check_leaks":{},"hidden_services":{},"add_hidden_service":{"name":"str","local_port":"int","virtual_port":"int"},"remove_hidden_service":{"name":"str"},"exit_ip":{},"refresh_ips":{},"bandwidth":{},"presets":{},"bridges":{},"set_bridges":{"enabled":"bool","type":"str"},"settings":{},"save_settings":{"mode":"str","dns_over_tor":"bool","kill_switch":"bool","socks_port":"int","trans_port":"int","dns_port":"int","exit_nodes":"str","exclude_exit_nodes":"str","strict_nodes":"bool"},"excluded_destinations":{},"add_excluded_destination":{"destination":"str"},"remove_excluded_destination":{"destination":"str"},"apply_exclusions":{}}'
|
||||||
;;
|
;;
|
||||||
call)
|
call)
|
||||||
case "$2" in
|
case "$2" in
|
||||||
@ -831,6 +953,18 @@ case "$1" in
|
|||||||
save_settings)
|
save_settings)
|
||||||
save_settings
|
save_settings
|
||||||
;;
|
;;
|
||||||
|
excluded_destinations)
|
||||||
|
get_excluded_destinations
|
||||||
|
;;
|
||||||
|
add_excluded_destination)
|
||||||
|
add_excluded_destination
|
||||||
|
;;
|
||||||
|
remove_excluded_destination)
|
||||||
|
remove_excluded_destination
|
||||||
|
;;
|
||||||
|
apply_exclusions)
|
||||||
|
apply_exclusions
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
echo '{"error": "Unknown method"}'
|
echo '{"error": "Unknown method"}'
|
||||||
;;
|
;;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user