diff --git a/README.md b/README.md index abfcfe4..641d86e 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ This is a v2ray module for Magisk, and includes binaries for arm, arm64, x86, x6 ## Install -- You can download the release installer zip file and install it via the Magisk Manager App. +You can download the release installer zip file and install it via the Magisk Manager App. @@ -26,78 +26,108 @@ This is a v2ray module for Magisk, and includes binaries for arm, arm64, x86, x6 - Please make sure the config is correct. You can check it by running a command : - `export V2RAY_LOCATION_ASSET=/data/v2ray; v2ray -test -config /data/v2ray/config.json` in android terminal. + `export V2RAY_LOCATION_ASSET=/data/v2ray; v2ray -test -config /data/v2ray/config.json` in android terminal or ssh. + +- Tips: Please notice that the default configuration has already set inbounds section to cooperate work with transparent proxy script. It is recommended that you only edit the first element of outbounds section to your proxy server and edit file `/data/v2ray/appid.list` to select which App to proxy. +## Usage -## Start/Stop service +### Normal usage ( Default and Recommended ) -- V2ray service is autorun on boot. If you don't want it run automatically, you can just add a file `/data/v2ray/no-autostart` . +#### Manage service start / stop -- You can start / stop manually by execute the service script in `$MODDIR/v2ray.service` . For example, in my environment , the script's absolute path is `/sbin/.magisk/img/v2ray/v2ray.service` . +- V2Ray service is auto-run after system boot up by default. +- You can start or stop v2ray service by simply turn on or turn off the module via Magisk Manager App. Start service may wait about 10 second and stop service may take effect immediately. -- So, if you want to start v2ray service, just run: - `/sbin/.magisk/img/v2ray/v2ray.service start` - or stop v2ray service: +#### Select which App to proxy - `/sbin/.magisk/img/v2ray/v2ray.service stop ` +- If you expect transparent proxy ( read Transparent proxy section for more detail ) for some Apps, just write down these App' uid in file `/data/v2ray/appid.list` . + + Each App's uid should separate by space or just one App's uid per line. ( for Android App's uid , you can search App's package name in file `/data/system/packages.list` , or you can look into some App like Shadowsocks. ) + +- If you expect all Apps proxy by V2Ray with transparent proxy, just write a single number `0` in file `/data/v2ray/appid.list` . + +- Transparent proxy won't take effect until the V2Ray service start normally and file `/data/v2ray/appid.list` is not empty. + + + +### Advanced usage ( for Debug and Develop only ) + +#### Enter manual mode + +If you want to control V2Ray by running command totally, just add a file `/data/v2ray/manual`. In this situation, V2Ray service won't start on boot automatically and you cann't manage service start/stop via Magisk Manager App. + + + +#### Manage service start / stop + +- V2Ray service script is `$MODDIR/scripts/v2ray.service`. + +- For example, in my environment ( Magisk version: 18100 ; Magisk Manager version v7.1.1 ) + + - Start service : + + `/sbin/.magisk/img/v2ray/scripts/v2ray.service start` + + - Stop service : + + `/sbin/.magisk/img/v2ray/scripts/v2ray.service stop` + + + +#### Manage transparent proxy enable / disable + +- Transparent proxy script is `$MODDIR/scripts/v2ray.tproxy`. + +- For example, in my environment ( Magisk version: 18100 ; Magisk Manager version v7.1.1 ) + + - Enable Transparent proxy : + + `/sbin/.magisk/img/v2ray/scripts/v2ray.tproxy enable` + + - Disable Transparent proxy : + + `/sbin/.magisk/img/v2ray/scripts/v2ray.tproxy disable` - or restart v2ray service: - `/sbin/.magisk/img/v2ray/v2ray.service restart` ## Transparent proxy +### What is "Transparent proxy" + +> "A 'transparent proxy' is a proxy that does not modify the request or response beyond what is required for proxy authentication and identification". "A 'non-transparent proxy' is a proxy that modifies the request or response in order to provide some added service to the user agent, such as group annotation services, media type transformation, protocol reduction, or anonymity filtering". +> +> ​ -- [Transparent proxy explanation in Wikipedia](https://en.wikipedia.org/wiki/Proxy_server#Transparent_proxy) + + + ### Working principle This module also contains a simple script that helping you to make transparent proxy via iptables. In fact , the script is just make some REDIRECT and TPROXY rules to redirect app's network into 65535 port in localhost. And 65535 port is listen by v2ray inbond with dokodemo-door protocol. In summarize, the App proxy network path is looks like : -**Android App** ( Browser, Google, Facebook, Twitter ... ... ) +**Android App** ( Google, Facebook, Twitter ... ) ⇕ ( TCP & UDP network protocol ) -Android system **iptables** [ localhost inside ] +Android system **iptables** [ localhost inside ] ⇕ ( REDIRECT & TPROXY iptables rules ) -127.0.0.1:65535 [ Inbond ] ----- **V2Ray** ----- [ Outbond ] +[ 127.0.0.1:65535 Inbond ] -- **V2Ray** -- [ Outbond ] -​ ( Shadowsocks, Vmess ) ⇕ + ⇕ ( Shadowsocks, Vmess ) - [ Internet outside ] ( SS, V2Ray) **Proxy Server** +**Proxy Server** ( SS, V2Ray) [ Internet outside ] -​ ( HTTP, TCP, ... other application protocol ) ⇕ + ⇕ ( HTTP, TCP, ... other application protocol ) - ( Google, Facebook, Twitter ... ... ) **App Server** - - - -### Choose proxy target - -- Select mode : You can write a list of App's uid into `/data/v2ray/appid.list` file so that the script would select these App's network proxy via V2Ray. Each App's uid should separate by space or just One App's uid per line. - -- Global mode : You can write a single number "0" into `/data/v2ray/appid.list` file to make all App's network proxy via V2Ray. - - - -### Enable/Disable proxy - -- Only when the V2Ray service start normally on boot and `/data/v2ray/appid.list` file is not empty, the transparent proxy iptables script can run automatically. - -- Otherwise, you can execute iptables script in `$MODDIR/v2ray.redirect` . For example, in my environment: - - Enable transparent proxy: - - `/sbin/.magisk/img/v2ray/v2ray.redirect enable` - - Disable transparent proxy: - - `/sbin/.magisk/img/v2ray/v2ray.redirect disable` +**App Server** ( Google, Facebook, Twitter ... ) diff --git a/common/service.sh b/common/service.sh index 2fc51ad..89e93f1 100644 --- a/common/service.sh +++ b/common/service.sh @@ -8,4 +8,5 @@ MODDIR=${0%/*} # This script will be executed in late_start service mode -if [ ! -f /data/v2ray/no-autostart ] ; then $MODDIR/v2ray.service start && [ -f /data/v2ray/appid.list ] && $MODDIR/v2ray.redirect enable ; fi +if [ ! -f /data/v2ray/manual ] ; then $MODDIR/scripts/v2ray.service start && [ -f /data/v2ray/appid.list ] && $MODDIR/scripts/v2ray.tproxy enable ; fi +inotifyd $MODDIR/scripts/v2ray.inotify $MODDIR & diff --git a/install.sh b/install.sh index 2649bfe..058ee7c 100644 --- a/install.sh +++ b/install.sh @@ -132,15 +132,15 @@ print_modname() { on_install() { # The following is the default implementation: extract $ZIPFILE/system to $MODPATH # Extend/change the logic to whatever you want - ui_print "- Extracting module files" - unzip -o "$ZIPFILE" 'system/*' -d $MODPATH >&2 + ## ui_print "- Extracting module files" + ## unzip -o "$ZIPFILE" 'system/*' -d $MODPATH >&2 # install v2ray execute file ui_print "- Install V2Ray core $ARCH execute files" + mkdir -p $MODPATH/scripts mkdir -p $MODPATH/system/bin mkdir -p $MODPATH/system/etc - unzip -j -o "$ZIPFILE" "v2ray/etc/v2ray.service" -d $MODPATH >&2 - unzip -j -o "$ZIPFILE" "v2ray/etc/v2ray.redirect" -d $MODPATH >&2 + unzip -j -o "$ZIPFILE" 'v2ray/scripts/*' -d $MODPATH/scripts >&2 unzip -j -o "$ZIPFILE" "v2ray/bin/$ARCH/*" -d $MODPATH/system/bin >&2 # copy v2ray data and config @@ -149,6 +149,7 @@ on_install() { mkdir -p /data/v2ray/run [ -f /data/v2ray/config.json ] || \ unzip -j -o "$ZIPFILE" "v2ray/etc/config.json" -d /data/v2ray >&2 + [ -f /data/v2ray/resolv.conf ] || \ unzip -j -o "$ZIPFILE" "v2ray/etc/resolv.conf" -d /data/v2ray >&2 unzip -j -o "$ZIPFILE" "v2ray/etc/geosite.dat" -d /data/v2ray >&2 unzip -j -o "$ZIPFILE" "v2ray/etc/geoip.dat" -d /data/v2ray >&2 @@ -163,10 +164,11 @@ set_permissions() { inet_uid="3003" # The following is the default rule, DO NOT remove set_perm_recursive $MODPATH 0 0 0755 0644 - set_perm $MODPATH/v2ray.service 0 0 0755 - set_perm $MODPATH/v2ray.redirect 0 0 0755 - set_perm $MODPATH/system/bin/v2ray ${inet_uid} ${inet_uid} 6755 - set_perm $MODPATH/system/bin/v2ctl ${inet_uid} ${inet_uid} 6755 + set_perm $MODPATH/scripts/v2ray.inotify 0 0 0755 + set_perm $MODPATH/scripts/v2ray.service 0 0 0755 + set_perm $MODPATH/scripts/v2ray.tproxy 0 0 0755 + set_perm $MODPATH/system/bin/v2ray ${inet_uid} ${inet_uid} 0755 + set_perm $MODPATH/system/bin/v2ctl ${inet_uid} ${inet_uid} 0755 set_perm /data/v2ray ${inet_uid} ${inet_uid} 0755 # Here are some examples: diff --git a/v2ray/scripts/v2ray.inotify b/v2ray/scripts/v2ray.inotify new file mode 100644 index 0000000..cb82d11 --- /dev/null +++ b/v2ray/scripts/v2ray.inotify @@ -0,0 +1,34 @@ +#!/system/bin/sh + +inotify=`realpath $0` +scripts_dir=`dirname ${inotify}` +service="${scripts_dir}/v2ray.service" +tproxy="${scripts_dir}/v2ray.tproxy" + +events=$1 +monitor_dir=$2 +monitor_file=$3 + +start_v2ray() { + ${service} start && \ + [ -f /data/v2ray/appid.list ] && ${tproxy} enable +} + +stop_v2ray() { + ${tproxy} disable + ${service} stop +} + +main() { +if [ ! -f /data/v2ray/manual ] ; then + if [ "${monitor_file}" = "disable" ] ; then + if [ "${events}" = "d" ] ; then + start_v2ray + elif [ "${events}" = "n" ] ; then + stop_v2ray + fi + fi +fi +} + +main diff --git a/v2ray/etc/v2ray.service b/v2ray/scripts/v2ray.service similarity index 87% rename from v2ray/etc/v2ray.service rename to v2ray/scripts/v2ray.service index 9966d02..5ffb412 100644 --- a/v2ray/etc/v2ray.service +++ b/v2ray/scripts/v2ray.service @@ -5,6 +5,7 @@ V2RAY=/system/bin/${NAME} DATAPATH=/data/${NAME} RUNPATH=${DATAPATH}/run PIDFILE=${RUNPATH}/${NAME}.pid +EXECLOG=${RUNPATH}/error.log CONFFILE=${DATAPATH}/config.json V2RAY_OPTS="-config ${CONFFILE}" @@ -36,9 +37,9 @@ do_start() { chown -R inet:inet ${DATAPATH} chown inet:inet ${V2RAY} chmod 6755 ${V2RAY} - ${V2RAY} ${V2RAY_OPTS} & + nohup ${V2RAY} ${V2RAY_OPTS} &>${EXECLOG} & echo -n $! > ${PIDFILE} - sleep 10 + sleep 5 if probe_service ; then echo "Start ${NAME} service Done." else @@ -72,7 +73,11 @@ case "$1" in do_start || \ simple_clean_iptables ;; + status) + probe_service || \ + echo "${NAME} service is stopped." + ;; *) - echo "$0: usage: $0 {start|stop|restart}" + echo "$0: usage: $0 {start|stop|restart|status}" ;; esac diff --git a/v2ray/etc/v2ray.redirect b/v2ray/scripts/v2ray.tproxy similarity index 54% rename from v2ray/etc/v2ray.redirect rename to v2ray/scripts/v2ray.tproxy index db39acb..85842ba 100644 --- a/v2ray/etc/v2ray.redirect +++ b/v2ray/scripts/v2ray.tproxy @@ -7,11 +7,22 @@ proxy_port="65535" proxy_mark="0x20151130" appid_file="/data/v2ray/appid.list" table_file="/data/misc/net/rt_tables" +iptables_wait="iptables -w 10" appid_list=`[ -f ${appid_file} ] && cat ${appid_file}` intranet=(0.0.0.0/8 10.0.0.0/8 127.0.0.0/8 169.254.0.0/16 172.16.0.0/12 192.168.0.0/16 224.0.0.0/4 240.0.0.0/4) +suit_iptables_version() { + iptables_version=`iptables -V | grep -o "v1\.[0-9]"` + ## just for lower version iptables + if [ "${iptables_version}" = "v1.4" ] ; then + export ANDROID_DATA=/data + export ANDROID_ROOT=/system + iptables_wait="iptables -w" + fi +} + probe_uid_app_name() { app_name=`grep " $1 " /data/system/packages.list | cut -d ' ' -f 1` app_name=`echo ${app_name} | sed 's/ / \& /g'` @@ -41,81 +52,81 @@ create_route_table() { flush_tcp_iptables() { echo "Clean TCP redirection iptables rules." - iptables -w 10 -t nat -D OUTPUT -p tcp -j TCP_PRE_PROXY 2>/dev/null - if eval "iptables -w 10 -t nat -L TCP_PRE_PROXY &>/dev/null" ; then - iptables -w 10 -t nat -F TCP_PRE_PROXY - iptables -w 10 -t nat -X TCP_PRE_PROXY + ${iptables_wait} -t nat -D OUTPUT -p tcp -j TCP_PRE_PROXY 2>/dev/null + if eval "iptables-save -t nat | grep -q ':TCP_PRE_PROXY '" ; then + ${iptables_wait} -t nat -F TCP_PRE_PROXY + ${iptables_wait} -t nat -X TCP_PRE_PROXY fi if eval "iptables-save -t nat | grep -q ':V2RAY '" ; then - iptables -w 10 -t nat -F V2RAY - iptables -w 10 -t nat -X V2RAY + ${iptables_wait} -t nat -F V2RAY + ${iptables_wait} -t nat -X V2RAY fi } flush_udp_iptables() { echo "Clean UDP redirection iptables rules." - iptables -w 10 -t mangle -D PREROUTING -p udp -j V2RAY 2>/dev/null - iptables -w 10 -t mangle -D OUTPUT -p udp -j UDP_PRE_PROXY 2>/dev/null + ${iptables_wait} -t mangle -D PREROUTING -p udp -j V2RAY 2>/dev/null + ${iptables_wait} -t mangle -D OUTPUT -p udp -j UDP_PRE_PROXY 2>/dev/null if eval "iptables-save -t mangle | grep -q ':UDP_PRE_PROXY '" ; then - iptables -w 10 -t mangle -F UDP_PRE_PROXY - iptables -w 10 -t mangle -X UDP_PRE_PROXY + ${iptables_wait} -t mangle -F UDP_PRE_PROXY + ${iptables_wait} -t mangle -X UDP_PRE_PROXY fi if eval "iptables-save -t mangle | grep -q ':V2RAY '" ; then - iptables -w 10 -t mangle -F V2RAY - iptables -w 10 -t mangle -X V2RAY + ${iptables_wait} -t mangle -F V2RAY + ${iptables_wait} -t mangle -X V2RAY fi } init_tcp_iptables() { echo "Create TCP redirection iptables rules." ## create NAT iptables for TCP redirect - iptables -w 10 -t nat -N V2RAY - iptables -w 10 -t nat -N TCP_PRE_PROXY + ${iptables_wait} -t nat -N V2RAY + ${iptables_wait} -t nat -N TCP_PRE_PROXY ## bypass intranet for subnet in ${intranet[@]}; do - iptables -w 10 -t nat -A V2RAY -d ${subnet} -j RETURN + ${iptables_wait} -t nat -A V2RAY -d ${subnet} -j RETURN done ## bypass v2ray program - iptables -w 10 -t nat -A TCP_PRE_PROXY -m owner --uid-owner ${inet_uid} -j RETURN + ${iptables_wait} -t nat -A TCP_PRE_PROXY -m owner --uid-owner ${inet_uid} -j RETURN ## apply to NAT iptables OUTPUT - iptables -w 10 -t nat -A V2RAY -p tcp -j REDIRECT --to-ports ${proxy_port} + ${iptables_wait} -t nat -A V2RAY -p tcp -j REDIRECT --to-ports ${proxy_port} } init_udp_iptables() { echo "Create UDP redirection iptables rules." ## create Mangle iptables for UDP redirect - iptables -w 10 -t mangle -N V2RAY - iptables -w 10 -t mangle -N UDP_PRE_PROXY + ${iptables_wait} -t mangle -N V2RAY + ${iptables_wait} -t mangle -N UDP_PRE_PROXY ## bypass intranet for subnet in ${intranet[@]}; do - iptables -w 10 -t mangle -A UDP_PRE_PROXY -d ${subnet} -j RETURN + ${iptables_wait} -t mangle -A UDP_PRE_PROXY -d ${subnet} -j RETURN done ## bypass v2ray program - iptables -w 10 -t mangle -A UDP_PRE_PROXY -m owner --uid-owner ${inet_uid} -j RETURN + ${iptables_wait} -t mangle -A UDP_PRE_PROXY -m owner --uid-owner ${inet_uid} -j RETURN ## apply to Mangle iptables OUTPUT & PREROUTING - iptables -w 10 -t mangle -A V2RAY -p udp -m mark --mark ${proxy_mark} -j TPROXY --on-ip 127.0.0.1 --on-port ${proxy_port} + ${iptables_wait} -t mangle -A V2RAY -p udp -m mark --mark ${proxy_mark} -j TPROXY --on-ip 127.0.0.1 --on-port ${proxy_port} } redirect_iptables() { if [ "${appid_list}" = "0" ] ; then ## redirect global network echo "Redirect TCP & UDP with Global mode." - iptables -w 10 -t nat -A TCP_PRE_PROXY -m owner ! --uid-owner ${inet_uid} -j V2RAY - iptables -w 10 -t mangle -A UDP_PRE_PROXY -m owner ! --uid-owner ${inet_uid} -j MARK --set-mark ${proxy_mark} + ${iptables_wait} -t nat -A TCP_PRE_PROXY -m owner ! --uid-owner ${inet_uid} -j V2RAY + ${iptables_wait} -t mangle -A UDP_PRE_PROXY -m owner ! --uid-owner ${inet_uid} -j MARK --set-mark ${proxy_mark} else ## effect assign app for appid in ${appid_list}; do probe_uid_app_name ${appid} && \ - iptables -w 10 -t nat -A TCP_PRE_PROXY -m owner --uid-owner ${appid} -j V2RAY && \ - iptables -w 10 -t mangle -A UDP_PRE_PROXY -m owner --uid-owner ${appid} -j MARK --set-mark ${proxy_mark} + ${iptables_wait} -t nat -A TCP_PRE_PROXY -m owner --uid-owner ${appid} -j V2RAY && \ + ${iptables_wait} -t mangle -A UDP_PRE_PROXY -m owner --uid-owner ${appid} -j MARK --set-mark ${proxy_mark} done fi } apply_iptables_rules() { - iptables -w 10 -t nat -A OUTPUT -p tcp -j TCP_PRE_PROXY - iptables -w 10 -t mangle -A OUTPUT -p udp -j UDP_PRE_PROXY - iptables -w 10 -t mangle -A PREROUTING -p udp -j V2RAY + ${iptables_wait} -t nat -A OUTPUT -p tcp -j TCP_PRE_PROXY + ${iptables_wait} -t mangle -A OUTPUT -p udp -j UDP_PRE_PROXY + ${iptables_wait} -t mangle -A PREROUTING -p udp -j V2RAY } disable_redirect() { @@ -125,7 +136,6 @@ disable_redirect() { } enable_redirect() { - disable_redirect create_route_table init_tcp_iptables init_udp_iptables @@ -133,14 +143,18 @@ enable_redirect() { apply_iptables_rules } +suit_iptables_version + case "$1" in enable) + disable_redirect enable_redirect ;; disable) disable_redirect ;; renew) + disable_redirect enable_redirect ;; *)