jabberwock 0 Posted ... (edited) The following script took hours of trial and error due to having to "fly blind". This script is to be executed by the pi user, which must be set to auto-login. This script will wait for the designated interface to 1) Be up and 2) Match an expected IP address before attempting to launch AirVPN. I needed a way to launch AirVPN when and only when the above criteria is met. My scenario is that I want my Pi 4b to only connect to AirVPN when the GSB interface (usb0) is up and has its DHCP-assigned IP from the GSM stick's router. The GSM stick itself has port forwarding disabled in the firmware. AT&T does not allow port forwarding through these devices either. I needed AirVPN for port forwarding, so I could reach this solar-powered pi from any network in the world. Prerequisites: You must have tmux installed, or please modify the script to launch things in the background as you like. Place this script where you please. Name it "airvpn.sh" and make sure to chmod +x airvpn.sh to make it executable. Then in your .bashrc, zshrc, or whichever script will launch during auto-login - place: sudo ./airvpn.sh Here is the script: #!/bin/bash # Helper to start up AirVPN from auto-login # Author's scenario that inspired this script: # I have a raspberry pi with a GSM USB stick. No other interface can be used. # The firmware on the GSM does not allow port forwarding. # I need to be able to reach my pi over SSH after it connects to the mobile broadband network. # AirVPN was the way to go as it allows port forwarding. # The kludgy reverse tunnel back into a VPC was very slow and also a greater security risk as # it exposes the VPC as well as the Pi should either be compromised. function start_airvpn() { # set this to the interface you want to be available before connecting to AirVPN local interface="usb0" # first 3 octets you expect the interface to have as IPv4 address: local first_three="192.168.0" # Change these if you must local bluetit_lock_file="/etc/airvpn/bluetit.lock" # location of bluetit.lock local tmux_session_name="airvpn" # target name for tmux session local seconds_to_abort=10 # number of seconds a user has to ctrl+c to stop the script local log_prefix="[AirVPN-Extension]" # prefix for dmesg log entries # -------------------------------------------------------------- # !!! Only edit below if you are confident in your abilties. !!! # -------------------------------------------------------------- #local PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin:$PATH #source /etc/profile local force_restart=0 function dmsg() { # log to dmesg (kernel messge buffer) echo "$log_prefix $1" | tee /dev/kmsg return 0 } case $1 in -f) force_restart=1 ;; *) force_restart=0 ;; esac if [ $UID -ne 0 ]; then echo "Please run this script as root or via \`sudo\`" exit 1 fi if [ $force_restart -eq 0 ]; then if [ -f $bluetit_lock_file ]; then echo "$log_prefix: Found bluetit lock file. Exiting. Use -f to override." exit 0 fi fi function wait_seconds() { # pass seconds integer to this function; default $seconds_to_abort if [ "$1" ]; then local re='^[0-9]+$' if ! [[ $1 =~ $re ]] ; then echo "$log_prefix: non-number passed to wait_seconds()" exit 1 fi local wait=$1 else local wait=$seconds_to_abort fi local count=1 while :; do sleep 1 (( count+=1 )) if [ "$count" -eq $wait ]; then break fi done } # ---------------------------------------- # Wait for GSM and then connect to AirVPN. # ---------------------------------------- local sys_class_path="/sys/class/net/$interface" echo "$log_prefix Ready to configure AirVPN connection. Interrupt within $seconds_to_abort second(s) to cancel." wait_seconds $seconds_to_abort dmsg "Stopping bluetit service until interface $interface comes up." service bluetit stop dmsg "Waiting 5 seconds." sleep 5 dmsg "Waiting for $sys_class_path" while :; do if [ -d $sys_class_path ]; then dmsg "$interface appeared." if [ "$(cat $sys_class_path/operstate)" == "up" ]; then dmsg "$interface is up." dmsg "Waiting for an IP address that matches $first_three (Cycling every 2 seconds)" while :; do current_first_three=$(ip a s $interface | awk '/inet.*brd/ {print $2}' | cut -d'.' -f1-3) if [ "$current_first_three" == $first_three ]; then dmsg "Found $current_first_three on $interface" break fi sleep 2 done dmsg "Restarting bluetit service." while :; do if service bluetit start; then tmux kill-session -t $tmux_session_name &> /dev/null dmsg "Connecting to AirVPN via Goldcrest." tmux new -d -s $tmux_session_name "goldcrest --air-connect" # ensure the tmux session persists even if its command fails, so we can see: tmux set-option -t $tmux_session_name remain-on-exit on dmsg "tmux session '$tmux_session_name' is available for interacting." dmsg "To interact, type \`sudo tmux attach -t $tmux_session_name\`" exit 0 else dmsg "bluetit returned $?. Trying again in 5 seconds..." sleep 5 continue fi done fi fi dmsg "Waiting 5 seconds." sleep 5 done } start_airvpn "$1" Edited ... by wabbajack Made suggestions from shellcheck linter. Updated header comments. Implemented edits suggested by staff. Quote Share this post Link to post
OpenSourcerer 1441 Posted ... Thank you for your submission. Unsure I can test it myself in the near future, but anyways, if it works, cool One remark: 18 hours ago, wabbajack said: local ip_first_3=$(ifconfig usb0 | grep "inet " | tr -s ' ' | cut -d' ' -f3 | cut -d'.' -f1-3) Since net-tools has been obsolete for years, consider using iproute2 here: local ip_first_three=$(ip a s $interface | awk '/inet.*brd/ {print $2}' | cut -d'.' -f1-3) Quote Hide OpenSourcerer's signature Hide all signatures 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