3

I am helping to organize a little conference. There is no internet connection, so we are limited to a mobile LTE connection with a limited volume.

We have a Ubuntu-based server that acts as a router, provides a DHCP and DNS server and routes from its subnet 192.168.1.0/24 to the LTE connection (USB Stick).

Even though our configuration of NATing from the internal network to the LTE-based internet works, we want to prevent that a client uses too much of the valuable volume, and limit each client (MAC address?) to a certain amount of data, e.g. 100MB. If a client reaches that limit (sum of up- and downloads), we want to be informed (a log entry suffices), and he should be either throttled (if possible) or cut off from the internet connection (but he should still be able to communicate in the local network).

Is there any mechanism or software we could use for this scenario?

muffel
  • 422

1 Answers1

2

The following is just an idea as I'm new to traffic shaping. It's NOT a working or complete script and is missing the tc part or the like, and many other necessities...it is only presented as a curiosity, I don't have time to finish right now...

cron the script to run every minute

cron * * * * * sh /path/to/bitshaper.sh /path/to/whitelist /path/to/blacklist

bitshaper.sh

#!/bin/sh
## limit 1MB
limit=1000000

## ip addresses that are unrestricted
WHITELIST=`cat "$1"`
## ip addresses that are throttled immediately
BLACKLIST=`cat "$2"`

## chain...when routing it'll be FORWARD, otherwise use INPUT for playing
CHAIN='INPUT'

## working directory
WD=/var/tmp/bitshaper
mkdir "$WD" 2> /dev/null && cd "$WD"

## create unique CHAIN name so we can easily identify with iptables -L
## rules for monitoring bytes now should have a target of -j $RULE_ID
RULE_ID='BITSHAPER'
iptables -N $RULE_ID 2> /dev/null

## get byte count stats
STATS=`iptables -L "$CHAIN" -vn | tail -n +3`
## get dhcpd leases
HOSTS=`grep -E '^lease ' /var/lib/dhcp/dhcpd.leases | tr -d '[a-z {]' | sort -u`

for host in $HOSTS; do
  case $WHITELIST in *$host*) continue;; esac
  success=false
  for stat in "$STATS"; do
    ## $RULE_ID has to be specific enough to not match anything else
    case $stat in *${RULE_ID}*${host}*)
      success=true
      tmp=${stat#*[0-9] }
      bytes=${tmp%% *}
      [ $bytes -gt  $limit ] && {
        # use tc to shape traffic
      }
      break
    ;;
    esac
  done
  if [ $success = 'false' ]; then
    ## have host but no firewall rule, add one to track usage
    iptables -t filter -A $CHAIN -s $host -j $RULE_ID
  fi
done

## blacklist host here or somewhere
gwillie
  • 231