Skip to content

Commit

Permalink
treehouses shadowsocks (fixes #1596) (#1621)
Browse files Browse the repository at this point in the history
Co-authored-by: dogi <dogi@users.noreply.github.com>
  • Loading branch information
darthnoward and dogi authored Jul 10, 2020
1 parent a8cbf58 commit c0e11c0
Show file tree
Hide file tree
Showing 9 changed files with 341 additions and 1 deletion.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ bootoption <console|desktop> [autologin] sets the boot mode
<modules|params>
openvpn [use|show|delete] helps setting up an openvpn client
[notice|start|stop|load]
shadowsocks [list|add|enable|start] manage shadowsocks, a socks5 proxy designed
[enter|disable|stop|remove] to "protect" your Internet traffic
coralenv [install|demo-on|demo-off] plays with the coral environmental board
[demo-always-on]
memory [total|used|free] displays the total memory of the device, the memory used as well as the available free memory
Expand Down
10 changes: 10 additions & 0 deletions _treehouses
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,16 @@ treehouses openvpn show
treehouses openvpn start
treehouses openvpn stop
treehouses openvpn use
treehouses shadowsocks
treehouses shadowsocks add
treehouses shadowsocks disable
treehouses shadowsocks enable
treehouses shadowsocks enter
treehouses shadowsocks list
treehouses shadowsocks restart
treehouses shadowsocks remove
treehouses shadowsocks start
treehouses shadowsocks stop
treehouses password
treehouses password disable
treehouses password enable
Expand Down
12 changes: 12 additions & 0 deletions modules/default.sh
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,18 @@ function default_network {
rm -rf /etc/hostapd.conf
rm -rf /etc/network/interfaces.d/*

for i in /etc/shadowsocks-libev/*
do
if [ "$i" != "/etc/shadowsocks-libev/config.json" ]; then
rm -rf $i
if echo $i | grep -q json; then
i="$(echo $i | cut -d "/" -f 4 | sed 's/.json//g')"
stop_service shadowsocks-libev-local@$i.service
disable_service shadowsocks-libev-local@$i.service
fi
fi
done

stop_service hostapd
stop_service dnsmasq
disable_service hostapd
Expand Down
2 changes: 2 additions & 0 deletions modules/help.sh
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ bootoption <console|desktop> [autologin] sets the boot mode
<modules|params>
openvpn [use|show|delete] helps setting up an openvpn client
[notice|start|stop|load]
shadowsocks [list|add|enable|start] manage shadowsocks, a socks5 proxy designed
[enter|disable|stop|remove] to "protect" your Internet traffic
coralenv [install|demo-on|demo-off] plays with the coral environmental board
[demo-always-on]
memory [total|used|free] displays the total memory of the device, the memory used as well as the available free memory
Expand Down
277 changes: 277 additions & 0 deletions modules/shadowsocks.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,277 @@
function shadowsocks {
checkroot
check_missing_packages "shadowsocks-libev"
check_missing_packages "proxychains4"

local name port name_conf running location

if [ ! -d /etc/shadowsocks-libev ]; then
mkdir /etc/shadowsocks-libev
fi

if [ $# -eq 0 ]; then
shadowsocks list
fi

case "$1" in
list)
checkargn $# 1

echo
echo "Config:"
find /etc/shadowsocks-libev/*.json |\
sed -e 's/\/etc\/shadowsocks-libev\///g' -e 's/.json//g' -e 's/config//g'
echo

if [ -z "$(pidof ss-local)" ]; then
echo "No instance of shadowsocks client running."
else
echo "Running:"
echo
printf "CONFIG\t\tPORT\t\t\tLOCATION\n"
for pid in $(pidof ss-local)
do
name="$(ps ax | grep -E "^ *$pid" |\
awk '{print $7}' |\
sed -e 's/\/etc\/shadowsocks-libev\///g' -e 's/.json//g')"
port="$(lsof -i -P -n |\
grep LISTEN | grep $pid |\
awk '{print $9}' | cut -d ":" -f 2)"
if [ -f /etc/shadowsocks-libev/$name.conf ]; then
location="$(proxychains4 -f /etc/shadowsocks-libev/$name.conf -q curl -s ipinfo.io |\
grep \"country\" | cut -d ":" -f 2 |\
sed -e 's/"//g' -e 's/,//g')"
location="$location -$(proxychains4 -f /etc/shadowsocks-libev/$name.conf -q curl -s ipinfo.io |\
grep \"region\" | cut -d ":" -f 2 |\
sed -e 's/"//g' -e 's/,//g')"
else
location="$(proxychains4 -q curl -s ipinfo.io |\
grep \"country\" | cut -d ":" -f 2 |\
sed -e 's/"//g' -e 's/,//g')"
location="$location - $(proxychains4 -q curl -s ipinfo.io |\
grep \"region\" | cut -d ":" -f 2 |\
sed -e 's/"//g' -e 's/,//g')"
fi
printf "%s\t\t%s\t\t%s\n" "$name" "$port" "$location"
done
fi
echo

if systemctl | grep shadowsocks-libev-local | grep -q failed; then
echo "Failed:"
echo
name="$(systemctl |\
grep shadowsocks-libev-local | grep failed |\
awk '{print $2}' | cut -d "@" -f 2 | cut -d "." -f 1)"
for i in $name
do
printf "%s\n\tRun \`journalctl -u shadowsocks-libev-local@%s.service\` for more info.\n" "$i" "$i"
done
else
echo "No instance of shadowsocks client failed."
fi
echo
exit 0 ;;

start | enable)
checkargn $# 2

echo
for i in /etc/shadowsocks-libev/*.json
do
if [ "$2" = "$(echo $i | cut -d "/" -f 4 | cut -d "." -f 1)" ]; then
if [ "$1" = "start" ]; then
systemctl start shadowsocks-libev-local@$2.service
if systemctl --quiet is-active shadowsocks-libev-local@$2.service; then
echo "$2 started."
echo "Use \`$BASENAME shadowsocks enter $2\` to enter shell session proxied by shadowsocks client."
else
echo "$2 fails to start."
echo "Please check your config." && exit 1
fi
else
systemctl enable shadowsocks-libev-local@$2.service --quiet
echo "$2 enabled."
fi
echo

if [ ! -f /etc/shadowsocks-libev/$2.conf ]; then
if grep -q local_port /etc/shadowsocks-libev/$2.json; then
cp "$TEMPLATES/network/proxychains4.conf" /etc/shadowsocks-libev/$2.conf
echo "socks5 127.0.0.1 $(grep local_port /etc/shadowsocks-libev/$2.json |\
awk '{print $2}' | sed 's/,//g')" >> /etc/shadowsocks-libev/$name_conf.conf
else
echo "Config not valid."
echo "You may be unable to enter proxied shell session."
echo
exit 1
fi
fi
exit 0
fi
done

echo "Config \"$2\" not found."
echo "Please do \`$BASENAME shadowsocks add $2\` first."
echo
exit 1;;

restart)
checkargn $# 2
systemctl restart shadowsocks-libev-local@$2.service --quiet
echo "$2 restarted." ;;

stop)
checkargn $# 2
systemctl stop shadowsocks-libev-local@$2.service --quiet
echo "$2 stopped." ;;

disable)
checkargn $# 2
systemctl disable shadowsocks-libev-local@$2.service --quiet
echo "$2 disabled" ;;

add)
if [ $# -eq 2 ] && [ -f "$2" ]; then
name_conf="$(echo $2 | sed -e 's/json//g' -e 's/\.//g' -e 's/\///g' )"

if [ -f /etc/shadowsocks-libev/$name_conf.json ]; then
echo "$name_conf.json already exists."
echo "Abort."
echo
exit 1
fi
if ! jq -e . >/dev/null 2>&1 <<< "$(<$2)"; then
echo "Invalid json format"
echo "Abort." && exit 1
fi
cp "$2" /etc/shadowsocks-libev/$name_conf.json
elif [ ! -f "$2" ]; then
echo "Invalid file location"
echo "Abort." && exit 1
else
checkargn $# 1
echo
echo "Existing config:"
name="$(find /etc/shadowsocks-libev/*.json |\
sed -e 's/\/etc\/shadowsocks-libev\///g' -e 's/.json//g' -e 's/config//g')"
echo $name
echo
read -r -p "Enter the name for your config: " name_conf
if echo $name_conf | grep -q ".json"; then
name_conf="${name_conf//.json/}"
fi

if [ -f /etc/shadowsocks-libev/$name_conf.json ]; then
echo "$name_conf.json already exists."
echo "Abort."
echo
exit 1
fi

cp "$TEMPLATES/network/shadowsocks.json" /etc/shadowsocks-libev/$name_conf.json
if [ -z "$EDITOR" ]; then
vim /etc/shadowsocks-libev/$name_conf.json
else
$EDITOR /etc/shadowsocks-libev/$name_conf.json
fi
echo

if [ -z "$(diff $TEMPLATES/network/shadowsocks.json /etc/shadowsocks-libev/$name_conf.json)" ]; then
echo "Config not saved."
rm -rf /etc/shadowsocks-libev/$name_conf.json
echo "Abort."
exit 1
fi
fi

if grep -q local_port /etc/shadowsocks-libev/$name_conf.json; then
cp "$TEMPLATES/network/proxychains4.conf" /etc/shadowsocks-libev/$name_conf.conf
echo "socks5 127.0.0.1 $(grep local_port /etc/shadowsocks-libev/$name_conf.json |\
awk '{print $2}' | sed 's/,//g')" >> /etc/shadowsocks-libev/$name_conf.conf
echo "Config named \"$name_conf\" saved."
echo "Use \`$BASENAME shadowsocks start $name_conf\` to start client."
echo
exit 0
else
rm -rf /etc/shadowsocks-libev/$name_conf.json
echo "The config is not valid."
echo "Abort."
echo
exit 1
fi ;;

remove)
checkargn $# 2
if echo $2 | grep -q ".json"; then
name="${2//.json/}"
else
name="$2"
fi
rm -rf /etc/shadowsocks-libev/$name.*
shadowsocks stop $name
shadowsocks disable $name
echo "$name removed."
;;

enter)
checkargn $# 2
if echo $2 | grep -q ".json"; then
name="${2//.json/}"
else
name="$2"
fi

if [ ! -z "$(pidof ss-local)" ]; then
for pid in $(pidof ss-local)
do
running="$(ps ax | grep -E "^ *$pid" |\
awk '{print $7}' |\
sed -e 's/\/etc\/shadowsocks-libev\///g' -e 's/.json//g')"
if [ "$name" == "$running" ]; then
if [ -f /etc/shadowsocks-libev/$name.conf ]; then
proxychains4 -q -f /etc/shadowsocks-libev/$name.conf $SHELL
echo "$name Session terminated."
exit 0
else
echo "Proxychains4 configuration file not found."
echo "Abort."
exit 1
fi
break
fi
done
echo "$name is not running!"
echo "Please do \`$BASENAME shadowsocks start $name\` first."
exit 1
else
echo "No instance of Shadowsocks client running!"
echo "Abort." && exit 1
fi ;;

*)
echo "Error: No option as $1."
shadowsocks_help
exit 1;;
esac
}

function shadowsocks_help {
echo
echo "Usage: $BASENAME shadowsocks [add|disable|enable|enter]"
echo " [list|restart|remove|start|stop]"
echo
echo " $BASENAME shadowsocks list"
echo " list all information regarding shadowsocks clients"
echo " $BASENAME shadowsocks add <json file>"
echo " add configuration file for shadowsocks clients"
echo " $BASENAME shadowsocks enter"
echo " enter a proxied shell session by shadowsocks client"
echo " $BASENAME shadowsocks enable/disable"
echo " enable/disable autorun for shadowsocks clients"
echo " $BASENAME shadowsocks start/stop/restart"
echo " start/stop/restart shadowsocks clients"
echo " $BASENAME shadowsocks remove"
echo " remove shadowsocks clients config json"
echo
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@treehouses/cli",
"version": "1.23.11",
"version": "1.23.12",
"remote": "2500",
"description": "Thin command-line interface for Raspberry Pi low level configuration.",
"main": "cli.sh",
Expand Down
11 changes: 11 additions & 0 deletions templates/network/proxychains4.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
strict_chain

proxy_dns

remote_dns_subnet 224

tcp_read_time_out 15000
tcp_connect_time_out 8000

[ProxyList]

9 changes: 9 additions & 0 deletions templates/network/shadowsocks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"server": "",
"local_address": "127.0.0.1",
"local_port": ,
"timeout": 300,
"server_port": ,
"password": "",
"method": ""
}
17 changes: 17 additions & 0 deletions tests/shadowsocks.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/usr/bin/env bats
load test-helper

@test "$clinom shadowsocks" {
run "${clicmd}" shadowsocks list
assert_success && assert_output -p 'Config'
}

@test "$clinom shadowsocks start config" {
run "${clicmd}" shadowsocks start config
assert_success && assert_output -p 'config started'
}

@test "$clinom shadowsocks remove" {
run "${clicmd}" shadowsocks remove config
assert_success && assert_output -p 'removed'
}

0 comments on commit c0e11c0

Please sign in to comment.