#!/usr/bin/env bash

# Usage:       ./simple-ssh-reverse-tunnel
#                or
#              bash simple-ssh-reverse-tunnel
# Description: Open or close a ssh reverse tunnel based on a web page.
# Author:      Patrick Neumann (patrick@neumannsland.de)
# Platform:    Raspbian GNU/Linux 9.x
# Version:     1.02
# Date:        2019-04-22 (first release: 2013-03-06)
# Link:        (work in progress)
# License:     GPL3
# Warranty:    This program is distributed WITHOUT ANY WARRANTY

#=== CONFIGURATION (binaries) ==================================================
# Relative paths are more portable but less secure.
# Absolute paths are more secure but less portable.
readonly WHICH_BIN="which"                                              # common
readonly PRINTF_BIN="$( ${WHICH_BIN} "printf" )"                        # common
readonly OPENSSL_BIN="$( ${WHICH_BIN} "openssl" )"                      # common
readonly CUT_BIN="$( ${WHICH_BIN} "cut" )"                              # common
readonly WGET_BIN="$( ${WHICH_BIN} "wget" )"                            # common
readonly SSH_BIN="$( ${WHICH_BIN} "ssh" )"                              # common
readonly PGREP_BIN="$( ${WHICH_BIN} "pgrep" )"                          # common
readonly LOGGER_BIN="$( ${WHICH_BIN} "logger" )"                        # common
readonly PKILL_BIN="$( ${WHICH_BIN} "pkill" )"                          # common
readonly SLEEP_BIN="$( ${WHICH_BIN} "sleep" )"                          # common

#=== FUNCTION ==================================================================
# NAME: transform
# DESCRIPTION: transform file name or commands into sha512.
# PARAMETER 1: command (string)
#===============================================================================
transform () {
  ${PRINTF_BIN} "${1}" | ${OPENSSL_BIN} dgst -sha512 | ${CUT_BIN} -d " " -f 2
}

#=== CONFIGURATION (user) ======================================================
SERVER="example.com"
DIR="cnc/"
FILENAME="$( transform "any-string" )"
PORT="22222"

#=== CONFIGURATION (dynamic) ===================================================
CONTENT="$( ${WGET_BIN} -q \
                        "https://${SERVER}/${DIR}/${FILENAME}.html" \
                        -O- )"
COMMAND="${SSH_BIN} -nNTXYR :${PORT}:localhost:22 ${SERVER}"

#-------------------------------------------------------------------------------
# This is the real magic of this script...
#-------------------------------------------------------------------------------
case "${CONTENT}" in

  "$( transform "open" )" )
    if ! ${PGREP_BIN} -f "${COMMAND}" > /dev/null 2>&1 ; then
      # Place port and user in "~/.ssh/config" before!
      ${COMMAND} &
      ${LOGGER_BIN} "${0} - backward channel initiated"
    fi
    ;;

  "$( transform "close" )" )
    if ${PGREP_BIN} -f "${COMMAND}" > /dev/null 2>&1 ; then
      # 1st try to interupt
      ${PKILL_BIN} -INT -f "${COMMAND}"
      ${SLEEP_BIN} 5

      if ${PGREP_BIN} -f "${COMMAND}" > /dev/null 2>&1 ; then
				# if needed: try (harder) to terminate
        ${PKILL_BIN} -f "${COMMAND}"
        ${SLEEP_BIN} 5

        if ${PGREP_BIN} -f "${COMMAND}" > /dev/null 2>&1 ; then
          # if nothing helps: KILL!
          ${PKILL_BIN} -KILL -f "${COMMAND}"
        fi

      fi
      ${LOGGER_BIN} "${0} - backward channel closed"
    fi
    ;;

  * )
    ${LOGGER_BIN} "${0} - RECEIVED UNKNOWN COMMAND!"
    exit 1
    ;;

esac

exit 0