1- #! /bin/bash
1+ #! /usr/ bin/env bash
22
33cleanup () {
44 # When you run `docker stop` or any equivalent, a SIGTERM signal is sent to PID 1.
55 # A process running as PID 1 inside a container is treated specially by Linux:
66 # it ignores any signal with the default action. As a result, the process will
77 # not terminate on SIGINT or SIGTERM unless it is coded to do so. Because of this,
88 # I've defined behavior for when SIGINT and SIGTERM is received.
9- if [ " $openvpn_child " ]; then
9+ if [[ -n " $openvpn_child " ] ]; then
1010 echo " Stopping OpenVPN..."
1111 kill -TERM " $openvpn_child "
1212 fi
@@ -17,12 +17,9 @@ cleanup() {
1717 exit 0
1818}
1919
20- is_ip () {
21- echo " $1 " | grep -Eq " [0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*"
22- }
23-
20+ # OpenVPN log levels are 1-11.
2421# shellcheck disable=SC2153
25- if ! (echo " $VPN_LOG_LEVEL " | grep -Eq ' ^([1-9]|1[0-1])$ ' ) ; then
22+ if [[ " $VPN_LOG_LEVEL " -lt 1 || " $VPN_LOG_LEVEL " -gt 11 ]] ; then
2623 echo " WARNING: Invalid log level $VPN_LOG_LEVEL . Setting to default."
2724 vpn_log_level=3
2825else
@@ -40,12 +37,12 @@ Allowing subnets: ${SUBNETS:-none}
4037Using OpenVPN log level: $vpn_log_level
4138Listening on: ${LISTEN_ON:- none} "
4239
43- if [ -n " $VPN_CONFIG_FILE " ]; then
40+ if [[ -n " $VPN_CONFIG_FILE " ] ]; then
4441 config_file_original=" /data/vpn/$VPN_CONFIG_FILE "
4542else
4643 # Capture the filename of the first .conf file to use as the OpenVPN config.
4744 config_file_original=$( find /data/vpn -name " *.conf" 2> /dev/null | sort | head -1)
48- if [ -z " $config_file_original " ]; then
45+ if [[ -z " $config_file_original " ] ]; then
4946 >&2 echo " ERROR: No configuration file found. Please check your mount and file permissions. Exiting."
5047 exit 1
5148 fi
@@ -70,10 +67,8 @@ echo -e "Changes made.\n"
7067
7168trap cleanup INT TERM
7269
73- # NOTE: When testing with the kill switch enabled, don't forget to pass in the
74- # local subnet. It will save a lot of headache.
7570default_gateway=$( ip r | grep ' default via' | cut -d " " -f 3)
76- if [ " $KILL_SWITCH " = " on" ]; then
71+ if [[ " $KILL_SWITCH " == " on" ] ]; then
7772 local_subnet=$( ip r | grep -v ' default via' | grep eth0 | tail -n 1 | cut -d " " -f 1)
7873
7974 echo " Creating VPN kill switch and local routes."
@@ -100,29 +95,42 @@ if [ "$KILL_SWITCH" = "on" ]; then
10095 done
10196
10297 echo " Allowing remote servers in configuration file..."
103- remote_port =$( grep " port " " $config_file_modified " | cut -d " " -f 2)
104- remote_proto =$( grep " proto " " $config_file_modified " | cut -d " " -f 2 | cut -c1-3)
105- remotes=$( grep " remote " " $config_file_modified " | cut -d " " -f 2-4 )
98+ global_port =$( grep " port " " $config_file_modified " | cut -d " " -f 2)
99+ global_protocol =$( grep " proto " " $config_file_modified " | cut -d " " -f 2 | cut -c1-3)
100+ remotes=$( grep " remote " " $config_file_modified " )
106101
107102 echo " Using:"
108- echo " ${remotes} " | while IFS= read -r line; do
109- # strip any comments from line that could mess up cuts
110- clean_line=${line%% #* }
111- addr=$( echo " $clean_line " | cut -d " " -f 1)
112- port=$( echo " $clean_line " | cut -s -d " " -f 2)
113- proto=$( echo " $clean_line " | cut -s -d " " -f 3 | cut -c1-3)
114- port=${port:- ${remote_port:- 1194} }
115- proto=${proto:- ${remote_proto:- udp} }
116-
117- if is_ip " $addr " ; then
118- echo " IP: $addr PORT: $port PROTO: $proto "
119- iptables -A OUTPUT -o eth0 -d " $addr " -p " ${proto} " --dport " ${port} " -j ACCEPT
120- else
121- for ip in $( dig -4 +short " $addr " ) ; do
122- echo " $addr (IP: $ip PORT: $port PROTO: $proto )"
123- iptables -A OUTPUT -o eth0 -d " $ip " -p " ${proto} " --dport " ${port} " -j ACCEPT
124- echo " $ip $addr " >> /etc/hosts
125- done
103+ comment_regex=' ^[[:space:]]*[#;]'
104+ echo " $remotes " | while IFS= read -r line; do
105+ # Ignore comments.
106+ if ! [[ " $line " =~ $comment_regex ]]; then
107+ # Remove the line prefix 'remote '.
108+ line=${line# remote }
109+
110+ # Remove any trailing comments.
111+ line=${line%%#* }
112+
113+ # Split the line into an array.
114+ # The first element is an address (IP or domain), the second is a port,
115+ # and the fourth is a protocol.
116+ IFS=' ' read -r -a remote <<< " $line"
117+ address=${remote[0]}
118+ # Use port from 'remote' line, then 'port' line, then '1194'.
119+ port=${remote[1]:- ${global_port:- 1194} }
120+ # Use protocol from 'remote' line, then 'proto' line, then 'udp'.
121+ protocol=${remote[2]:- ${global_protocol:- udp} }
122+
123+ ip_regex=' ^(([1-9]?[0-9]|1[0-9][0-9]|2([0-4][0-9]|5[0-5]))\.){3}([1-9]?[0-9]|1[0-9][0-9]|2([0-4][0-9]|5[0-5]))$'
124+ if [[ " $address " =~ $ip_regex ]]; then
125+ echo " IP: $address PORT: $port PROTOCOL: $protocol "
126+ iptables -A OUTPUT -o eth0 -d " $address " -p " $protocol " --dport " $port " -j ACCEPT
127+ else
128+ for ip in $( dig -4 +short " $address " ) ; do
129+ echo " $address (IP: $ip PORT: $port PROTOCOL: $protocol )"
130+ iptables -A OUTPUT -o eth0 -d " $ip " -p " $protocol " --dport " $port " -j ACCEPT
131+ echo " $ip $address " >> /etc/hosts
132+ done
133+ fi
126134 fi
127135 done
128136
@@ -145,16 +153,16 @@ else
145153 echo -e " Routes created.\n"
146154fi
147155
148- if [ " $HTTP_PROXY " = " on" ]; then
149- if [ " $PROXY_USERNAME " ]; then
150- if [ " $PROXY_PASSWORD " ]; then
156+ if [[ " $HTTP_PROXY " == " on" ] ]; then
157+ if [[ -n " $PROXY_USERNAME " ] ]; then
158+ if [[ -n " $PROXY_PASSWORD " ] ]; then
151159 echo " Configuring HTTP proxy authentication."
152160 echo -e " \nBasicAuth $PROXY_USERNAME $PROXY_PASSWORD " >> /data/tinyproxy.conf
153161 else
154162 echo " WARNING: Proxy username supplied without password. Starting HTTP proxy without credentials."
155163 fi
156- elif [ -f " /run/secrets/$PROXY_USERNAME_SECRET " ]; then
157- if [ -f " /run/secrets/$PROXY_PASSWORD_SECRET " ]; then
164+ elif [[ -f " /run/secrets/$PROXY_USERNAME_SECRET " ] ]; then
165+ if [[ -f " /run/secrets/$PROXY_PASSWORD_SECRET " ] ]; then
158166 echo " Configuring proxy authentication."
159167 echo -e " \nBasicAuth $( cat /run/secrets/$PROXY_USERNAME_SECRET ) $( cat /run/secrets/$PROXY_PASSWORD_SECRET ) " >> /data/tinyproxy.conf
160168 else
@@ -164,21 +172,21 @@ if [ "$HTTP_PROXY" = "on" ]; then
164172 /data/scripts/tinyproxy_wrapper.sh &
165173fi
166174
167- if [ " $SOCKS_PROXY " = " on" ]; then
168- if [ " $LISTEN_ON " ]; then
175+ if [[ " $SOCKS_PROXY " == " on" ] ]; then
176+ if [[ -n " $LISTEN_ON " ] ]; then
169177 sed -i " s/internal: eth0/internal: $LISTEN_ON /" /data/sockd.conf
170178 fi
171- if [ " $PROXY_USERNAME " ]; then
172- if [ " $PROXY_PASSWORD " ]; then
179+ if [[ -n " $PROXY_USERNAME " ] ]; then
180+ if [[ -n " $PROXY_PASSWORD " ] ]; then
173181 echo " Configuring SOCKS proxy authentication."
174182 adduser -S -D -g " $PROXY_USERNAME " -H -h /dev/null " $PROXY_USERNAME "
175183 echo " $PROXY_USERNAME :$PROXY_PASSWORD " | chpasswd 2> /dev/null
176184 sed -i ' s/socksmethod: none/socksmethod: username/' /data/sockd.conf
177185 else
178186 echo " WARNING: Proxy username supplied without password. Starting SOCKS proxy without credentials."
179187 fi
180- elif [ -f " /run/secrets/$PROXY_USERNAME_SECRET " ]; then
181- if [ -f " /run/secrets/$PROXY_PASSWORD_SECRET " ]; then
188+ elif [[ -f " /run/secrets/$PROXY_USERNAME_SECRET " ] ]; then
189+ if [[ -f " /run/secrets/$PROXY_PASSWORD_SECRET " ] ]; then
182190 echo " Configuring proxy authentication."
183191 adduser -S -D -g " $( cat /run/secrets/$PROXY_USERNAME_SECRET ) " -H -h /dev/null " $( cat /run/secrets/$PROXY_USERNAME_SECRET ) "
184192 echo " $( cat /run/secrets/$PROXY_USERNAME_SECRET ) :$( cat /run/secrets/$PROXY_PASSWORD_SECRET ) " | chpasswd 2> /dev/null
@@ -201,8 +209,8 @@ openvpn_args=(
201209 " --verb" " $vpn_log_level "
202210)
203211
204- if [ " $OPENVPN_AUTH_SECRET " ]; then
205- if [ -f " /run/secrets/$OPENVPN_AUTH_SECRET " ]; then
212+ if [[ -n " $OPENVPN_AUTH_SECRET " ] ]; then
213+ if [[ -f " /run/secrets/$OPENVPN_AUTH_SECRET " ] ]; then
206214 echo " Configuring OpenVPN authentication."
207215 openvpn_args+=(" --auth-user-pass" " /run/secrets/$OPENVPN_AUTH_SECRET " )
208216 else
0 commit comments