|
- #
- # Copyright (c) 2020 Bubble, Inc. All rights reserved. For personal (non-commercial) use, see license: https://getbubblenow.com/bubble-license/
- #
- import requests
- import traceback
- import sys
- import os
- import time
- import uuid
- import datetime
- import redis
- import json
- from bubble_config import bubble_network, bubble_port
-
- # Write python PID to file so that mitmdump_monitor.sh can check for excessive memory usage and restart if needed
- MITMDUMP_PID_FILE_PATH = '/home/mitmproxy/mitmdump.pid'
- MITMDUMP_PID_FILE = open(MITMDUMP_PID_FILE_PATH, "w")
- MITMDUMP_PID_FILE.write("%d" % os.getpid())
- MITMDUMP_PID_FILE.close()
-
- HEADER_USER_AGENT = 'User-Agent'
- HEADER_REFERER = 'Referer'
-
- CTX_BUBBLE_MATCHERS='X-Bubble-Matchers'
- CTX_BUBBLE_ABORT='X-Bubble-Abort'
- CTX_BUBBLE_PASSTHRU='X-Bubble-Passthru'
- CTX_BUBBLE_REQUEST_ID='X-Bubble-RequestId'
- CTX_CONTENT_LENGTH='X-Bubble-Content-Length'
- CTX_CONTENT_LENGTH_SENT='X-Bubble-Content-Length-Sent'
- BUBBLE_URI_PREFIX='/__bubble/'
-
- REDIS = redis.Redis(host='127.0.0.1', port=6379, db=0)
- BUBBLE_ACTIVITY_LOG_PREFIX = 'bubble_activity_log_'
- BUBBLE_ACTIVITY_LOG_EXPIRATION = 600
-
- def redis_set(name, value, ex):
- REDIS.set(name, value, nx=True, ex=ex)
- REDIS.set(name, value, xx=True, ex=ex)
-
-
- def bubble_log(message):
- print(str(datetime.datetime.time(datetime.datetime.now()))+': ' + message, file=sys.stderr)
-
-
- def bubble_activity_log(client_addr, server_addr, event, data):
- key = BUBBLE_ACTIVITY_LOG_PREFIX + str(time.time() * 1000.0) + '_' + str(uuid.uuid4())
- value = json.dumps({
- 'source': 'mitmproxy',
- 'client_addr': client_addr,
- 'server_addr': server_addr,
- 'event': event,
- 'data': data
- })
- bubble_log('bubble_activity_log: setting '+key+' = '+value)
- redis_set(key, value, BUBBLE_ACTIVITY_LOG_EXPIRATION)
- pass
-
-
- def bubble_passthru(remote_addr, addr, fqdn):
- headers = {
- 'X-Forwarded-For': remote_addr,
- 'Accept' : 'application/json',
- 'Content-Type': 'application/json'
- }
- try:
- data = {
- 'addr': str(addr),
- 'fqdn': str(fqdn),
- 'remoteAddr': remote_addr
- }
- response = requests.post('http://127.0.0.1:'+bubble_port+'/api/filter/passthru', headers=headers, json=data)
- return response.ok
- except Exception as e:
- bubble_log('bubble_passthru API call failed: '+repr(e))
- traceback.print_exc()
- return False
-
-
- def bubble_matchers(req_id, remote_addr, flow, host):
- headers = {
- 'X-Forwarded-For': remote_addr,
- 'Accept' : 'application/json',
- 'Content-Type': 'application/json'
- }
- if HEADER_USER_AGENT not in flow.request.headers:
- bubble_log('bubble_matchers: no User-Agent header, setting to UNKNOWN')
- user_agent = 'UNKNOWN'
- else:
- user_agent = flow.request.headers[HEADER_USER_AGENT]
-
- if HEADER_REFERER not in flow.request.headers:
- bubble_log('bubble_matchers: no Referer header, setting to NONE')
- referer = 'NONE'
- else:
- try:
- referer = flow.request.headers[HEADER_REFERER].encode().decode()
- except Exception as e:
- bubble_log('bubble_matchers: error parsing Referer header: '+repr(e))
- referer = 'NONE'
-
- try:
- data = {
- 'requestId': req_id,
- 'fqdn': host,
- 'uri': flow.request.path,
- 'userAgent': user_agent,
- 'referer': referer,
- 'remoteAddr': remote_addr
- }
- response = requests.post('http://127.0.0.1:'+bubble_port+'/api/filter/matchers/'+req_id, headers=headers, json=data)
- if response.ok:
- return response.json()
- bubble_log('bubble_matchers response not OK, returning empty matchers array: '+str(response.status_code)+' / '+repr(response.text))
- except Exception as e:
- bubble_log('bubble_matchers API call failed: '+repr(e))
- traceback.print_exc()
- return None
-
- def add_flow_ctx(flow, name, value):
- if not hasattr(flow, 'bubble_ctx'):
- flow.bubble_ctx = {}
- flow.bubble_ctx[name] = value
-
- def get_flow_ctx(flow, name):
- if not hasattr(flow, 'bubble_ctx'):
- return None
- if not name in flow.bubble_ctx:
- return None
- return flow.bubble_ctx[name]
|