From 9e38188d57b584a993eb78caa15c886c01ea8852 Mon Sep 17 00:00:00 2001 From: Mike Crute Date: Sun, 13 Dec 2015 17:44:39 -0800 Subject: Initial import --- redirecting_proxy.py | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++ translating_proxy.py | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 165 insertions(+) create mode 100755 redirecting_proxy.py create mode 100755 translating_proxy.py diff --git a/redirecting_proxy.py b/redirecting_proxy.py new file mode 100755 index 0000000..29f5df4 --- /dev/null +++ b/redirecting_proxy.py @@ -0,0 +1,84 @@ +#!/usr/bin/python +import time +import select +import socket + + +class Proxy: + + buffer_size = 4096 * 2 + delay = 0.0001 + + def __init__(self, host_port, to_host_port): + self.forward_to = to_host_port + self.input_list = [] + self.channel = {} + + self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + self.server.bind(host_port) + self.server.listen(200) + + def main_loop(self): + self.input_list.append(self.server) + + while time.sleep(self.delay) or True: + for self.s in select.select(self.input_list, [], [])[0]: + if self.s == self.server: + self.on_accept() + break + + self.data = self.s.recv(self.buffer_size) + if len(self.data) == 0: + self.on_close() + break + else: + self.on_recv() + + def on_accept(self): + forward = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + clientsock, clientaddr = self.server.accept() + try: + forward.connect(self.forward_to) + + self.input_list.append(clientsock) + self.input_list.append(forward) + self.channel[clientsock] = forward + self.channel[forward] = clientsock + except Exception: + clientsock.close() + + def on_close(self): + out = self.channel[self.s] + + self.input_list.remove(self.s) + self.input_list.remove(self.channel[self.s]) + + self.channel[out].close() + self.channel[self.s].close() + + del self.channel[out] + del self.channel[self.s] + + def on_recv(self): + if self.allow_data(): + print repr(self.data) + self.channel[self.s].send(self.data) + + def allow_data(self): + return not ("admin.$cmd" in self.data and "shutdown" in self.data) + + +if __name__ == '__main__': + import os, sys + + if len(sys.argv) < 3 or ":" not in sys.argv[2]: + program = os.path.basename(sys.argv[0]) + print "usage: {} :".format(program) + sys.exit(1) + + try: + to_host, to_port = sys.argv[2].split(":") + Proxy(('', int(sys.argv[1])), (to_host, int(to_port))).main_loop() + except KeyboardInterrupt: + sys.exit(1) diff --git a/translating_proxy.py b/translating_proxy.py new file mode 100755 index 0000000..7e03e1b --- /dev/null +++ b/translating_proxy.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python + +import struct +from bson import BSON +from StringIO import StringIO + + +DB_OFFSET = 16 + 4 # headers + flags + +OP_REPLY = 1 +OP_UPDATE = 2001 +OP_INSERT = 2002 +OP_QUERY = 2004 +OP_GET_MORE = 2005 +OP_DELETE = 2006 + +# Touchup DB +OP_TOUCHUP_DB = set((OP_UPDATE, OP_INSERT, OP_QUERY, OP_GET_MORE, OP_DELETE)) + +def fixup_ns(raw_data, replace_with): + try: + data = BSON(raw_data).decode() + except: + return + + if "ns" in data: + db, collection = data["ns"].split(".", 1) + data["ns"] = ".".join((replace_with, collection)) + return BSON.encode(data) + else: + return raw_data + + +def fixup_db(data, replace_with): + null = data.index("\x00") + db, collection = data[:null].split(".", 1) + replace_with = "admin" if db == "admin" else replace_with + fixed_up = "{}.{}\x00".format(replace_with, collection) + return fixed_up, (collection == "system.indexes") + + +def handle_line(line): + output = StringIO() + + length, req_id, resp_to, msg_type, flags = struct.unpack_from("