OSDN Git Service

luci-app-unblockneteasemusic: initial fw4 support
[immortalwrt/luci.git] / applications / luci-app-unblockneteasemusic / root / etc / init.d / unblockneteasemusic
1 #!/bin/sh /etc/rc.common
2 # SPDX-License-Identifier: GPL-3.0-only
3 #
4 # Copyright (C) 2019-2021 Tianling Shen <cnsztl@immortalwrt.org>
5
6 USE_PROCD=1
7
8 START=99
9 STOP=10
10
11 NAME="unblockneteasemusic"
12 UPGRADE_CONF="/lib/upgrade/keep.d/$NAME"
13
14 IPT_N="iptables -t nat"
15 RULES_UC="/usr/share/$NAME/rules/default.uc"
16 RULES_NFT="/etc/nftables.d/90-$NAME-rules.nft"
17
18 is_enabled() {
19         local enabled
20         config_get_bool enabled "$1" "$2" "${3:-0}"
21         if [ "$enabled" -eq "1" ]; then
22                 return 0
23         else
24                 return 1
25         fi
26 }
27
28 append_param() {
29         procd_append_param command "$1" $2
30 }
31
32 append_param_arg() {
33         local value
34         config_get value "$1" "$2" $4
35         [ -n "$value" ] && append_param "$3" "$value"
36 }
37
38 append_param_env() {
39         local value
40         config_get value "$1" "$2" $4
41         [ -n "$value" ] && procd_append_param env "$3"="$value"
42 }
43
44 uci_get_by_name() {
45         local ret
46         ret="$(uci -q get "$NAME".@"$1"["${4:-0}"]."$2")"
47         echo "${ret:-$3}"
48 }
49
50 start_service()
51 {
52         config_load "$NAME"
53         is_enabled "config" "enable" || exit 1
54
55         local update_time
56         config_get update_time "config" "update_time" "3"
57         sed -i "/$NAME/d" /etc/crontabs/root
58         is_enabled "config" "auto_update" && echo "0 ${update_time} * * * /usr/share/$NAME/update.sh update_core" >> "/etc/crontabs/root"
59         echo "*/5 * * * * /usr/share/$NAME/log_check.sh" >> "/etc/crontabs/root"
60         /etc/init.d/cron restart
61
62         [ ! -s "/usr/share/$NAME/core/app.js" ] && { rm -f "/usr/share/$NAME/local_ver"; sh "/usr/share/$NAME/update.sh" "update_core_non_restart"; }
63         [ ! -s "/usr/share/$NAME/core/app.js" ] && { echo "Core Not Found, please download it before starting." >> "/tmp/$NAME.log"; exit 1; }
64
65         procd_open_instance "$NAME"
66         procd_set_param command node "/usr/share/$NAME/core/app.js"
67         append_param "-a" "0.0.0.0"
68
69         local http_port https_port hijack_ways
70         config_get http_port "config" "http_port" "5200"
71         config_get https_port "config" "https_port" "5201"
72         config_get hijack_ways "config" "hijack_ways" "use_ipset"
73         [ "${hijack_ways}" = "use_hosts" ] && { http_port="80"; https_port="443"; }
74         append_param "-p" "${http_port}":"${https_port}"
75
76         if is_enabled "config" "pub_access"; then
77                 uci -q batch <<-EOF
78                         add firewall rule
79                         set firewall.@rule[-1].name='unblockneteasemusic_pub_access'
80                         set firewall.@rule[-1].proto='tcp'
81                         set firewall.@rule[-1].src='wan'
82                         set firewall.@rule[-1].dest_port='${http_port}-${https_port}'
83                         set firewall.@rule[-1].target='ACCEPT'
84                         commit firewall
85                 EOF
86                 fw4 reload
87         fi
88
89         local music_source
90         config_get music_source "config" "music_source" "default"
91         [ "${music_source}" != "default" ] && append_param -o "${music_source}"
92
93         append_param_arg "config" "cnrelay" "-c"
94         append_param_arg "config" "endpoint_url" "-e" "https://music.163.com"
95         append_param_arg "config" "netease_server_ip" "-f"
96         append_param_arg "config" "proxy_server_ip" "-u"
97         is_enabled "config" "strict_mode" && append_param "-s"
98
99         procd_set_param env LOG_FILE="/tmp/$NAME.log"
100
101         append_param_env "config" "joox_cookie" "JOOX_COOKIE"
102         append_param_env "config" "migu_cookie" "MIGU_COOKIE"
103         append_param_env "config" "qq_cookie" "QQ_COOKIE"
104         append_param_env "config" "youtube_key" "YOUTUBE_KEY"
105         append_param_env "config" "self_issue_cert_crt" "SIGN_CERT" "/usr/share/$NAME/core/server.crt"
106         append_param_env "config" "self_issue_cert_key" "SIGN_KEY" "/usr/share/$NAME/core/server.key"
107
108         is_enabled "config" "enable_flac" && procd_append_param env ENABLE_FLAC="true"
109         is_enabled "config" "local_vip" && procd_append_param env ENABLE_LOCAL_VIP="true"
110         case "$(config_get "config" "replace_music_source")" in
111                 "lower_than_192kbps") procd_append_param env MIN_BR="192000" ;;
112                 "lower_than_320kbps") procd_append_param env MIN_BR="320000" ;;
113                 "lower_than_999kbps") procd_append_param env MIN_BR="600000" ;;
114                 "replace_all") procd_append_param env MIN_BR="9999999" ;;
115         esac
116         procd_append_param env JSON_LOG="true"
117
118         procd_set_param stdout 1
119         procd_set_param stderr 1
120         procd_set_param respawn
121
122         local lan_addr
123         lan_addr="$(uci -q get network.lan.ipaddr)"
124         if [ "${hijack_ways}" = "use_ipset" ]; then
125                 ## TODO:wating for dnsmasq support nftset
126                 mkdir -p "/tmp/dnsmasq.d"
127                 rm -f "/tmp/dnsmasq.d/dnsmasq-$NAME.conf"
128                 cat <<-EOF > "/tmp/dnsmasq.d/dnsmasq-$NAME.conf"
129                         dhcp-option=252,http://${lan_addr}:${http_port}/proxy.pac
130                         ipset=/.music.163.com/neteasemusic
131                         ipset=/interface.music.163.com/neteasemusic
132                         ipset=/interface3.music.163.com/neteasemusic
133                         ipset=/apm.music.163.com/neteasemusic
134                         ipset=/apm3.music.163.com/neteasemusic
135                         ipset=/clientlog.music.163.com/neteasemusic
136                         ipset=/clientlog3.music.163.com/neteasemusic
137                 EOF
138                 /etc/init.d/dnsmasq reload
139
140                 ip_addr_num="$(uci show "$NAME" | grep -c "filter_mode")"
141                 let ip_addr_num="ip_addr_num-1"
142                 local acl_http_addr acl_https_addr
143                 [ "${ip_addr_num}" -ge "0" ] && for i in $(seq 0 "${ip_addr_num}")
144                 do
145                         ip_addr="$(uci_get_by_name "acl_rule" "ip_addr" "" "$i")"
146                         filter_mode="$(uci_get_by_name "acl_rule" "filter_mode" "" "$i")"
147                         case "${filter_mode}" in
148                         "disable_http")
149                                 [ -n "$(command -v fw4)" ] && acl_http_addr="${acl_http_addr}${ip_addr}\n" || ipset -! add "acl_neteasemusic_http" "${ip_addr}"
150                                 ;;
151                         "disable_https")
152                                 [ -n "$(command -v fw4)" ] && acl_https_addr="${acl_https_addr}${ip_addr}\n" || ipset -! add "acl_neteasemusic_https" "${ip_addr}"
153                                 ;;
154                         "disable_all")
155                                 if [ -n "$(command -v fw4)" ]; then
156                                         acl_http_addr="${acl_http_addr}${ip_addr}\n"
157                                         acl_https_addr="${acl_https_addr}${ip_addr}\n"
158                                 else
159                                         ipset -! add "acl_neteasemusic_http" "${ip_addr}"
160                                         ipset -! add "acl_neteasemusic_https" "${ip_addr}"
161                                 fi
162                                 ;;
163                         esac
164                 done
165
166                 local neteasemusic_addr
167                 netease_music_ips="$(uclient-fetch -qO- "http://httpdns.n.netease.com/httpdns/v2/d?domain=music.163.com,interface.music.163.com,interface3.music.163.com,apm.music.163.com,apm3.music.163.com,clientlog.music.163.com,clientlog3.music.163.com" |jsonfilter -e '@.data.*.ip.*')"
168                 netease_music_ips2="$(uclient-fetch -qO- "https://music.httpdns.c.163.com/d" --post-data="music.163.com,interface.music.163.com,interface3.music.163.com,apm.music.163.com,apm3.music.163.com,clientlog.music.163.com,clientlog3.music.163.com" |jsonfilter -e '@.dns.*["ips"].*')"
169                 ## Feature: use ucode to init NAT rules
170                 local tmp="/tmp/$NAME"
171                 local neteasemusic_addr="$(echo -e "${netease_music_ips}\n${netease_music_ips2}" |sort -u |awk '{print $1}')"
172                 json_init
173                 json_add_int o_http_port "${http_port}"
174                 json_add_int o_https_port "${https_port}"
175                 json_add_string o_acl_http_addr "$acl_http_addr"
176                 json_add_string o_acl_https_addr "$acl_https_addr"
177                 json_add_string o_neteasemusic_addr "$neteasemusic_addr"
178                 json_dump -i >"$tmp.json"
179
180                 if ucode -S -i "$RULES_UC" -E "$tmp.json" >"$tmp.nft" \
181                         && ! cmp -s "$tmp.nft" "$RULES_NFT"; then
182                         echo "table inet chk {include \"$tmp.nft\";}" >"$tmp.nft.chk"
183                         if nft -f "$tmp.nft.chk" -c; then
184                                 mv "$tmp.nft" "$RULES_NFT"
185                                 fw4 reload
186                         fi
187                         rm -f "$tmp.nft.chk"
188                 fi
189                 rm -f "$tmp.json"
190                 rm -f "$tmp.nft"
191         elif [ "${hijack_ways}" = "use_hosts" ]; then
192                 mkdir -p "/tmp/dnsmasq.d"
193                 rm -f "/tmp/dnsmasq.d/dnsmasq-$NAME.conf"
194                 cat <<-EOF > "/tmp/dnsmasq.d/dnsmasq-$NAME.conf"
195                         dhcp-option=252,http://${lan_addr}:${http_port}/proxy.pac
196                         address=/music.163.com/${lan_addr}
197                         address=/interface.music.163.com/${lan_addr}
198                         address=/interface3.music.163.com/${lan_addr}
199                         address=/apm.music.163.com/${lan_addr}
200                         address=/apm3.music.163.com/${lan_addr}
201                         address=/clientlog.music.163.com/${lan_addr}
202                         address=/clientlog3.music.163.com/${lan_addr}
203                         address=/music.httpdns.c.163.com/0.0.0.0
204                 EOF
205                 /etc/init.d/dnsmasq reload
206
207                 ip route add "223.252.199.10" dev lo
208         fi
209
210         procd_close_instance
211 } >"/dev/null" 2>&1
212
213 stop_service()
214 {
215         config_load "$NAME"
216
217         sed -i "/$NAME/d" "/etc/crontabs/root"
218         /etc/init.d/cron restart
219
220         rm -f "${UPGRADE_CONF}"
221         is_enabled "config" "keep_core_when_upgrade" && {
222                 echo "/usr/share/$NAME/core/" >> "${UPGRADE_CONF}"
223                 echo "/usr/share/$NAME/local_ver" >> "${UPGRADE_CONF}"
224         }
225         local self_issue_cert_crt self_issue_cert_key
226         config_get "self_issue_cert_crt" "config" "self_issue_cert_crt"
227         config_get "self_issue_cert_key" "config" "self_issue_cert_key"
228         { [ -f "${self_issue_cert_crt}" ] && [ -f "${self_issue_cert_key}" ]; } && {
229                 echo "${self_issue_cert_crt}" >> "${UPGRADE_CONF}"
230                 echo "${self_issue_cert_key}" >> "${UPGRADE_CONF}"
231         }
232
233         local rule="$(uci show firewall | grep "name='unblockneteasemusic_pub_access'" | awk -F '.' '{ print $2}')"
234         [ -n "${rule}" ] && {
235                 uci -q batch <<-EOF
236                         delete firewall.${rule}
237                         commit firewall
238                 EOF
239         }
240         if [ -f "$RULES_NFT" ]; then
241                 rm -f "$RULES_NFT"
242         fi
243         fw4 reload
244
245         rm -f "/tmp/dnsmasq.d/dnsmasq-$NAME.conf"
246         /etc/init.d/dnsmasq reload
247         ip route del "223.252.199.10"
248
249         rm -f "/tmp/$NAME.log"
250 } >"/dev/null" 2>&1
251
252 reload_service() {
253         stop
254         start
255 }
256
257 service_triggers() {
258         procd_add_reload_trigger "$NAME"
259 }