README and added second excluded network

This commit is contained in:
Eneko Nieto
2021-02-07 16:18:51 +01:00
parent 43bb2ef0dd
commit a6188c7064
4 changed files with 32 additions and 169 deletions

14
README.md Normal file
View File

@@ -0,0 +1,14 @@
# Limitator
## Monthly quota for OpenWRT
### Install
1) Copy `limitator` to `/etc/init.d/`
2) Run `chmod +x /etc/init.d/limitator`
3) Copy `config/limitator` to `/etc/config/`
4) Edit `/etc/config/` if needed.
5) Copy `www/*` to `/www/`
6) Run `chmod +x /www/cgi-bin/limitator.json`
7) Run `opkg update && opkg install iptables-mod-extra coreutils-date`
8) Run `mkdir ~/limitator`
9) Run `crontab -e` and copy&paste contents in `crontab` file.
10) Reboot.

View File

@@ -1,3 +1,5 @@
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# Limitator # Limitator
# Save used bytes to local file # Save used bytes to local file
*/10 7-23 * * * /etc/init.d/limitator save & */10 7-23 * * * /etc/init.d/limitator save &
@@ -5,3 +7,9 @@
1 0 1-12,14-31 * * /etc/init.d/limitator restart & 1 0 1-12,14-31 * * /etc/init.d/limitator restart &
# Reset the quota monthly # Reset the quota monthly
1 0 13 * * /etc/init.d/limitator reset & 1 0 13 * * /etc/init.d/limitator reset &
# Reboot at 4:30am every day
# Note: To avoid infinite reboot loop, wait 70 seconds
# and touch a file in /etc so clock will be set
# properly to 4:31 on reboot before cron starts.
30 4 * * * sleep 70 && touch /etc/banner && reboot

View File

@@ -18,6 +18,7 @@ config_get START_TIME limitator start_time '07:00' # Starting time of internet p
config_get END_TIME limitator end_time '23:00' # Ending time of internet plan limited hours. config_get END_TIME limitator end_time '23:00' # Ending time of internet plan limited hours.
config_get INTRANET limitator intranet '10.0.0.0/8' # Traffic in Intranet does not count for quota. config_get INTRANET limitator intranet '10.0.0.0/8' # Traffic in Intranet does not count for quota.
config_get EXCLUDE_NETWORK limitator exclude_network # Traffic originated in specified network does not count for quota. config_get EXCLUDE_NETWORK limitator exclude_network # Traffic originated in specified network does not count for quota.
config_get EXCLUDE_NETWORK2 limitator exclude_network2 # Traffic originated in specified network does not count for quota.
config_get USED_BYTES_FILE limitator used_bytes_file '/root/limitator/used_bytes' # A persistent file to save used bytes value. config_get USED_BYTES_FILE limitator used_bytes_file '/root/limitator/used_bytes' # A persistent file to save used bytes value.
config_get LOG_FILE limitator log_file '/root/limitator/log' # A persistent file to log. config_get LOG_FILE limitator log_file '/root/limitator/log' # A persistent file to log.
config_get IPTABLES_CHAIN limitator iptables_chain 'LIMITATOR' # Name of iptables chain. config_get IPTABLES_CHAIN limitator iptables_chain 'LIMITATOR' # Name of iptables chain.
@@ -44,7 +45,11 @@ get_saved_used_bytes(){
get_iptables_quota_rule_num(){ get_iptables_quota_rule_num(){
if [ -n "$EXCLUDE_NETWORK" ];then if [ -n "$EXCLUDE_NETWORK" ];then
echo -n 3 if [ -n "$EXCLUDE_NETWORK2" ];then
echo -n 5
else
echo -n 3
fi
else else
echo -n 1 echo -n 1
fi fi
@@ -122,6 +127,10 @@ set_iptables_rule(){
iptables -I $IPTABLES_CHAIN 1 -s $EXCLUDE_NETWORK -j ACCEPT iptables -I $IPTABLES_CHAIN 1 -s $EXCLUDE_NETWORK -j ACCEPT
iptables -I $IPTABLES_CHAIN 2 -d $EXCLUDE_NETWORK -j ACCEPT iptables -I $IPTABLES_CHAIN 2 -d $EXCLUDE_NETWORK -j ACCEPT
fi fi
if [ -n "$EXCLUDE_NETWORK2" ];then
iptables -I $IPTABLES_CHAIN 3 -s $EXCLUDE_NETWORK2 -j ACCEPT
iptables -I $IPTABLES_CHAIN 4 -d $EXCLUDE_NETWORK2 -j ACCEPT
fi
iptables -I $IPTABLES_CHAIN $(get_iptables_quota_rule_num) -c 0 $(get_saved_used_bytes) -m quota --quota $(get_remaining_quota) -j ACCEPT iptables -I $IPTABLES_CHAIN $(get_iptables_quota_rule_num) -c 0 $(get_saved_used_bytes) -m quota --quota $(get_remaining_quota) -j ACCEPT
iptables -I $IPTABLES_CHAIN $(($(get_iptables_quota_rule_num) + 1)) -j REJECT iptables -I $IPTABLES_CHAIN $(($(get_iptables_quota_rule_num) + 1)) -j REJECT

View File

@@ -1,168 +0,0 @@
#!/bin/sh /etc/rc.common
START=95
STOP=01
EXTRA_COMMANDS="save reset show json"
EXTRA_HELP=<<EOF
reset Resets quota
save Saves counters to persistent storage
show Shows remaining quota
json Print data in JSON format
EOF
config_load "limitator"
config_get MONTHLY_QUOTA limitator quota 15 # Monthly quota in GB
config_get WAN_DEV limitator wan_dev 'wlan0' # Interface name for WAN
config_get FIRST_DAY limitator first_day 13 # Day of month when internet plan starts accounting.
config_get START_TIME limitator start_time '07:00' # Starting time of internet plan limited hours.
config_get END_TIME limitator end_time '23:00' # Ending time of internet plan limited hours.
config_get INTRANET limitator intranet '10.0.0.0/8' # Traffic in Intranet does not count for quota.
config_get EXCLUDE_NETWORK limitator exclude_network # Traffic originated in specified network does not count for quota.
config_get USED_BYTES_FILE limitator used_bytes_file '/root/limitator/used_bytes' # A persistent file to save used bytes value.
config_get LOG_FILE limitator log_file '/root/limitator/log' # A persistent file to log.
config_get IPTABLES_CHAIN limitator iptables_chain 'LIMITATOR' # Name of iptables chain.
config_get IPTABLES_FORWARD limitator iptables_forward 'forwarding_rule' # Name of iptables rule for forward.
config_get IPTABLES_INPUT limitator iptables_input 'input_rule' # Name of iptables rule for input.
config_get IPTABLES_OUTPUT limitator iptables_output 'output_rule' # Name of iptables rule for output.
check_environment(){
# Detect if iptables-mod-extra module is installed
[ -z "$(opkg info iptables-mod-extra|grep installed)" ] && echo "iptables-mod-extra module is not installed." && opkg update && opkg install iptables-mod-extra
# Detect if xt_quota module is loaded
[ -z "$(lsmod|grep xt_quota)" ] && echo "xt_quota module is not loaded" && modprobe xt_quota
}
get_saved_used_bytes(){
local used_bytes
if [ -s "$USED_BYTES_FILE" ];then
used_bytes=$(cat $USED_BYTES_FILE 2>/dev/null)
else
used_bytes=0
fi
echo -n $used_bytes
}
get_iptables_quota_rule_num(){
if [ -n "$EXCLUDE_NETWORK" ];then
echo -n 3
else
echo -n 1
fi
}
get_current_used_bytes(){
local used_bytes=$(iptables -vnxL $IPTABLES_CHAIN $(get_iptables_quota_rule_num) | awk '{print $2}')
if [ -n "$used_bytes" ];then
echo -n $used_bytes
else
get_saved_used_bytes
fi
}
set_saved_used_bytes(){
local used_bytes=$(get_current_used_bytes)
if [ $used_bytes -gt 0 ];then
echo -n $used_bytes > $USED_BYTES_FILE
fi
}
get_total_quota_until_today(){
local current_time=$(date +'%s')
local first_day=$(date -d $(date +"%Y-%m-$FIRST_DAY") +'%s')
local next_first_day
if [ $current_time -ge $first_day ]; then
next_first_day=$(date -d $(date -d "1 month" +"%Y-%m-$FIRST_DAY") +'%s')
else
next_first_day=$first_day
first_day=$(date -d $(date -d "1 month ago" +"%Y-%m-$FIRST_DAY") +'%s')
fi
local seconds_in_month=$(($next_first_day - $first_day))
local montly_quota_bytes=$(($MONTHLY_QUOTA * 1024 * 1024 * 1024))
local elapsed_seconds_tomorrow=$(($(date -d $(date -d "1 day" +'%Y-%m-%d') +'%s') - $first_day))
echo -n $(($montly_quota_bytes * $elapsed_seconds_tomorrow / $seconds_in_month))
}
get_remaining_quota(){
echo -n $(($(get_total_quota_until_today) - $(get_current_used_bytes)))
}
show_remaining_quota(){
echo Remaining: $(($(get_remaining_quota) / 1024 / 1024)) MB
echo Total quota until today: $(($(get_total_quota_until_today) / 1024 / 1024)) MB
}
get_json(){
echo -n "{ \"remaining\": $(get_remaining_quota), \"used_bytes\": $(get_current_used_bytes), \"current_quota\": $(get_total_quota_until_today), \"total_quota\": $(($MONTHLY_QUOTA * 1024 * 1024 * 1024)) }"
}
reset_quota(){
iptables -Z $IPTABLES_CHAIN $(get_iptables_quota_rule_num)
echo -n 0 > ${USED_BYTES_FILE}
}
del_iptables_rule(){
iptables -F $IPTABLES_CHAIN
for chain_name in $IPTABLES_FORWARD $IPTABLES_INPUT $IPTABLES_OUTPUT
do
while true
do
line=$(iptables -L $chain_name|sed -e '1,2d'|grep -n $IPTABLES_CHAIN|head -1|cut -d : -f 1 2>/dev/null)
[ -n "$(echo $line|grep -E ^[[:digit:]]+$)" ] && iptables -D $chain_name $line || break
done
done
iptables -X $IPTABLES_CHAIN
}
set_iptables_rule(){
iptables -N $IPTABLES_CHAIN
if [ -n "$EXCLUDE_NETWORK" ];then
iptables -I $IPTABLES_CHAIN 1 -s $EXCLUDE_NETWORK -j ACCEPT
iptables -I $IPTABLES_CHAIN 2 -d $EXCLUDE_NETWORK -j ACCEPT
fi
iptables -I $IPTABLES_CHAIN $(get_iptables_quota_rule_num) -c 0 $(get_saved_used_bytes) -m quota --quota $(get_remaining_quota) -j ACCEPT
iptables -I $IPTABLES_CHAIN $(($(get_iptables_quota_rule_num) + 1)) -j REJECT
# Iptables requires UTC time
local start_time_utc=$(date -u +%H:%M --date=@$(date -d "today $START_TIME" +%s))
local end_time_utc=$(date -u +%H:%M --date=@$(date -d "today $END_TIME" +%s))
iptables -I $IPTABLES_FORWARD -i $WAN_DEV ! -s $INTRANET -m time --timestart $start_time_utc --timestop $end_time_utc -j $IPTABLES_CHAIN
iptables -I $IPTABLES_FORWARD -o $WAN_DEV ! -d $INTRANET -m time --timestart $start_time_utc --timestop $end_time_utc -j $IPTABLES_CHAIN
iptables -I $IPTABLES_INPUT -i $WAN_DEV ! -s $INTRANET -m time --timestart $start_time_utc --timestop $end_time_utc -j $IPTABLES_CHAIN
iptables -I $IPTABLES_OUTPUT -o $WAN_DEV ! -d $INTRANET -m time --timestart $start_time_utc --timestop $end_time_utc -j $IPTABLES_CHAIN
}
start() {
set_iptables_rule
}
stop() {
set_saved_used_bytes
echo $(date +'%F %H:%M') used_bytes=$(get_current_used_bytes) >> $LOG_FILE
del_iptables_rule
}
restart() {
stop
start
}
save() {
set_saved_used_bytes
}
reset() {
reset_quota
restart
}
show() {
show_remaining_quota
}
json() {
get_json
}