uci_firewall.sh 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. #!/bin/sh
  2. # Copyright (C) 2008 John Crispin <[email protected]>
  3. . /etc/functions.sh
  4. IPTABLES="echo iptables"
  5. IPTABLES=iptables
  6. config_clear
  7. include /lib/network
  8. scan_interfaces
  9. CONFIG_APPEND=1
  10. config_load firewall
  11. config fw_zones
  12. ZONE_LIST=$CONFIG_SECTION
  13. CUSTOM_CHAINS=1
  14. DEF_INPUT=DROP
  15. DEF_OUTPUT=DROP
  16. DEF_FORWARD=DROP
  17. load_policy() {
  18. config_get input $1 input
  19. config_get output $1 output
  20. config_get forward $1 forward
  21. DEF_INPUT="${input:-$DEF_INPUT}"
  22. DEF_OUTPUT="${output:-$DEF_OUTPUT}"
  23. DEF_FORWARD="${forward:-$DEF_FORWARD}"
  24. }
  25. create_zone() {
  26. local exists
  27. [ "$1" == "loopback" ] && return
  28. config_get exists $ZONE_LIST $1
  29. [ -n "$exists" ] && return
  30. config_set $ZONE_LIST $1 1
  31. $IPTABLES -N zone_$1
  32. $IPTABLES -N zone_$1_MSSFIX
  33. $IPTABLES -N zone_$1_ACCEPT
  34. $IPTABLES -N zone_$1_DROP
  35. $IPTABLES -N zone_$1_REJECT
  36. $IPTABLES -N zone_$1_forward
  37. $IPTABLES -A zone_$1_forward -j zone_$1_$5
  38. $IPTABLES -A zone_$1 -j zone_$1_$3
  39. $IPTABLES -A output -j zone_$1_$4
  40. $IPTABLES -N zone_$1_nat -t nat
  41. $IPTABLES -N zone_$1_prerouting -t nat
  42. [ "$6" == "1" ] && $IPTABLES -t nat -A POSTROUTING -j zone_$1_nat
  43. }
  44. addif() {
  45. local network="$1"
  46. local ifname="$2"
  47. local zone="$3"
  48. local n_if n_zone
  49. config_get n_if core "${network}_ifname"
  50. config_get n_zone core "${network}_zone"
  51. [ -n "$n_zone" ] && {
  52. if [ "$n_zone" != "$zone" ]; then
  53. delif "$network" "$n_if" "$n_zone"
  54. else
  55. return
  56. fi
  57. }
  58. logger "adding $network ($ifname) to firewall zone $zone"
  59. $IPTABLES -A input -i "$ifname" -j zone_${zone}
  60. $IPTABLES -I zone_${zone}_MSSFIX 1 -o "$ifname" -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
  61. $IPTABLES -I zone_${zone}_ACCEPT 1 -o "$ifname" -j ACCEPT
  62. $IPTABLES -I zone_${zone}_DROP 1 -o "$ifname" -j DROP
  63. $IPTABLES -I zone_${zone}_REJECT 1 -o "$ifname" -j reject
  64. $IPTABLES -I zone_${zone}_ACCEPT 1 -i "$ifname" -j ACCEPT
  65. $IPTABLES -I zone_${zone}_DROP 1 -i "$ifname" -j DROP
  66. $IPTABLES -I zone_${zone}_REJECT 1 -i "$ifname" -j reject
  67. $IPTABLES -I zone_${zone}_nat 1 -t nat -o "$ifname" -j MASQUERADE
  68. $IPTABLES -I PREROUTING 1 -t nat -i "$ifname" -j zone_${zone}_prerouting
  69. $IPTABLES -A forward -i "$ifname" -j zone_${zone}_forward
  70. uci_set_state firewall core "${network}_ifname" "$ifname"
  71. uci_set_state firewall core "${network}_zone" "$zone"
  72. }
  73. delif() {
  74. local network="$1"
  75. local ifname="$2"
  76. local zone="$3"
  77. logger "removing $network ($ifname) from firewall zone $zone"
  78. $IPTABLES -D input -i "$ifname" -j zone_$zone
  79. $IPTABLES -D zone_${zone}_MSSFIX -o "$ifname" -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
  80. $IPTABLES -D zone_${zone}_ACCEPT -o "$ifname" -j ACCEPT
  81. $IPTABLES -D zone_${zone}_DROP -o "$ifname" -j DROP
  82. $IPTABLES -D zone_${zone}_REJECT -o "$ifname" -j reject
  83. $IPTABLES -D zone_${zone}_ACCEPT -i "$ifname" -j ACCEPT
  84. $IPTABLES -D zone_${zone}_DROP -i "$ifname" -j DROP
  85. $IPTABLES -D zone_${zone}_REJECT -i "$ifname" -j reject
  86. $IPTABLES -D zone_${zone}_nat -t nat -o "$ifname" -j MASQUERADE
  87. $IPTABLES -D PREROUTING -t nat -i "$ifname" -j zone_${zone}_prerouting
  88. $IPTABLES -D forward -i "$ifname" -j zone_${zone}_forward
  89. uci_revert_state firewall core "${network}_ifname"
  90. uci_revert_state firewall core "${network}_zone"
  91. }
  92. load_synflood() {
  93. local rate=${1:-25}
  94. local burst=${2:-50}
  95. echo "Loading synflood protection"
  96. $IPTABLES -N syn_flood
  97. $IPTABLES -A syn_flood -p tcp --syn -m limit --limit $rate/second --limit-burst $burst -j RETURN
  98. $IPTABLES -A syn_flood -j DROP
  99. $IPTABLES -A INPUT -p tcp --syn -j syn_flood
  100. }
  101. fw_set_chain_policy() {
  102. local chain=$1
  103. local target=$2
  104. [ "$target" == "REJECT" ] && {
  105. $IPTABLES -A $chain -j reject
  106. target=DROP
  107. }
  108. $IPTABLES -P $chain $target
  109. }
  110. fw_defaults() {
  111. [ -n "$DEFAULTS_APPLIED" ] && {
  112. echo "Error: multiple defaults sections detected"
  113. return;
  114. }
  115. DEFAULTS_APPLIED=1
  116. load_policy "$1"
  117. echo 1 > /proc/sys/net/ipv4/tcp_syncookies
  118. for f in /proc/sys/net/ipv4/conf/*/accept_redirects
  119. do
  120. echo 0 > $f
  121. done
  122. for f in /proc/sys/net/ipv4/conf/*/accept_source_route
  123. do
  124. echo 0 > $f
  125. done
  126. uci_revert_state firewall core
  127. uci_set_state firewall core "" firewall_state
  128. $IPTABLES -P INPUT DROP
  129. $IPTABLES -P OUTPUT DROP
  130. $IPTABLES -P FORWARD DROP
  131. $IPTABLES -F
  132. $IPTABLES -t nat -F
  133. $IPTABLES -t nat -X
  134. $IPTABLES -X
  135. config_get_bool drop_invalid $1 drop_invalid 1
  136. [ "$drop_invalid" -gt 0 ] && {
  137. $IPTABLES -A INPUT -m state --state INVALID -j DROP
  138. $IPTABLES -A OUTPUT -m state --state INVALID -j DROP
  139. $IPTABLES -A FORWARD -m state --state INVALID -j DROP
  140. }
  141. $IPTABLES -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
  142. $IPTABLES -A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
  143. $IPTABLES -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
  144. $IPTABLES -A INPUT -i lo -j ACCEPT
  145. $IPTABLES -A OUTPUT -o lo -j ACCEPT
  146. config_get syn_flood $1 syn_flood
  147. config_get syn_rate $1 syn_rate
  148. config_get syn_burst $1 syn_burst
  149. [ "$syn_flood" == "1" ] && load_synflood $syn_rate $syn_burst
  150. echo "Adding custom chains"
  151. fw_custom_chains
  152. $IPTABLES -N input
  153. $IPTABLES -N output
  154. $IPTABLES -N forward
  155. $IPTABLES -A INPUT -j input
  156. $IPTABLES -A OUTPUT -j output
  157. $IPTABLES -A FORWARD -j forward
  158. $IPTABLES -N reject
  159. $IPTABLES -A reject -p tcp -j REJECT --reject-with tcp-reset
  160. $IPTABLES -A reject -j REJECT --reject-with icmp-port-unreachable
  161. fw_set_chain_policy INPUT "$DEF_INPUT"
  162. fw_set_chain_policy OUTPUT "$DEF_OUTPUT"
  163. fw_set_chain_policy FORWARD "$DEF_FORWARD"
  164. }
  165. fw_zone() {
  166. local name
  167. local network
  168. local masq
  169. config_get name $1 name
  170. config_get network $1 network
  171. config_get masq $1 masq
  172. load_policy $1
  173. [ -z "$network" ] && network=$name
  174. create_zone "$name" "$network" "$input" "$output" "$forward" "$masq"
  175. fw_custom_chains_zone "$name"
  176. }
  177. fw_rule() {
  178. local src
  179. local src_ip
  180. local src_mac
  181. local src_port
  182. local src_mac
  183. local dest
  184. local dest_ip
  185. local dest_port
  186. local proto
  187. local target
  188. local ruleset
  189. config_get src $1 src
  190. config_get src_ip $1 src_ip
  191. config_get src_mac $1 src_mac
  192. config_get src_port $1 src_port
  193. config_get dest $1 dest
  194. config_get dest_ip $1 dest_ip
  195. config_get dest_port $1 dest_port
  196. config_get proto $1 proto
  197. config_get target $1 target
  198. config_get ruleset $1 ruleset
  199. src_port_first=${src_port%-*}
  200. src_port_last=${src_port#*-}
  201. [ "$src_port_first" -ne "$src_port_last" ] && { \
  202. src_port="$src_port_first:$src_port_last"; }
  203. dest_port_first=${dest_port%-*}
  204. dest_port_last=${dest_port#*-}
  205. [ "$dest_port_first" -ne "$dest_port_last" ] && { \
  206. dest_port="$dest_port_first:$dest_port_last"; }
  207. ZONE=input
  208. TARGET=$target
  209. [ -z "$target" ] && target=DROP
  210. [ -n "$src" -a -z "$dest" ] && ZONE=zone_$src
  211. [ -n "$src" -a -n "$dest" ] && ZONE=zone_${src}_forward
  212. [ -n "$dest" ] && TARGET=zone_${dest}_$target
  213. add_rule() {
  214. $IPTABLES -I $ZONE 1 \
  215. ${proto:+-p $proto} \
  216. ${src_ip:+-s $src_ip} \
  217. ${src_port:+--sport $src_port} \
  218. ${src_mac:+-m mac --mac-source $src_mac} \
  219. ${dest_ip:+-d $dest_ip} \
  220. ${dest_port:+--dport $dest_port} \
  221. -j $TARGET
  222. }
  223. [ "$proto" == "tcpudp" -o -z "$proto" ] && {
  224. proto=tcp
  225. add_rule
  226. proto=udp
  227. add_rule
  228. return
  229. }
  230. add_rule
  231. }
  232. fw_forwarding() {
  233. local src
  234. local dest
  235. local masq
  236. config_get src $1 src
  237. config_get dest $1 dest
  238. config_get_bool mtu_fix $1 mtu_fix 0
  239. [ -n "$src" ] && z_src=zone_${src}_forward || z_src=forward
  240. [ -n "$dest" ] && z_dest=zone_${dest}_ACCEPT || z_dest=ACCEPT
  241. $IPTABLES -I $z_src 1 -j $z_dest
  242. [ "$mtu_fix" -gt 0 -a -n "$dest" ] && $IPTABLES -I $z_src 1 -j zone_${dest}_MSSFIX
  243. }
  244. fw_redirect() {
  245. local src
  246. local src_ip
  247. local src_port
  248. local src_dport
  249. local src_mac
  250. local dest_ip
  251. local dest_port dest_port2
  252. local proto
  253. config_get src $1 src
  254. config_get src_ip $1 src_ip
  255. config_get src_port $1 src_port
  256. config_get src_dport $1 src_dport
  257. config_get src_mac $1 src_mac
  258. config_get dest_ip $1 dest_ip
  259. config_get dest_port $1 dest_port
  260. config_get proto $1 proto
  261. [ -z "$src" -o -z "$dest_ip" ] && { \
  262. echo "redirect needs src and dest_ip"; return ; }
  263. src_port_first=${src_port%-*}
  264. src_port_last=${src_port#*-}
  265. [ "$src_port_first" -ne "$src_port_last" ] && { \
  266. src_port="$src_port_first:$src_port_last"; }
  267. src_dport_first=${src_dport%-*}
  268. src_dport_last=${src_dport#*-}
  269. [ "$src_dport_first" -ne "$src_dport_last" ] && { \
  270. src_dport="$src_dport_first:$src_dport_last"; }
  271. dest_port2=$dest_port
  272. dest_port_first=${dest_port2%-*}
  273. dest_port_last=${dest_port2#*-}
  274. [ "$dest_port_first" -ne "$dest_port_last" ] && { \
  275. dest_port2="$dest_port_first:$dest_port_last"; }
  276. add_rule() {
  277. $IPTABLES -A zone_${src}_prerouting -t nat \
  278. ${proto:+-p $proto} \
  279. ${src_ip:+-s $src_ip} \
  280. ${src_port:+--sport $src_port} \
  281. ${src_dport:+--dport $src_dport} \
  282. ${src_mac:+-m mac --mac-source $src_mac} \
  283. -j DNAT --to-destination $dest_ip${dest_port:+:$dest_port}
  284. $IPTABLES -I zone_${src}_forward 1 \
  285. ${proto:+-p $proto} \
  286. -d $dest_ip \
  287. ${src_ip:+-s $src_ip} \
  288. ${src_port:+--sport $src_port} \
  289. ${dest_port2:+--dport $dest_port2} \
  290. ${src_mac:+-m mac --mac-source $src_mac} \
  291. -j ACCEPT
  292. }
  293. [ "$proto" == "tcpudp" -o -z "$proto" ] && {
  294. proto=tcp
  295. add_rule
  296. proto=udp
  297. add_rule
  298. return
  299. }
  300. add_rule
  301. }
  302. fw_include() {
  303. local path
  304. config_get path $1 path
  305. [ -e $path ] && . $path
  306. }
  307. fw_addif() {
  308. local up
  309. local ifname
  310. config_get up $1 up
  311. config_get ifname $1 ifname
  312. [ -n "$up" ] || return 0
  313. (ACTION="ifup" INTERFACE="$1" . /etc/hotplug.d/iface/20-firewall)
  314. }
  315. fw_custom_chains() {
  316. [ -n "$CUSTOM_CHAINS" ] || return 0
  317. $IPTABLES -N input_rule
  318. $IPTABLES -N output_rule
  319. $IPTABLES -N forwarding_rule
  320. $IPTABLES -N prerouting_rule -t nat
  321. $IPTABLES -N postrouting_rule -t nat
  322. $IPTABLES -A INPUT -j input_rule
  323. $IPTABLES -A OUTPUT -j output_rule
  324. $IPTABLES -A FORWARD -j forwarding_rule
  325. $IPTABLES -A PREROUTING -t nat -j prerouting_rule
  326. $IPTABLES -A POSTROUTING -t nat -j postrouting_rule
  327. }
  328. fw_custom_chains_zone() {
  329. local zone="$1"
  330. [ -n "$CUSTOM_CHAINS" ] || return 0
  331. $IPTABLES -N input_${zone}
  332. $IPTABLES -N forwarding_${zone}
  333. $IPTABLES -N prerouting_${zone} -t nat
  334. $IPTABLES -I zone_${zone} 1 -j input_${zone}
  335. $IPTABLES -I zone_${zone}_forward 1 -j forwarding_${zone}
  336. $IPTABLES -I zone_${zone}_prerouting 1 -t nat -j prerouting_${zone}
  337. }
  338. fw_init() {
  339. DEFAULTS_APPLIED=
  340. echo "Loading defaults"
  341. config_foreach fw_defaults defaults
  342. echo "Loading zones"
  343. config_foreach fw_zone zone
  344. echo "Loading rules"
  345. config_foreach fw_rule rule
  346. echo "Loading forwarding"
  347. config_foreach fw_forwarding forwarding
  348. echo "Loading redirects"
  349. config_foreach fw_redirect redirect
  350. echo "Loading includes"
  351. config_foreach fw_include include
  352. uci_set_state firewall core loaded 1
  353. unset CONFIG_APPEND
  354. config_load network
  355. config_foreach fw_addif interface
  356. }
  357. fw_stop() {
  358. $IPTABLES -F
  359. $IPTABLES -t nat -F
  360. $IPTABLES -t nat -X
  361. $IPTABLES -X
  362. $IPTABLES -P INPUT ACCEPT
  363. $IPTABLES -P OUTPUT ACCEPT
  364. $IPTABLES -P FORWARD ACCEPT
  365. uci_revert_state firewall core
  366. }