Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/bin/sh
- export DEBUG= # uncomment/comment to enable/disable debug mode
- # name: tomato-blocked-domains.sh
- # version: 0.1.2 (beta), 01-may-2018, by eibgrad
- # purpose: block access to certain domains by certain clients
- # script type: jffs script called from firewall script
- # installation:
- # 1. modify CLIENT_IP and/or CLIENT_MAC variables to include which
- # clients should be denied access to blocked domains
- # 2. copy modified script to /jffs (or external storage, e.g., usb)
- # 3. make script executable:
- # chmod +x /jffs/tomato-blocked-domains.sh
- # 4. call the script from the firewall script:
- # /jffs/tomato-blocked-domains.sh
- # 5. add ipset directive(s) w/ your blocked domains to dnsmasq custom
- # configuration:
- # ipset=/amazon.com/netflix.com/blocked_domains
- # ipset=/youtube.com/blocked_domains
- # 6. reboot
- (
- [ ${DEBUG+x} ] && set -x
- # ------------------------------ BEGIN OPTIONS ------------------------------- #
- # clients to be blocked based on mac address (one host/network per line)
- CLIENT_IP="
- 192.168.1.100/30 # dhcp (sub-range)
- 192.168.1.104/29 # dhcp (sub-range)
- 192.168.1.112/28 # dhcp (sub-range)
- 192.168.1.128/31 # dhcp (sub-range)
- 192.168.1.117 # mom's pc
- #192.168.2.0/24 # guest network
- "
- # clients to be blocked based on mac address (one per line)
- CLIENT_MAC="
- 4B:5D:CA:1C:04:08 # dad's ipad
- #FA:70:53:C4:D6:B0
- A0:D6:A8:65:A5:91
- "
- # state checking: "state NEW" vs. no state
- # state NEW (default):
- # * any pre-existing LAN->WAN connections persist until/unless they
- # timeout/close
- # * more efficient (only LAN->WAN packets used to establish NEW
- # connections are inspected)
- # no state:
- # * any pre-existing LAN->WAN connections are stopped/blocked
- # * less efficient (every LAN->WAN packet is inspected)
- FW_STATE="-m state --state NEW"
- #FW_STATE="" # uncomment/comment to disable/enable state checking
- # ------------------------------- END OPTIONS -------------------------------- #
- # ---------------------- DO NOT CHANGE BELOW THIS LINE ----------------------- #
- FW_CHAIN="blocked_domains"
- IPSET_HOST="blocked_domains" # must match ipset directive(s) in dnsmasq
- configure_ipset() {
- # verify DNSMasq supports ipset
- if ! dnsmasq -v | grep -Eq '^.*(^|[[:space:]]+)ipset([[:space:]]+|$)'; then
- echo "warning: installed version of DNSMasq does NOT support ipset"
- return 1
- fi
- # load ipset module
- if ! modprobe ip_set 2>/dev/null; then
- echo "warning: installed firmware does NOT support ipset"
- return 1
- fi
- # ipset sub-modules vary depending on ipset version; adjust accordingly
- if modprobe ip_set_hash_ip 2>/dev/null; then
- # ipset protocol 6
- modprobe ip_set_hash_net
- else
- # ipset protocol 4
- modprobe ip_set_iphash
- modprobe ip_set_nethash
- fi
- # iptables "set" module varies depending on version; adjust accordingly
- modprobe ipt_set 2>/dev/null || modprobe xt_set
- # parse the iptables version into sub-versions
- _subver() { awk -v v="$v" -v i="$1" 'BEGIN {split(v,a,"."); print a[i]}'; }
- local v="$(iptables --version | grep -o '[0-9\.]*')"
- local v1=$(_subver 1)
- local v2=$(_subver 2)
- local v3=$(_subver 3)
- # iptables v1.4.4 and above has deprecated --set in favor of --match-set
- if [[ $v1 -gt 1 || $v2 -gt 4 ]] || [[ $v2 -eq 4 && $v3 -ge 4 ]]; then
- MATCH_SET="--match-set"
- else
- MATCH_SET="--set"
- fi
- return 0
- }
- # load appropriate versions of ipset and set modules
- configure_ipset || exit 0
- # cleanup from prior execution (if applicable)
- (
- iptables -D FORWARD -i br0 $FW_STATE -j $FW_CHAIN
- iptables -F $FW_CHAIN && iptables -X $FW_CHAIN
- ipset -F $IPSET_HOST && ipset -X $IPSET_HOST
- ) 2>/dev/null
- # create ipset hash table
- ipset -N $IPSET_HOST iphash -q
- # create firewall chain
- iptables -N $FW_CHAIN
- OIFS="$IFS"; IFS=$'\n'
- for ip in $CLIENT_IP; do
- IFS="$OIFS"
- # skip comments and blank lines
- echo $ip | grep -Eq '^[[:space:]]*(#|$)' && continue
- # isolate the ip address (the rest is treated as comments)
- ip="$(echo $ip | awk '{print $1}')"
- # add rules for current ip address to firewall chain
- iptables -A $FW_CHAIN -p tcp -s $ip -m set $MATCH_SET $IPSET_HOST dst \
- -j REJECT --reject-with tcp-reset
- iptables -A $FW_CHAIN -s $ip -m set $MATCH_SET $IPSET_HOST dst \
- -j REJECT --reject-with icmp-host-prohibited
- IFS=$'\n'
- done
- IFS="$OIFS"
- OIFS="$IFS"; IFS=$'\n'
- for mac in $CLIENT_MAC; do
- IFS="$OIFS"
- # skip comments and blank lines
- echo $mac | grep -Eq '^[[:space:]]*(#|$)' && continue
- # isolate the mac address (the rest is treated as comments)
- mac="$(echo $mac | awk '{print $1}')"
- # add rules for current mac address to firewall chain
- iptables -A $FW_CHAIN -p tcp -m mac --mac-source $mac -m set $MATCH_SET $IPSET_HOST dst \
- -j REJECT --reject-with tcp-reset
- iptables -A $FW_CHAIN -m mac --mac-source $mac -m set $MATCH_SET $IPSET_HOST dst \
- -j REJECT --reject-with icmp-host-prohibited
- IFS=$'\n'
- done
- IFS="$OIFS"
- # force all connections through firewall chain for inspection
- iptables -I FORWARD -i br0 $FW_STATE -j $FW_CHAIN
- ) 2>&1 | logger -p user.$([ ${DEBUG+x} ] && echo debug || echo notice) \
- -t $(echo $(basename $0) | grep -Eo '^.{0,23}')[$$]
Add Comment
Please, Sign In to add comment