diff --git a/Makefile b/Makefile index 3a21300..a15e0ec 100644 --- a/Makefile +++ b/Makefile @@ -17,13 +17,16 @@ build: -e "s,{{BACKDOORURL}},$${BACKDOORURL},g" \ -e "s,{{BACKDOORURLPATH}},$${BACKDOORURLPATH},g" \ src/ssh-backdoor-open > scripts/ssh-backdoor-open && \ + chmod +x scripts/* && \ true' install: build bash -c '. config.env && \ - cp -v scripts/ssh-backdoor-open "$${BACKDOORURLPATH}" && \ + cp -av scripts/ssh-backdoor-open "$${BACKDOORURLPATH}" && \ mkdir -p ${PREFIX} && \ - cp -v scripts/ssh-backdoor ${PREFIX}/ssh-backdoor && \ + cp -av scripts/ssh-backdoor ${PREFIX}/ssh-backdoor && \ + cp -av scripts/ssh-backdoor-connect-local ${PREFIX}/ssh-backdoor-connect-local && \ + cp -av scripts/ssh-backdoor-connect ${PREFIX}/ssh-backdoor-connect && \ true' clean: diff --git a/src/ssh-backdoor b/src/ssh-backdoor index dbbe66a..d757a44 100755 --- a/src/ssh-backdoor +++ b/src/ssh-backdoor @@ -2,6 +2,7 @@ from datetime import timedelta, datetime from tabulate import tabulate +import psutil import random import sqlite3 import time, os, sys @@ -27,6 +28,14 @@ def setup_options(): default = False, help = "Clear the database of everything, first" ) + parser.add_argument( + "--kill", + action = 'store', + dest = 'kill', + default = None, + type = str, + help="Kill processes of given ID" + ) parser.add_argument( "--list","-l", action = 'store_true', @@ -75,12 +84,23 @@ def setup_options(): return options +def eprint(s): + ewrite(str(s) + "\n") + + +def ewrite(s): + sys.stderr.write(str(s)) + sys.stderr.flush() + + class DataBase: def __init__(self, DB): self.alive = 7 * 24 * 3600 # 7 days self.DBfile = DB self.conn = None self.db = None + self.id = None + self.to_die = False if not os.path.exists(self.DBfile): self.createDB() self.conn_init() @@ -124,23 +144,64 @@ class DataBase: self.db.execute("DELETE FROM ports WHERE id = ?", (row[0],)) self.conn_end() + def die(self): + eprint("\n\nDying by request\n\n") + parent = self.get_pid() + if parent > 1: + try: + os.kill(parent, 9) + except OSError: + pass + sys.exit(1) + + + def check_die(self): """ kills process, and parents, if set to die """ - pass + if self.id == None: + return + self.db = self.conn.cursor() + self.db.execute("SELECT id,pid,die FROM ports WHERE id = ?", (self.id,)) + result = self.db.fetchall() + if len(result) == 0: + return None + to_die = result[0][2] + # if parent process is 1, then ssh connection has died + self.to_die = self.to_die or to_die == 1 or result[0][1] == 1 + if self.to_die: + self.die() + + + def set_to_die(self, id): + """ set to die """ + + self.db = self.conn.cursor() + self.db.execute("SELECT id FROM ports WHERE id = ?", (id,)) + result = self.db.fetchall() + if len(result) == 0: + eprint("No such ID found") + return None + self.db.execute("UPDATE ports SET die = 1 WHERE id = ?", + (id,) + ) + self.conn_end() + def update(self, id): + self.id = id port = self.get_port(id) if port == None: port = self.new_port() - + parent = self.get_pid() self.db = self.conn.cursor() - self.db.execute("INSERT OR REPLACE INTO ports(id,port,date,pid,host) \ - VALUES(?,?,?,?,?)",( + self.db.execute("INSERT OR REPLACE INTO ports(id,port,date,pid,host,die) \ + VALUES(?,?,?,?,?,?)",( id, port, int(time.time()), - self.get_pid(), - os.getenv("SSH_CLIENT","-").split(" ")[0] + parent, + os.getenv("SSH_CLIENT","-").split(" ")[0], + self.to_die ) ) self.conn_end() @@ -197,38 +258,47 @@ 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.kill: + db.set_to_die(opts.kill) + sys.exit(0) + if opts.id != None: print(db.update(opts.id)) if opts.wait: - sys.stderr.write( + ewrite( " Connected\r" ) while True: if time.time() - start_time > 3600: sys.exit(0) + db.check_die() db.update(opts.id) for i in range(10): - db.die() - time.sleep(3 + random.random()) - sys.stderr.write( + time.sleep(1)#0 * random.random()) + ewrite( " " + time.strftime("%c") + "\r" diff --git a/src/ssh-backdoor-open b/src/ssh-backdoor-open index 9d1f929..21aaf86 100755 --- a/src/ssh-backdoor-open +++ b/src/ssh-backdoor-open @@ -2,7 +2,6 @@ export PATH=$PATH:/usr/local/bin -set -x if [[ "$1" = update ]]; then set -e curl --fail {{BACKDOORURL}} > /tmp/ssh-backdoor-open && { @@ -14,11 +13,13 @@ if [[ "$1" = update ]]; then fi _ssh() { - timeout 3700 ssh \ + timeout -k 10 3700 ssh \ -o UserKnownHostsFile=/dev/null \ -o StrictHostKeyChecking=no \ -o ConnectTimeout=10 \ - -p ${BACKDOORPORT} + -o ServerAliveInterval=15 \ + -o ServerAliveCountMax=3 \ + -p ${BACKDOORPORT} \ ${BACKDOORHOST} \ "$@" #~ -o "ExitOnForwardFailure yes" \ @@ -28,6 +29,7 @@ BACKDOORHOST={{BACKDOORHOST}} BACKDOORPORT={{BACKDOORPORT}} USER=$( id -u -n ) echo use of ssh-add is encouraged +( sleep 3; printf "%d\r" $SECONDS ) & while true; do port=$( _ssh bin/ssh-backdoor $USER@$HOSTNAME ) [[ -z "$port" ]] && { sleep 2; continue; } @@ -42,3 +44,4 @@ while true; do } sleep 10 done +kill %1