diff --git a/README.md b/README.md new file mode 100644 index 0000000..17edb25 --- /dev/null +++ b/README.md @@ -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. \ No newline at end of file diff --git a/crontab b/crontab index a5b4aca..06773d9 100644 --- a/crontab +++ b/crontab @@ -1,3 +1,5 @@ +PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin + # Limitator # Save used bytes to local file */10 7-23 * * * /etc/init.d/limitator save & @@ -5,3 +7,9 @@ 1 0 1-12,14-31 * * /etc/init.d/limitator restart & # Reset the quota monthly 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 diff --git a/limitator b/limitator index 36379cb..fc1b517 100644 --- a/limitator +++ b/limitator @@ -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 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_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 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. @@ -44,7 +45,11 @@ get_saved_used_bytes(){ get_iptables_quota_rule_num(){ if [ -n "$EXCLUDE_NETWORK" ];then - echo -n 3 + if [ -n "$EXCLUDE_NETWORK2" ];then + echo -n 5 + else + echo -n 3 + fi else echo -n 1 fi @@ -122,6 +127,10 @@ set_iptables_rule(){ iptables -I $IPTABLES_CHAIN 1 -s $EXCLUDE_NETWORK -j ACCEPT iptables -I $IPTABLES_CHAIN 2 -d $EXCLUDE_NETWORK -j ACCEPT 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) + 1)) -j REJECT diff --git a/limitator.old b/limitator.old deleted file mode 100644 index 6ec2024..0000000 --- a/limitator.old +++ /dev/null @@ -1,168 +0,0 @@ -#!/bin/sh /etc/rc.common -START=95 -STOP=01 - -EXTRA_COMMANDS="save reset show json" -EXTRA_HELP=</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 -}