Skip to content

Instantly share code, notes, and snippets.

@rfc1459
Created April 27, 2011 21:20
Show Gist options
  • Save rfc1459/945240 to your computer and use it in GitHub Desktop.
Save rfc1459/945240 to your computer and use it in GitHub Desktop.
Simple Packet Authentication client for xt_pknock
#!/usr/bin/env python
import hashlib
import hmac
import re
import struct
import socket
from socket import AF_INET, SOCK_DGRAM
import sys
import urllib2
from time import time
_IPRE = re.compile(r'Current IP Address: (?P<addr>(?:(?:(?:2(?:5[0-5]|[0-4][0-9]))|[0-1]?[0-9]?[0-9])\.){3}(?:(?:(?:2(?:5[0-5]|[0-4][0-9]))|[0-1]?[0-9]?[0-9])))')
def _get_external_address():
ufd = urllib2.urlopen('http://checkip.dyndns.org/')
udata = ufd.readlines()
ufd.close()
assert len(udata) >= 1, "Empty reply from DynDNS"
m = _IPRE.search(udata[0])
assert m is not None, "Invalid reply from DynDNS: %r" % udata[0]
return m.group('addr')
class Spa(object):
def __init__(self, target, secret, myaddr=None):
self.target = target
self.secret = secret
self.myaddr = myaddr if myaddr is not None else _get_external_address()
def __gen_spa(self):
epoch_mins = int(time() / 60)
s = hmac.HMAC(self.secret, digestmod=hashlib.sha256)
s.update(socket.inet_aton(self.myaddr))
s.update(struct.pack("i", epoch_mins))
return s.hexdigest() + '\0'
def send(self):
spa = self.__gen_spa()
s = socket.socket(family=AF_INET, type=SOCK_DGRAM)
s.sendto(spa, self.target)
s.close()
def main(target, secret, addr=None):
spa = Spa(target, secret, addr)
print "Knocking %s:%d" % target
spa.send()
print "Done"
if __name__ == '__main__':
if len(sys.argv) < 4:
print >>sys.stderr, "Usage: %s target port secret [local_addr]" % sys.argv[0]
else:
taddr = socket.gethostbyname(sys.argv[1])
tport = int(sys.argv[2])
secret = sys.argv[3]
addr = socket.gethostbyname(sys.argv[4]) if len(sys.argv) > 4 else None
main((taddr, tport), secret, addr)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment