run.sh (2879B)
1 #!/bin/sh 2 # BCP38 filtering implementation for CeroWrt. 3 # 4 # This program is free software; you can redistribute it and/or modify it under 5 # the terms of the GNU General Public License as published by the Free Software 6 # Foundation; either version 3 of the License, or (at your option) any later 7 # version. 8 # 9 # Author: Toke Høiland-Jørgensen <toke@toke.dk> 10 11 STOP=$1 12 IPSET_NAME=bcp38-ipv4 13 IPTABLES_CHAIN=BCP38 14 15 . /lib/functions.sh 16 17 config_load bcp38 18 19 add_bcp38_rule() 20 { 21 local subnet="$1" 22 local action="$2" 23 24 if [ "$action" == "nomatch" ]; then 25 ipset add "$IPSET_NAME" "$subnet" nomatch 26 else 27 ipset add "$IPSET_NAME" "$subnet" 28 fi 29 } 30 31 detect_upstream() 32 { 33 local interface="$1" 34 35 subnets=$(ip route show dev "$interface" | grep 'scope link' | awk '{print $1}') 36 for subnet in $subnets; do 37 # ipset test doesn't work for subnets, so strip out the subnet part 38 # and test for that; add as exception if there's a match 39 addr=$(echo $subnet | sed 's|/[0-9]\+$||') 40 ipset test "$IPSET_NAME" $addr 2>/dev/null && add_bcp38_rule $subnet nomatch 41 done 42 } 43 44 run() { 45 local section="$1" 46 local enabled 47 local interface 48 local detect_upstream 49 config_get_bool enabled "$section" enabled 0 50 config_get interface "$section" interface 51 config_get detect_upstream "$section" detect_upstream 52 53 if [ "$enabled" -eq "1" -a -n "$interface" -a -z "$STOP" ] ; then 54 setup_ipset 55 setup_iptables "$interface" 56 config_list_foreach "$section" match add_bcp38_rule match 57 config_list_foreach "$section" nomatch add_bcp38_rule nomatch 58 [ "$detect_upstream" -eq "1" ] && detect_upstream "$interface" 59 fi 60 exit 0 61 } 62 63 setup_ipset() 64 { 65 ipset create "$IPSET_NAME" hash:net family ipv4 66 ipset flush "$IPSET_NAME" 67 } 68 69 setup_iptables() 70 { 71 local interface="$1" 72 iptables -N "$IPTABLES_CHAIN" 2>/dev/null 73 iptables -F "$IPTABLES_CHAIN" 2>/dev/null 74 75 iptables -I output_rule -m state --state NEW -j "$IPTABLES_CHAIN" 76 iptables -I input_rule -m state --state NEW -j "$IPTABLES_CHAIN" 77 iptables -I forwarding_rule -m state --state NEW -j "$IPTABLES_CHAIN" 78 79 # always accept DHCP traffic 80 iptables -A "$IPTABLES_CHAIN" -p udp --dport 67:68 --sport 67:68 -j RETURN 81 iptables -A "$IPTABLES_CHAIN" -o "$interface" -m set --match-set "$IPSET_NAME" dst -j REJECT --reject-with icmp-net-unreachable 82 iptables -A "$IPTABLES_CHAIN" -i "$interface" -m set --match-set "$IPSET_NAME" src -j DROP 83 } 84 85 destroy_ipset() 86 { 87 ipset flush "$IPSET_NAME" 2>/dev/null 88 ipset destroy "$IPSET_NAME" 2>/dev/null 89 } 90 91 destroy_iptables() 92 { 93 iptables -D output_rule -m state --state NEW -j "$IPTABLES_CHAIN" 2>/dev/null 94 iptables -D input_rule -m state --state NEW -j "$IPTABLES_CHAIN" 2>/dev/null 95 iptables -D forwarding_rule -m state --state NEW -j "$IPTABLES_CHAIN" 2>/dev/null 96 iptables -F "$IPTABLES_CHAIN" 2>/dev/null 97 iptables -X "$IPTABLES_CHAIN" 2>/dev/null 98 } 99 100 destroy_iptables 101 destroy_ipset 102 config_foreach run bcp38 103 104 exit 0