From e25a63c386ac0d4cf8f3715f4c126e7d004d6588 Mon Sep 17 00:00:00 2001 From: Simon Date: Sun, 6 Mar 2022 18:07:38 +0000 Subject: [PATCH] auto blacklist for 60 seconds on bad ID --- const.py | 3 ++- hblink.py | 10 ++++++++++ hotspot_proxy_v2.py | 43 +++++++++++++++++++++++++++++++++++++------ 3 files changed, 49 insertions(+), 7 deletions(-) diff --git a/const.py b/const.py index 53279da..37b1f65 100755 --- a/const.py +++ b/const.py @@ -73,8 +73,9 @@ RPTA = b'RPTA' RPTO = b'RPTO' DMRA = b'DMRA' -#Prox commands +#Proxy commands PRIN = b'PRIN' +PRBL = b'PRBL' #Bridge Control commands BC = b'BC' diff --git a/hblink.py b/hblink.py index f846eda..fec6739 100755 --- a/hblink.py +++ b/hblink.py @@ -808,6 +808,14 @@ class HBSYSTEM(DatagramProtocol): self.send_master(RPTCL + self._config['RADIO_ID']) logger.info('(%s) De-Registration sent to Master: %s:%s', self._system, self._config['MASTER_SOCKADDR'][0], self._config['MASTER_SOCKADDR'][1]) + def proxy_IPBlackList(self,sockddr): + _timenow = time() + _bltime = _timenow + 60 + _bltime = str(bltime) + _prpacket = b''.join([PRBL,_bltime.encode('UTF-8')]) + self.transport.write(_prpacket,sockaddr) + + def validate_id(self,_peer_id): if 'ALLOW_UNREG_ID' not in self._config: @@ -954,6 +962,7 @@ class HBSYSTEM(DatagramProtocol): logger.info('(%s) Sent Challenge Response to %s for login: %s', self._system, int_id(_peer_id), self._peers[_peer_id]['SALT']) else: self.transport.write(b''.join([MSTNAK, _peer_id]), _sockaddr) + self.proxy_IPBlackList(_sockaddr) logger.warning('(%s) Invalid Login from %s Radio ID: %s Denied by Registation ACL or not registered ID', self._system, _sockaddr[0], int_id(_peer_id)) else: self.transport.write(b''.join([MSTNAK, _peer_id]), _sockaddr) @@ -1030,6 +1039,7 @@ class HBSYSTEM(DatagramProtocol): if ('ALLOW_UNREG_ID' in self._config and not self._config['ALLOW_UNREG_ID']) and _this_peer['CALLSIGN'].decode('utf8').rstrip() != self.validate_id(_peer_id): del self._peers[_peer_id] self.transport.write(b''.join([MSTNAK, _peer_id]), _sockaddr) + self.proxy_IPBlackList(_sockaddr) logger.info('(%s) Callsign does not match subscriber database: ID: %s, Sent Call: %s, DB call %s', self._system, int_id(_peer_id),_this_peer['CALLSIGN'].decode('utf8').rstrip(),self.validate_id(_peer_id)) else: self.send_peer(_peer_id, b''.join([RPTACK, _peer_id])) diff --git a/hotspot_proxy_v2.py b/hotspot_proxy_v2.py index 4a52bac..433cdad 100644 --- a/hotspot_proxy_v2.py +++ b/hotspot_proxy_v2.py @@ -28,7 +28,7 @@ from datetime import datetime # Does anybody read this stuff? There's a PEP somewhere that says I should do this. __author__ = 'Simon Adlem - G7RZU' -__copyright__ = 'Copyright (c) Simon Adlem, G7RZU 2020,2021' +__copyright__ = 'Copyright (c) Simon Adlem, G7RZU 2020,2021,2022' __credits__ = 'Jon Lee, G4TSN; Norman Williams, M6NBP; Christian, OA4DOA' __license__ = 'GNU GPLv3' __maintainer__ = 'Simon Adlem G7RZU' @@ -51,7 +51,7 @@ def IsIPv6Address(ip): class Proxy(DatagramProtocol): - def __init__(self,Master,ListenPort,connTrack,blackList,Timeout,Debug,ClientInfo,DestportStart,DestPortEnd): + def __init__(self,Master,ListenPort,connTrack,blackList,IPBlackList,Timeout,Debug,ClientInfo,DestportStart,DestPortEnd): self.master = Master self.connTrack = connTrack self.peerTrack = {} @@ -59,6 +59,7 @@ class Proxy(DatagramProtocol): self.debug = Debug self.clientinfo = ClientInfo self.blackList = blackList + self.IPBlackList = IPBlackList self.destPortStart = DestportStart self.destPortEnd = DestPortEnd self.numPorts = DestPortEnd - DestportStart @@ -72,7 +73,6 @@ class Proxy(DatagramProtocol): self.transport.write(b'RPTCL'+_peer_id, (self.master,self.peerTrack[_peer_id]['dport'])) self.connTrack[self.peerTrack[_peer_id]['dport']] = False del self.peerTrack[_peer_id] - def datagramReceived(self, data, addr): @@ -96,6 +96,9 @@ class Proxy(DatagramProtocol): RPTA = b'RPTA' RPTO = b'RPTO' + #Proxy control commands + PRBL = b'PRBL' + _peer_id = False host,port = addr @@ -104,10 +107,22 @@ class Proxy(DatagramProtocol): Debug = self.debug + if host in self.IPBlackList: + return + #If the packet comes from the master if host == self.master: _command = data[:4] + if _command == PRBL: + _bltime = data[4:].decode('UTF-8') + _bltime = float(_bltime) + try: + self.IPBlackList[self.peerTrack[_peer_id]['shost']] = _bltime + except KeyError: + pass + return + if _command == DMRD: _peer_id = data[11:15] elif _command == RPTA: @@ -209,6 +224,8 @@ if __name__ == '__main__': Debug = False ClientInfo = False BlackList = [1234567] + #e.g. {10.0.0.1: 0, 10.0.0.2: 0} + IPBlackList = {} #******************* @@ -241,7 +258,7 @@ if __name__ == '__main__': if ListenIP == '::' and IsIPv4Address(Master): Master = '::ffff:' + Master - reactor.listenUDP(ListenPort,Proxy(Master,ListenPort,CONNTRACK,BlackList,Timeout,Debug,ClientInfo,DestportStart,DestPortEnd),interface=ListenIP) + reactor.listenUDP(ListenPort,Proxy(Master,ListenPort,CONNTRACK,BlackList,IPBlackList,Timeout,Debug,ClientInfo,DestportStart,DestPortEnd),interface=ListenIP) def loopingErrHandle(failure): print('(GLOBAL) STOPPING REACTOR TO AVOID MEMORY LEAK: Unhandled error innowtimed loop.\n {}'.format(failure)) @@ -258,13 +275,27 @@ if __name__ == '__main__': freePorts = totalPorts - count print("{} ports out of {} in use ({} free)".format(count,totalPorts,freePorts)) - + + def blackListTrimmer(): + _timenow = time() + _dellist = [] + for entry in IPBlackList: + deletetime = IPBlackList[entry] + if deletetime and deletetime < _timenow: + _dellist.append(entry) + + for delete in _dellist: + IPBlackList.pop(delete) if Stats == True: stats_task = task.LoopingCall(stats) statsa = stats_task.start(30) statsa.addErrback(loopingErrHandle) - + + blacklist_task = task.LoopingCall(blackListTrimmer) + blacklista = blacklist_task.start(15) + blacklista.addErrback(loopingErrHandle) + reactor.run()