#!/bin/sh /etc/rc.common # Copyright (C) 2018 Ycarus (Yannick Chabanois) START=99 STOP=10 USE_PROCD=1 . /usr/lib/unbound/iptools.sh _bypass_ip() { local ip=$1 local type=$2 [ -z "$type" ] && type="all" valid_ip4=$( valid_subnet4 $ip) valid_ip6=$( valid_subnet6 $ip) if [ "$valid_ip4" = "ok" ]; then ipset -q add ss_rules_dst_bypass_$type $ip elif [ "$valid_ip6" = "ok" ]; then ipset -q add ss_rules6_dst_bypass_$type $ip fi } _bypass_domain() { local domain local intf config_get domain $1 name config_get intf $1 interface [ -z "$intf" ] && intf="all" if [ -n "$domain" ]; then resolve=$(dig a +nocmd +noall +answer $domain | awk '{print $5}') for ip in $resolve; do _bypass_ip $ip $intf done resolve=$(dig aaaa +nocmd +noall +answer $domain | awk '{print $5}') for ip in $resolve; do _bypass_ip $ip $intf done uci -q add_list dhcp.@dnsmasq[0].ipset="/$domain/ss_rules_dst_bypass_$intf,ss_rules6_dst_bypass_$intf" fi } _bypass_proto() { local proto local intf config_get proto $1 proto config_get intf $1 interface local intfid="$(uci -q get omr-bypass.$intf.id)" [ -z "$intf" ] && intf="all" [ -z "$proto" ] && return if [ "$intf" = "all" ]; then ndpi_rules="-A omr-bypass-dpi -m ndpi --$proto -j MARK --set-mark 0x539 $ndpi_rules" else ndpi_rules="-A omr-bypass-dpi -m ndpi --$proto -j MARK --set-mark 0x539$intfid $ndpi_rules" fi } _intf_rule() { local intf config_get intf $1 ifname count=$((count+1)) local mode config_get mode $1 multipath "off" [ "$mode" = "off" ] && return [ "$(echo $1 | grep _dev)" != "" ] && return ipset -q flush ss_rules_dst_bypass_$intf > /dev/null 2>&1 ipset -q flush ss_rules6_dst_bypass_$intf > /dev/null 2>&1 ipset -q --exist restore <<-EOF create ss_rules_dst_bypass_$intf hash:net hashsize 64 create ss_rules6_dst_bypass_$intf hash:net family inet6 hashsize 64 EOF ip rule add prio 1 fwmark 0x539$count lookup $count > /dev/null 2>&1 ip -6 rule add prio 1 fwmark 0x539$count lookup $count > /dev/null 2>&1 if [ "$(iptables -w 40 -t mangle -L | grep ss_rules_dst_bypass_$intf)" = "" ]; then iptables-restore --wait=60 --noflush <<-EOF *mangle -A PREROUTING -m set --match-set ss_rules_dst_bypass_$intf dst -j MARK --set-mark 0x539$count COMMIT EOF if [ "$(iptables -w 40 -t nat -L | grep ss_rules_pre_src)" != "" ]; then iptables-restore --wait=60 --noflush <<-EOF *nat -I ss_rules_pre_src 1 -m mark --mark 0x539$count -j RETURN -I ss_rules_local_out 1 -m mark --mark 0x539$count -j RETURN COMMIT EOF fi fi if [ "$(ip6tables -w 40 -t mangle -L | grep ss_rules6_dst_bypass_$intf)" = "" ]; then ip6tables-restore --wait=60 --noflush <<-EOF *mangle -A PREROUTING -m set --match-set ss_rules6_dst_bypass_$intf dst -j MARK --set-mark 0x539$count COMMIT EOF if [ "$(ip6tables -w 40 -t nat -L | grep ss_rules6_pre_src)" != "" ]; then ip6tables-restore --wait=60 --noflush <<-EOF *nat -I ss_rules6_pre_src 1 -m mark --mark 0x539$count -j RETURN -I ss_rules6_local_out 1 -m mark --mark 0x539$count -j RETURN COMMIT EOF fi fi uci -q set omr-bypass.$intf=interface uci -q set omr-bypass.$intf.id=$count } _bypass_ip_set() { local ip local interface config_get ip $1 ip config_get interface $1 interface _bypass_ip $ip $interface } start_service() { local count logger -t "omr-bypass" "Starting OMR-ByPass..." ipset -q flush ss_rules_dst_bypass_all > /dev/null 2>&1 ipset -q flush ss_rules6_dst_bypass_all > /dev/null 2>&1 ipset -q --exist restore <<-EOF create ss_rules_dst_bypass_all hash:net hashsize 64 create ss_rules6_dst_bypass_all hash:net family inet6 hashsize 64 EOF config_load network config_foreach _intf_rule interface local ndpi_rules="" config_load omr-bypass config_foreach _bypass_ip_set ips uci -q del dhcp.@dnsmasq[0].ipset config_foreach _bypass_domain domains uci -q commit dhcp /etc/init.d/dnsmasq reload config_foreach _bypass_proto dpis ip rule add prio 1 fwmark 0x539 lookup 991337 > /dev/null 2>&1 ip -6 rule add prio 1 fwmark 0x539 lookup 991337 > /dev/null 2>&1 if [ "$(iptables -w 40 -t mangle -L | grep 'match-set ss_rules_dst_bypass_all dst MARK set')" = "" ]; then iptables-restore --wait=60 --noflush <<-EOF *mangle -A PREROUTING -m set --match-set ss_rules_dst_bypass_all dst -j MARK --set-mark 0x539 COMMIT EOF fi if [ "$(ip6tables -w 40 -t mangle -L | grep 'match-set ss_rules6_dst_bypass_all dst MARK set')" = "" ]; then ip6tables-restore --wait=60 --noflush <<-EOF *mangle -A PREROUTING -m set --match-set ss_rules6_dst_bypass_all dst -j MARK --set-mark 0x539 COMMIT EOF fi iptables-save --counters | grep -v omr-bypass-dpi | iptables-restore --counters ip6tables-save --counters | grep -v omr-bypass-dpi | ip6tables-restore --counters ndpi_rules=$(echo $ndpi_rules | awk 'NF') if [ "$ndpi_rules" != "" ]; then iptables-restore --wait=60 --noflush <<-EOF *mangle :omr-bypass-dpi - -A PREROUTING -m addrtype ! --dst-type LOCAL -j omr-bypass-dpi $ndpi_rules COMMIT EOF ip6tables-restore --wait=60 --noflush <<-EOF *mangle :omr-bypass-dpi - -A PREROUTING -m addrtype ! --dst-type LOCAL -j omr-bypass-dpi $ndpi_rules COMMIT EOF fi logger -t "omr-bypass" "OMR-ByPass is running" } service_triggers() { procd_add_reload_trigger omr-bypass network shadowsocks-libev } reload_service() { start }