121 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Bash
		
	
	
	
	
	
			
		
		
	
	
			121 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Bash
		
	
	
	
	
	
| #!/bin/sh
 | |
| 
 | |
| . /etc/functions.sh
 | |
| 
 | |
| if [ "$ACTION" = "add" ] && [ "$INTERFACE" = "wan" ]; then
 | |
| 	local wanip=$(uci -P/var/state get network.wan.ipaddr)
 | |
| 
 | |
| 	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"
 | |
| 
 | |
| 			local net
 | |
| 			for net in $(find_networks "$dest"); do
 | |
| 				local lanip=$(uci -P/var/state get network.$net.ipaddr)
 | |
| 				local lanmk=$(uci -P/var/state get network.$net.netmask)
 | |
| 
 | |
| 				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
 | |
| 
 | |
| 				local p
 | |
| 				for p in ${proto:-tcp udp}; do
 | |
| 					case "$p" in
 | |
| 						tcp|udp)
 | |
| 							iptables -t nat -A nat_reflection_in \
 | |
| 								-s $lanip/$lanmk -d $exthost \
 | |
| 								-p $p --dport $epmin${epmax:+:$epmax} \
 | |
| 								-j DNAT --to $inthost:$ipmin${ipmax:+-$ipmax}
 | |
| 
 | |
| 							iptables -t nat -A nat_reflection_out \
 | |
| 								-s $lanip/$lanmk -d $inthost \
 | |
| 								-p $p --dport $ipmin${ipmax:+:$ipmax} \
 | |
| 								-j SNAT --to-source $lanip
 | |
| 
 | |
| 							iptables -t filter -A nat_reflection_fwd \
 | |
| 								-s $lanip/$lanmk -d $inthost \
 | |
| 								-p $p --dport $ipmin${ipmax:+:$ipmax} \
 | |
| 								-j ACCEPT
 | |
| 						;;
 | |
| 					esac
 | |
| 				done
 | |
| 			done
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	config_load firewall
 | |
| 	config_foreach setup_fwd redirect
 | |
| fi
 |