62f509729175ba304e393152472fad48d03bf1fc
[openwrt.git] / package / firewall / files / reflection.hotplug
1 #!/bin/sh
2
3 . /etc/functions.sh
4 . /usr/share/libubox/jshn.sh
5
6 find_iface_address()
7 {
8         local iface="$1"
9         local ipaddr="$2"
10         local prefix="$3"
11
12         local idx=1
13         local tmp="$(ubus call network.interface."$iface" status 2>/dev/null)"
14
15         json_load "${tmp:-{}}"
16         json_get_type tmp address
17
18         if [ "$tmp" = array ]; then
19                 json_select address
20
21                 while true; do
22                         json_get_type tmp $idx
23                         [ "$tmp" = object ] || break
24
25                         json_select $((idx++))
26                         json_get_var tmp address
27
28                         case "$tmp" in
29                                 *:*) json_select .. ;;
30                                 *)
31                                         [ -n "$ipaddr" ] && json_get_var $ipaddr address
32                                         [ -n "$prefix" ] && json_get_var $prefix mask
33                                         return 0 
34                                 ;;
35                         esac
36                 done
37         fi
38
39         return 1
40 }
41
42 if [ "$ACTION" = "add" ] && [ "$INTERFACE" = "wan" ]; then
43         local wanip
44         find_iface_address wan wanip
45         [ -n "$wanip" ] || return
46
47         iptables -t nat -F nat_reflection_in 2>/dev/null || {
48                 iptables -t nat -N nat_reflection_in
49                 iptables -t nat -A prerouting_rule -j nat_reflection_in
50         }
51
52         iptables -t nat -F nat_reflection_out 2>/dev/null || {
53                 iptables -t nat -N nat_reflection_out
54                 iptables -t nat -A postrouting_rule -j nat_reflection_out
55         }
56
57         iptables -t filter -F nat_reflection_fwd 2>/dev/null || {
58                 iptables -t filter -N nat_reflection_fwd
59                 iptables -t filter -A forwarding_rule -j nat_reflection_fwd
60         }
61
62         find_networks() {
63                 find_networks_cb() {
64                         local cfg="$1"
65                         local zone="$2"
66
67                         local name
68                         config_get name "$cfg" name
69
70                         [ "$name" = "$zone" ] && {
71                                 local network
72                                 config_get network "$cfg" network
73
74                                 echo ${network:-$zone}
75                                 return 1
76                         }
77                 }
78
79                 config_foreach find_networks_cb zone "$1"
80         }
81
82         setup_fwd() {
83                 local cfg="$1"
84
85                 local reflection
86                 config_get_bool reflection "$cfg" reflection 1
87                 [ "$reflection" == 1 ] || return
88
89                 local src
90                 config_get src "$cfg" src
91
92                 local target
93                 config_get target "$cfg" target DNAT
94
95                 [ "$src" = wan ] && [ "$target" = DNAT ] && {
96                         local dest
97                         config_get dest "$cfg" dest "lan"
98                         [ "$dest" != "*" ] || return
99
100                         local net
101                         for net in $(find_networks "$dest"); do
102                                 local lanip lanmk
103                                 find_iface_address "$net" lanip lanmk
104                                 [ -n "$lanip" ] || return
105
106                                 local proto
107                                 config_get proto "$cfg" proto
108
109                                 local epmin epmax extport
110                                 config_get extport "$cfg" src_dport
111                                 [ -n "$extport" ] || return
112
113                                 epmin="${extport%[-:]*}"; epmax="${extport#*[-:]}"
114                                 [ "${epmin#!}" != "$epmax" ] || epmax=""
115
116                                 local ipmin ipmax intport
117                                 config_get intport "$cfg" dest_port "$extport"
118
119                                 ipmin="${intport%[-:]*}"; ipmax="${intport#*[-:]}"
120                                 [ "${ipmin#!}" != "$ipmax" ] || ipmax=""
121
122                                 local exthost
123                                 config_get exthost "$cfg" src_dip "$wanip"
124
125                                 local inthost
126                                 config_get inthost "$cfg" dest_ip
127                                 [ -n "$inthost" ] || return
128
129                                 [ "$proto" = tcpudp ] && proto="tcp udp"
130
131                                 [ "${inthost#!}" = "$inthost" ] || return 0
132                                 [ "${exthost#!}" = "$exthost" ] || return 0
133
134                                 [ "${epmin#!}" != "$epmin" ] && \
135                                         extport="! --dport ${epmin#!}${epmax:+:$epmax}" || \
136                                         extport="--dport $epmin${epmax:+:$epmax}"
137
138                                 [ "${ipmin#!}" != "$ipmin" ] && \
139                                         intport="! --dport ${ipmin#!}${ipmax:+:$ipmax}" || \
140                                         intport="--dport $ipmin${ipmax:+:$ipmax}"
141
142                                 local p
143                                 for p in ${proto:-tcp udp}; do
144                                         case "$p" in
145                                                 tcp|udp|6|17)
146                                                         iptables -t nat -A nat_reflection_in \
147                                                                 -s $lanip/$lanmk -d $exthost \
148                                                                 -p $p $extport \
149                                                                 -j DNAT --to $inthost:${ipmin#!}${ipmax:+-$ipmax}
150
151                                                         iptables -t nat -A nat_reflection_out \
152                                                                 -s $lanip/$lanmk -d $inthost \
153                                                                 -p $p $intport \
154                                                                 -j SNAT --to-source $lanip
155
156                                                         iptables -t filter -A nat_reflection_fwd \
157                                                                 -s $lanip/$lanmk -d $inthost \
158                                                                 -p $p $intport \
159                                                                 -j ACCEPT
160                                                 ;;
161                                         esac
162                                 done
163                         done
164                 }
165         }
166
167         config_load firewall
168         config_foreach setup_fwd redirect
169 fi