eibgrad

tomato-blocked-domains.sh

Apr 25th, 2018 (edited)
2,397
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 5.43 KB | None | 0 0
  1. #!/bin/sh
  2. export DEBUG= # uncomment/comment to enable/disable debug mode
  3.  
  4. #         name: tomato-blocked-domains.sh
  5. #      version: 0.1.2 (beta), 01-may-2018, by eibgrad
  6. #      purpose: block access to certain domains by certain clients
  7. #  script type: jffs script called from firewall script
  8. # installation:
  9. #   1. modify CLIENT_IP and/or CLIENT_MAC variables to include which
  10. #      clients should be denied access to blocked domains
  11. #   2. copy modified script to /jffs (or external storage, e.g., usb)
  12. #   3. make script executable:
  13. #        chmod +x /jffs/tomato-blocked-domains.sh
  14. #   4. call the script from the firewall script:
  15. #        /jffs/tomato-blocked-domains.sh
  16. #   5. add ipset directive(s) w/ your blocked domains to dnsmasq custom
  17. #      configuration:
  18. #        ipset=/amazon.com/netflix.com/blocked_domains
  19. #        ipset=/youtube.com/blocked_domains
  20. #   6. reboot
  21.  
  22. (
  23. [ ${DEBUG+x} ] && set -x
  24.  
  25. # ------------------------------ BEGIN OPTIONS ------------------------------- #
  26.  
  27. # clients to be blocked based on mac address (one host/network per line)
  28. CLIENT_IP="
  29. 192.168.1.100/30  # dhcp (sub-range)
  30. 192.168.1.104/29  # dhcp (sub-range)
  31. 192.168.1.112/28  # dhcp (sub-range)
  32. 192.168.1.128/31  # dhcp (sub-range)
  33. 192.168.1.117     # mom's pc
  34. #192.168.2.0/24    # guest network
  35. "
  36.  
  37. # clients to be blocked based on mac address (one per line)
  38. CLIENT_MAC="
  39. 4B:5D:CA:1C:04:08 # dad's ipad
  40. #FA:70:53:C4:D6:B0
  41. A0:D6:A8:65:A5:91
  42. "
  43.  
  44. # state checking: "state NEW" vs. no state
  45. #   state NEW (default):
  46. #     * any pre-existing LAN->WAN connections persist until/unless they
  47. #       timeout/close
  48. #     * more efficient (only LAN->WAN packets used to establish NEW
  49. #       connections are inspected)
  50. #   no state:
  51. #     * any pre-existing LAN->WAN connections are stopped/blocked
  52. #     * less efficient (every LAN->WAN packet is inspected)
  53.  
  54. FW_STATE="-m state --state NEW"
  55. #FW_STATE="" # uncomment/comment to disable/enable state checking
  56.  
  57. # ------------------------------- END OPTIONS -------------------------------- #
  58.  
  59. # ---------------------- DO NOT CHANGE BELOW THIS LINE ----------------------- #
  60.  
  61. FW_CHAIN="blocked_domains"
  62.  
  63. IPSET_HOST="blocked_domains" # must match ipset directive(s) in dnsmasq
  64.  
  65. configure_ipset() {
  66.     # verify DNSMasq supports ipset
  67.     if ! dnsmasq -v | grep -Eq '^.*(^|[[:space:]]+)ipset([[:space:]]+|$)'; then
  68.         echo "warning: installed version of DNSMasq does NOT support ipset"
  69.         return 1
  70.     fi
  71.  
  72.     # load ipset module
  73.     if ! modprobe ip_set 2>/dev/null; then
  74.         echo "warning: installed firmware does NOT support ipset"
  75.         return 1
  76.     fi
  77.  
  78.     # ipset sub-modules vary depending on ipset version; adjust accordingly
  79.     if  modprobe ip_set_hash_ip 2>/dev/null; then
  80.         # ipset protocol 6
  81.         modprobe ip_set_hash_net
  82.     else
  83.         # ipset protocol 4
  84.         modprobe ip_set_iphash
  85.         modprobe ip_set_nethash
  86.     fi
  87.  
  88.     # iptables "set" module varies depending on version; adjust accordingly
  89.     modprobe ipt_set 2>/dev/null || modprobe xt_set
  90.  
  91.     # parse the iptables version into sub-versions
  92.     _subver() { awk -v v="$v" -v i="$1" 'BEGIN {split(v,a,"."); print a[i]}'; }
  93.     local v="$(iptables --version | grep -o '[0-9\.]*')"
  94.     local v1=$(_subver 1)
  95.     local v2=$(_subver 2)
  96.     local v3=$(_subver 3)
  97.  
  98.     # iptables v1.4.4 and above has deprecated --set in favor of --match-set
  99.     if [[ $v1 -gt 1 || $v2 -gt 4 ]] || [[ $v2 -eq 4 && $v3 -ge 4 ]]; then
  100.        MATCH_SET="--match-set"
  101.     else
  102.        MATCH_SET="--set"
  103.     fi
  104.  
  105.     return 0
  106. }
  107.  
  108. # load appropriate versions of ipset and set modules
  109. configure_ipset || exit 0
  110.  
  111. # cleanup from prior execution (if applicable)
  112. (
  113. iptables -D FORWARD -i br0 $FW_STATE -j $FW_CHAIN
  114. iptables -F $FW_CHAIN && iptables -X $FW_CHAIN
  115. ipset -F $IPSET_HOST && ipset -X $IPSET_HOST
  116. ) 2>/dev/null
  117.  
  118. # create ipset hash table
  119. ipset -N $IPSET_HOST iphash -q
  120.  
  121. # create  firewall chain
  122. iptables -N $FW_CHAIN
  123.  
  124. OIFS="$IFS"; IFS=$'\n'
  125. for ip in $CLIENT_IP; do
  126.     IFS="$OIFS"
  127.  
  128.     # skip comments and blank lines
  129.     echo $ip | grep -Eq '^[[:space:]]*(#|$)' && continue
  130.  
  131.     # isolate the ip address (the rest is treated as comments)
  132.     ip="$(echo $ip | awk '{print $1}')"
  133.  
  134.     # add rules for current ip address to firewall chain
  135.     iptables -A $FW_CHAIN -p tcp -s $ip -m set $MATCH_SET $IPSET_HOST dst \
  136.         -j REJECT --reject-with tcp-reset
  137.     iptables -A $FW_CHAIN -s $ip -m set $MATCH_SET $IPSET_HOST dst \
  138.         -j REJECT --reject-with icmp-host-prohibited
  139.  
  140.     IFS=$'\n'
  141. done
  142. IFS="$OIFS"
  143.  
  144. OIFS="$IFS"; IFS=$'\n'
  145. for mac in $CLIENT_MAC; do
  146.     IFS="$OIFS"
  147.  
  148.     # skip comments and blank lines
  149.     echo $mac | grep -Eq '^[[:space:]]*(#|$)' && continue
  150.  
  151.     # isolate the mac address (the rest is treated as comments)
  152.     mac="$(echo $mac | awk '{print $1}')"
  153.  
  154.     # add rules for current mac address to firewall chain
  155.     iptables -A $FW_CHAIN -p tcp -m mac --mac-source $mac -m set $MATCH_SET $IPSET_HOST dst \
  156.         -j REJECT --reject-with tcp-reset
  157.     iptables -A $FW_CHAIN -m mac --mac-source $mac -m set $MATCH_SET $IPSET_HOST dst \
  158.         -j REJECT --reject-with icmp-host-prohibited
  159.  
  160.     IFS=$'\n'
  161. done
  162. IFS="$OIFS"
  163.  
  164. # force all connections through firewall chain for inspection
  165. iptables -I FORWARD -i br0 $FW_STATE -j $FW_CHAIN
  166.  
  167. ) 2>&1 | logger -p user.$([ ${DEBUG+x} ] && echo debug || echo notice) \
  168.     -t $(echo $(basename $0) | grep -Eo '^.{0,23}')[$$]
Add Comment
Please, Sign In to add comment