S50smartdns 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570
  1. #!/bin/sh
  2. #
  3. # Copyright (C) 2018-2024 Ruilin Peng (Nick) <[email protected]>.
  4. #
  5. # smartdns is free software: you can redistribute it and/or modify
  6. # it under the terms of the GNU General Public License as published by
  7. # the Free Software Foundation, either version 3 of the License, or
  8. # (at your option) any later version.
  9. #
  10. # smartdns is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. SMARTDNS_BIN=/opt/usr/sbin/smartdns
  18. SMARTDNS_CONF=/opt/etc/smartdns/smartdns.conf
  19. DNSMASQ_CONF="/etc/dnsmasq.conf /var/etc/dnsmasq.conf /etc/storage/dnsmasq/dnsmasq.conf"
  20. SMARTDNS_PID=/run/smartdns.pid
  21. SMARTDNS_CHECK_PID=/tmp/smartdns_delay_check.pid
  22. if [ ! -d "/run" ]; then
  23. SMARTDNS_PID=/var/run/smartdns.pid
  24. fi
  25. SMARTDNS_PORT=535
  26. SMARTDNS_OPT=/opt/etc/smartdns/smartdns-opt.conf
  27. # workmode
  28. # DO NOT CHANGE THIS, CHANGE MODE IN smartdns-opt.conf
  29. # 0: run as port only
  30. # 1: redirect port
  31. # 2: replace
  32. SMARTDNS_WORKMODE="1"
  33. SMARTDNS_INIT_SCRIPT="$0"
  34. if [ -f "$SMARTDNS_OPT" ]; then
  35. . "$SMARTDNS_OPT"
  36. fi
  37. set_iptable()
  38. {
  39. local redirect_tcp
  40. redirect_tcp=0
  41. grep ^bind-tcp $SMARTDNS_CONF > /dev/null 2>&1
  42. if [ $? -eq 0 ]; then
  43. redirect_tcp=1;
  44. fi
  45. IPS="$(ifconfig | grep "inet addr" | grep -v ":127" | grep "Bcast" | awk '{print $2}' | awk -F: '{print $2}')"
  46. for IP in $IPS
  47. do
  48. if [ $redirect_tcp -eq 1 ]; then
  49. iptables -t nat -A PREROUTING -p tcp -d "$IP" --dport 53 -j REDIRECT --to-ports "$SMARTDNS_PORT" > /dev/null 2>&1
  50. fi
  51. iptables -t nat -A PREROUTING -p udp -d "$IP" --dport 53 -j REDIRECT --to-ports "$SMARTDNS_PORT" > /dev/null 2>&1
  52. done
  53. }
  54. clear_iptable()
  55. {
  56. IPS="$(ifconfig | grep "inet addr" | grep -v ":127" | grep "Bcast" | awk '{print $2}' | awk -F: '{print $2}')"
  57. for IP in $IPS
  58. do
  59. iptables -t nat -D PREROUTING -p tcp -d "$IP" --dport 53 -j REDIRECT --to-ports "$SMARTDNS_PORT" > /dev/null 2>&1
  60. iptables -t nat -D PREROUTING -p udp -d "$IP" --dport 53 -j REDIRECT --to-ports "$SMARTDNS_PORT" > /dev/null 2>&1
  61. done
  62. }
  63. get_dnsmasq_cmd()
  64. {
  65. CMD="$(ps 2>/dev/null | grep -e '[a-zA-Z]\{0,2\} \{1,\}dnsmasq' | grep -v grep 2>/dev/null)"
  66. if [ ! -z "$CMD" ]; then
  67. return
  68. fi
  69. CMD="$(ps 2>/dev/null | grep '/usr/sbin/dnsmasq' | grep -v grep 2>/dev/null)"
  70. if [ ! -z "$CMD" ]; then
  71. return
  72. fi
  73. CMD="$(ps 2>/dev/null | grep 'dnsmasq' | grep -v grep 2>/dev/null)"
  74. if [ ! -z "$CMD" ]; then
  75. return
  76. fi
  77. CMD="$(ps ax 2>/dev/null | grep -e '[a-zA-Z]\{0,2\} \{1,\}dnsmasq' | grep -v grep 2>/dev/null)"
  78. if [ ! -z "$CMD" ]; then
  79. return
  80. fi
  81. CMD="$(ps ax 2>/dev/null | grep /usr/sbin/dnsmasq | grep -v grep 2>/dev/null)"
  82. if [ ! -z "$CMD" ]; then
  83. return
  84. fi
  85. CMD="$(ps ax 2>/dev/null | grep 'dnsmasq' | grep -v grep 2>/dev/null)"
  86. if [ ! -z "$CMD" ]; then
  87. return
  88. fi
  89. }
  90. get_dnsmasq_cmdline()
  91. {
  92. local CMD=""
  93. local loop=0
  94. while [ $loop -lt 3 ]; do
  95. get_dnsmasq_cmd
  96. if [ ! -z "$CMD" ]; then
  97. break;
  98. fi
  99. $SMARTDNS_INIT_SCRIPT stop
  100. sleep 1
  101. loop=$((loop+1))
  102. done
  103. if [ -z "$CMD" ]; then
  104. echo "cannot find dnsmasq"
  105. service restart_dnsmasq 2>/dev/null
  106. return 1
  107. fi
  108. # check multiple dnsmasq
  109. linecount="$(echo "$CMD" | wc -l)"
  110. if [ $linecount -eq 1 ]; then
  111. PID="$(echo "$CMD" | awk '{print $1}')"
  112. elif [ $linecount -gt 1 ]; then
  113. PID1="$(echo "$CMD" | awk 'NR==1{print $1}')"
  114. PID2="$(echo "$CMD" | awk 'NR==2{print $1}')"
  115. PID2_PPID="$(grep 'PPid:' /proc/$PID2/status | awk '{print $2}' 2>/dev/null)"
  116. if [ "$PID2_PPID" != "$PID1" ]; then
  117. kill -9 "$PID2" 2>/dev/null
  118. fi
  119. PID=$PID1
  120. else
  121. echo "find multiple dnsmasq, but not started by the same process"
  122. return 1
  123. fi
  124. if [ ! -d "/proc/$PID" ]; then
  125. echo "dnsmasq is not running"
  126. return 1
  127. fi
  128. CMD="$(echo "$CMD" | head -n 1)"
  129. DNSMASQ_CMD="$(echo "$CMD" | awk '{for(i=5; i<=NF;i++)printf $i " "}')"
  130. return 0
  131. }
  132. restart_dnsmasq()
  133. {
  134. if [ -z "$DNSMASQ_CMD" ]; then
  135. get_dnsmasq_cmdline
  136. if [ $? -ne 0 ]; then
  137. echo "cannot find dnsmasq"
  138. return 1
  139. fi
  140. fi
  141. if [ ! -z "$PID" ]; then
  142. kill -9 "$PID"
  143. fi
  144. $DNSMASQ_CMD
  145. return $?
  146. }
  147. add_dhcp_options6()
  148. {
  149. CONF_FILE=$1
  150. IPS="$(ifconfig | grep "inet addr" | grep -v ":127" | grep "Bcast" | awk '{print $2}' | awk -F: '{print $2}')"
  151. for IP in $IPS
  152. do
  153. DHCP_OPTION="$(grep "dhcp-option=" "$CONF_FILE" | grep "$IP" | head -n 1)"
  154. if [ -z "$DHCP_OPTION" ]; then
  155. continue
  156. fi
  157. SERVER_TAG="$(echo "$DHCP_OPTION" | awk -F= '{print $2}' | awk -F, '{print $1}')"
  158. LOCAL_SERVER_IP="$IP"
  159. grep "dhcp-option *= *$SERVER_TAG, *6 *, *$LOCAL_SERVER_IP" "$CONF_FILE" 1>/dev/null 2>&1
  160. if [ $? -eq 0 ]; then
  161. continue
  162. fi
  163. DHCP_OPTION="dhcp-option=$SERVER_TAG,6,$LOCAL_SERVER_IP"
  164. echo "$DHCP_OPTION" >> "$CONF_FILE"
  165. RESTART_DNSMASQ=1
  166. done
  167. return 1
  168. }
  169. clear_dhcp_options6()
  170. {
  171. CONF_FILE=$1
  172. IPS="$(ifconfig | grep "inet addr" | grep -v ":127" | grep "Bcast" | awk '{print $2}' | awk -F: '{print $2}')"
  173. for IP in $IPS
  174. do
  175. DHCP_OPTION="$(grep "dhcp-option=" "$CONF_FILE" | grep "$IP" | head -n 1)"
  176. if [ -z "$DHCP_OPTION" ]; then
  177. continue
  178. fi
  179. SERVER_TAG="$(echo "$DHCP_OPTION" | awk -F= '{print $2}' | awk -F, '{print $1}')"
  180. LOCAL_SERVER_IP="$IP"
  181. grep "dhcp-option *= *$SERVER_TAG, *6 *, *$LOCAL_SERVER_IP" "$CONF_FILE" 1>/dev/null 2>&1
  182. if [ $? -ne 0 ]; then
  183. continue
  184. fi
  185. sed -i "/^dhcp-option *=$SERVER_TAG,6,/d" "$CONF_FILE"
  186. RESTART_DNSMASQ=1
  187. done
  188. return 1
  189. }
  190. set_dnsmasq_conf()
  191. {
  192. local LOCAL_SERVER_IP=""
  193. local SERVER_TAG=""
  194. local CONF_FILE=$1
  195. local DHCP_OPTIONS=""
  196. add_dhcp_options6 "$CONF_FILE"
  197. grep "^port *=0" "$CONF_FILE" > /dev/null 2>&1
  198. if [ $? -ne 0 ]; then
  199. sed -i "/^port *=/d" "$CONF_FILE"
  200. echo "port=0" >> "$CONF_FILE"
  201. RESTART_DNSMASQ=1
  202. fi
  203. }
  204. do_set_dnsmasq()
  205. {
  206. local RESTART_DNSMASQ=0
  207. for conf in $DNSMASQ_CONF
  208. do
  209. if [ ! -e "$conf" ]; then
  210. continue
  211. fi
  212. set_dnsmasq_conf "$conf"
  213. done
  214. if [ $RESTART_DNSMASQ -ne 0 ]; then
  215. restart_dnsmasq
  216. fi
  217. }
  218. kill_dnsmasq_delay_check_pid()
  219. {
  220. if [ ! -e "$SMARTDNS_CHECK_PID" ]; then
  221. return
  222. fi
  223. PID="$(cat $SMARTDNS_CHECK_PID)"
  224. if [ -d "/proc/$PID" ]; then
  225. kill -9 $PID
  226. fi
  227. rm -f $SMARTDNS_CHECK_PID
  228. }
  229. dnsmasq_delay_check()
  230. {
  231. sleep 8
  232. rm -f $SMARTDNS_CHECK_PID
  233. get_dnsmasq_cmdline
  234. if [ -z "$DNSMASQ_CMD" ] ; then
  235. $SMARTDNS_INIT_SCRIPT restart
  236. return
  237. fi
  238. do_set_dnsmasq
  239. pid="$(cat $SMARTDNS_PID |head -n 1 2>/dev/null)"
  240. if [ -z "$pid" ]; then
  241. do_clear_dnsmasq
  242. $SMARTDNS_INIT_SCRIPT start > /dev/null 2>&1 &
  243. elif [ ! -d "/proc/$pid" ]; then
  244. do_clear_dnsmasq
  245. $SMARTDNS_INIT_SCRIPT start > /dev/null 2>&1 &
  246. fi
  247. exit 0
  248. }
  249. begin_dnsmasq_delay_check()
  250. {
  251. DNSMASQ_CMD=""
  252. kill_dnsmasq_delay_check_pid
  253. get_dnsmasq_cmdline
  254. dnsmasq_delay_check > /dev/null 2>&1 &
  255. PID=$!
  256. echo $PID > $SMARTDNS_CHECK_PID
  257. }
  258. set_dnsmasq()
  259. {
  260. get_dnsmasq_cmdline
  261. do_set_dnsmasq
  262. begin_dnsmasq_delay_check
  263. }
  264. set_jffs_dnsmasq()
  265. {
  266. local RESTART_DNSMASQ=0
  267. if [ "$(nvram get jffs2_scripts)" -ne 1 ]; then
  268. nvram set jffs2_scripts="1"
  269. nvram commit
  270. fi
  271. touch /jffs/configs/dnsmasq.conf.add
  272. if [ -e "/jffs/configs/dnsmasq.conf.add" ]; then
  273. set_dnsmasq_conf "/jffs/configs/dnsmasq.conf.add"
  274. fi
  275. if [ -e "/jffs/configs/dnsmasq.conf" ]; then
  276. set_dnsmasq_conf "/jffs/configs/dnsmasq.conf"
  277. fi
  278. if [ $RESTART_DNSMASQ -ne 0 ]; then
  279. restart_dnsmasq
  280. fi
  281. }
  282. clear_dnsmasq_conf()
  283. {
  284. local LOCAL_SERVER_IP=""
  285. local SERVER_TAG=""
  286. local CONF_FILE=$1
  287. clear_dhcp_options6 "$CONF_FILE"
  288. grep "^port *=" "$CONF_FILE" > /dev/null 2>&1
  289. if [ $? -eq 0 ]; then
  290. sed -i "/^port *=/d" "$CONF_FILE"
  291. RESTART_DNSMASQ=1
  292. fi
  293. }
  294. do_clear_dnsmasq()
  295. {
  296. local RESTART_DNSMASQ=0
  297. for conf in $DNSMASQ_CONF
  298. do
  299. if [ ! -e "$conf" ]; then
  300. continue
  301. fi
  302. clear_dnsmasq_conf "$conf"
  303. done
  304. if [ $RESTART_DNSMASQ -ne 0 ]; then
  305. if [ $? -eq 0 ]; then
  306. return
  307. fi
  308. restart_dnsmasq
  309. fi
  310. }
  311. clear_dnsmasq()
  312. {
  313. kill_dnsmasq_delay_check_pid
  314. do_clear_dnsmasq
  315. }
  316. clear_jffs_dnsmasq()
  317. {
  318. local RESTART_DNSMASQ=0
  319. if [ -e "/jffs/configs/dnsmasq.conf.add" ]; then
  320. clear_dnsmasq_conf "/jffs/configs/dnsmasq.conf.add"
  321. fi
  322. if [ -e "/jffs/configs/dnsmasq.conf" ]; then
  323. clear_dnsmasq_conf "/jffs/configs/dnsmasq.conf"
  324. fi
  325. if [ $RESTART_DNSMASQ -ne 0 ]; then
  326. restart_dnsmasq
  327. fi
  328. }
  329. set_smartdns_port()
  330. {
  331. if [ "$SMARTDNS_WORKMODE" = "0" ]; then
  332. return 0
  333. elif [ "$SMARTDNS_WORKMODE" = "1" ]; then
  334. sed -i "s/^\(bind .*\):53\(@[^ ]*\)\?\( .*\)\?$/\1:$SMARTDNS_PORT\2 \3/g" $SMARTDNS_CONF
  335. sed -i "s/^\(bind-tcp .*\):53\(@[^ ]*\)\?\( .*\)\?$/\1:$SMARTDNS_PORT\2 \3/g" $SMARTDNS_CONF
  336. elif [ "$SMARTDNS_WORKMODE" = "2" ]; then
  337. sed -i "s/^\(bind .*\):$SMARTDNS_PORT\(@[^ ]*\)\?\( .*\)\?$/\1:53\2 \3/g" $SMARTDNS_CONF
  338. sed -i "s/^\(bind-tcp .*\):$SMARTDNS_PORT\(@[^ ]*\)\?\( .*\)\?$/\1:53\2 \3/g" $SMARTDNS_CONF
  339. elif [ "$SMARTDNS_WORKMODE" = "3" ]; then
  340. return 0
  341. else
  342. return 1
  343. fi
  344. return 0
  345. }
  346. set_rule()
  347. {
  348. if [ "$SMARTDNS_WORKMODE" = "0" ]; then
  349. return 0
  350. elif [ "$SMARTDNS_WORKMODE" = "1" ]; then
  351. set_iptable
  352. return $?
  353. elif [ "$SMARTDNS_WORKMODE" = "2" ]; then
  354. set_dnsmasq
  355. return $?
  356. elif [ "$SMARTDNS_WORKMODE" = "3" ]; then
  357. set_jffs_dnsmasq
  358. return $?
  359. else
  360. return 1
  361. fi
  362. }
  363. clear_rule()
  364. {
  365. if [ "$SMARTDNS_WORKMODE" = "0" ]; then
  366. return 0
  367. elif [ "$SMARTDNS_WORKMODE" = "1" ]; then
  368. clear_iptable
  369. return $?
  370. elif [ "$SMARTDNS_WORKMODE" = "2" ]; then
  371. clear_dnsmasq
  372. return $?
  373. elif [ "$SMARTDNS_WORKMODE" = "3" ]; then
  374. clear_jffs_dnsmasq
  375. return $?
  376. else
  377. return 1
  378. fi
  379. }
  380. get_tz()
  381. {
  382. if [ -e "/etc/localtime" ]; then
  383. return
  384. fi
  385. for tzfile in /etc/TZ /var/etc/TZ
  386. do
  387. if [ ! -e "$tzfile" ]; then
  388. continue
  389. fi
  390. tz="$(cat $tzfile 2>/dev/null)"
  391. done
  392. if [ -z "$tz" ]; then
  393. return
  394. fi
  395. export TZ=$tz
  396. }
  397. case "$1" in
  398. start)
  399. set_rule
  400. if [ $? -ne 0 ]; then
  401. exit 1
  402. fi
  403. SMARTDNS_OPTION=""
  404. [ "$SMARTDNS_CRASH_RESTART" = "1" ] && SMARTDNS_OPTION="$SMARTDNS_OPTION -R"
  405. set_smartdns_port
  406. get_tz
  407. $SMARTDNS_BIN -c "$SMARTDNS_CONF" -p $SMARTDNS_PID $SMARTDNS_OPTION
  408. if [ $? -ne 0 ]; then
  409. clear_rule
  410. exit 1
  411. fi
  412. ;;
  413. status)
  414. pid="$(cat $SMARTDNS_PID |head -n 1 2>/dev/null)"
  415. if [ -z "$pid" ]; then
  416. echo "smartdns not running."
  417. exit 0
  418. fi
  419. if [ -d "/proc/$pid" ]; then
  420. echo "smartdns is running"
  421. exit 0
  422. fi
  423. echo "smartdns not running."
  424. exit 0
  425. ;;
  426. stop)
  427. pid="$(cat "$SMARTDNS_PID" | head -n 1 2>/dev/null)"
  428. if [ -z "$pid" ]; then
  429. echo "smartdns not running."
  430. exit 0
  431. fi
  432. kill -15 "$pid" 2>/dev/null
  433. SLEEP=$(which usleep 2>/dev/null)
  434. SLEEPTIME=200000
  435. if [ -z "$SLEEP" ]; then
  436. SLEEP="sleep"
  437. SLEEPTIME=0.2
  438. fi
  439. N=300
  440. while [ $N -gt 0 ]
  441. do
  442. pid="$(cat "$SMARTDNS_PID" | head -n 1 2>/dev/null)"
  443. if [ -z "$pid" ]; then
  444. break
  445. fi
  446. if [ ! -d "/proc/$pid" ]; then
  447. break
  448. fi
  449. stat="$(cat /proc/${pid}/stat 2>/dev/null | awk '{print $3}' 2>/dev/null)"
  450. if [ "$stat" = "Z" ]; then
  451. $SLEEP $SLEEPTIME
  452. break
  453. fi
  454. $SLEEP $SLEEPTIME 2>/dev/null
  455. N=$((N-1))
  456. done
  457. kill -9 "$pid" 2>/dev/null
  458. clear_rule
  459. exit 0
  460. ;;
  461. restart)
  462. $0 stop
  463. $0 start
  464. ;;
  465. reload)
  466. ;;
  467. enable)
  468. nvram set apps_state_enable=2
  469. nvram set apps_state_error=0
  470. nvram set apps_state_install=5
  471. nvram set apps_state_action=install
  472. nvram set apps_u2ec_ex=2
  473. ;;
  474. firewall-start|reload|force-reload|reconfigure)
  475. $0 restart
  476. ;;
  477. *)
  478. ;;
  479. esac