1- #! /bin/sh
1+ #! /bin/ash
2+ # shellcheck shell=ash
3+ # shellcheck disable=SC2169 # making up for lack of ash support
24
3- function cleanup {
5+ cleanup () {
46 # When you run `docker stop` or any equivalent, a SIGTERM signal is sent to PID 1.
57 # A process running as PID 1 inside a container is treated specially by Linux:
68 # it ignores any signal with the default action. As a result, the process will
79 # not terminate on SIGINT or SIGTERM unless it is coded to do so. Because of this,
810 # I've defined behavior for when SIGINT and SIGTERM is received.
9- if [ $healthcheck_child ]; then
10- echo " Stopping healthcheck script..."
11- kill -TERM $healthcheck_child
12- fi
13-
14- if [ $openvpn_child ]; then
11+ if [ " $openvpn_child " ]; then
1512 echo " Stopping OpenVPN..."
16- kill -TERM $openvpn_child
13+ kill -TERM " $openvpn_child "
1714 fi
1815
1916 sleep 1
20- rm $config_file_modified
17+ rm " $config_file_modified "
2118 echo " Exiting."
2219 exit 0
2320}
2421
22+ is_ip () {
23+ echo " $1 " | grep -Eq " [0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*"
24+ }
25+
2526# Capture the filename of the first .conf file to use as the OpenVPN config.
26- config_file_original=$( ls -1 /data/vpn/ * .conf 2> /dev/null | head -1)
27- if [ -z $config_file_original ]; then
27+ config_file_original=$( find /data/vpn -name " *.conf" 2> /dev/null | sort | head -1)
28+ if [ -z " $config_file_original " ]; then
2829 >&2 echo " ERROR: No configuration file found. Please check your mount and file permissions. Exiting."
2930 exit 1
3031fi
3132
32- if ! $( echo $VPN_LOG_LEVEL | grep -Eq ' ^([1-9]|1[0-1])$' ) ; then
33+ # shellcheck disable=SC2153
34+ if ! (echo " $VPN_LOG_LEVEL " | grep -Eq ' ^([1-9]|1[0-1])$' ); then
3335 echo " WARNING: Invalid log level $VPN_LOG_LEVEL . Setting to default."
3436 vpn_log_level=3
3537else
@@ -47,26 +49,26 @@ Using OpenVPN log level: $vpn_log_level
4749"
4850
4951# Create a new configuration file to modify so the original is left untouched.
50- config_file_modified=${config_file_original} .modified
52+ config_file_modified=" ${config_file_original} .modified"
5153
5254echo " Creating $config_file_modified and making required changes to that file."
53- cp $config_file_original $config_file_modified
55+ cp " $config_file_original " " $config_file_modified "
5456
5557# These configuration file changes are required by Alpine.
5658sed -i \
5759 -e ' /up /c up \/etc\/openvpn\/up.sh' \
5860 -e ' /down /c down \/etc\/openvpn\/down.sh' \
5961 -e ' s/^proto udp$/proto udp4/' \
6062 -e ' s/^proto tcp$/proto tcp4/' \
61- $config_file_modified
63+ " $config_file_modified "
6264
6365echo -e " Changes made.\n"
6466
6567trap cleanup INT TERM
6668
6769# NOTE: When testing with the kill switch enabled, don't forget to pass in the
6870# local subnet. It will save a lot of headache.
69- if [ $KILL_SWITCH = " on" ]; then
71+ if [ " $KILL_SWITCH " = " on" ]; then
7072 local_subnet=$( ip r | grep -v ' default via' | grep eth0 | tail -n 1 | cut -d " " -f 1)
7173 default_gateway=$( ip r | grep ' default via' | cut -d " " -f 3)
7274
@@ -80,33 +82,40 @@ if [ $KILL_SWITCH = "on" ]; then
8082 iptables -A OUTPUT -o lo -j ACCEPT
8183
8284 echo " Allowing Docker network connections..."
83- iptables -A INPUT -s $local_subnet -j ACCEPT
84- iptables -A OUTPUT -d $local_subnet -j ACCEPT
85+ iptables -A INPUT -s " $local_subnet " -j ACCEPT
86+ iptables -A OUTPUT -d " $local_subnet " -j ACCEPT
8587
8688 echo " Allowing specified subnets..."
8789 # for every specified subnet...
8890 for subnet in ${SUBNETS// ,/ } ; do
8991 # create a route to it and...
90- ip route add $subnet via $default_gateway dev eth0
92+ ip route add " $subnet " via " $default_gateway " dev eth0
9193 # allow connections
92- iptables -A INPUT -s $subnet -j ACCEPT
93- iptables -A OUTPUT -d $subnet -j ACCEPT
94+ iptables -A INPUT -s " $subnet " -j ACCEPT
95+ iptables -A OUTPUT -d " $subnet " -j ACCEPT
9496 done
9597
9698 echo " Allowing remote servers in configuration file..."
97- remote_port=$( grep " port " $config_file_modified | cut -d " " -f 2)
98- remote_proto=$( grep " proto " $config_file_modified | cut -d " " -f 2 | cut -c1-3)
99- remotes=$( grep " remote " $config_file_modified | cut -d " " -f 2-4)
99+ remote_port=$( grep " port " " $config_file_modified " | cut -d " " -f 2)
100+ remote_proto=$( grep " proto " " $config_file_modified " | cut -d " " -f 2 | cut -c1-3)
101+ remotes=$( grep " remote " " $config_file_modified " | cut -d " " -f 2-4)
100102
101103 echo " Using:"
102- echo " $remotes " | while IFS= read line; do
103- domain=$( echo " $line " | cut -d " " -f 1)
104- port=$( echo " $line " | cut -d " " -f 2)
105- proto=$( echo " $line " | cut -d " " -f 3 | cut -c1-3)
106- for ip in $( dig -4 +short $domain ) ; do
107- echo " $domain (IP:$ip PORT:$port )"
108- iptables -A OUTPUT -o eth0 -d $ip -p ${proto:- $remote_proto } --dport ${port:- $remote_port } -j ACCEPT
109- done
104+ echo " ${remotes} " | while IFS= read -r line; do
105+ # strip any comments from line that could mess up cuts
106+ clean_line=${line%% #* }
107+ addr=$( echo " $clean_line " | cut -d " " -f 1)
108+ port=$( echo " $clean_line " | cut -d " " -f 2)
109+ proto=$( echo " $clean_line " | cut -d " " -f 3 | cut -c1-3)
110+ if is_ip " $addr " ; then
111+ echo " IP: $addr PORT: $port "
112+ iptables -A OUTPUT -o eth0 -d " $addr " -p " ${proto:- $remote_proto } " --dport " ${port:- $remote_port } " -j ACCEPT
113+ else
114+ for ip in $( dig -4 +short " $addr " ) ; do
115+ echo " $addr (IP: $ip PORT: $port )"
116+ iptables -A OUTPUT -o eth0 -d " $ip " -p " ${proto:- $remote_proto } " --dport " ${port:- $remote_port } " -j ACCEPT
117+ done
118+ fi
110119 done
111120
112121 echo " Allowing connections over VPN interface..."
124133fi
125134
126135if [ " $HTTP_PROXY " = " on" ]; then
127- if [ $PROXY_USERNAME ]; then
128- if [ $PROXY_PASSWORD ]; then
136+ if [ " $PROXY_USERNAME " ]; then
137+ if [ " $PROXY_PASSWORD " ]; then
129138 echo " Configuring proxy authentication."
130139 echo -e " \nBasicAuth $PROXY_USERNAME $PROXY_PASSWORD " >> /data/tinyproxy.conf
131140 else
@@ -136,10 +145,10 @@ if [ "$HTTP_PROXY" = "on" ]; then
136145fi
137146
138147if [ " $SOCKS_PROXY " = " on" ]; then
139- if [ $PROXY_USERNAME ]; then
140- if [ $PROXY_PASSWORD ]; then
148+ if [ " $PROXY_USERNAME " ]; then
149+ if [ " $PROXY_PASSWORD " ]; then
141150 echo " Configuring proxy authentication."
142- adduser -S -D -g $PROXY_USERNAME -H -h /dev/null $PROXY_USERNAME
151+ adduser -S -D -g " $PROXY_USERNAME " -H -h /dev/null " $PROXY_USERNAME "
143152 echo " $PROXY_USERNAME :$PROXY_PASSWORD " | chpasswd 2> /dev/null
144153 sed -i ' s/socksmethod: none/socksmethod: username/' /data/sockd.conf
145154 else
151160
152161echo -e " Running OpenVPN client.\n"
153162
154- openvpn --config $config_file_modified \
155- --verb $vpn_log_level \
163+ openvpn --config " $config_file_modified " \
164+ --verb " $vpn_log_level " \
156165 --auth-nocache \
157166 --connect-retry-max 10 \
158167 --pull-filter ignore " route-ipv6" \
0 commit comments