mirror of
https://dev.iopsys.eu/feed/iopsys.git
synced 2025-12-10 07:44:50 +01:00
650 lines
19 KiB
Bash
650 lines
19 KiB
Bash
#!/bin/sh
|
|
|
|
. /lib/functions.sh
|
|
|
|
day=""
|
|
next_days=""
|
|
prev_days=""
|
|
schedule_added=""
|
|
|
|
ACCESS_RULE=""
|
|
IP_RULE=""
|
|
|
|
ACL_FILE=""
|
|
parentalcontrol_ipv4_forward=""
|
|
parentalcontrol_ipv6_forward=""
|
|
|
|
bundle_path="$(uci -q get parentalcontrol.globals.bundle_path)"
|
|
|
|
default_bundle_dir="${bundle_path}/default/"
|
|
bundle_archive="/etc/parentalcontrol/urlbundles.tar.xz"
|
|
|
|
log() {
|
|
echo "$*" |logger -t urlfilter.init -p debug
|
|
}
|
|
|
|
process_default_bundles() {
|
|
if [ -s "$bundle_archive" ]; then
|
|
if mkdir -p "$default_bundle_dir"; then
|
|
if tar -xJf "$bundle_archive" -C "$default_bundle_dir"; then
|
|
log "default bundles placed at $default_bundle_dir"
|
|
else
|
|
log "default bundles could not be placed at $default_bundle_dir"
|
|
fi
|
|
else
|
|
log "could not create directory: $default_bundle_dir"
|
|
fi
|
|
else
|
|
log "default bundles not available"
|
|
fi
|
|
}
|
|
|
|
remove_default_bundles() {
|
|
rm -rf "$default_bundle_dir"
|
|
}
|
|
|
|
# Function to calculate UTC time and relative day
|
|
get_relative_day() {
|
|
local hour="$1"
|
|
local offset="$2"
|
|
local relative_day="$3"
|
|
local utc_hour
|
|
|
|
# we need to force hours and minutes to be treated as base 10 (decimal)
|
|
# otherwise shell will treat, for example, 09 as octal
|
|
# hour=$((10#$hour)) does not work on busybox
|
|
# so we use another trick
|
|
hour=$(expr $hour + 0)
|
|
|
|
# Extract the sign and the hour part of the offset
|
|
local sign=${offset:0:1}
|
|
local offset_hour=${offset:1:2}
|
|
|
|
# Adjust hour based on the offset
|
|
if [ "$sign" = "-" ]; then
|
|
utc_hour=$((hour + offset_hour))
|
|
else
|
|
utc_hour=$((hour - offset_hour))
|
|
fi
|
|
|
|
# Handle overflow/underflow of UTC hours to keep within 0-23 range
|
|
if [ $utc_hour -lt 0 ]; then
|
|
if [ "$relative_day" = "today" ]; then
|
|
relative_day="yesterday"
|
|
else
|
|
relative_day="today"
|
|
fi
|
|
elif [ $utc_hour -ge 24 ]; then
|
|
if [ "$relative_day" = "today" ]; then
|
|
relative_day="tomorrow"
|
|
else
|
|
relative_day="tomorrow"
|
|
fi
|
|
else
|
|
if [ "$relative_day" = "tomorrow" ]; then
|
|
relative_day="tomorrow"
|
|
else
|
|
relative_day="today"
|
|
fi
|
|
fi
|
|
|
|
echo "$relative_day"
|
|
}
|
|
|
|
get_next_day() {
|
|
local weekday="$1"
|
|
case "$weekday" in
|
|
"Mon"|"Monday") echo "Tuesday"
|
|
;;
|
|
"Tue"|"Tuesday") echo "Wednesday"
|
|
;;
|
|
"Wed"|"Wednesday") echo "Thursday"
|
|
;;
|
|
"Thu"|"Thursday") echo "Friday"
|
|
;;
|
|
"Fri"|"Friday") echo "Saturday"
|
|
;;
|
|
"Sat"|"Saturday") echo "Sunday"
|
|
;;
|
|
"Sun"|"Sunday") echo "Monday"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
get_previous_day() {
|
|
local weekday="$1"
|
|
case "$weekday" in
|
|
"Mon"|"Monday") echo "Sunday"
|
|
;;
|
|
"Tue"|"Tuesday") echo "Monday"
|
|
;;
|
|
"Wed"|"Wednesday") echo "Tuesday"
|
|
;;
|
|
"Thu"|"Thursday") echo "Wednesday"
|
|
;;
|
|
"Fri"|"Friday") echo "Thursday"
|
|
;;
|
|
"Sat"|"Saturday") echo "Friday"
|
|
;;
|
|
"Sun"|"Sunday") echo "Saturday"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
add_access_rule() {
|
|
local rule_prefix="$1"
|
|
local start_time="$2"
|
|
local stop_time="$3"
|
|
local weekdays="$4"
|
|
local target="$5"
|
|
local rule
|
|
local start_hm stop_hm
|
|
|
|
if [ -z "$target" ]; then
|
|
return
|
|
fi
|
|
|
|
if [ -n "$weekdays" ]; then
|
|
|
|
start_hm=$(echo "$start_time" | awk -F: '{ print $1,$2 }' | sed 's/ //')
|
|
stop_hm=$(echo "$stop_time" | awk -F: '{ print $1,$2 }' | sed 's/ //')
|
|
|
|
if [ "$start_hm" = "$stop_hm" ]; then
|
|
return
|
|
fi
|
|
|
|
rule_prefix="$rule_prefix -m time --timestart $start_time --timestop $stop_time --weekdays $weekdays"
|
|
fi
|
|
|
|
rule="$rule_prefix -j $target"
|
|
|
|
echo "iptables -w -A parentalcontrol_forward ${rule}" >> "$ACL_FILE"
|
|
echo "ip6tables -w -A parentalcontrol_forward ${rule}" >> "$ACL_FILE"
|
|
}
|
|
|
|
generate_ip_rule() {
|
|
local utc_start_relative_day="$1"
|
|
local utc_end_relative_day="$2"
|
|
local utc_start_time="$3"
|
|
local utc_stop_time="$4"
|
|
local target="$5"
|
|
|
|
# Handle the cases based on the relation between utc_start_relative_day and utc_end_relative_day
|
|
if [ "$utc_start_relative_day" = "yesterday" ] && [ "$utc_end_relative_day" = "yesterday" ]; then
|
|
# Rule for yesterday only
|
|
add_access_rule "$IP_RULE" "$utc_start_time" "$utc_stop_time" "$prev_days" "$target"
|
|
|
|
elif [ "$utc_start_relative_day" = "yesterday" ] && [ "$utc_end_relative_day" = "today" ]; then
|
|
# Rule for yesterday to today
|
|
add_access_rule "$IP_RULE" "$utc_start_time" "23:59:59" "$prev_days" "$target"
|
|
add_access_rule "$IP_RULE" "00:00" "$utc_stop_time" "$day" "$target"
|
|
|
|
elif [ "$utc_start_relative_day" = "today" ] && [ "$utc_end_relative_day" = "today" ]; then
|
|
# Rule for today only
|
|
add_access_rule "$IP_RULE" "$utc_start_time" "$utc_stop_time" "$day" "$target"
|
|
|
|
elif [ "$utc_start_relative_day" = "today" ] && [ "$utc_end_relative_day" = "tomorrow" ]; then
|
|
# Rule for today to tomorrow
|
|
add_access_rule "$IP_RULE" "$utc_start_time" "23:59:59" "$day" "$target"
|
|
add_access_rule "$IP_RULE" "00:00" "$utc_stop_time" "$next_days" "$target"
|
|
|
|
elif [ "$utc_start_relative_day" = "tomorrow" ] && [ "$utc_end_relative_day" = "tomorrow" ]; then
|
|
# Rule for tomorrow only
|
|
add_access_rule "$IP_RULE" "$utc_start_time" "$utc_stop_time" "$next_days" "$target"
|
|
else
|
|
log "Error: Unhandled case"
|
|
fi
|
|
}
|
|
|
|
handle_day_list() {
|
|
local value=$1
|
|
|
|
val=$(echo $value | cut -c 1-3)
|
|
next_day_val=$(get_next_day $val)
|
|
prev_day_val=$(get_previous_day $val)
|
|
if [ -z $day ]; then
|
|
day="$val"
|
|
next_days="$next_day_val"
|
|
prev_days="$prev_day_val"
|
|
else
|
|
day="$day,$val"
|
|
next_days="$next_days,$next_day_val"
|
|
prev_days="$prev_days,$prev_day_val"
|
|
fi
|
|
}
|
|
|
|
handle_schedule() {
|
|
local schedule_section="$1"
|
|
local type="$2"
|
|
local schedule_ref="$3"
|
|
local local_start_time local_stop_time duration zone_offset local_start_hh local_stop_hh
|
|
local is_enabled
|
|
local target
|
|
local day_config
|
|
local relative_day_end="today"
|
|
|
|
IP_RULE="$ACCESS_RULE"
|
|
day=""
|
|
next_days=""
|
|
prev_days=""
|
|
local all_days="Monday Tuesday Wednesday Thursday Friday Saturday Sunday"
|
|
|
|
zone_offset=$(date +%z)
|
|
|
|
config_get_bool is_enabled "$schedule_section" "enable" 0
|
|
if [ $is_enabled -eq 0 ]; then
|
|
return
|
|
fi
|
|
|
|
if [ "$type" = "profile_bedtime_schedule" ]; then
|
|
target="DROP"
|
|
|
|
config_get local_start_time "$schedule_section" "start_time" "00:00:00"
|
|
config_get local_stop_time "$schedule_section" "end_time" "23:59:59"
|
|
|
|
local_start_hh=$(echo $local_start_time | awk -F: '{ print $1 }')
|
|
local_stop_hh=$(echo $local_stop_time | awk -F: '{ print $1 }')
|
|
|
|
config_get day_config "$schedule_section" "day" "$all_days"
|
|
else
|
|
if [ "$schedule_ref" != "$schedule_section" ]; then
|
|
return
|
|
fi
|
|
|
|
# for access rules to be effective for a schedule, need to add DROP rule
|
|
# to block the access outside the defined schedule
|
|
# therefore, set flag
|
|
if [ "$schedule_added" = "0" ]; then
|
|
schedule_added="1"
|
|
fi
|
|
|
|
# internet_access has been updated to be internet_break
|
|
# so drop traffic during the schedule, and allow outside the schedule
|
|
target="DROP"
|
|
|
|
config_get local_start_time "$schedule_section" "start_time" "00:00"
|
|
config_get duration "$schedule_section" "duration"
|
|
|
|
local hh=$(echo $local_start_time | awk -F: '{ print $1 }')
|
|
local mm=$(echo $local_start_time | awk -F: '{ print $2 }')
|
|
local hh_s=`expr $hh \* 3600`
|
|
local mm_s=`expr $mm \* 60`
|
|
local ss=$(( hh_s + mm_s ))
|
|
local_start_hh=$hh
|
|
|
|
if [ -n "$duration" ]; then
|
|
local stop_ss rem_ss mm
|
|
stop_ss=$(( ss + duration ))
|
|
hh=$(( stop_ss / 3600 ))
|
|
rem_ss=$(( stop_ss % 3600 ))
|
|
mm=$(( rem_ss / 60 ))
|
|
ss=$(( rem_ss % 60 ))
|
|
local_stop_time="$hh:$mm:$ss"
|
|
local_stop_hh="$hh"
|
|
else
|
|
# if duration is not specified, then apply rule to end of the day
|
|
local_stop_time="23:59:59"
|
|
local_stop_hh="23"
|
|
fi
|
|
|
|
config_get day_config "$schedule_section" "day" "$all_days"
|
|
fi
|
|
|
|
IFS=" "
|
|
for d in $day_config; do
|
|
handle_day_list $d
|
|
done
|
|
|
|
utc_start_time=$(date -u -d @$(date "+%s" -d "$local_start_time") +%H:%M)
|
|
utc_start_time="$utc_start_time"
|
|
utc_stop_time=$(date -u -d @$(date "+%s" -d "$local_stop_time") +%H:%M)
|
|
utc_stop_time="$utc_stop_time"
|
|
|
|
# Determine whether the local end hour crosses midnight
|
|
if [ "$local_start_hh" -gt "$local_stop_hh" ]; then
|
|
relative_day_end="tomorrow"
|
|
fi
|
|
|
|
local utc_start_relative_day=$(get_relative_day "$local_start_hh" "$zone_offset" "today")
|
|
local utc_end_relative_day=$(get_relative_day "$local_stop_hh" "$zone_offset" "$relative_day_end")
|
|
|
|
generate_ip_rule "$utc_start_relative_day" "$utc_end_relative_day" "$utc_start_time" "$utc_stop_time" "$target"
|
|
}
|
|
|
|
handle_bedtime() {
|
|
local mac_addresses="$1"
|
|
local mac
|
|
|
|
# if mac addresses are present, then we apply the rule for each mac address
|
|
# otherwise apply the rule to everybody
|
|
for mac in $mac_addresses; do
|
|
ACCESS_RULE="-m mac --mac-source $mac"
|
|
|
|
config_foreach handle_schedule profile_bedtime_schedule "profile_bedtime_schedule" ""
|
|
done
|
|
}
|
|
|
|
handle_internet_break() {
|
|
local mac_addresses="$1"
|
|
local mac
|
|
|
|
local schedule_ref
|
|
config_get schedule_ref "$profile_section" "internet_break_schedule"
|
|
|
|
for mac in $mac_addresses; do
|
|
ACCESS_RULE="-m mac --mac-source $mac"
|
|
|
|
schedule_added="0"
|
|
|
|
# check if schedule is defined for this profile/internet_break instance
|
|
# and if yes, create rule accordingly
|
|
if [ -n "$schedule_ref" ]; then
|
|
config_load "schedules"
|
|
config_foreach handle_schedule schedule "schedule" "$schedule_ref"
|
|
fi
|
|
done
|
|
}
|
|
|
|
parse_macs() {
|
|
local maclist="$1"
|
|
local m mac
|
|
|
|
for m in $maclist; do
|
|
# trim whitespace
|
|
mac="$(echo "$m" | tr -d ' \t\r\n')"
|
|
|
|
# validate format
|
|
if echo "$mac" | grep -qE '^[0-9A-Fa-f]{2}(:[0-9A-Fa-f]{2}){5}$'; then
|
|
echo "$mac"
|
|
else
|
|
log "parse_macs(): Invalid MAC in mac list: '$mac'"
|
|
fi
|
|
done
|
|
}
|
|
|
|
handle_profile() {
|
|
local profile_section="$1"
|
|
local internet_break_enable bedtime_enable hostlist maclist
|
|
|
|
config_get_bool internet_break_enable "$profile_section" "internet_break_enable" 0
|
|
config_get_bool bedtime_enable "$profile_section" "bedtime_enable" 0
|
|
|
|
if [ $internet_break_enable -eq 0 ] && [ $bedtime_enable -eq 0 ]; then
|
|
return
|
|
fi
|
|
|
|
config_get hostlist "$profile_section" "host"
|
|
config_get maclist "$profile_section" "mac"
|
|
|
|
# If both lists are empty, nothing to do
|
|
if [ -z "$hostlist" ] && [ -z "$maclist" ]; then
|
|
return
|
|
fi
|
|
|
|
ACCESS_RULE=""
|
|
|
|
# both uci options contain mac addresses
|
|
# one is given directly by the user
|
|
# other is resolved by the data model from Hosts.Host object
|
|
local mac_addresses="$(parse_macs "${hostlist} ${maclist}" | awk '{ if (NF && !seen[$0]++) { print $0 } }' | tr '\n' ' ')"
|
|
|
|
# default value of Hosts.AccessControl.{i}.Enable is false,
|
|
# so, if not defined in uci as 1, assume 0
|
|
if [ $internet_break_enable -gt 0 ]; then
|
|
handle_internet_break "${mac_addresses}"
|
|
# handle_internet_break may have loaded schedules uci
|
|
# so, reload parentalcontrol
|
|
config_load "parentalcontrol"
|
|
fi
|
|
|
|
if [ $bedtime_enable -gt 0 ]; then
|
|
handle_bedtime "${mac_addresses}"
|
|
fi
|
|
}
|
|
|
|
add_internet_schedule_rules() {
|
|
ACL_FILE="/tmp/parentalcontrol_access_control/access_control.rules"
|
|
|
|
rm -f $ACL_FILE
|
|
|
|
mkdir -p /tmp/parentalcontrol_access_control/
|
|
touch $ACL_FILE
|
|
|
|
echo "iptables -w -F parentalcontrol_forward" >> $ACL_FILE
|
|
echo "ip6tables -w -F parentalcontrol_forward" >> $ACL_FILE
|
|
|
|
parentalcontrol_ipv4_forward=$(iptables -w -t filter --list -n | grep parentalcontrol_forward)
|
|
if [ -z "$parentalcontrol_ipv4_forward" ]; then
|
|
echo "iptables -w -t filter -N parentalcontrol_forward" >> $ACL_FILE
|
|
ret=$?
|
|
[ $ret -eq 0 ] && echo "iptables -w -t filter -I FORWARD -j parentalcontrol_forward" >> $ACL_FILE
|
|
fi
|
|
|
|
parentalcontrol_ipv6_forward=$(ip6tables -w -t filter --list -n | grep parentalcontrol_forward)
|
|
if [ -z "$parentalcontrol_ipv6_forward" ]; then
|
|
echo "ip6tables -w -t filter -N parentalcontrol_forward" >> $ACL_FILE
|
|
ret=$?
|
|
[ $ret -eq 0 ] && echo "ip6tables -w -t filter -I FORWARD -j parentalcontrol_forward" >> $ACL_FILE
|
|
fi
|
|
|
|
# Load /etc/config/parentalcontrol UCI file
|
|
config_load "parentalcontrol"
|
|
config_foreach handle_profile "profile"
|
|
|
|
# apply the rules
|
|
sh $ACL_FILE
|
|
}
|
|
|
|
add_iptables_nfqueue_rules() {
|
|
local queue_num="$1"
|
|
|
|
# Check if urlfilter used
|
|
if ! uci show parentalcontrol | grep -q profile_urlfilter; then
|
|
return
|
|
fi
|
|
|
|
# IPv4
|
|
# FORWARD
|
|
if ! iptables -w -nL | grep -q "URLFILTER_FORWARD"; then
|
|
iptables -w -N URLFILTER_FORWARD
|
|
iptables -w -I FORWARD 1 -j URLFILTER_FORWARD
|
|
|
|
# capture DNS responses (sport 53)
|
|
iptables -w -A URLFILTER_FORWARD -p tcp --sport 53 -j NFQUEUE --queue-num $queue_num --queue-bypass
|
|
iptables -w -A URLFILTER_FORWARD -p udp --sport 53 -j NFQUEUE --queue-num $queue_num --queue-bypass
|
|
|
|
# HTTP/HTTPS flows
|
|
iptables -w -A URLFILTER_FORWARD -p tcp --match multiport --ports 80,443 -j NFQUEUE --queue-num $queue_num --queue-bypass
|
|
iptables -w -A URLFILTER_FORWARD -p udp --match multiport --ports 80,443 -j NFQUEUE --queue-num $queue_num --queue-bypass
|
|
fi
|
|
|
|
# INPUT
|
|
if ! iptables -w -nL | grep -q "URLFILTER_INPUT"; then
|
|
iptables -w -N URLFILTER_INPUT
|
|
iptables -w -I INPUT 1 -j URLFILTER_INPUT
|
|
|
|
iptables -w -A URLFILTER_INPUT -p tcp --sport 53 ! -i lo -j NFQUEUE --queue-num $queue_num --queue-bypass
|
|
iptables -w -A URLFILTER_INPUT -p udp --sport 53 ! -i lo -j NFQUEUE --queue-num $queue_num --queue-bypass
|
|
fi
|
|
|
|
# OUTPUT
|
|
if ! iptables -w -nL | grep -q "URLFILTER_OUTPUT"; then
|
|
iptables -w -N URLFILTER_OUTPUT
|
|
iptables -w -I OUTPUT 1 -j URLFILTER_OUTPUT
|
|
|
|
iptables -w -A URLFILTER_OUTPUT -p tcp --sport 53 ! -o lo -j NFQUEUE --queue-num $queue_num --queue-bypass
|
|
iptables -w -A URLFILTER_OUTPUT -p udp --sport 53 ! -o lo -j NFQUEUE --queue-num $queue_num --queue-bypass
|
|
fi
|
|
|
|
# ebtables bypass for IPv4
|
|
ebtables --concurrent -A FORWARD -p ip --ip-protocol 6 --ip-destination-port 443 -j SKIPLOG 2>/dev/null
|
|
ebtables --concurrent -A FORWARD -p ip --ip-protocol 6 --ip-source-port 53 -j SKIPLOG 2>/dev/null
|
|
ebtables --concurrent -A FORWARD -p ip --ip-protocol 17 --ip-source-port 53 -j SKIPLOG 2>/dev/null
|
|
|
|
# IPv6
|
|
# FORWARD
|
|
if ! ip6tables -w -nL | grep -q "URLFILTER_FORWARD6"; then
|
|
ip6tables -w -N URLFILTER_FORWARD6
|
|
ip6tables -w -I FORWARD 1 -j URLFILTER_FORWARD6
|
|
|
|
ip6tables -w -A URLFILTER_FORWARD6 -p tcp --sport 53 -j NFQUEUE --queue-num $queue_num --queue-bypass
|
|
ip6tables -w -A URLFILTER_FORWARD6 -p udp --sport 53 -j NFQUEUE --queue-num $queue_num --queue-bypass
|
|
|
|
ip6tables -w -A URLFILTER_FORWARD6 -p tcp --match multiport --ports 80,443 -j NFQUEUE --queue-num $queue_num --queue-bypass
|
|
ip6tables -w -A URLFILTER_FORWARD6 -p udp --match multiport --ports 80,443 -j NFQUEUE --queue-num $queue_num --queue-bypass
|
|
fi
|
|
|
|
# INPUT
|
|
if ! ip6tables -w -nL | grep -q "URLFILTER_INPUT6"; then
|
|
ip6tables -w -N URLFILTER_INPUT6
|
|
ip6tables -w -I INPUT 1 -j URLFILTER_INPUT6
|
|
|
|
ip6tables -w -A URLFILTER_INPUT6 -p tcp --sport 53 ! -i lo -j NFQUEUE --queue-num $queue_num --queue-bypass
|
|
ip6tables -w -A URLFILTER_INPUT6 -p udp --sport 53 ! -i lo -j NFQUEUE --queue-num $queue_num --queue-bypass
|
|
fi
|
|
|
|
# OUTPUT
|
|
if ! ip6tables -w -nL | grep -q "URLFILTER_OUTPUT6"; then
|
|
ip6tables -w -N URLFILTER_OUTPUT6
|
|
ip6tables -w -I OUTPUT 1 -j URLFILTER_OUTPUT6
|
|
|
|
ip6tables -w -A URLFILTER_OUTPUT6 -p tcp --sport 53 ! -o lo -j NFQUEUE --queue-num $queue_num --queue-bypass
|
|
ip6tables -w -A URLFILTER_OUTPUT6 -p udp --sport 53 ! -o lo -j NFQUEUE --queue-num $queue_num --queue-bypass
|
|
fi
|
|
|
|
# ebtables bypass for IPv6
|
|
ebtables --concurrent -A FORWARD -p ip6 --ip6-protocol 6 --ip6-destination-port 443 -j SKIPLOG 2>/dev/null
|
|
ebtables --concurrent -A FORWARD -p ip6 --ip6-protocol 6 --ip6-source-port 53 -j SKIPLOG 2>/dev/null
|
|
ebtables --concurrent -A FORWARD -p ip6 --ip6-protocol 17 --ip6-source-port 53 -j SKIPLOG 2>/dev/null
|
|
}
|
|
|
|
remove_iptables_nfqueue_rules() {
|
|
# IPv4
|
|
for chain in URLFILTER_FORWARD URLFILTER_INPUT URLFILTER_OUTPUT; do
|
|
if iptables -w -nL | grep -q "$chain"; then
|
|
iptables -w -D FORWARD -j $chain 2>/dev/null
|
|
iptables -w -D INPUT -j $chain 2>/dev/null
|
|
iptables -w -D OUTPUT -j $chain 2>/dev/null
|
|
iptables -w -F $chain
|
|
iptables -w -X $chain
|
|
fi
|
|
done
|
|
|
|
ebtables --concurrent -D FORWARD -p ip --ip-protocol 6 --ip-destination-port 443 -j SKIPLOG 2>/dev/null
|
|
ebtables --concurrent -D FORWARD -p ip --ip-protocol 6 --ip-source-port 53 -j SKIPLOG 2>/dev/null
|
|
ebtables --concurrent -D FORWARD -p ip --ip-protocol 17 --ip-source-port 53 -j SKIPLOG 2>/dev/null
|
|
|
|
# IPv6
|
|
for chain in URLFILTER_FORWARD6 URLFILTER_INPUT6 URLFILTER_OUTPUT6; do
|
|
if ip6tables -w -nL | grep -q "$chain"; then
|
|
ip6tables -w -D FORWARD -j $chain 2>/dev/null
|
|
ip6tables -w -D INPUT -j $chain 2>/dev/null
|
|
ip6tables -w -D OUTPUT -j $chain 2>/dev/null
|
|
ip6tables -w -F $chain
|
|
ip6tables -w -X $chain
|
|
fi
|
|
done
|
|
|
|
ebtables --concurrent -D FORWARD -p ip6 --ip6-protocol 6 --ip6-destination-port 443 -j SKIPLOG 2>/dev/null
|
|
ebtables --concurrent -D FORWARD -p ip6 --ip6-protocol 6 --ip6-source-port 53 -j SKIPLOG 2>/dev/null
|
|
ebtables --concurrent -D FORWARD -p ip6 --ip6-protocol 17 --ip6-source-port 53 -j SKIPLOG 2>/dev/null
|
|
}
|
|
|
|
remove_internet_schedule_rules() {
|
|
# remove from iptables, if chain exists
|
|
if iptables -w -nL FORWARD|grep -iqE "parentalcontrol_forward"; then
|
|
iptables -w -t filter -D FORWARD -j parentalcontrol_forward
|
|
iptables -w -F parentalcontrol_forward
|
|
iptables -w -X parentalcontrol_forward
|
|
fi
|
|
# remove from ip6tables, if chain exists
|
|
if ip6tables -w -nL FORWARD|grep -iqE "parentalcontrol_forward"; then
|
|
ip6tables -w -t filter -D FORWARD -j parentalcontrol_forward
|
|
ip6tables -w -F parentalcontrol_forward
|
|
ip6tables -w -X parentalcontrol_forward
|
|
fi
|
|
}
|
|
|
|
get_host_ip_from_mac() {
|
|
local mac="$1"
|
|
local ip=""
|
|
|
|
# Validate MAC format
|
|
if ! echo "$mac" | grep -qE '^([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$'; then
|
|
log "get_host_ip_from_mac(): Invalid MAC address format '$mac'"
|
|
return 1
|
|
fi
|
|
|
|
# Try to find IP from ARP table
|
|
ip="$(cat /proc/net/arp | awk -v mac="$mac" 'tolower($4) == tolower(mac) {print $1; exit}')"
|
|
|
|
if [ -n "$ip" ]; then
|
|
URLFILTER_IPS="${URLFILTER_IPS} ${ip}"
|
|
return 0
|
|
else
|
|
log "get_host_ip_from_mac(): No IP found for MAC $mac in ARP table"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Global array for resolved IPs
|
|
URLFILTER_IPS=""
|
|
|
|
resolve_profile_hosts() {
|
|
local section="$1"
|
|
local hostlist maclist h m
|
|
|
|
config_get hostlist "$section" host
|
|
config_get maclist "$section" mac
|
|
|
|
for h in $hostlist; do
|
|
get_host_ip_from_mac "$h"
|
|
done
|
|
|
|
for m in $maclist; do
|
|
get_host_ip_from_mac "$m"
|
|
done
|
|
}
|
|
|
|
# Main function to collect IPs and delete conntrack entries
|
|
flush_conntrack_for_hosts() {
|
|
URLFILTER_IPS=""
|
|
local count max
|
|
|
|
config_foreach resolve_profile_hosts profile
|
|
|
|
URLFILTER_IPS="$(echo "$URLFILTER_IPS" | tr ' ' '\n' | sort -u | xargs)"
|
|
for ip in $URLFILTER_IPS; do
|
|
count=0
|
|
max=1000
|
|
while conntrack -D -s "$ip" >/dev/null 2>&1; do
|
|
count=$((count+1))
|
|
if [ $count -ge $max ]; then
|
|
log "Warning: Forced to stop conntrack delete after $max deletions for $ip (possible loop)"
|
|
break
|
|
fi
|
|
done
|
|
done
|
|
}
|
|
|
|
OVERRIDE_JSON="/etc/parentalcontrol/urlbundle_override.json"
|
|
DM_PLUGIN_PATH="/usr/share/bbfdm/micro_services/parentalcontrol/urlbundle_override.json"
|
|
|
|
enable_urlfilter_dm() {
|
|
if [ -f "${DM_PLUGIN_PATH}" ]; then
|
|
rm ${DM_PLUGIN_PATH}
|
|
echo "Please restart to apply"
|
|
fi
|
|
}
|
|
|
|
disable_urlfilter_dm() {
|
|
mkdir -p "$(dirname ${DM_PLUGIN_PATH})"
|
|
|
|
if [ ! -f "${DM_PLUGIN_PATH}" ]; then
|
|
if [ -f "${OVERRIDE_JSON}" ]; then
|
|
cp "${OVERRIDE_JSON}" "${DM_PLUGIN_PATH}"
|
|
echo "Please restart to apply"
|
|
|
|
fi
|
|
fi
|
|
}
|