diff --git a/net/mwan3/Makefile b/net/mwan3/Makefile index 65e2925c3b6da3..62dfdf71c24666 100644 --- a/net/mwan3/Makefile +++ b/net/mwan3/Makefile @@ -25,6 +25,8 @@ define Package/mwan3 +iptables \ +iptables-mod-conntrack-extra \ +iptables-mod-ipopt \ + +iptables-mod-extra \ + +libcap-bin \ +jshn TITLE:=Multiwan hotplug script with connection tracking support MAINTAINER:=Florian Eckert diff --git a/net/mwan3/files/etc/hotplug.d/iface/15-mwan3 b/net/mwan3/files/etc/hotplug.d/iface/15-mwan3 index 39b19fc3391f5d..723bb201b7c22e 100644 --- a/net/mwan3/files/etc/hotplug.d/iface/15-mwan3 +++ b/net/mwan3/files/etc/hotplug.d/iface/15-mwan3 @@ -37,7 +37,7 @@ mwan3_init mwan3_set_connected_${family} } -if [ "$MWAN3_STARTUP" != 1 ]; then +if [ "$MWAN3_STARTUP" != 1 ] && [ "$ACTION" = "ifup" ]; then mwan3_set_user_iface_rules $INTERFACE $DEVICE fi diff --git a/net/mwan3/files/lib/mwan3/common.sh b/net/mwan3/files/lib/mwan3/common.sh index 867a2bd2d7aa87..de209af75457f9 100644 --- a/net/mwan3/files/lib/mwan3/common.sh +++ b/net/mwan3/files/lib/mwan3/common.sh @@ -5,6 +5,8 @@ get_uptime() { echo "${uptime%%.*}" } +IP4="ip -4" +IP6="ip -6" SCRIPTNAME="$(basename "$0")" MWAN3TRACK_STATUS_DIR="/var/run/mwan3track" @@ -19,3 +21,49 @@ LOG() [ "$facility" = "debug" ] && return logger -t "$SCRIPTNAME[$$]" -p $facility "$*" } + +mwan3_get_true_iface() +{ + local family V + _true_iface=$2 + config_get family "$2" family ipv4 + if [ "$family" = "ipv4" ]; then + V=4 + elif [ "$family" = "ipv6" ]; then + V=6 + fi + ubus call "network.interface.${2}_${V}" status &>/dev/null && _true_iface="${2}_${V}" + export "$1=$_true_iface" +} + +mwan3_get_src_ip() +{ + local family _src_ip true_iface device addr_cmd default_ip IP sed_str + true_iface=$2 + unset "$1" + config_get family "$true_iface" family ipv4 + if [ "$family" = "ipv4" ]; then + addr_cmd='network_get_ipaddr' + default_ip="0.0.0.0" + sed_str='s/ *inet \([^ \/]*\).*/\1/;T; pq' + IP="$IP4" + elif [ "$family" = "ipv6" ]; then + addr_cmd='network_get_ipaddr6' + default_ip="::" + sed_str='s/ *inet6 \([^ \/]*\).* scope.*/\1/;T; pq' + IP="$IP6" + fi + + $addr_cmd _src_ip "$true_iface" + if [ -z "$_src_ip" ]; then + network_get_device device $true_iface + _src_ip=$($IP address ls dev $device 2>/dev/null | sed -ne "$sed_str") + if [ -n "$_src_ip" ]; then + LOG warn "no src $family address found from netifd for interface '$true_iface' dev '$device' guessing $_src_ip" + else + _src_ip="$default_ip" + LOG warn "no src $family address found for interface '$true_iface' dev '$device'" + fi + fi + export "$1=$_src_ip" +} diff --git a/net/mwan3/files/lib/mwan3/mwan3.sh b/net/mwan3/files/lib/mwan3/mwan3.sh index 7fd8a8e7ddc030..ed4a05a71cf364 100644 --- a/net/mwan3/files/lib/mwan3/mwan3.sh +++ b/net/mwan3/files/lib/mwan3/mwan3.sh @@ -2,8 +2,6 @@ . /usr/share/libubox/jshn.sh -IP4="ip -4" -IP6="ip -6" IPS="ipset" IPT4="iptables -t mangle -w" IPT6="ip6tables -t mangle -w" @@ -25,7 +23,6 @@ IPv6_REGEX="${IPv6_REGEX}([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]) IPv4_REGEX="((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)" MWAN3_STATUS_DIR="/var/run/mwan3" -MWAN3TRACK_STATUS_DIR="/var/run/mwan3track" MWAN3_INTERFACE_MAX="" DEFAULT_LOWEST_METRIC=256 MMX_MASK="" @@ -81,20 +78,6 @@ mwan3_update_iface_to_table() config_foreach update_table interface } -mwan3_get_true_iface() -{ - local family V - _true_iface=$2 - config_get family "$iface" family ipv4 - if [ "$family" = "ipv4" ]; then - V=4 - elif [ "$family" = "ipv6" ]; then - V=6 - fi - ubus call "network.interface.${iface}_${V}" status &>/dev/null && _true_iface="${iface}_${V}" - export "$1=$_true_iface" -} - mwan3_route_line_dev() { # must have mwan3 config already loaded @@ -284,7 +267,7 @@ mwan3_set_connected_ipv4() mwan3_set_connected_ipv6() { - local connected_network_v6 source_network_v6 error + local connected_network_v6 error local update="" [ $NO_IPV6 -eq 0 ] || return @@ -295,10 +278,6 @@ mwan3_set_connected_ipv6() mwan3_push_update -! add mwan3_connected_v6 "$connected_network_v6" done - mwan3_push_update -! create mwan3_source_v6 hash:net family inet6 - for source_network_v6 in $($IP6 addr ls | sed -ne 's/ *inet6 \([^ \/]*\).* scope global.*/\1/p'); do - mwan3_push_update -! add mwan3_source_v6 "$source_network_v6" - done mwan3_push_update -! add mwan3_connected mwan3_connected_v6 error=$(echo "$update" | $IPS restore 2>&1) || LOG error "set_connected_ipv6: $error" } @@ -387,12 +366,6 @@ mwan3_set_general_iptables() -p ipv6-icmp \ -m icmp6 --icmpv6-type 137 \ -j RETURN - # do not mangle outgoing echo request - mwan3_push_update -A mwan3_hook \ - -m set --match-set mwan3_source_v6 src \ - -p ipv6-icmp \ - -m icmp6 --icmpv6-type 128 \ - -j RETURN fi mwan3_push_update -A mwan3_hook \ @@ -417,6 +390,10 @@ mwan3_set_general_iptables() mwan3_push_update -A PREROUTING -j mwan3_hook fi if [ -n "${current##*-A OUTPUT -j mwan3_hook*}" ]; then + mwan3_push_update -A OUTPUT \ + -m owner \ + --uid-owner $(id -u mwan3) \ + -j RETURN mwan3_push_update -A OUTPUT -j mwan3_hook fi mwan3_push_update COMMIT diff --git a/net/mwan3/files/usr/sbin/mwan3 b/net/mwan3/files/usr/sbin/mwan3 index e9ecd906d2dc5f..8d4a2b1c0fab3d 100755 --- a/net/mwan3/files/usr/sbin/mwan3 +++ b/net/mwan3/files/usr/sbin/mwan3 @@ -152,6 +152,7 @@ start_() local enabled hotplug_pids MWAN3_STARTUP MWAN3_STARTUP=1 mwan3_lock "command" "mwan3" + user_exists mwan3 || user_add mwan3 uci_toggle_state mwan3 globals enabled "1" config_load mwan3 @@ -203,6 +204,7 @@ stop_() table="$($IPT -S)" { echo "*mangle"; + [ -z "${table##*OUTPUT -m owner --uid-owner $(id -u mwan3)*}" ] && echo "-D OUTPUT -m owner --uid-owner $(id -u mwan3) -j RETURN" [ -z "${table##*PREROUTING -j mwan3_hook*}" ] && echo "-D PREROUTING -j mwan3_hook" [ -z "${table##*OUTPUT -j mwan3_hook*}" ] && echo "-D OUTPUT -j mwan3_hook" echo "$table" | awk '{print "-F "$2}' | grep mwan3 | sort -u diff --git a/net/mwan3/files/usr/sbin/mwan3track b/net/mwan3/files/usr/sbin/mwan3track index 78287d134d1d64..ae31197065eb53 100755 --- a/net/mwan3/files/usr/sbin/mwan3track +++ b/net/mwan3/files/usr/sbin/mwan3track @@ -11,6 +11,10 @@ PING="/bin/ping" IFDOWN_EVENT=0 IFUP_EVENT=0 +CAPSH(){ + capsh --caps="cap_net_raw+eip cap_setpcap,cap_setuid,cap_setgid+ep" --keep=1 --user=mwan3 --addamb=cap_net_raw -- -c "$*" +} + clean_up() { LOG notice "Stopping mwan3track for interface \"${INTERFACE}\"" [ -n "$SLEEP_PID" ] && kill "$SLEEP_PID" @@ -68,6 +72,12 @@ validate_track_method() { esac } +validate_capsh() { + command -v capsh &>/dev/null && return + LOG error "Missing capsh. Please install libcap-bin. Tracking disabled." && + exit 1 +} + disconnected() { STATUS='offline' echo "offline" > $MWAN3TRACK_STATUS_DIR/$INTERFACE/STATUS @@ -149,10 +159,11 @@ update_status() { } main() { - local reliability count timeout interval failure_interval + local reliability count timeout interval failure_interval family local recovery_interval down up size local keep_failure_interval check_quality failure_latency local recovery_latency failure_loss recovery_loss + local max_ttl httping_ssl family track_ips INTERFACE=$1 @@ -165,6 +176,7 @@ main() { trap if_up USR2 config_load mwan3 + config_get family $INTERFACE family ipv4 config_get track_method $INTERFACE track_method ping config_get_bool httping_ssl $INTERFACE httping_ssl 0 validate_track_method $track_method $SRC_IP || { @@ -214,16 +226,11 @@ main() { if [ $host_up_count -lt $reliability ]; then case "$track_method" in ping) - # pinging IPv6 hosts with an interface is troublesome - # https://bugs.openwrt.org/index.php?do=details&task_id=2897 - # so get the IP address of the interface and use that instead - if [ $check_quality -eq 0 ]; then - $PING -${family#ipv} -I ${SRC_IP:-$DEVICE} -c $count -W $timeout -s $size -t $max_ttl -q $track_ip &> /dev/null + CAPSH $PING -${family#ipv} -I $SOURCE -c $count -W $timeout -s $size -t $max_ttl -q $track_ip &> /dev/null result=$? else - ping_result_raw="$($PING -${family#ipv} -I ${SRC_IP:-$DEVICE} -c $count -W $timeout -s $size -t $max_ttl -q $track_ip 2>/dev/null)" - + ping_result_raw="$(CAPSH $PING -${family#ipv} -I $SOURCE -c $count -W $timeout -s $size -t $max_ttl -q $track_ip 2>/dev/null)" ping_status=$? ping_result=$(echo "$ping_result_raw" | tail -n2) @@ -237,28 +244,28 @@ main() { fi ;; arping) - arping -I $DEVICE -c $count -w $timeout -q $track_ip &> /dev/null + CAPSH arping -I $SOURCE -c $count -w $timeout -q $track_ip &> /dev/null result=$? ;; httping) if [ "$httping_ssl" -eq 1 ]; then - httping -y $SRC_IP -c $count -t $timeout -q "https://$track_ip" &> /dev/null + CAPSH httping -y $SRC_IP -c $count -t $timeout -q "https://$track_ip" &> /dev/null else - httping -y $SRC_IP -c $count -t $timeout -q "http://$track_ip" &> /dev/null + CAPSH httping -y $SRC_IP -c $count -t $timeout -q "http://$track_ip" &> /dev/null fi result=$? ;; nping-tcp) - result=$(nping -e $DEVICE -c $count $track_ip --tcp | grep Lost | awk '{print $12}') + result=$(CAPSH nping -e $SOURCE -c $count $track_ip --tcp | grep Lost | awk '{print $12}') ;; nping-udp) - result=$(nping -e $DEVICE -c $count $track_ip --udp | grep Lost | awk '{print $12}') + result=$(CAPSH nping -e $SOURCE -c $count $track_ip --udp | grep Lost | awk '{print $12}') ;; nping-icmp) - result=$(nping -e $DEVICE -c $count $track_ip --icmp | grep Lost | awk '{print $12}') + result=$(CAPSH nping -e $SOURCE -c $count $track_ip --icmp | grep Lost | awk '{print $12}') ;; nping-arp) - result=$(nping -e $DEVICE -c $count $track_ip --arp | grep Lost | awk '{print $12}') + result=$(CAPSH nping -e $SOURCE -c $count $track_ip --arp | grep Lost | awk '{print $12}') ;; esac if [ $check_quality -eq 0 ]; then