After some more hours .... ( I have not yet tested it my self)
Code:
#!/bin/sh -x
# set +x remove debug
# set -x enable debug
# https://www.shellcheck.net/ own reminder
#
# Session time quota v0.1 by Pernils Snygg 2022-01-07
#
# The script is to limit the total time used by a device per day.
# This is achieved by checking the arp table for the device.
# (arp table is flushed every 45 sec by default)
# If the device is found the counter increase with the time elapsed since last time the device was found.
# The client and time quota can be edit with these variables.
client_default=192.168.1.127 # default ip or mac (in format: 00:00:00:aa:aa)
# limits is entered in minutes
mon_lim=70 # Monday
tue_lim=70 # Thuesday
wen_lim=5 # ...
thu_lim=5
fri_lim=150
sat_lim=150
sun_lim=5
# Install :
# In dd-wrt web interface goto Administration -> Command, and copy and paste the script
# and click the button Save startup or Save Custom.
#
#
# Under Administration -> Management ad a cron job pointing to the script.
# Save startup button : /tmp/.rc_startup
# Save custom button : /tmp/.rc_custom
#
# The script can be called by arguments : client monday tuesday ..
#
# Example of cronscript executed every 5 minutes, remember cron must be called by root
# (60 minutes mon-wen and 120 the rest of the week)
#
# */5 * * * * root /tmp/.rc_starup 192.168.1.254 60 60 60 120 120 120 1
#
# */5 * * * * root /tmp/.rc_starup 8a:fe:60:70:9f:c7 60 60 60 120 120 120 1
#
# above the same time quota but with mac address
# You can add as many clients you need but clients who never shuts off like tablets will
# by there broadcast trigger the counter mechanism even not in use.
#
# Have a idea to fix this but future will tell if it will be implemented.
#
# The counters is reset at midnight or if the router is rebooted.
#
#
access_log=/tmp/lars_access # Name of the access_log file
u_time_default=0 # default start value for users used time in seconds [$u_time]
# The same for ip as mac address
delete_rules() {
nr=$(iptables -S FORWARD |grep -wn "$s_client" | cut -d: -f1 | head -n 1)
# client have an entry already in the access_log, (lineNum is set)
# if [ -z "$lineNum" ]; then
# sed '1 c$s_client $s_date $s_time $u_time' $access_log > ${access_log}.tmp
# cat ${access_log}.tmp > $access_log # possible bug if race condition
# rm ${access_log}.tmp # the { } is to mark where varibale name stops
# else
# echo "$s_client" "$s_date" "$s_time" "$u_time" >>$access_log # no entry = append access_log
# fi
}
read_session_log() {
# create new session_file if missing
if [ ! -f $access_log ]; then touch $access_log; fi
# client not found in the access log
else
s_date=$(date +"%F") # current date
s_time=$(date +"%T") # current time
u_time=$u_time_default # default user time
fi
}
validate_session() {
case $(date +%u) in # get maxlimit for current day * 60 for second
1) maxlimits=$((mon_lim * 60)) # minute * 60 for second
;;
2) maxlimits=$((tue_lim * 60))
;;
3) maxlimits=$((wen_lim * 60))
;;
4) maxlimits=$((thu_lim * 60))
;;
5) maxlimits=$((fri_lim * 60))
;;
6) maxlimits=$((sat_lim * 60))
;;
7) maxlimits=$((sun_lim * 60))
esac
# rester counter if passing midnight
if [ $(date -d $(date +"%F") +"%Y%m%d") -gt $(date -d $s_date +"%Y%m%d") ]; then
u_time=$u_time_default
s_time=$(date +"%T")
fi
if [ $u_time -le $maxlimits ]; then # limits have not reach
TIME1=$(date +"%T") # current time stamp
TIME2=$s_time # last checked time stamp
# Convert the times to seconds from the Epoch
SEC1=$(date +%s -d "${TIME1}")
SEC2=$(date +%s -d "${TIME2}")
# Use expr to do the math, current time - last checked time + users used time
DIFFSEC=$(( SEC1 - SEC2 + u_time)) #u_time is in seconds
# DIFFMIN=$(( $DIFFSEC / 60 ))
# DIFF=`date +%H:%M:%S -d @${DIFFSEC}` # format to hh:mm:ss
write_log "$s_client" "$(date +"%F %T")" $DIFFSEC
accept_client # remove rules
else
drop_client # dropin client ip / mac (user have consumed its limits)
fi
}
# **************************
# MAIN
# **************************
s_client=$client_default
if [ "$1" ]; then s_client=$1; fi # sets arguments if exists
if [ "$2" ]; then mon_lim=$2; fi
if [ "$3" ]; then tue_lim=$3; fi
if [ "$4" ]; then wen_lim=$4; fi
if [ "$5" ]; then thu_lim=$5; fi
if [ "$6" ]; then fri_lim=$6; fi
if [ "$7" ]; then sat_lim=$7; fi
if [ "$8" ]; then sun_lim=$8; fi
if [ "$9" ]; then c_reset_at=$9; fi # counter resets at
if arp | grep -w "$s_client"; then # see if $s_client exist in arp table
Posted: Thu Jul 20, 2023 16:16 Post subject: Contribution
Dear all,
I've read this topic delightfully because I ran into the same issue.
I tried to make it easier to configure it.
Here is a gist that works on my Netgear R7000.
I've included a threshold based on packet (but it could/should be done on bytes instead) to allow for an idle laptop not to account for children triggered traffic (windows update background, etc)
I hope it may be of use, even if I quite unearthed the topic!