I have a teenage lad who needs to learn some discipline with internet access etc. etc. My main problem is that he is downloading so much that he is using more than his fair share. What I'd like to do is set a download quota for him so that he can learn what this all means. Can anyone point me to decent tools / tutorials / or show me how to do this? I have his mother's support on this so this should not turn into a lesson in teenage behaviour :-).
There are ways of achieving this kind of thing, but the appropriate method depends on your configuration. In order to be able to give a reasonable suggestion can you please post the following information.
How do you connect to the internet (broadand router/modem) ?
Thanx for the quick reply I realised that I had not supplied enough info - DOH!!!!!!!!! Anyway here's the stuff: Connection is via eth0 to a broadband router. Ther eis one PC connected and four users on the PC using Hardy Heron. Funny thing is that /dev/eth0 does not exist and I thought that this would be the obvious place to start.
That's the most difficult setup to implement quotas on because there is no real correlation between the user an the network traffic. I think however that I can figure something out to do what you want.
Over what time period do you want to set the quota? Daily/weekly/monthly? And what effect do you want to have when the quota runs out?
Well what I'd really like to do is stop his access to the eth0 interface so that he has no way of accessing the internet once he has reached his limit after a month. I'm sure that he can do it in three days so it will be a hard lesson for him to learn :-). Is it not possible to do this on a per user basis?
I didn't get much time to look at this today, but I put something together in about 20 minutes to get started. I have done some basic testing and it does work but might not be the most robust yet.
The main script:
#!/bin/bash
#
#
# posted by reborg on The UNIX and Linux Forums
# (c) 2009 - The UNIX and Linux Forums
#
CONFIGFILE=/etc/bandlimit.conf
RUNDIR=/var/run/bandcap
STATSFILE=/proc/net/dev
AWK=/usr/bin/awk
DATE=/bin/date
IPTABLES=/sbin/iptables
TOUCH=/usr/bin/touch
WHO=/usr/bin/who
NETWORK_BLOCKED=0
block_network() {
if [[ $NETWORK_BLOCKED -ne 1 ]] ; then
$IPTABLES -A INPUT -j DROP
NETWORK_BLOCKED=1
fi
}
unblock_network() {
$IPTABLES -D INPUT -j DROP > /dev/null 2>&1
NETWORK_BLOCKED=0
}
init() {
if [[ -f ${RUNDIR}/pidfile ]] ; then
exit
else
echo $$ > ${RUNDIR}/pidfile
fi
INTERFACE=$($AWK '$1 == "INTERFACE" {print $2}' $CONFIGFILE)
USER_BANDWIDTH=$($AWK -v user="$username" '$1 == user { printf "%i\n", $2 * 1024 * 1024 ; exit}' $CONFIGFILE)
if [[ -z "$USER_BANDWIDTH" ]] ; then
unblock_network
CAP_USER=0
return
fi
CAP_USER=1
$TOUCH ${RUNDIR}/${username}.$($DATE +%m)
[[ -d $RUNDIR ]] || mkdir -p $RUNDIR
if [[ ! -f "${RUNDIR}/${username}" ]] ; then
echo $USER_BANDWIDTH > "${RUNDIR}/$username"
fi
REMAINING=$(< "${RUNDIR}/${username}" )
# note IFS on the next line is '<space><tab>:'
while IFS=' :' read net bandwidth junk; do
if [[ "$net" = "$INTERFACE" ]] ; then
STARTUP_BANDWIDTH=$bandwidth
fi
done < $STATSFILE
if (( REMAINING > 0 )) ; then
unblock_network
fi
}
run() {
while : ; do
set -- $($WHO)
if [[ $# -lt 1 ]] ; then
sleep 60
next
fi
if [[ "$1" != "$username" ]] ; then
username="$1"
init
fi
if [[ $CAP_USER -eq 1 ]] ; then
while IFS=' :' read net bandwidth junk; do
if [[ "$net" = "$INTERFACE" ]] ; then
LAST_MONTH=$($DATE -d "last month" +%m)
if [[ -f ${RUNDIR}/${username}.${LAST_MONTH} ]] ; then
rm ${RUNDIR}/${username}.${LAST_MONTH}
$TOUCH ${RUNDIR}/${username}.$($DATE +%m)
REMAINING=$USER_BANDWIDTH
STARTUP_BANDWIDTH=$bandwidth
unblock_network
fi
(( SESSION = bandwidth - STARTUP_BANDWIDTH ))
(( REMAINING = REMAINING - SESSION ))
if (( REMAINING <= 0 )) ; then
block_network
echo 0 > ${RUNDIR}/$username
else
echo $REMAINING > ${RUNDIR}/$username
fi
fi
done < $STATSFILE
fi
sleep 60
done
}
if [[ ! -f $CONFIGFILE ]] ; then
echo "No bandwidth limits set" >& 2
exit 2
fi
run
Config file
The format of this file is:
INTERFACE <iterface name>
<username> <monthly bandwidth limit in megabytes>
In this version you can have only one INTERFACE line and as many user lines as you want. Don't forget to update the INTERFACE line to eth0 if you use the attached sample config file.
INTERFACE wlan0
testuser 100
Init script
#!/bin/bash
PIDFILE=/var/run/bandcap/pidfile
case $1 in
start)
if [[ -f "$PIDFILE" ]] ; then
PID=$(< "$PIDFILE")
/bin/ps -fp $PID | grep -q userband_limit.sh
if [[ $? -eq 0 ]] ; then
echo "User bandwidth limiter already running" >&2
exit 1
else
rm "$PIDFILE"
$START_COMMAND
fi
else
( /usr/bin/userband_limit.sh & )
fi
;;
stop)
if [[ -f "$PIDFILE" ]] ; then
PID=$(< "$PIDFILE")
/bin/ps -fp $PID | grep -q userband_limit.sh
if [[ $? -ne 0 ]] ; then
rm "$PIDFILE"
echo "User bandwidth limiter already stopped" >&2
exit 1
else
rm "$PIDFILE"
/bin/kill $PID
fi
else
echo "User bandwidth limiter already stopped" >&2
exit 1
fi
;;
esac
Instructions:
Download the three files attached
Open a terminal and cd to the directory where you downloaded the files
Edit the config file to add your usernames and bandwidth limits
sudo gedit /etc/bandlimit.conf
Start the bandwidth monitor
/etc/init.d/userband_init.sh start
NOTES
Stopping the limiter using text /etc/init.d/userband_init.sh stop
does not unblock the network. If you need to unblock the network you need run text sudo /sbin/iptables -D INPUT -j DROP
It can take up to 1 minute after a new user who has no limit or who has not exceeded their limit logs in for the network to become available.