-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
108 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
#!/usr/bin/env python2 | ||
|
||
import argparse, ConfigParser, os, socket, subprocess | ||
|
||
class Knocker: | ||
def __init__(self, host, target_port, openseq, closeseq): | ||
self.host = host; | ||
self.target_port = target_port; | ||
self.openseq = openseq; | ||
self.closeseq = closeseq; | ||
|
||
self.skt = socket.socket(socket.AF_INET, socket.SOCK_STREAM); | ||
|
||
def is_open(self): | ||
return self.knock(self.target_port); | ||
|
||
def open(self): | ||
print self.openseq; | ||
for port in self.openseq: | ||
self.knock(port); | ||
|
||
def close(self): | ||
print self.closeseq; | ||
for port in self.closeseq: | ||
self.knock(port); | ||
|
||
def knock(self, port): | ||
try: | ||
self.skt.connect( (self.host, port) ); | ||
self.skt.shutdown(2); | ||
return True; | ||
except: | ||
return False; | ||
|
||
|
||
if __name__ == "__main__": | ||
cfg = { | ||
'host': 'localhost', | ||
'port': 22, | ||
'command': 'ssh localhost', | ||
'openseq': [1234, 5678, 9123], | ||
'closeseq': [2345, 6789, 1234] | ||
}; | ||
|
||
# configure from config file | ||
cp = ConfigParser.SafeConfigParser(); | ||
cp.read([os.path.expanduser("~/.knocker")]); | ||
|
||
if cp.has_section('config'): | ||
for op in cfg.keys(): | ||
if cp.has_option('config', op): | ||
if op in ['host', 'command']: | ||
cfg[op] = cp.get('config', op); | ||
|
||
elif op == 'port': | ||
cfg[op] = cp.getint('config', op); | ||
|
||
elif op in ['openseq', 'closeseq']: | ||
_ = cp.get('config', op); | ||
_ = _.replace(' ', ''); | ||
_ = _.split(','); | ||
cfg[op] = [ int(__) for __ in _ ]; | ||
|
||
# configure from command line | ||
p = argparse.ArgumentParser(description="Port Knocker"); | ||
|
||
p.add_argument('-H', '--host', action='store', type=str, | ||
dest='host', default=cfg['host'], help="host"); | ||
|
||
p.add_argument('-p', '--target-port', action='store', type=int, | ||
dest='port', default=cfg['port'], help="target port to open"); | ||
|
||
p.add_argument('-r', '--command', action='store', type=str, | ||
dest='command', default=cfg['command'], help="command to run"); | ||
|
||
p.add_argument('-o', '--open-seq', action='store', type=int, nargs='+', | ||
dest='openseq', default=cfg['openseq'], help="open sequence"); | ||
|
||
p.add_argument('-c', '--close-seq', action='store', type=int, nargs='+', | ||
dest='closeseq', default=cfg['closeseq'], help="close sequence"); | ||
|
||
p.add_argument('-O', '--no-open', action='store_false', default=True, | ||
dest='doopen', help="don't try to open the port"); | ||
|
||
p.add_argument('-C', '--no-close', action='store_false', default=True, | ||
dest='doclose', help="don't try to close the port"); | ||
|
||
args = p.parse_args(); | ||
|
||
# start knocking | ||
knocker = Knocker(args.host, args.port, args.openseq, args.closeseq); | ||
|
||
if args.doopen and not knocker.is_open(): | ||
print "\033[92m -> opening ports...", | ||
knocker.open(); | ||
print "done\033[0m" | ||
|
||
print " \033[92m-> starting command...\033[0m" | ||
|
||
# run command | ||
subprocess.call(args.command, shell=True); | ||
|
||
print " \033[92m-> command done\033[0m" | ||
|
||
if args.doclose: | ||
print " \033[92m-> closing ports...", | ||
knocker.close(); | ||
print "done\033[0m" |