Jump to content
Not connected, Your IP: 3.145.100.144

Recommended Posts

Posted ... (edited)

Hello,

after I posted some suggestions for Eddie's CLI version in this thread and received some helpful information there, I set out to write my own little interface in bash for it to implement the suggestions. Being no programmer it turned out to be quite a project for me, and I would like to share it here in case anybody else prefers to run Eddie in the terminal rather than as a full GUI application. This script still uses Eddie itself, it's just a wrapper to make it as easy to use in the command line as it is as a desktop application. Screenshots are attached.

 

Some features and advantages:

  • uses less resources (top shows usually 0.3% CPU usage compared to 4-5% for the desktop version)
  • can be exited without disconnecting
  • interactive, sortable server list
  • option to connect to another VPN with openconnect (since I need to do that from time to time, but it should be easy to add other connection methods as well)
  • option to lock down the system's network traffic by default, so even without Eddie running with its own network lock there will be no leaks

What to watch out for:

  • The default network lock works with direct rules in firewalld because I'm using Fedora. It should be easy to change it to use iptables directly on other distributions since firewalld's direct rules are just a way to directly manipulate iptables. Once activated, the lock will stay in place until manually deactivated (also surviving reboots), so no internet connection will be possible unless connected to AirVPN or other whitelisted VPNs. AirVPN's network lock overwrites the default network lock, so there will be no interference.
  • Check your /etc/resolv.conf file while not running Eddie (because Eddie's network lock replaces that file temporarily) to make sure your router is not set as a nameserver (so no 192.168... address). Some routers will push themselves on that list by DHCP whenever you connect to their network. Since communication with the router is allowed in the lock rules, DNS requests will be handled by the router and sent to whatever DNS server is configured there even when network traffic should be blocked. There are ways to prevent that file from being changed by DHCP, best configure network manager for that if you use it.
  • To connect to other VPNs, their IPs must be whitelisted and DNS requests for their domains must be allowed in the default network lock rules. The rules for airvpn.org can be copied and adjusted.
  • I haven't yet included an option to pass command line arguments to Eddie. So if you need to set more advanced options like black-/whitelists, use of certain protocols etc., you need to set them manually in the connect_server function. All the possible options can be found in 'man eddie-ui'.
  • You need to insert your own API key in line 5. It can be found in your account under Client Area -> API. Without this, connections will still work, but user info and connection status in the main window will not be properly updated.
  • I tried to only use basic system tools. The script relies mostly on dialog, awk and curl (and firewalld as described and openconnect if needed), so it should work on most systems, but I'm not sure.
  • And, lastly, VERY IMPORTANT: As I said, I'm no programmer and new to this, so even though I tried my best to make this script secure and error free, there might very well be some bad practice, never-ever-do-this mistakes or other hiccups in there. It works well for me, but better check it yourself.

Feel free to use this as you wish, I hope someone can benefit from this. I'm happy about any improvements and corrections and will update this if I find the time.

UPDATE: A new version which uses Hummingbird and has been improved in many aspects (including automatic connection at boot) can be found here.

 

#!/bin/bash
# an interactive shell script to control the command line version of the AirVPN Eddie client and openconnect more comfortably

PROFILE_PATH="$HOME/.airvpn/default.xml"
API_KEY="<your api key>"

DIALOG_OK=0
DIALOG_CANCEL=1
DIALOG_EXTRA=3
DIALOG_ESC=255
HEIGHT=0
WIDTH=0
BACKTITLE="VPN Control"
FORMAT="text"
URL="https://airvpn.org/api/"
PID=$$

function check_sudo {
# check if user has sudo privileges
sudo -vn &> /dev/null
# gain sudo privileges for commands that need it (better than running everything with sudo)
if [ $? = "1" ]
then
	unset EXIT_STATUS_SUDO
	PASS_PROMPT="Establishing VPN connections and changing network traffic rules requires root privileges. Please enter your password:"
	until [ "$EXIT_STATUS_SUDO" = "0" ]
	do
		dialog \
		--backtitle "$BACKTITLE" \
		--title "Password Needed" \
		--output-fd 1 \
		--insecure \
		--passwordbox "$PASS_PROMPT" 11 35 | xargs printf '%s\n' | sudo -Svp '' &> /dev/null
		EXIT_STATUS_PIPE=( "${PIPESTATUS[@]}" )
		EXIT_STATUS_DIALOG="${EXIT_STATUS_PIPE[0]}"
		EXIT_STATUS_SUDO="${EXIT_STATUS_PIPE[2]}"
		EXIT_SUDO_TEST="${EXIT_STATUS_PIPE[2]}"
		PASS_PROMPT="The password you entered is incorrect. Please try again:"
		case $EXIT_STATUS_DIALOG in
			$DIALOG_CANCEL|$DIALOG_ESC)
				return 1
				;;
		esac
	done
	# keep sudo permission until script exits or permissions are revoked (e.g. when computer goes to sleep)
	while [ "$EXIT_SUDO_TEST" = "0" ]; do sudo -vn; EXIT_SUDO_TEST=$?; sleep 60; kill -0 "$PID" || exit; done &> /dev/null &
fi

return 0
}

function get_list {
	SERVICE_NAME="status"
	ARGS="{
	\"format\":\"$FORMAT\",
	\"service\":\"$SERVICE_NAME\"
	}"
	timeout --signal=SIGINT 10 curl -s -d "$ARGS" -X POST "$URL" > "/tmp/.eddie_server_list.txt"
}

function sort_list {
	# pipe server status list to awk, filter out unnecessary stuff,
	# combine lines that relate to same server into single lines which are saved as array,
	# loop through array to format info,
	# print array and sort according to options,
	# add numbers to list for menu
	LIST=$(awk -F '[.]' \
		'BEGIN{OFS=";"} \
		/^servers/ && !/ip_/ && !/country_code/ {c=$2; \
		if (c in servers) servers[c]=servers[c] OFS $3; \
		else servers[c]=$3; \
		for (k in servers) gsub(/;bw=/, "  :", servers[k]); \
		for (k in servers) gsub(/;bw_max=/, "/", servers[k]); \
		for (k in servers) gsub(/;currentload=/, "  :", servers[k]); \
		for (k in servers) gsub(/;health=/, "%:", servers[k]); \
		for (k in servers) gsub(/;.*=/, ":", servers[k]); \
		for (k in servers) gsub(/^.*=/, "", servers[k])} \
		END{ \
		for (c in servers) print servers[c]}' "/tmp/.eddie_server_list.txt" | sort -t ":" $1 | awk -F '[;]' 'BEGIN{OFS=":"} {print v++";"$1}')
}

function get_userinfo {
	SERVICE_NAME="userinfo"
	ARGS="{
	\"format\":\"$FORMAT\",
	\"service\":\"$SERVICE_NAME\",
	\"key\":\"$API_KEY\"
	}"
	# filter specific lines, save values to variables after protecting whitespace
	read U_LOGIN U_EXP U_CONNECTED U_DEVICE U_SERVER_NAME U_SERVER_COUNTRY U_SERVER_LOCATION U_TIME <<< $( \
	timeout --signal=SIGINT 10 curl -s -d "$ARGS" -X POST "$URL" | \
	awk -F '[=]' \
		'BEGIN{ORS=";"} \
		/^user.login|^user.expiration_days|^user.connected|^sessions.*device_name|^connection.server_name|^connection.server_country=|^connection.server_location|^connection.connected_since_date/ \
		{print $2}' | \
	sed 's/\ /\\\ /g' | sed 's/;/\ /g' \
	)
	if [ "$U_CONNECTED" = "1" ]
	then
		U_CONNECTED="connected"
		U_SERVER_FULL="$U_SERVER_NAME ($U_SERVER_LOCATION, $U_SERVER_COUNTRY)"
		U_TIME=$(date -d "$U_TIME UTC" +"%m/%d/%Y %H:%M:%S")
	else
		U_CONNECTED="not connected"
		U_SERVER_FULL="--"
		U_TIME="--"
	fi
}

function connect_server {
	if [ "$KILLED" = "true" ]
	then
		# create pipes to process status of client
		if [ ! -p "/tmp/.eddie_fifo1" ]
		then
			mkfifo "/tmp/.eddie_fifo1"
		fi
		if [ ! -p "/tmp/.eddie_fifo2" ]
		then
			mkfifo "/tmp/.eddie_fifo2"
		fi
		# run eddie in background and detached from current window, pipe output to named pipe
		(sudo eddie-ui --cli --netlock --connect --server="$1" --profile="$PROFILE_PATH" | tee "/tmp/.eddie_fifo2" &> "/tmp/.eddie_fifo1" &) 
		cat "/tmp/.eddie_fifo2" | dialog --backtitle "$BACKTITLE" --title "Connecting to AirVPN..." --progressbox 20 80 &
		timeout --signal=SIGINT 60 grep -q -m 1 "Initialization Sequence Completed" "/tmp/.eddie_fifo1"
		INIT_EXIT=$?
		pkill -f cat.*eddie_fifo2
		if [ $INIT_EXIT = "0" ]
		then
			get_userinfo
		else
			U_CONNECTED="error during connection attempt"
			U_SERVER_FULL="--"
			U_TIME="--"
		fi
	else
		U_CONNECTED="error during disconnection"
		U_SERVER_FULL="--"
		U_TIME="--"
	fi
}

function disconnect_server {
	# check for running instance of eddie
	pgrep -f mono.*eddie-ui &> /dev/null
	if [ $? = 0 ]
	then
		# kill process and wait for confirmation from process output
		if [ -p "/tmp/.eddie_fifo1" -a -p "/tmp/.eddie_fifo2" ]
		then
			sudo pkill -2 -f mono.*eddie-ui &
			cat "/tmp/.eddie_fifo1" | dialog --backtitle "$BACKTITLE" --title "Disconnecting AirVPN..." --progressbox 20 80 &
			timeout --signal=SIGINT 10 grep -q -m 1 "Shutdown complete" "/tmp/.eddie_fifo2"
		else
			# in case connection was started without this script
			sudo pkill -2 -f mono.*eddie-ui
			sleep 5
		fi
		# give some time to completely close process, without sleep it's too early for new connection
		sleep 3
		pgrep -f mono.*eddie-ui &> /dev/null
		if [ $? = 1 ]
		then
			KILLED1="true"
		else
			KILLED1="false"
		fi
	else
		KILLED1="true"
	fi

	# check for running instance of openconnect
	pgrep -f "openconnect.*--" &> /dev/null
	if [ $? = 0 ]
	then
		sudo pkill -2 -f "openconnect.*--"
		sleep 1
		pgrep -f "openconnect.*--" &> /dev/null
		if [ $? = 1 ]
		then
			KILLED2="true"
			# somehow openconnect doesn't receive SIGINT and shuts down improperly,
			# so vpnc can't restore resolv.conf by itself
			sudo cp "/var/run/vpnc/resolv.conf-backup" "/etc/resolv.conf"
		else
			KILLED2="false"
		fi
	else
		KILLED2="true"
	fi

	if [ "$KILLED1" = "true" -a "$KILLED2" = "true" ]
	then
		KILLED="true"
	else
		KILLED="false"
	fi
}

function define_lock {
	if [ "$1" = "activate" ]
	then
		GAUGE_TITLE="Activating Network Lock"
		RULE_ACTION="add-rule"
	elif [ "$1" = "deactivate" ]
	then
		GAUGE_TITLE="Deactivating Network Lock"
		RULE_ACTION="remove-rule"
	else
		return 1
	fi

	GAUGE_BODY="$1"
	IPRULES=(\
	#allow loopback
	"sudo firewall-cmd --direct --permanent --$RULE_ACTION ipv4 filter INPUT 0 -i lo -j ACCEPT" \
	"sudo firewall-cmd --direct --permanent --$RULE_ACTION ipv4 filter OUTPUT 0 -o lo -j ACCEPT" \
		
		#allow lan (out) and broadcasting/dhcp
	"sudo firewall-cmd --direct --permanent --$RULE_ACTION ipv4 filter OUTPUT 0 -s 192.168.0.0/16 -d 192.168.0.0/16 -j ACCEPT" \
	"sudo firewall-cmd --direct --permanent --$RULE_ACTION ipv4 filter INPUT 0 -s 255.255.255.255 -j ACCEPT" \
	"sudo firewall-cmd --direct --permanent --$RULE_ACTION ipv4 filter OUTPUT 0 -d 255.255.255.255 -j ACCEPT" \
		
		# allow tun device to communicate (so any VPN connection should be possible, also without Air, but respective DNS requests must be allowed)
	"sudo firewall-cmd --direct --permanent --$RULE_ACTION ipv4 filter FORWARD 0 -o tun+ -j ACCEPT" \
	"sudo firewall-cmd --direct --permanent --$RULE_ACTION ipv4 filter FORWARD 0 -i tun+ -j ACCEPT" \
	"sudo firewall-cmd --direct --permanent --$RULE_ACTION ipv4 filter OUTPUT 998 -o tun+ -j ACCEPT" \
		
		# optional masquerade rule (NAT/ports)
	"sudo firewall-cmd --direct --permanent --$RULE_ACTION ipv4 nat POSTROUTING 0 -o tun+ -j MASQUERADE" \

	# allow ipv4 only to airvpn.org for status update
	#	allow DNS query to resolve hostname (hex string reads "06 airvpn 03 org" - numbers are counting bits),
	#	restrict packet length to length of this specific request package (might change?) to avoid hijacking
	#	of query (very unlikely I guess, but who cares if we're already being paranoid for the fun of it),
	#	whitelist destination IP for TCP handshake
	"sudo firewall-cmd --direct --permanent --$RULE_ACTION ipv4 filter OUTPUT 1 -p udp --dport 53 -m string --hex-string '|06 61697276706e 03 6f7267|' --algo bm -m length --length 0:126 -m recent --set -j ACCEPT" \
	"sudo firewall-cmd --direct --permanent --$RULE_ACTION ipv4 filter OUTPUT 1 -p tcp --dport 53 -m string --hex-string '|06 61697276706e 03 6f7267|' --algo bm -m length --length 0:126 -m recent --set -j ACCEPT" \
	#	add rules for other domains you wish to allow DNS requests to here (packet length can be determined with e.g. wireshark) and adjust array index
	#
	#	allow SYN request to whitelisted IP to initiate handshake, remove IP from whitelist
	"sudo firewall-cmd --direct --permanent --$RULE_ACTION ipv4 filter OUTPUT 1 -p tcp --syn --dport 53 -m recent --remove -j ACCEPT" \
	#	allow outgoing connection to Air's IP
	"sudo firewall-cmd --direct --permanent --$RULE_ACTION ipv4 filter OUTPUT 1 -d 5.196.64.52 -j ACCEPT" \
	#	add rules for other IPs you wish to allow connections to here
	#
	#	allow communication
	"sudo firewall-cmd --direct --permanent --$RULE_ACTION ipv4 filter INPUT 1 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT" \
	
	# drop outgoing ipv4 (if not specifically allowed by other rules)
	"sudo firewall-cmd --direct --permanent --$RULE_ACTION ipv4 filter OUTPUT 999 -j DROP" \
	# block incoming ipv4
	"sudo firewall-cmd --direct --permanent --$RULE_ACTION ipv4 filter INPUT 999 -j DROP" \
	
	# drop all ipv6
	"sudo firewall-cmd --direct --permanent --$RULE_ACTION ipv6 filter OUTPUT 0 -j DROP" \
	"sudo firewall-cmd --direct --permanent --$RULE_ACTION ipv6 filter INPUT 0 -j DROP" \

	# reload and restart firewalld to activate permanent rule changes
	"sudo firewall-cmd --reload" \
	"sudo systemctl restart firewalld"\
	)

	toggle_lock
}

function toggle_lock {
	PERCENTAGE_STEP=$(awk -v rules="${#IPRULES[@]}" 'BEGIN {print 100/rules}')
	PERCENTAGE=0
	COUNTER=0
	# initial window
	dialog --backtitle "$BACKTITLE" \
		--title "$GAUGE_TITLE" \
		--mixedgauge "Applying iptable rules to $GAUGE_BODY the default network lock..." 35 80 "$(awk -v per="$PERCENTAGE" 'BEGIN {printf "%.0f", per}')" \
		"Allow Loopback IN" "${RESULT[0]}" \
		"Allow Loopback OUT" "${RESULT[1]}" \
		"Allow LAN OUT" "${RESULT[2]}" \
		"Allow DHCP IN" "${RESULT[3]}" \
		"Allow DHCP OUT" "${RESULT[4]}" \
		"Allow tun out FORWARD" "${RESULT[5]}" \
		"Allow tun in FORWARD" "${RESULT[6]}" \
		"Allow tun out OUT" "${RESULT[7]}" \
		"tun masquerade" "${RESULT[8]}" \
		"Allow DNS via UDP to airvpn.org" "${RESULT[9]}" \
		"Allow DNS via TCP to airvpn.org" "${RESULT[10]}" \
		"Allow connection initiation" "${RESULT[11]}" \
		"Allow traffic to airvpn.org" "${RESULT[12]}" \
		"Allow established connections" "${RESULT[13]}" \
		"Block IPv4 OUT" "${RESULT[14]}" \
		"Block IPv4 IN" "${RESULT[15]}" \
		"Block IPv6 OUT" "${RESULT[16]}" \
		"Block IPv6 IN" "${RESULT[17]}" \
		"activate changes" "${RESULT[18]}" \
		"restart firewalld" "${RESULT[19]}"
	
	for i in "${IPRULES[@]}"
	do
		RESULT["$COUNTER"]=$(eval $i)
		(( COUNTER++ ))
		PERCENTAGE=$(awk -v per="$PERCENTAGE" -v per_step="$PERCENTAGE_STEP" 'BEGIN {print per+per_step}')
		# progress window
		dialog --backtitle "$BACKTITLE" \
			--title "$GAUGE_TITLE" \
			--mixedgauge "Applying iptable rules to $GAUGE_BODY the default network lock..." 35 80 "$(awk -v per="$PERCENTAGE" 'BEGIN {printf "%.0f", per}')" \
			"Allow Loopback IN" "${RESULT[0]}" \
			"Allow Loopback OUT" "${RESULT[1]}" \
			"Allow LAN OUT" "${RESULT[2]}" \
			"Allow DHCP IN" "${RESULT[3]}" \
			"Allow DHCP OUT" "${RESULT[4]}" \
			"Allow tun out FORWARD" "${RESULT[5]}" \
			"Allow tun in FORWARD" "${RESULT[6]}" \
			"Allow tun out OUT" "${RESULT[7]}" \
			"tun masquerade" "${RESULT[8]}" \
			"Allow DNS via UDP to airvpn.org" "${RESULT[9]}" \
			"Allow DNS via TCP to airvpn.org" "${RESULT[10]}" \
			"Allow connection initiation" "${RESULT[11]}" \
			"Allow traffic to airvpn.org" "${RESULT[12]}" \
			"Allow established connections" "${RESULT[13]}" \
			"Block IPv4 OUT" "${RESULT[14]}" \
			"Block IPv4 IN" "${RESULT[15]}" \
			"Block IPv6 OUT" "${RESULT[16]}" \
			"Block IPv6 IN" "${RESULT[17]}" \
			"activate changes" "${RESULT[18]}" \
			"restart firewalld" "${RESULT[19]}"
	done

	# final window to show results
	dialog --backtitle "$BACKTITLE" \
		--title "$GAUGE_TITLE" \
		--mixedgauge "Applying iptable rules to $GAUGE_BODY the default network lock..." 35 80 "$(awk -v per="$PERCENTAGE" 'BEGIN {printf "%.0f", per}')" \
		"Allow Loopback IN" "${RESULT[0]}" \
		"Allow Loopback OUT" "${RESULT[1]}" \
		"Allow LAN OUT" "${RESULT[2]}" \
		"Allow DHCP IN" "${RESULT[3]}" \
		"Allow DHCP OUT" "${RESULT[4]}" \
		"Allow tun out FORWARD" "${RESULT[5]}" \
		"Allow tun in FORWARD" "${RESULT[6]}" \
		"Allow tun out OUT" "${RESULT[7]}" \
		"tun masquerade" "${RESULT[8]}" \
		"Allow DNS via UDP to airvpn.org" "${RESULT[9]}" \
		"Allow DNS via TCP to airvpn.org" "${RESULT[10]}" \
		"Allow connection initiation" "${RESULT[11]}" \
		"Allow traffic to airvpn.org" "${RESULT[12]}" \
		"Allow established connections" "${RESULT[13]}" \
		"Block IPv4 OUT" "${RESULT[14]}" \
		"Block IPv4 IN" "${RESULT[15]}" \
		"Block IPv6 OUT" "${RESULT[16]}" \
		"Block IPv6 IN" "${RESULT[17]}" \
		"activate changes" "${RESULT[18]}" \
		"restart firewalld" "${RESULT[19]}"
	sleep 2
	unset RESULT

	check_lock
}

function check_lock {
	# check for success (not really though, needs improvement)
	LOCK_RULES=$( sudo firewall-cmd --direct --permanent --get-all-rules | wc -l )
	if [ "$LOCK_RULES" -gt 16 ]
	then
		LOCK_ACTIVE="active"
	else
		LOCK_ACTIVE="inactive"
	fi
}

function yesno {
dialog \
	--backtitle "$BACKTITLE" \
	--title "$1" \
	--clear \
	--yesno "$2" \
	$HEIGHT $WIDTH
EXIT_STATUS=$?
}

check_sudo
if [ $? = "1" ]
then
	clear
	exit
fi

get_userinfo
# if currently connected by openconnect, set status to unknown (connection could have been established outside of this script)
pgrep openconnect &> /dev/null
if [ $? = 0 ]
then
	U_CONNECTED="connected (openconnect)"
	U_SERVER_FULL="unknown"
	U_TIME="unknown"
fi

check_lock

while true; do
	exec 3>&1
	selection=$(dialog \
		--cr-wrap \
		--backtitle "$BACKTITLE" \
		--title "Main Menu" \
		--clear \
		--cancel-label "Quit" \
		--menu "This is a control script for VPN connections, primarily for Eddie, the AirVPN client.\nThis script can be exited and re-entered without affecting a running connection.\n\nUser: $U_LOGIN\nDays Until Expiration: $U_EXP\n\nDefault Network Lock: $LOCK_ACTIVE\n\nStatus: $U_CONNECTED\nServer: $U_SERVER_FULL\nConnected Since: $U_TIME\n\nPlease select one of the following options:" $HEIGHT $WIDTH 6 \
		"0" "Connect to Recommended Server" \
		"1" "Connect to Specific Server" \
		"2" "Connect via openconnect" \
		"3" "Disconnect" \
		"4" "Refresh User Info" \
		"5" "Toggle Default Network Lock" \
		2>&1 1>&3)
	EXIT_STATUS=$?
	exec 3>&-
	case $EXIT_STATUS in
		$DIALOG_CANCEL|$DIALOG_ESC)
			yesno "Quit" "Exit Script?"
			case $EXIT_STATUS in
				$DIALOG_CANCEL|$DIALOG_ESC)
					;;
				$DIALOG_OK)
					break
					;;
			esac
			;;
	esac
	case $selection in
		0 )
			check_sudo
			if [ $? = "0" ]
			then
				disconnect_server
				connect_server ""
			fi
			;;
		1 )
			while true; do
			exec 3>&1
			SERVER_SORT=$(dialog \
				--backtitle "$BACKTITLE" \
				--title "Sort Server List" \
				--no-collapse \
				--ok-label "sort ascending" \
				--extra-button \
				--extra-label "sort descending" \
				--menu "Please choose how you want to sort the server list." \
				14 0 7 \
				"1" "Name" \
				"2" "Country" \
				"3" "Location" \
				"4" "Continent" \
				"5" "Bandwidth" \
				"6" "Users" \
				"7" "Load" \
				2>&1 1>&3)
			EXIT_STATUS=$?
			exec 3>&-
			case $EXIT_STATUS in
				$DIALOG_CANCEL|$DIALOG_ESC)
					break
					;;
				$DIALOG_EXTRA)
					SERVER_SORT_OPTION="r"
					;;
				$DIALOG_OK)
					SERVER_SORT_OPTION=""
					;;
			esac
			if [ "$SERVER_SORT" = "5" -o "$SERVER_SORT" = "6" -o "$SERVER_SORT" = "7" ]
			then
				SERVER_NUM_OPTION="n"
			else
				SERVER_NUM_OPTION=""
			fi
			if [ ! -f "/tmp/.eddie_server_list.txt" ]
			then
				get_list
			fi
			while true
			do
				sort_list "-k$SERVER_SORT,$SERVER_SORT$SERVER_SORT_OPTION$SERVER_NUM_OPTION"
				IFS=$';\n'
				exec 3>&1
				SERVER_NMBR=$(dialog \
					--backtitle "$BACKTITLE" \
					--title "Server List" \
					--colors \
					--no-collapse \
					--extra-button \
					--extra-label "Refresh List" \
					--column-separator ":" \
					--menu "Choose a server from the list to connect to it. (Press ESC to go back.)\n\n\Zb #    Name           Country        Location                Continent Bandwidth Users Load Health\ZB" \
					40 102 31 $LIST 2>&1 1>&3)
				EXIT_STATUS=$?
				exec 3>&-
				IFS=$' \t\n'
				case $EXIT_STATUS in
					$DIALOG_CANCEL)
						break 2
						;;
					$DIALOG_ESC)
						break
						;;
					$DIALOG_EXTRA)
						get_list
						;;
					$DIALOG_OK)
						check_sudo
						if [ $? = "0" ]
						then
							SELECTED_SERVER=$(printf -- '%s\n' "${LIST[@]}" | grep "^$SERVER_NMBR;" | cut -d ";" -f 2 | cut -d ":" -f 1)
							disconnect_server
							connect_server "$SELECTED_SERVER"
							break 2
						fi
						;;
				esac
			done
			done
			;;
		2 )
			exec 3>&1
			# adjust field lengths if necessary
			CONNECT_INFO=$(dialog \
				--backtitle "$BACKTITLE" \
				--title "VPN via openconnect" \
				--insecure \
				--mixedform "Please provide your login credentials to connect to a VPN via openconnect:\n(Leave unneeded fields blank and type options as in command line, separated by space.)" $HEIGHT $WIDTH 6 \
				"Server:" 1 1 "" 1 21 25 0 0 \
				"Group:" 2 1 "" 2 21 25 0 0 \
				"User:" 3 1 "" 3 21 25 0 0 \
				"Password:" 4 1 "" 4 21 25 0 1 \
				"Additional Options:" 5 1 "" 5 21 25 0 0 \
				2>&1 1>&3)
			EXIT_STATUS=$?
			exec 3>&-
			case $EXIT_STATUS in
				$DIALOG_CANCEL|$DIALOG_ESC)
					;;
				$DIALOG_OK)
					check_sudo
					if [ $? = "0" ]
					then
						disconnect_server
						if [ "$KILLED" = "true" ]
						then
							if [ ! -p "/tmp/.eddie_fifo1" ]
							then
								mkfifo "/tmp/.eddie_fifo1"
							fi
							ALT_SERVER=$(echo -n "$CONNECT_INFO" | cut -d$'\n' -f 1)
							ALT_GROUP=$(echo -n "$CONNECT_INFO" | cut -d$'\n' -f 2)
							ALT_USER=$(echo -n "$CONNECT_INFO" | cut -d$'\n' -f 3)
							ALT_PASS=$(echo -n "$CONNECT_INFO" | cut -d$'\n' -f 4)
							ALT_OPTS=$(echo -n "$CONNECT_INFO" | cut -d$'\n' -f 5)
							echo "$ALT_PASS" | (sudo openconnect $ALT_OPTS --authgroup=$ALT_GROUP --user=$ALT_USER --passwd-on-stdin $ALT_SERVER &> "/tmp/.eddie_fifo1" &)
							timeout --signal=SIGINT 3 cat "/tmp/.eddie_fifo1" | dialog --backtitle "$BACKTITLE" --title "Connecting via openconnect..." --timeout 5 --programbox 20 80
							U_CONNECTED="connected"
							U_SERVER_FULL="$ALT_SERVER"
							U_TIME=$(date +"%m/%d/%Y %H:%M:%S")
						else
							U_CONNECTED="error during disconnection"
							U_SERVER_FULL="--"
							U_TIME="--"
						fi
					fi
					;;
			esac
			;;
		3 )
			check_sudo
			if [ $? = "0" ]
			then
				disconnect_server
				if [ "$KILLED" = "true" ]
				then
						get_userinfo
				else
						U_CONNECTED="error during disconnection"
						U_SERVER_FULL="--"
						U_TIME="--"
				fi
				if [ -p "/tmp/.eddie_fifo1" ]
				then
					rm "/tmp/.eddie_fifo1"
				fi
				if [ -p "/tmp/.eddie_fifo2" ]
				then
					rm "/tmp/.eddie_fifo2"
				fi
			fi
			;;
		4 )
			get_userinfo
			;;
		5 )
			pgrep -f mono.*eddie-ui &> /dev/null
			if [ $? = 0 ]
			then
				dialog --backtitle "$BACKTITLE" --title "Toggle Network Lock" --timeout 3 --msgbox "You need to be disconnected to change network traffic rules." 10 35
			else
				if [ "$LOCK_ACTIVE" = "inactive" ]
				then
					yesno "Toggle Network Lock" "Are you sure you want to activate the default network lock and block all connections while not connected to (any) VPN?"
					case $EXIT_STATUS in
						$DIALOG_CANCEL|$DIALOG_ESC)
							;;
						$DIALOG_OK)
							check_sudo
							if [ $? = "0" ]
							then
								define_lock "activate"
							fi
							;;
					esac
				else
					yesno "Toggle Network Lock" "Are you sure you want to deactivate the default network lock and allow all connections, even when not connected to a VPN?"
					case $EXIT_STATUS in
						$DIALOG_CANCEL|$DIALOG_ESC)
							;;
						$DIALOG_OK)
							check_sudo
							if [ $? = "0" ]
							then
								define_lock "deactivate"
							fi
							;;
					esac
				fi
			fi
			;;
	esac
done

clear

vpn_main.png

vpn_list1.png

vpn_list2.png

vpn_opencon.png

vpn_lock.png

vpn_disconnect.png

Edited ... by nwlyoc
new version available

Share this post


Link to post

This is fantastic! Holy hell, the community really is awesome around here

 

The default network lock works with direct rules in firewalld because I'm using Fedora. It should be easy to change it to use iptables directly on other distributions since firewalld's direct rules are just a way to directly manipulate iptables.

 

I'm up for some testing on Debian and I'll let you know if there's something that needs to be done to make it work there, if at all.


NOT AN AIRVPN TEAM MEMBER. USE TICKETS FOR PROFESSIONAL SUPPORT.

LZ1's New User Guide to AirVPN « Plenty of stuff for advanced users, too!

Want to contact me directly? All relevant methods are on my About me page.

Share this post


Link to post

Thank you! I believe the syntax for iptable rules is identical, it's just the first half of the commands that needs to be exchanged. Let me know if it works!

Share this post


Link to post

Is this ready for use on Ubuntu/Debian distributions? I've been clamoring to build a low power embedded Deluge box with VPN only internet access. I have no need for a window manager so I am all about the command line. 

Share this post


Link to post

Please try! I don't see why it shouldn't work on Debian based distros since there is no distro specific stuff in there except the default network lock which relies on firewalld, but as discussed above, it should only be a small adjustment to change it to iptables if you care about that feature. I have a lot of work at the moment, so I can't test it myself or make further improvements, but I've fixed some minor stuff last week and it's still working very well for me, using it all day. Just make sure you have the tools installed that are listed above (most likely installed by default) and you should be fine. If you choose to try it out, let me know in case there are any problems!

Share this post


Link to post

I recently upgraded from build 1853 to 1879, and just noticed that the Tools menu is no longer displayed. I discovered that when I needed to access the scheduler.

Any ideas? Im going to try dropping back to the previous version...

Share this post


Link to post

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Security Check
    Play CAPTCHA Audio
    Refresh Image

×
×
  • Create New...