#!/bin/sh . /etc/functions.sh . /usr/share/libubox/jshn.sh find_iface_address() { local iface="$1" local ipaddr="$2" local prefix="$3" local tmp="$(ubus call network.interface."$iface" status 2>/dev/null)" json_load "${tmp:-{}}" json_get_type tmp address if [ "$tmp" = array ]; then json_select address json_get_type tmp 1 if [ "$tmp" = object ]; then json_select 1 [ -n "$ipaddr" ] && json_get_var "$ipaddr" address [ -n "$prefix" ] && json_get_var "$prefix" mask fi fi } if [ "$ACTION" = "add" ] && [ "$INTERFACE" = "wan" ]; then local wanip find_iface_address wan wanip [ -n "$wanip" ] || return iptables -t nat -F nat_reflection_in 2>/dev/null || { iptables -t nat -N nat_reflection_in iptables -t nat -A prerouting_rule -j nat_reflection_in } iptables -t nat -F nat_reflection_out 2>/dev/null || { iptables -t nat -N nat_reflection_out iptables -t nat -A postrouting_rule -j nat_reflection_out } iptables -t filter -F nat_reflection_fwd 2>/dev/null || { iptables -t filter -N nat_reflection_fwd iptables -t filter -A forwarding_rule -j nat_reflection_fwd } find_networks() { find_networks_cb() { local cfg="$1" local zone="$2" local name config_get name "$cfg" name [ "$name" = "$zone" ] && { local network config_get network "$cfg" network echo ${network:-$zone} return 1 } } config_foreach find_networks_cb zone "$1" } setup_fwd() { local cfg="$1" local reflection config_get_bool reflection "$cfg" reflection 1 [ "$reflection" == 1 ] || return local src config_get src "$cfg" src local target config_get target "$cfg" target DNAT [ "$src" = wan ] && [ "$target" = DNAT ] && { local dest config_get dest "$cfg" dest "lan" [ "$dest" != "*" ] || return local net for net in $(find_networks "$dest"); do local lanip lanmk find_iface_address "$net" lanip lanmk [ -n "$lanip" ] || return local proto config_get proto "$cfg" proto local epmin epmax extport config_get extport "$cfg" src_dport [ -n "$extport" ] || return epmin="${extport%[-:]*}"; epmax="${extport#*[-:]}" [ "${epmin#!}" != "$epmax" ] || epmax="" local ipmin ipmax intport config_get intport "$cfg" dest_port "$extport" ipmin="${intport%[-:]*}"; ipmax="${intport#*[-:]}" [ "${ipmin#!}" != "$ipmax" ] || ipmax="" local exthost config_get exthost "$cfg" src_dip "$wanip" local inthost config_get inthost "$cfg" dest_ip [ -n "$inthost" ] || return [ "$proto" = tcpudp ] && proto="tcp udp" [ "${inthost#!}" = "$inthost" ] || return 0 [ "${exthost#!}" = "$exthost" ] || return 0 [ "${epmin#!}" != "$epmin" ] && \ extport="! --dport ${epmin#!}${epmax:+:$epmax}" || \ extport="--dport $epmin${epmax:+:$epmax}" [ "${ipmin#!}" != "$ipmin" ] && \ intport="! --dport ${ipmin#!}${ipmax:+:$ipmax}" || \ intport="--dport $ipmin${ipmax:+:$ipmax}" local p for p in ${proto:-tcp udp}; do case "$p" in tcp|udp|6|17) iptables -t nat -A nat_reflection_in \ -s $lanip/$lanmk -d $exthost \ -p $p $extport \ -j DNAT --to $inthost:${ipmin#!}${ipmax:+-$ipmax} iptables -t nat -A nat_reflection_out \ -s $lanip/$lanmk -d $inthost \ -p $p $intport \ -j SNAT --to-source $lanip iptables -t filter -A nat_reflection_fwd \ -s $lanip/$lanmk -d $inthost \ -p $p $intport \ -j ACCEPT ;; esac done done } } config_load firewall config_foreach setup_fwd redirect fi