commit 2177356ac1e682a3516f4caf4a1a92400bf6470b Author: Ville Rantanen Date: Fri Jul 5 14:25:29 2019 +0300 first commit diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..3a21300 --- /dev/null +++ b/Makefile @@ -0,0 +1,30 @@ + +PREFIX = ~/bin + +build: + bash -c '. config.env && \ + mkdir -p scripts && \ + cp src/ssh-backdoor scripts/ssh-backdoor && \ + cp src/ssh-backdoor-connect-local scripts/ssh-backdoor-connect-local && \ + cp src/ssh-backdoor-connect scripts/ssh-backdoor-connect && \ + sed \ + -e "s/{{BACKDOORHOST}}/$${BACKDOORHOST}/g" \ + -e "s/{{BACKDOORPORT}}/$${BACKDOORPORT}/g" \ + src/ssh-backdoor-connect > scripts/ssh-backdoor-connect && \ + sed \ + -e "s/{{BACKDOORHOST}}/$${BACKDOORHOST}/g" \ + -e "s/{{BACKDOORPORT}}/$${BACKDOORPORT}/g" \ + -e "s,{{BACKDOORURL}},$${BACKDOORURL},g" \ + -e "s,{{BACKDOORURLPATH}},$${BACKDOORURLPATH},g" \ + src/ssh-backdoor-open > scripts/ssh-backdoor-open && \ + true' + +install: build + bash -c '. config.env && \ + cp -v scripts/ssh-backdoor-open "$${BACKDOORURLPATH}" && \ + mkdir -p ${PREFIX} && \ + cp -v scripts/ssh-backdoor ${PREFIX}/ssh-backdoor && \ + true' + +clean: + rm -rf scripts diff --git a/src/qolop b/src/qolop new file mode 100755 index 0000000..d8b006d --- /dev/null +++ b/src/qolop @@ -0,0 +1,288 @@ +#!/bin/bash +_qColVersion() { echo Version 2019.06.21.0; } + +_qColHelp() { + _qColVersion + echo 'Quick shell COLOrizer Package +Source me in BASH! +Why the name qolop? Place a mirror next to it! + +Functions: +- _qCol: Print ANSI color codes by letter codes. + Can export all letter codes as varibles. +- _qCode: Print ANSI color codes by number sequence +- _qParse: Print ANSI color by english words ex. "red", "lightgreen", "gray on blue" +- _qPos: Move cursor +- _qClr: Clear screen +- _qReset: Reset terminal + +Examples: + source qolop # load functions +- As functions: + _title(){ _qClr; _qCol z G; echo "$@"; _qCol z; } + _text(){ _qCol z; _qCode 1 34; echo "$@"; _qCol z; } + _title Title; _text Colored; + +- As variables + TITLE=$( _qCol z G; ) + Z=$( _qCol z; ) + echo ${TITLE}Title${Z} + +- Export to variables (prefixed with _c. Also the default) + _qCol export _c + echo -e ${_cG}Title${_cZ} + +Run qolop as script to print ANSI code table, or evaluate commands + + qolop eval "_qCol G; printf hello; _qCol z" | qolop escape + + The first command produces string with ANSI commands, the + second will escape the escape characters, so you can copy/paste + it in to another echo -e command. + + qolop c G + qolop p green + + produce the same output, just the color code +' +} + +_qClr() { + # Clear screen + _qCol "CLR" + _qPos abs 0 0 +} + +_qCol() { + # print "easier" mapping of ANSI colors and controls + local K="\033[1;30m" + local R="\033[1;31m" + local G="\033[1;32m" + local B="\033[1;34m" + local Y="\033[1;33m" + local M="\033[1;35m" + local C="\033[1;36m" + local W="\033[1;37m" + + local k="\033[2;30m" + local r="\033[2;31m" + local g="\033[2;32m" + local b="\033[2;34m" + local y="\033[2;33m" + local m="\033[2;35m" + local c="\033[2;36m" + local w="\033[2;37m" + + local bk="\033[40m" + local br="\033[41m" + local bg="\033[42m" + local by="\033[43m" + local bb="\033[44m" + local bm="\033[45m" + local bc="\033[46m" + local bw="\033[47m" + + local S='\033[1m' #strong + local s='\033[2m' #strong off + local U='\033[4m' #underline + local u='\033[24m' #underline off + local z='\033[0m' #zero colors + local Z='\033[0m' #zero colors + local ic='\033[7m' #inverse colors + local io='\033[27m' #inverse off + local st='\033[9m' #strike on + local so='\033[29m' #strike off + local CLR='\033[2J' # Clear screen + local CLREND='\033[K' # Clear to end of line + local CLRBEG='\033[1K' # Clear to beginning of line + local CLRSCR="$CLR"'\033[0;0H' # Clear screen, reset cursor + + local color_keys=" K R G B Y M C W k r g b y m c w S s U u z Z \ + ic io st so bk br bg by bb bm bc bw \ + CLR CLREND CLRBEG CLRSCR " + + [[ "$1" = "export" ]] && { + local key + local prefix="$2" + [[ -z "$2" ]] && prefix=_c + for key in $color_keys; do + eval export ${prefix}${key}=\'${!key}\' + done + return + } + + local arg val + for ((arg=1;arg<=$#;arg++)) { + val=${!arg} + [[ ${color_keys} = *" $val "* ]] || { echo "No such color code '${val}'" >&2; return 1; } + printf ${!val} + } +} + +_qCode() { + # Enter numerical ANSI colors directly + local arg val + for ((arg=1;arg<=$#;arg++)) { + val=${!arg} + printf '\033['"${val}m" + } +} + +_qParse() { + # Parse written colors to codes: 'help' to get help + local val codes + val="${@,,}" + if [[ ${#val} -lt 3 ]]; then + continue + fi + if [[ ${val} = *"help"* ]]; then + echo "Parse format [light][colorname], or '[light][colorname] on [colorcolorname]'" >&2 + return + fi + if [[ ${val} = "light"* ]]; then + codes="${codes} S" + val=${val#light} + fi + case "$val" in + "black"*) codes="${codes} k";; + "red"*) codes="${codes} r";; + "green"*) codes="${codes} g";; + "yellow"*) codes="${codes} y";; + "blue"*) codes="${codes} b";; + "magenta"*) codes="${codes} m";; + "cyan"*) codes="${codes} c";; + "gray"*) codes="${codes} w";; + "white"*) codes="${codes} W";; + esac + if [[ ${val} = *" on "* ]]; then + case "$val" in + *"black") codes="${codes} bk";; + *"red") codes="${codes} br";; + *"green") codes="${codes} bg";; + *"yellow") codes="${codes} by";; + *"blue") codes="${codes} bb";; + *"magenta") codes="${codes} bm";; + *"cyan") codes="${codes} bc";; + *"gray") codes="${codes} bk";; + *"white") codes="${codes} bw";; + esac + fi + _qCol $codes +} + +_qPos() { + # Cursor position control + local n="$2" + local x="$3" + [[ -z "$n" ]] && n=1 + [[ -z "$x" ]] && x=1 + [[ "$1" = "save" ]] && { printf '\033[s'; return; } + [[ "$1" = "restore" ]] && { printf '\033[u'; return; } + [[ "$1" = "up" ]] && { printf '\033['${n}'A'; return; } + [[ "$1" = "down" ]] && { printf '\033['${n}'B'; return; } + [[ "$1" = "right" ]] && { printf '\033['${n}'C'; return; } + [[ "$1" = "left" ]] && { printf '\033['${n}'D'; return; } + [[ "$1" = "lineup" ]] && { printf '\033['${n}'E'; return; } + [[ "$1" = "linedown" ]] && { printf '\033['${n}'F'; return; } + [[ "$1" = "col" ]] && { printf '\033['${n}'G'; return; } + [[ "$1" = "abs" ]] && { printf '\033['${n}';'${x}'H'; return; } + echo "Command missing: save, restore, up, down, right, left, lineup, linedown, col, abs" >&2 + echo "Directional commands take one argument, abs uses two (row, col)" >&2 + return 1 +} + + +_qReset() { + # Reset terminal + printf '\033c' +} + +if [[ "$0" = "${BASH_SOURCE[0]}" ]]; then + [[ "$1" = "update" ]] && { + set -e + case $OSTYPE in + darwin*) + MYPATH=$( realpath "$0" ) + ;; + *) + MYPATH=$( readlink -f "$0" ) + ;; + esac + MYDIR=$( dirname "$MYPATH" ) + QTOOLS=0 + if [[ -f "$MYDIR/../rc" ]]; then if grep -q QTOOLS "$MYDIR/../rc"; then + QTOOLS=1 + fi;fi; + if [[ "$QTOOLS" -eq 1 ]]; then + echo "Update qolop with _q-tools-update" + exit 1 + fi + TMPFILE=$( mktemp ) + rm -f "$TMPFILE" + echo "Checking for newer version" + wget -q -O "$TMPFILE" https://bitbucket.org/MoonQ/tools/raw/tip/reporting/qolop + diff "$TMPFILE" "$MYPATH" || { + mv -v "$TMPFILE" "$MYPATH" + chmod +x "$MYPATH" + echo Updated + source "$MYPATH" + _qColVersion + } + rm -f "$TMPFILE" + exit 0 + } # end update + [[ "$1" = "eval" ]] && { + set -e + eval "$@" + exit + } + [[ "$1" = "escape" ]] && { + cat - | sed s/$'\e'/\\\\033/g + echo '' + exit + } + [[ "$1" = "c" ]] && { + shift 1 + _qCol "$@" + exit + } + [[ "$1" = "p" ]] && { + shift 1 + _qParse "$@" + exit + } + + _qColHelp + [[ "$1" = *"help" ]] && exit + [[ "$1" = "-h" ]] && exit + _qCol export "_" + printf "${_S}ANSI CODES AND QOLOP VARIABLES FOR _qCol FUNCTION +=================================================${_Z} +${_R}Co${_G}lo${_B}rs${_W} and ${_S}Mo${_U}di${_st}fi${_u}er${_ic}s${_Z} \\\033[Xm or \\\033[X;Y;Zm +${_S}====================${_Z} + 0 z Z Clear format + 1 S ${_S}Strong/Bold ${_Z} 30 k ${_k}Black ${_Z}30;1 K ${_K}Black ${_Z}40 bk ${_w}${_bk}Black ${_Z} + 2 s ${_s}Weak/Bold off ${_Z} 31 r ${_r}Red ${_Z}31;1 R ${_R}Red ${_Z}41 br ${_k}${_br}Red ${_Z} + 4 U ${_U}Underline ${_Z} 32 g ${_g}Green ${_Z}32;1 G ${_G}Green ${_Z}42 bg ${_k}${_bg}Green ${_Z} + 24 u ${_u}Underline off ${_Z} 33 y ${_y}Yellow ${_Z}33;1 Y ${_Y}Yellow ${_Z}43 by ${_k}${_by}Yellow ${_Z} + 7 ic ${_ic}Inverse color ${_Z} 34 b ${_b}Blue ${_Z}34;1 B ${_B}Blue ${_Z}44 bb ${_k}${_bb}Blue ${_Z} + 27 of ${_io}Inverse off ${_Z} 35 m ${_m}Magenta ${_Z}35;1 M ${_M}Magenta ${_Z}45 bm ${_k}${_bm}Magenta ${_Z} + 9 st ${_st}Strike ${_Z} 36 c ${_c}Cyan ${_Z}36;1 C ${_C}Cyan ${_Z}46 bc ${_k}${_bc}Cyan ${_Z} + 29 so ${_so}Strike off ${_Z} 37 w ${_w}White ${_Z}37;1 W ${_W}White ${_Z}47 bw ${_k}${_bw}White ${_Z} + Enter raw color code sequence with _qCode function +${_S}Clearing and movement${_Z} ESC[X or ESC[1X +${_S}=====================${_Z} + 2J CLR Clear screen + 2J ;H CLRSCR _qClr() Clear screen, move cursor to origo + K CLREND Clear to end of line + 1K CLRBEG Clear to beginning of line + _qReset() Reset terminal + + s _qPos save Save location u _qPos restore Restore location + A _qPos up Up E _qPos lineup Up line + B _qPos down Down F _qPos linedown Down line + C _qPos left Left y;xH _qPos abs y x Absolute Position + D _qPos right Right +" +fi + diff --git a/src/ssh-backdoor b/src/ssh-backdoor new file mode 100755 index 0000000..dbbe66a --- /dev/null +++ b/src/ssh-backdoor @@ -0,0 +1,235 @@ +#!/usr/bin/env python3 + +from datetime import timedelta, datetime +from tabulate import tabulate +import random +import sqlite3 +import time, os, sys + +def setup_options(): + ''' Setup the command line options ''' + from argparse import ArgumentParser + + parser=ArgumentParser(description="Alive notifier.") + parser.add_argument( + "--db", + action = 'store', + dest = 'DB', + default = '/tmp/ssh-backdoor.sqlite', + type = str, + help = "Sqlite file for database: %(default)s" + ) + # TODO --connect (replace ssh-local-connect) + parser.add_argument( + "--clear", + action = 'store_true', + dest = 'clear', + default = False, + help = "Clear the database of everything, first" + ) + parser.add_argument( + "--list","-l", + action = 'store_true', + dest = 'list', + default = False, + help = "List ports" + ) + parser.add_argument( + "--list-names", + action = 'store_true', + dest = 'list_names', + default = False, + help = "List alive host names only" + ) + parser.add_argument( + "--query", + action = 'store', + dest = 'query', + default = None, + type = str, + help="Query port for an id" + ) + parser.add_argument( + "--quiet", "-q", + action = 'store_true', + dest = 'quiet', + default = False, + help = "Quiet operation: %(default)s" + ) + parser.add_argument( + "--wait", "-w", + action = 'store_true', + dest = 'wait', + default = False, + help = "Enter infinite loop" + ) + parser.add_argument( + action = 'store', + dest = 'id', + default = None , + type = str, + nargs = '?', + help="Id name for port" + ) + options=parser.parse_args() + return options + + +class DataBase: + def __init__(self, DB): + self.alive = 7 * 24 * 3600 # 7 days + self.DBfile = DB + self.conn = None + self.db = None + if not os.path.exists(self.DBfile): + self.createDB() + self.conn_init() + self.clean_db() + + def clear(self): + self.db = self.conn.cursor() + self.db.execute("DELETE FROM ports") + self.conn_end() + + def conn_init(self): + self.conn = sqlite3.connect(self.DBfile) + self.db = self.conn.cursor() + self.conn.text_factory = str + + def conn_end(self): + self.conn.commit() + #self.conn.close() + + def createDB(self): + self.conn_init() + self.db.execute('CREATE TABLE ports (\ + id TEXT PRIMARY KEY,\ + host TEXT, \ + port INTEGER,\ + pid INTEGER,\ + die INTEGER,\ + date INTEGER)') + self.conn_end() + + def clean_db(self): + self.db = self.conn.cursor() + self.db.execute("SELECT id,port,date,pid,host FROM ports") + for row in self.db.fetchall(): + age = int(time.time() - row[2]) + running = self.is_running(row[3]) + if running: + continue + if age < self.alive: + continue + self.db.execute("DELETE FROM ports WHERE id = ?", (row[0],)) + self.conn_end() + + def die(self): + """ kills process, and parents, if set to die """ + pass + + def update(self, id): + port = self.get_port(id) + if port == None: + port = self.new_port() + + self.db = self.conn.cursor() + self.db.execute("INSERT OR REPLACE INTO ports(id,port,date,pid,host) \ + VALUES(?,?,?,?,?)",( + id, + port, + int(time.time()), + self.get_pid(), + os.getenv("SSH_CLIENT","-").split(" ")[0] + ) + ) + self.conn_end() + return port + + def list(self): + self.db = self.conn.cursor() + self.db.execute("SELECT id,port,host,date,pid FROM ports ORDER BY id") + rows = [] + for row in self.db: + row = list(row) + row[3] = self.human_age(row[3]) + row.append(self.is_running(row[4])) + # ~ row.append("ssh-nosave -p %d localhost"%( row[1], ) ) + rows.append(row) + return rows + + + def human_age(self, sec): + sec = timedelta(seconds = time.time() - sec) + d = datetime(1,1,1) + sec + return "%d %02d:%02d:%02d" % (d.day - 1, d.hour, d.minute, d.second) + + + def is_running(self, pid): + try: + os.kill(pid, 0) + except OSError: + return False + else: + return True + + def get_pid(self): + return os.getppid() + + def get_port(self, id): + self.db = self.conn.cursor() + self.db.execute("SELECT port FROM ports WHERE id = ?", (id,)) + result = self.db.fetchall() + if len(result) == 0: + return None + return result[0][0] + + def new_port(self): + self.db = self.conn.cursor() + while True: + port = random.randint(22200, 22400) + self.db.execute("SELECT port FROM ports WHERE port = ?", (port,)) + result = self.db.fetchall() + if len(result) == 0: + return port + +if __name__ == "__main__": + opts=setup_options() + db = DataBase(opts.DB) + start_time = time.time() + if opts.clear: + db.clear() + if opts.list_names: + for row in db.list(): + if row[5]: + print(row[0]) + sys.exit(0) + if opts.list: + print(tabulate( + db.list(), + headers = ['Id','Port','Host','Age','PID','Alive'] + )) + if opts.query != None: + port = db.get_port(opts.query) + if port == None: + sys.exit(1) + print(port) + sys.exit(0) + if opts.id != None: + print(db.update(opts.id)) + if opts.wait: + sys.stderr.write( + " Connected\r" + ) + while True: + if time.time() - start_time > 3600: + sys.exit(0) + db.update(opts.id) + for i in range(10): + db.die() + time.sleep(3 + random.random()) + sys.stderr.write( + " " + + time.strftime("%c") + + "\r" + ) diff --git a/src/ssh-backdoor-connect b/src/ssh-backdoor-connect new file mode 100755 index 0000000..4eed169 --- /dev/null +++ b/src/ssh-backdoor-connect @@ -0,0 +1,70 @@ +#!/bin/bash +SELECT_MONOCHROME=0 +SELECT_SHORTCUTS=0 +SELECT_NUMBERS=1 +SELECT_UNDERSCORES=0 +SELECT_MULTI=0 +SELECT_CENTER=0 +SELECT_MIDDLE=0 +SELECT_TOFILE="" +SELECT_TITLE="" + +source <( echo 'ZnVuY3Rpb24gc2VsZWN0X29wdGlvbiB7CiAgICBsb2NhbCBuZm9ybWF0CiAgICBsb2NhbCBvcHRjb3VudD0kIwogICAgcHJpbnRmIC12IG5mb3JtYXQgIiUlJWRkLiAiICR7I29wdGNvdW50fQogICAgbG9jYWwgbWF4X29wdD0kKCggJHsjU0VMRUNUX1RJVExFfSAtIDQgKSkKICAgIGxvY2FsIG11bHRpc2VsZWN0ZWQ9KCkKICAgIGxvY2FsIGNob2ljZXM9KCkKICAgIGxvY2FsIHNob3J0Y3V0cz0oKQogICAgbG9jYWwgaWR4PTAKICAgIGxvY2FsIGNsZWFuX29wdAogICAgZm9yIG9wdDsgZG8KICAgICAgbXVsdGlzZWxlY3RlZCs9KDApCiAgICAgIGlmIFtbICIkb3B0IiA9fiBeXFsuXF0gXV07IHRoZW4gIyBjaG9pY2Ugc3RhcnRzIHdpdGggW3hdCiAgICAgICAgc2hvcnRjdXRzKz0oICIke29wdDoxOjF9IiApCiAgICAgICAgY2hvaWNlcys9KCAiJHtvcHQ6M30iICkKICAgICAgZWxzZQogICAgICAgIHNob3J0Y3V0cys9KCAiJHtvcHQ6MDoxfSIgKQogICAgICAgIGNob2ljZXMrPSggIiRvcHQiICkKICAgICAgZmkKICAgICAgaWYgW1sgIiR7I2Nob2ljZXNbJGlkeF19IiAtZ3QgJG1heF9vcHQgXV07IHRoZW4KICAgICAgICBtYXhfb3B0PSIkeyNjaG9pY2VzWyRpZHhdfSIKICAgICAgZmkKICAgICAgKChpZHgrKykpCiAgICBkb25lCiAgICBpZiBbWyAkU0VMRUNUX0NFTlRFUiAtZXEgMSBdXTsgdGhlbgogICAgICBsb2NhbCBwYWRfY2VudGVyPSQoKCAoICQoIHRwdXQgY29scyApIC0gJG1heF9vcHQgKSAvIDIgLSA1ICkpCiAgICAgIGlmIFtbICRwYWRfY2VudGVyIC1ndCAwIF1dOyB0aGVuCiAgICAgICAgcHJpbnRmIC12IHBhZF9jZW50ZXIgIiUke3BhZF9jZW50ZXJ9cyIgIiAiCiAgICAgIGVsc2UKICAgICAgICAgcGFkX2NlbnRlcj0iIgogICAgICBmaQogICAgZmkKCiAgICAjIGxpdHRsZSBoZWxwZXJzIGZvciB0ZXJtaW5hbCBwcmludCBjb250cm9sIGFuZCBrZXkgaW5wdXQKICAgIEVTQz0kKCBwcmludGYgIlwwMzMiICkKICAgIGN1cnNvcl9ibGlua19vbigpICB7IHByaW50ZiAiJEVTQ1s/MjVoIjsgfQogICAgY3Vyc29yX2JsaW5rX29mZigpIHsgcHJpbnRmICIkRVNDWz8yNWwiOyB9CiAgICBjbGVhcl9zY3JlZW4oKSB7IHByaW50ZiAiJEVTQ1sySiI7IH0KICAgIGN1cnNvcl90bygpICAgICAgICB7IHByaW50ZiAiJEVTQ1skMTskezI6LTF9SCI7IH0KICAgIGlmIFtbICRTRUxFQ1RfTU9OT0NIUk9NRSAtZXEgMSBdXTsgdGhlbgogICAgICAgIHByaW50X29wdGlvbigpICAgICB7IHByaW50ZiAiICAkRVNDWzMwbSVzICRFU0NbMG0lcyAgJXMgICAkRVNDWzMwbSVzJEVTQ1swbSRFU0NbSyIgIiQxIiAiJDIiICIkMyIgIiQ0IjsgfQogICAgICAgIHByaW50X3NlbGVjdGVkKCkgICB7IHByaW50ZiAiICAkRVNDWzMwbSVzICRFU0NbMG0lc3sgJEVTQ1sxbSVzJEVTQ1swbSB9ICRFU0NbMzBtJXMkRVNDWzBtJEVTQ1tLIiAiJDEiICIkMiIgIiQzIiAiJDQiOyB9CiAgICAgICAgcHJpbnRfbXVsdGlzZWxlY3RlZCgpICAgeyBwcmludGYgIiRFU0NbMzA7MW0qJEVTQ1swbSI7IH0KICAgIGVsc2UKICAgICAgICBwcmludF9vcHRpb24oKSAgICAgeyBwcmludGYgIiAgJEVTQ1szMG0lcyAkRVNDWzMzbSVzICAlcyRFU0NbMG0gICAkRVNDWzMwbSVzJEVTQ1swbSRFU0NbSyIgIiQxIiAiJDIiICIkMyIgIiQ0IjsgfQogICAgICAgIHByaW50X3NlbGVjdGVkKCkgICB7IHByaW50ZiAiICAkRVNDWzMwbSVzICRFU0NbMzU7MW0lc3sgJEVTQ1szNzsxbSVzJEVTQ1swOzM1OzFtIH0gJEVTQ1swOzMwbSVzJEVTQ1swbSRFU0NbSyIgIiQxIiAiJDIiICIkMyIgIiQ0IjsgfQogICAgICAgIHByaW50X211bHRpc2VsZWN0ZWQoKSAgIHsgcHJpbnRmICIkRVNDWzMyOzFtKiRFU0NbMG0iOyB9CiAgICBmaQogICAgZ2V0X2N1cnNvcl9yb3coKSAgIHsgSUZTPSc7JyByZWFkIC1zZFIgLXAgJCdcRVs2bicgUk9XIENPTDsgZWNobyAke1JPVyMqW307IH0KICAgIGtleV9pbnB1dCgpICAgICAgICB7IHJlYWQgLXMgLW4xIGtleTEgMj4vZGV2L251bGwgPiYyCiAgICAgICAgICAgICAgICAgICAgICAgICByZWFkIC1zIC1uMiAtdCAwLjEga2V5MiAyPi9kZXYvbnVsbCA+JjIKICAgICAgICAgICAgICAgICAgICAgICAgIGxvY2FsIGlkeD0kc2VsZWN0ZWQKICAgICAgICAgICAgICAgICAgICAgICAgIHdoaWxlIHRydWU7IGRvCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGlkeD0kKCggKCRpZHggKyAxKSAlICRvcHRjb3VudCApKQogICAgICAgICAgICAgICAgICAgICAgICAgICBpZiBbWyAiJGtleTEiID0gIiR7c2hvcnRjdXRzWyRpZHhdfSIgXV07IHRoZW4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlY2hvICRpZHg7IHJldHVybjsKICAgICAgICAgICAgICAgICAgICAgICAgICAgZmkKICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgW1sgJGlkeCAtZXEgJHNlbGVjdGVkIF1dOyB0aGVuIGJyZWFrOyBmaQogICAgICAgICAgICAgICAgICAgICAgICAgZG9uZQogICAgICAgICAgICAgICAgICAgICAgICAgaWYgW1sgJGtleTEka2V5MiA9ICRFU0NbQSBdXTsgdGhlbiBlY2hvIHVwOyByZXR1cm47IGZpCiAgICAgICAgICAgICAgICAgICAgICAgICBpZiBbWyAka2V5MSRrZXkyID0gJEVTQ1tCIF1dOyB0aGVuIGVjaG8gZG93bjsgcmV0dXJuOyBmaQogICAgICAgICAgICAgICAgICAgICAgICAgaWYgW1sgJGtleTEka2V5MiA9ICRFU0NbQyBdXTsgdGhlbiBlY2hvIGxlZnQ7IHJldHVybjsgZmkKICAgICAgICAgICAgICAgICAgICAgICAgIGlmIFtbICRrZXkxJGtleTIgPSAkRVNDW0QgXV07IHRoZW4gZWNobyByaWdodDsgcmV0dXJuOyBmaQogICAgICAgICAgICAgICAgICAgICAgICAgaWYgW1sgJGtleTEgPSAkJ1xlJyAgXV07IHRoZW4gZWNobyBlc2M7IHJldHVybjsgICBmaQogICAgICAgICAgICAgICAgICAgICAgICAgaWYgW1sgJGtleTEgPSB4ICAgICAgXV07IHRoZW4gZWNobyBtdWx0aXNlbGVjdDsgcmV0dXJuOyAgIGZpCiAgICAgICAgICAgICAgICAgICAgICAgICBpZiBbWyAka2V5MSA9IHEgICAgICBdXTsgdGhlbiBlY2hvIGVzYzsgcmV0dXJuOyAgIGZpCiAgICAgICAgICAgICAgICAgICAgICAgICBpZiBbWyAka2V5MSA9ICIiICAgICBdXTsgdGhlbiBlY2hvIGVudGVyOyByZXR1cm47IGZpCiAgICAgICAgICAgICAgICAgICAgfQogICAgcmVzZXRfZGlzcGxheSgpICB7CiAgICAgICAgY3Vyc29yX2JsaW5rX29uOyBzdHR5IGVjaG87IHByaW50ZiAnXG4nOwogICAgfQogICAgaWYgW1sgJFNFTEVDVF9NSURETEUgLWVxIDEgXV07IHRoZW4KICAgICAgY2xlYXJfc2NyZWVuCiAgICAgIGN1cnNvcl90byAxCiAgICAgIGxvY2FsIHBhZF9taWRkbGU9JCgoICggJCggdHB1dCBsaW5lcyApIC0gJG9wdGNvdW50ICkgLyAyIC0gMiApKQogICAgICBpZiBbWyAkcGFkX21pZGRsZSAtZ3QgMCBdXTsgdGhlbgogICAgICAgIHByaW50ZiAiXG4lLjBzIiAkKCBzZXEgMSAkcGFkX21pZGRsZSApCiAgICAgIGZpCiAgICBmaQogICAgaWYgWyAtbiAiJFNFTEVDVF9USVRMRSIgXTsgdGhlbgogICAgICAgIHByaW50ZiAiJHtwYWRfY2VudGVyfSAgICRFU0NbMzU7MW0lcyRFU0NbMG0kRVNDW0sgIFxuIiAiJFNFTEVDVF9USVRMRSIKICAgIGZpCiAgICAjIGluaXRpYWxseSBwcmludCBlbXB0eSBuZXcgbGluZXMgKHNjcm9sbCBkb3duIGlmIGF0IGJvdHRvbSBvZiBzY3JlZW4pCiAgICBmb3Igb3B0OyBkbyBwcmludGYgIlxuIjsgZG9uZQogICAgIyBFeHRyYXMgZm9yIHRvcCBhbmQgYm90dG9tCiAgICBwcmludGYgIlxuXG4iCgogICAgIyBkZXRlcm1pbmUgY3VycmVudCBzY3JlZW4gcG9zaXRpb24gZm9yIG92ZXJ3cml0aW5nIHRoZSBvcHRpb25zCiAgICBsb2NhbCBsYXN0cm93PWBnZXRfY3Vyc29yX3Jvd2AKICAgIGxvY2FsIHN0YXJ0cm93PSQoKCAkbGFzdHJvdyAtICQjIC0gMiApKQogICAgI34gaWYgWyAtbiAiJFNFTEVDVF9USVRMRSIgXTsgdGhlbgogICAgICAjfiAoKHN0YXJ0cm93LS0pKQogICAgICAjfiAoKHN0YXJ0cm93LS0pKQogICAgI34gZmkKICAgIGxvY2FsIHRvcHJvdz0iK35+LS0iCiAgICBsb2NhbCBib3R0b21yb3c9Ii0tfn4rIgogICAgbG9jYWwgbGJvcmRlcmNoYXJzPSJ8OiciCiAgICBsb2NhbCByYm9yZGVyY2hhcnM9Inw6LiIKCgoKICAgICMgZW5zdXJlIGN1cnNvciBhbmQgaW5wdXQgZWNob2luZyBiYWNrIG9uIHVwb24gYSBjdHJsK2MgZHVyaW5nIHJlYWQgLXMKICAgIHRyYXAgImN1cnNvcl9ibGlua19vbjsgc3R0eSBlY2hvOyBwcmludGYgJ1xuJzsgZXhpdCAxIiAyCiAgICBjdXJzb3JfYmxpbmtfb2ZmCgogICAgbG9jYWwgc2VsZWN0ZWQ9MAogICAgbG9jYWwgYm90dG9tbGVuZ3RoPSQoKCAxMCArICRtYXhfb3B0ICkpCiAgICBsb2NhbCBtdWx0aXNlbGVjdF9wb3M9NgogICAgaWYgW1sgJFNFTEVDVF9OVU1CRVJTICAtZXEgMSBdXTsgdGhlbgogICAgICAgIGJvdHRvbWxlbmd0aD0kKCggJGJvdHRvbWxlbmd0aCArIDMgKSkKICAgICAgICBtdWx0aXNlbGVjdF9wb3M9JCgoICRtdWx0aXNlbGVjdF9wb3MgKyAzICkpCiAgICBmaQogICAgaWYgW1sgJFNFTEVDVF9TSE9SVENVVFMgLWVxIDEgXV07IHRoZW4KICAgICAgICBib3R0b21sZW5ndGg9JCgoICRib3R0b21sZW5ndGggKyAzICkpCiAgICAgICAgbXVsdGlzZWxlY3RfcG9zPSQoKCAkbXVsdGlzZWxlY3RfcG9zICsgMyApKQogICAgZmkKCiAgICB3aGlsZSB0cnVlOyBkbwogICAgICAgICMgcHJpbnQgb3B0aW9ucyBieSBvdmVyd3JpdGluZyB0aGUgbGFzdCBsaW5lcwogICAgICAgIGxvY2FsIGlkeD0wCiAgICAgICAgbG9jYWwgbmlkeAogICAgICAgIGxvY2FsIHNob3J0Y3V0CiAgICAgICAgY3Vyc29yX3RvICRzdGFydHJvdwogICAgICAgIGlmIFsgJHNlbGVjdGVkIC1sdCAwIF07IHRoZW4gc2VsZWN0ZWQ9JCgoJCMgLSAxKSk7IGZpCiAgICAgICAgaWYgWyAkc2VsZWN0ZWQgLWdlICQjIF07IHRoZW4gc2VsZWN0ZWQ9MDsgZmkKICAgICAgICBwcmludGYgIiR7cGFkX2NlbnRlcn0gICRFU0NbMzBtJXMkRVNDWzBtJEVTQ1tLICAiICIkdG9wcm93IgoKICAgICAgICBmb3Igb3B0OyBkbwogICAgICAgICAgICBvcHQ9IiR7Y2hvaWNlc1skaWR4XX0iCiAgICAgICAgICAgIGxvY2FsIGxib3JkZXI9IiR7bGJvcmRlcmNoYXJzOiRpZHg6MX0iCiAgICAgICAgICAgIGlmIFsgLXogIiRsYm9yZGVyIiBdOyB0aGVuIGxib3JkZXI9IiAiOyBmaQogICAgICAgICAgICBsb2NhbCByYm9yZGVyPSIke3Jib3JkZXJjaGFyczokKCggJG9wdGNvdW50IC0gJGlkeCAtIDEpKToxfSIKICAgICAgICAgICAgaWYgWyAteiAiJHJib3JkZXIiIF07IHRoZW4gcmJvcmRlcj0iICI7IGZpCiAgICAgICAgICAgIGlmIFtbICRTRUxFQ1RfVU5ERVJTQ09SRVMgLWVxIDEgXV07IHRoZW4KICAgICAgICAgICAgICAgIG9wdD0ke29wdC8vXy8gfQogICAgICAgICAgICBmaQogICAgICAgICAgICBpZiBbWyAkU0VMRUNUX05VTUJFUlMgIC1lcSAxIF1dOyB0aGVuCiAgICAgICAgICAgICAgICBwcmludGYgLXYgbmlkeCAiJG5mb3JtYXQiICQoKCBpZHggKyAxICkpCiAgICAgICAgICAgIGZpCiAgICAgICAgICAgIGlmIFtbICRTRUxFQ1RfU0hPUlRDVVRTIC1lcSAxIF1dOyB0aGVuCiAgICAgICAgICAgICAgICBwcmludGYgLXYgc2hvcnRjdXQgIiVzKSAiICIke3Nob3J0Y3V0c1skaWR4XX0iCiAgICAgICAgICAgIGZpCiAgICAgICAgICAgIHByaW50ZiAtdiBwYWRvcHQgIiUtJHttYXhfb3B0fXMiICIkb3B0IgogICAgICAgICAgICBjdXJzb3JfdG8gJCgoJHN0YXJ0cm93ICsgJGlkeCArIDEpKQogICAgICAgICAgICBwcmludGYgIiVzIiAiJHtwYWRfY2VudGVyfSIKICAgICAgICAgICAgaWYgWyAkaWR4IC1lcSAkc2VsZWN0ZWQgXTsgdGhlbgogICAgICAgICAgICAgICAgcHJpbnRfc2VsZWN0ZWQgIiRsYm9yZGVyIiAiJG5pZHgkc2hvcnRjdXQiICIkcGFkb3B0IiAgIiRyYm9yZGVyIgogICAgICAgICAgICBlbHNlCiAgICAgICAgICAgICAgICBwcmludF9vcHRpb24gIiRsYm9yZGVyIiAiJG5pZHgkc2hvcnRjdXQiICIkcGFkb3B0IiAiJHJib3JkZXIiCiAgICAgICAgICAgIGZpCiAgICAgICAgICAgIGlmICgoICR7bXVsdGlzZWxlY3RlZFskaWR4XX0gKSk7IHRoZW4KICAgICAgICAgICAgICBjdXJzb3JfdG8gJCgoJHN0YXJ0cm93ICsgJGlkeCArIDEpKSAkbXVsdGlzZWxlY3RfcG9zCiAgICAgICAgICAgICAgcHJpbnRfbXVsdGlzZWxlY3RlZAogICAgICAgICAgICBmaQogICAgICAgICAgICAoKGlkeCsrKSkKICAgICAgICBkb25lCiAgICAgICAgY3Vyc29yX3RvICQoKCRzdGFydHJvdyArICRpZHggKyAxKSkKICAgICAgICBwcmludGYgIiR7cGFkX2NlbnRlcn0kRVNDW0skRVNDWzMwbSUke2JvdHRvbWxlbmd0aH1zJEVTQ1swbSAgIiAiJGJvdHRvbXJvdyIKCiAgICAgICAgIyB1c2VyIGtleSBjb250cm9sCiAgICAgICAgbG9jYWwgdXNlcl9pbnB1dD1ga2V5X2lucHV0YAogICAgICAgIGNhc2UgIiR1c2VyX2lucHV0IiBpbgogICAgICAgICAgICBlbnRlcikgYnJlYWs7OwogICAgICAgICAgICBlc2MpICAgcmVzZXRfZGlzcGxheTsgZXhpdCAxOzsKICAgICAgICAgICAgdXApICAgICgoc2VsZWN0ZWQtLSkpOzsKICAgICAgICAgICAgZG93bikgICgoc2VsZWN0ZWQrKykpOzsKICAgICAgICAgICAgbXVsdGlzZWxlY3QpICBpZiAoKCAkU0VMRUNUX01VTFRJICkpOyB0aGVuCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtdWx0aXNlbGVjdGVkWyRzZWxlY3RlZF09JCgoIDEgLSAke211bHRpc2VsZWN0ZWRbJHNlbGVjdGVkXX0gKSk7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoKHNlbGVjdGVkKyspKTsKICAgICAgICAgICAgICAgICAgICAgICAgICBmaTs7CiAgICAgICAgICAgIFswLTldKikgc2VsZWN0ZWQ9JHVzZXJfaW5wdXQ7OwogICAgICAgIGVzYWMKICAgIGRvbmUKCiAgICAjIGN1cnNvciBwb3NpdGlvbiBiYWNrIHRvIG5vcm1hbAogICAgY3Vyc29yX3RvICRsYXN0cm93CiAgICByZXNldF9kaXNwbGF5CiAgICBsb2NhbCByZXR1cm52YWx1ZT0wCiAgICBsb2NhbCBpZHg9MAogICAgaWYgKCggJFNFTEVDVF9NVUxUSSApKTsgdGhlbgogICAgICBpZiBbWyAtbiAiJFNFTEVDVF9UT0ZJTEUiIF1dOyB0aGVuIHByaW50ZiAiIiA+ICIkU0VMRUNUX1RPRklMRSI7IGZpCiAgICAgIGZvciBvcHQ7IGRvCiAgICAgICAgaWYgKCggJHttdWx0aXNlbGVjdGVkWyRpZHhdfSApKTsgdGhlbgogICAgICAgICAgaWYgW1sgLW4gIiRTRUxFQ1RfVE9GSUxFIiBdXTsgdGhlbiBlY2hvICIke2Nob2ljZXNbJGlkeF19IiA+PiAiJFNFTEVDVF9UT0ZJTEUiOyBmaQogICAgICAgICAgcmV0dXJudmFsdWU9JCgoICRyZXR1cm52YWx1ZSArIDIqKiRpZHggKSkKICAgICAgICBmaQogICAgICAgICgoaWR4KyspKQogICAgICBkb25lCiAgICBlbHNlCiAgICAjIFNpbmdsZSBjaG9pY2UKICAgICAgcmV0dXJudmFsdWU9JHNlbGVjdGVkCiAgICAgIGlmIFtbIC1uICIkU0VMRUNUX1RPRklMRSIgXV07IHRoZW4KICAgICAgICBlY2hvICIke2Nob2ljZXNbJHNlbGVjdGVkXX0iID4gIiRTRUxFQ1RfVE9GSUxFIgogICAgICBmaQogICAgZmkKCiAgICByZXR1cm4gJCgoICRyZXR1cm52YWx1ZSArIDEwICkpCn0K' | base64 -d ) + +BACKDOORHOST={{BACKDOORHOST}} +BACKDOORPORT={{BACKDOORPORT}} +_list() { + echo 'usage: [-auto] user@host' + _ssh bin/ssh-backdoor -l + ids=( $( _ssh bin/ssh-backdoor --list-names ) ) + if [[ ${#ids[@]} -eq 0 ]]; then + exit + fi + select_option ${ids[@]} || choice=$(( $? - 10 )) + if [[ $choice -ge 0 ]]; then + host=${ids[$choice]} + else + exit + fi +} + +_ssh() { + ssh \ + -o UserKnownHostsFile=/dev/null \ + -o StrictHostKeyChecking=no \ + -o ConnectTimeout=10 \ + -p ${BACKDOORPORT} ${BACKDOORHOST} \ + "$@" + #~ -o "ExitOnForwardFailure yes" \ +} + + +[[ -z "$1" ]] && _list +for (( i=1; i<=$#; i++ )); do + [[ "${!i}" = "-h" ]] && _list + [[ "${!i}" = "-help" ]] && _list + [[ "${!i}" = "--help" ]] && _list + [[ "${!i}" = "-auto" ]] && { auto_reconnect=1; continue; } + host="${!i}" +done + +port=$( _ssh bin/ssh-backdoor --query "$host" ) +[[ $? -ne 0 ]] && { + echo No such id + _list +} +login=(${host//@/ }) +while :; do + _ssh \ + -tt \ + ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no \ + -tt -XYC -p $port ${login[0]}@localhost + [[ $? -eq 0 ]] && exit + [[ "$auto_reconnect" -ne 1 ]] && { exit $?; } + echo Auto-reconnect + for i in {1..10}; do + echo -n . + read -t 1 foo + [[ $? -eq 0 ]] && exit + done +done diff --git a/src/ssh-backdoor-connect-local b/src/ssh-backdoor-connect-local new file mode 100755 index 0000000..ef1a98f --- /dev/null +++ b/src/ssh-backdoor-connect-local @@ -0,0 +1,21 @@ +#!/bin/bash + +_list() { + echo usage: user@host + ssh-backdoor -l + exit +} + +[[ -z "$1" ]] && _list + +port=$( ssh-backdoor --query "$1" ) +[[ $? -ne 0 ]] && { + echo No such id + _list +} +login=(${1//@/ }) +set -x +exec ssh \ + -o UserKnownHostsFile=/dev/null \ + -o StrictHostKeyChecking=no \ + -tt -XYC -p $port ${login[0]}@localhost diff --git a/src/ssh-backdoor-open b/src/ssh-backdoor-open new file mode 100755 index 0000000..9d1f929 --- /dev/null +++ b/src/ssh-backdoor-open @@ -0,0 +1,44 @@ +#!/bin/bash + +export PATH=$PATH:/usr/local/bin + +set -x +if [[ "$1" = update ]]; then + set -e + curl --fail {{BACKDOORURL}} > /tmp/ssh-backdoor-open && { + mv -v /tmp/ssh-backdoor-open "$0" + chmod +x "$0" + #~ exec "$0" + exit + } +fi + +_ssh() { + timeout 3700 ssh \ + -o UserKnownHostsFile=/dev/null \ + -o StrictHostKeyChecking=no \ + -o ConnectTimeout=10 \ + -p ${BACKDOORPORT} + ${BACKDOORHOST} \ + "$@" + #~ -o "ExitOnForwardFailure yes" \ +} + +BACKDOORHOST={{BACKDOORHOST}} +BACKDOORPORT={{BACKDOORPORT}} +USER=$( id -u -n ) +echo use of ssh-add is encouraged +while true; do + port=$( _ssh bin/ssh-backdoor $USER@$HOSTNAME ) + [[ -z "$port" ]] && { sleep 2; continue; } + echo "$port port assigned" + #~ _ssh pkill -a -f $USER@$HOSTNAME + _ssh \ + -R $port:localhost:22 \ + bin/ssh-backdoor -w $USER@$HOSTNAME || { + true + # failed + #_ssh bin/ssh-kill $USER@$HOSTNAME $port || true + } + sleep 10 +done diff --git a/src/ssh-kill-all b/src/ssh-kill-all new file mode 100755 index 0000000..c4c3b44 --- /dev/null +++ b/src/ssh-kill-all @@ -0,0 +1,37 @@ +#/bin/bash +PATH=$PATH:$HOME/bin +pppid=$( ps --no-header o ppid $PPID ) +ppcom=$( ps --no-header o comm $pppid ) +if [[ $ppcom = sshd ]]; then + + pgrep -u $USER -x sshd | while read pid; do + row=$( ps --no-header o pid,start,comm $pid ) + printf "%s%s%s\r" $( qolop c Y ) "$row" $( qolop c Z ) + sleep 0.5 + if [[ $pid -eq $pppid ]]; then + printf "%s%s%s\r" $( qolop c G ) "$row" $( qolop c Z ) + else + kill -9 $pid &> /dev/null + printf "%s%s%s\r" $( qolop c R ) "$row" $( qolop c Z ) + fi + printf "\n" + done + + pgrep -u $USER -x ssh | while read pid; do + row=$( ps --no-header o pid,start,comm $pid ) + printf "%s%s%s\r" $( qolop c Y ) "$row" $( qolop c Z ) + sleep 0.5 + kill -9 $pid &> /dev/null + printf "%s%s%s\r" $( qolop c R ) "$row" $( qolop c Z ) + printf "\n" + done + + pgrep -u $USER -x python3 | while read pid; do + row=$( ps --no-header o pid,start,comm $pid ) + printf "%s%s%s\r" $( qolop c Y ) "$row" $( qolop c Z ) + sleep 0.5 + kill -9 $pid &> /dev/null + printf "%s%s%s\r" $( qolop c R ) "$row" $( qolop c Z ) + printf "\n" + done +fi diff --git a/src/ssh-list b/src/ssh-list new file mode 100755 index 0000000..3aa3888 --- /dev/null +++ b/src/ssh-list @@ -0,0 +1,4 @@ +#!/bin/bash + +ps axuw | grep -e [s]sh -e [p]ython3 +