luci_splash 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. #!/bin/sh /etc/rc.common
  2. START=70
  3. EXTRA_COMMANDS=clear_leases
  4. LIMIT_DOWN=0
  5. LIMIT_DOWN_BURST=0
  6. LIMIT_UP=0
  7. TC=/usr/sbin/tc
  8. IPT=/usr/sbin/iptables
  9. IPT6=/usr/sbin/ip6tables
  10. IPT_REPLAY=/var/run/luci_splash.iptlog
  11. LOCK=/var/run/luci_splash.lock
  12. [ -x $IPT6 ] && [ -f /proc/net/ipv6_route ] && HAS_IPV6=1
  13. silent() {
  14. "$@" 2>/dev/null
  15. }
  16. ipt_log() {
  17. $IPT -I "$@"
  18. echo $IPT -D "$@" >> $IPT_REPLAY
  19. }
  20. ipt6_log() {
  21. [ "$HAS_IPV6" = 1 ] || return
  22. $IPT6 -I "$@"
  23. echo $IPT6 -D "$@" >> $IPT_REPLAY
  24. }
  25. iface_add() {
  26. local cfg="$1"
  27. config_get zone "$cfg" zone
  28. [ -n "$zone" ] || return 0
  29. config_get net "$cfg" network
  30. [ -n "$net" ] || return 0
  31. config_get ifname "$net" ifname
  32. [ -n "$ifname" ] || return 0
  33. config_get ipaddr "$net" ipaddr
  34. [ -n "$ipaddr" ] || return 0
  35. config_get netmask "$net" netmask
  36. [ -n "$netmask" ] || return 0
  37. config_get ip6addr "$net" ip6addr
  38. config_get type "$net" type
  39. parentiface="$(uci -q get network.${net}.ifname)"
  40. [ -n "$parentiface" ] && [ ! "$type" = "bridge" ] && {
  41. parentiface=${parentiface#@}
  42. config_get parentproto "$parentiface" proto
  43. config_get parentipaddr "$parentiface" ipaddr
  44. config_get parentnetmask "$parentiface" netmask
  45. }
  46. eval "$(ipcalc.sh $ipaddr $netmask)"
  47. logger -s -p info -t splash "Add $NETWORK/$PREFIX ($ifname) to splashed networks."
  48. ### Add interface specific chain entry rules
  49. ipt_log "prerouting_${zone}_rule" -i "${ifname%:*}" -s "$NETWORK/$PREFIX" -j luci_splash_prerouting -t nat
  50. ipt_log "forwarding_${zone}_rule" -i "${ifname%:*}" -s "$NETWORK/$PREFIX" -j luci_splash_forwarding -t filter
  51. if [ "$HAS_IPV6" = 1 ] && [ -n "$ip6addr" ]; then
  52. ipt6_log "forwarding_${zone}_rule" -i "${ifname%:*}" -s "$ip6addr" -j luci_splash_forwarding -t filter
  53. fi
  54. ### Allow traffic to the same subnet
  55. $IPT -t nat -I luci_splash_prerouting -d "$ipaddr/${netmask:-32}" -j RETURN
  56. $IPT -t filter -I luci_splash_forwarding -d "$ipaddr/${netmask:-32}" -j RETURN
  57. ### Allow traffic to the mesh subnet
  58. [ "$parentproto" = "static" -a -n "$parentipaddr" ] && {
  59. $IPT -t nat -I luci_splash_prerouting -d "$parentipaddr/${parentnetmask:-32}" -j RETURN
  60. $IPT -t filter -I luci_splash_forwarding -d "$parentipaddr/${parentnetmask:-32}" -j RETURN
  61. }
  62. qos_iface_add "$ifname" "$NETWORK" "$PREFIX"
  63. }
  64. iface_del() {
  65. config_get zone "$1" zone
  66. [ -n "$zone" ] || return 0
  67. config_get net "$1" network
  68. [ -n "$net" ] || return 0
  69. config_get ifname "$net" ifname
  70. [ -n "$ifname" ] || return 0
  71. # Clear interface specific rules
  72. [ -s $IPT_REPLAY ] && {
  73. logger -s -p info -t splash "Remove $ifname from splashed networks."
  74. grep -- "-i ${ifname%:*}" $IPT_REPLAY | while read ln; do silent $ln; done
  75. sed -ie "/-i ${ifname%:*}/d" $IPT_REPLAY
  76. }
  77. qos_iface_del "$ifname"
  78. }
  79. mac_add() {
  80. config_get mac "$1" mac
  81. append MACS "$mac"
  82. }
  83. whitelist_add() {
  84. config_get mac "$1" mac
  85. iface=$2
  86. $TC filter add dev "$iface" parent ffff: protocol ip prio 1 u32 match ether src $mac police pass
  87. $TC filter add dev "$iface" parent 1:0 protocol ip prio 1 u32 match ether dst $mac classid 1:1
  88. }
  89. subnet_add() {
  90. local cfg="$1"
  91. config_get ipaddr "$cfg" ipaddr
  92. config_get netmask "$cfg" netmask
  93. [ -n "$ipaddr" ] && {
  94. $IPT -t nat -I luci_splash_prerouting -d "$ipaddr/${netmask:-32}" -j RETURN
  95. $IPT -t filter -I luci_splash_forwarding -d "$ipaddr/${netmask:-32}" -j RETURN
  96. }
  97. }
  98. qos_iface_add() {
  99. local iface="$1"
  100. local network="$2"
  101. local prefix="$3"
  102. # 77 -> download root qdisc
  103. # ffff -> upload root qdisc
  104. silent $TC qdisc del dev "$iface" root handle 1:
  105. silent $TC class del dev "$iface" parent 1: classid 1:ffff
  106. silent $TC class del dev "$iface" parent 1: classid 1:1
  107. silent $TC filter del dev "$iface" parent ffff: protocol ip prio 1 u32
  108. silent $TC filter del dev "$iface" parent ffff: protocol ip prio 2 u32
  109. silent $TC filter del dev "$iface" parent ffff: protocol ip prio 3 u32
  110. if [ "$LIMIT_UP" -gt 0 -a "$LIMIT_DOWN" -gt 0 ]; then
  111. # Setup qdiscs
  112. $TC qdisc add dev "$iface" root handle 1: htb default 1
  113. silent $TC qdisc add dev "$iface" ingress
  114. # Default class - all clients which are not otherwise handled are put in that class
  115. # and share that bandwidth.
  116. $TC class add dev "$iface" parent 1: classid 1:ffff htb rate ${LIMIT_DOWN}kbit
  117. # default class and class for whitelisted clients = unlimited
  118. $TC class add dev "$iface" parent 1: classid 1:1 htb rate 100mbit
  119. # All traffic to the dhcp subnet is put into the limited class
  120. $TC filter add dev "$iface" parent 1:0 protocol ip prio 3 u32 match ip dst $network/$prefix classid 1:ffff
  121. $TC qdisc add dev "$iface" parent 1:ffff sfq perturb 10
  122. $TC filter add dev "$iface" parent ffff: protocol ip prio 3 u32 match ip src $network/$prefix police rate ${LIMIT_UP}kbit mtu 6k burst 6k drop
  123. # classify packets by their iptables MARK set in luci_splash_mark_in (mangle table)
  124. # every client gets his own class and so his own bandwidth limit
  125. $TC filter add dev "$iface" parent 1:0 protocol ip prio 2 fw
  126. config_foreach whitelist_add whitelist $iface
  127. fi
  128. }
  129. qos_iface_del() {
  130. local iface="$1"
  131. silent $TC qdisc del dev "$iface" root handle 77:
  132. }
  133. boot() {
  134. ### Setup splash-relay
  135. uci get uhttpd.splash 2>/dev/null || {
  136. uci batch <<EOF
  137. set uhttpd.splash=uhttpd
  138. set uhttpd.splash.home="/www/cgi-bin/splash/"
  139. set uhttpd.splash.interpreter=".sh=/bin/ash"
  140. set uhttpd.splash.listen_http="8082"
  141. set uhttpd.splash.index_page="splash.sh"
  142. set uhttpd.splash.error_page="/splash.sh"
  143. set uhttpd.splash.http_keepalive='0'
  144. commit uhttpd
  145. EOF
  146. }
  147. ### We are started by the firewall include
  148. exit 0
  149. }
  150. start() {
  151. lock $LOCK
  152. logger -s -p info -t splash "Starting luci-splash"
  153. include /lib/network
  154. . /lib/functions/network.sh
  155. scan_interfaces
  156. config_load luci_splash
  157. ### Find QoS limits
  158. config_get LIMIT_UP general limit_up
  159. config_get LIMIT_DOWN general limit_down
  160. config_get LIMIT_DOWN_BURST general limit_down_burst
  161. LIMIT_UP="$((8*${LIMIT_UP:-0}))"
  162. LIMIT_DOWN="$((8*${LIMIT_DOWN:-0}))"
  163. LIMIT_DOWN_BURST="${LIMIT_DOWN_BURST:+$((8*$LIMIT_DOWN_BURST))}"
  164. LIMIT_DOWN_BURST="${LIMIT_DOWN_BURST:-$(($LIMIT_DOWN / 5 * 6))}"
  165. ### Load required modules
  166. [ "$LIMIT_UP" -gt 0 -a "$LIMIT_DOWN" -gt 0 ] && {
  167. silent insmod act_police
  168. silent insmod cls_fw
  169. silent insmod cls_u32
  170. silent insmod sch_htb
  171. silent insmod sch_sfq
  172. silent insmod sch_ingress
  173. }
  174. ### Create subchains
  175. $IPT -t nat -N luci_splash_prerouting
  176. $IPT -t nat -N luci_splash_leases
  177. $IPT -t filter -N luci_splash_forwarding
  178. $IPT -t filter -N luci_splash_filter
  179. if [ "$HAS_IPV6" = 1 ]; then
  180. $IPT6 -t filter -N luci_splash_forwarding
  181. $IPT6 -t filter -N luci_splash_filter
  182. fi
  183. ### Clear iptables replay log
  184. [ -s $IPT_REPLAY ] && . $IPT_REPLAY
  185. echo -n > $IPT_REPLAY
  186. ### Add interface independant prerouting rules
  187. $IPT -t nat -A luci_splash_prerouting -j luci_splash_leases
  188. $IPT -t nat -A luci_splash_leases -p udp --dport 53 -j REDIRECT --to-ports 53
  189. $IPT -t nat -A luci_splash_leases -p tcp --dport 80 -j REDIRECT --to-ports 8082
  190. ### Add interface independant forwarding rules
  191. $IPT -t filter -A luci_splash_forwarding -j luci_splash_filter
  192. $IPT -t filter -A luci_splash_filter -p tcp -j REJECT --reject-with tcp-reset
  193. $IPT -t filter -A luci_splash_filter -j REJECT --reject-with icmp-net-prohibited
  194. if [ "$HAS_IPV6" = 1 ]; then
  195. $IPT6 -t filter -A luci_splash_forwarding -j luci_splash_filter
  196. $IPT6 -t filter -A luci_splash_filter -p tcp -j REJECT --reject-with tcp-reset
  197. $IPT6 -t filter -A luci_splash_filter -j REJECT --reject-with adm-prohibited
  198. fi
  199. ### Add QoS chain
  200. $IPT -t mangle -N luci_splash_mark_out
  201. $IPT -t mangle -N luci_splash_mark_in
  202. $IPT -t mangle -I PREROUTING -j luci_splash_mark_out
  203. $IPT -t mangle -I POSTROUTING -j luci_splash_mark_in
  204. if [ "$HAS_IPV6" = 1 ]; then
  205. $IPT6 -t mangle -N luci_splash_mark_out
  206. $IPT6 -t mangle -N luci_splash_mark_in
  207. $IPT6 -t mangle -I PREROUTING -j luci_splash_mark_out
  208. $IPT6 -t mangle -I POSTROUTING -j luci_splash_mark_in
  209. fi
  210. ### Build the main and portal rule
  211. config_foreach iface_add iface
  212. config_foreach subnet_add subnet
  213. ### Add the community homepage to the list of allowed destination subnets
  214. hp=$(uci -q get freifunk.community.homepage) && {
  215. chp=${hp#http*://}
  216. chp=${chp%%/*}
  217. $IPT -t nat -I luci_splash_prerouting -d "${chp}/32" -j RETURN
  218. $IPT -t filter -I luci_splash_forwarding -d "${chp}/32" -j RETURN
  219. }
  220. ### Find active mac addresses
  221. MACS=""
  222. config_foreach mac_add blacklist
  223. config_foreach mac_add whitelist
  224. config_load luci_splash_leases
  225. config_foreach mac_add lease
  226. ### Add crontab entry
  227. test -f /etc/crontabs/root || touch /etc/crontabs/root
  228. grep -q luci-splash /etc/crontabs/root || {
  229. echo '*/5 * * * * /usr/sbin/luci-splash sync' >> /etc/crontabs/root
  230. }
  231. lock -u $LOCK
  232. ### Populate iptables
  233. [ -n "$MACS" ] && luci-splash add-rules $MACS
  234. }
  235. stop() {
  236. lock $LOCK
  237. include /lib/network
  238. scan_interfaces
  239. config_load luci_splash
  240. ### Clear interface rules
  241. config_foreach iface_del iface
  242. silent $IPT -t mangle -D PREROUTING -j luci_splash_mark_out
  243. silent $IPT -t mangle -D POSTROUTING -j luci_splash_mark_in
  244. if [ "$HAS_IPV6" = 1 ]; then
  245. silent $IPT6 -t mangle -D PREROUTING -j luci_splash_mark_out
  246. silent $IPT6 -t mangle -D POSTROUTING -j luci_splash_mark_in
  247. fi
  248. ### Clear subchains
  249. silent $IPT -t nat -F luci_splash_prerouting
  250. silent $IPT -t nat -F luci_splash_leases
  251. silent $IPT -t filter -F luci_splash_forwarding
  252. silent $IPT -t filter -F luci_splash_filter
  253. silent $IPT -t mangle -F luci_splash_mark_out
  254. silent $IPT -t mangle -F luci_splash_mark_in
  255. if [ "$HAS_IPV6" = 1 ]; then
  256. $IPT6 -t filter -F luci_splash_forwarding
  257. $IPT6 -t filter -F luci_splash_filter
  258. $IPT6 -t mangle -F luci_splash_mark_out
  259. $IPT6 -t mangle -F luci_splash_mark_in
  260. fi
  261. ### Delete subchains
  262. silent $IPT -t nat -X luci_splash_prerouting
  263. silent $IPT -t nat -X luci_splash_leases
  264. silent $IPT -t filter -X luci_splash_forwarding
  265. silent $IPT -t filter -X luci_splash_filter
  266. silent $IPT -t mangle -X luci_splash_mark_out
  267. silent $IPT -t mangle -X luci_splash_mark_in
  268. if [ "$HAS_IPV6" = 1 ]; then
  269. $IPT6 -t filter -X luci_splash_forwarding
  270. $IPT6 -t filter -X luci_splash_filter
  271. $IPT6 -t mangle -X luci_splash_mark_out
  272. $IPT6 -t mangle -X luci_splash_mark_in
  273. fi
  274. sed -ie '/\/usr\/sbin\/luci-splash sync/d' /var/spool/cron/crontabs/root
  275. lock -u $LOCK
  276. }
  277. clear_leases() {
  278. ### Find active mac addresses
  279. MACS=""
  280. config_foreach mac_add lease
  281. ### Clear leases
  282. [ -n "$MACS" ] && luci-splash remove $MACS
  283. }