The main Bubble source repository. Contains the Bubble API server, the web UI, documentation and utilities. https://getbubblenow.com
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

bubble_api.py 4.2 KiB

4 år sedan
4 år sedan
4 år sedan
4 år sedan
4 år sedan
4 år sedan
4 år sedan
4 år sedan
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. #
  2. # Copyright (c) 2020 Bubble, Inc. All rights reserved. For personal (non-commercial) use, see license: https://getbubblenow.com/bubble-license/
  3. #
  4. import requests
  5. import traceback
  6. import sys
  7. import os
  8. import time
  9. import uuid
  10. import datetime
  11. import redis
  12. import json
  13. from bubble_config import bubble_network, bubble_port
  14. # Write python PID to file so that mitmdump_monitor.sh can check for excessive memory usage and restart if needed
  15. MITMDUMP_PID_FILE_PATH = '/home/mitmproxy/mitmdump.pid'
  16. MITMDUMP_PID_FILE = open(MITMDUMP_PID_FILE_PATH, "w")
  17. MITMDUMP_PID_FILE.write("%d" % os.getpid())
  18. MITMDUMP_PID_FILE.close()
  19. HEADER_USER_AGENT = 'User-Agent'
  20. HEADER_REFERER = 'Referer'
  21. CTX_BUBBLE_MATCHERS='X-Bubble-Matchers'
  22. CTX_BUBBLE_ABORT='X-Bubble-Abort'
  23. CTX_BUBBLE_PASSTHRU='X-Bubble-Passthru'
  24. CTX_BUBBLE_REQUEST_ID='X-Bubble-RequestId'
  25. CTX_CONTENT_LENGTH='X-Bubble-Content-Length'
  26. CTX_CONTENT_LENGTH_SENT='X-Bubble-Content-Length-Sent'
  27. BUBBLE_URI_PREFIX='/__bubble/'
  28. REDIS = redis.Redis(host='127.0.0.1', port=6379, db=0)
  29. BUBBLE_ACTIVITY_LOG_PREFIX = 'bubble_activity_log_'
  30. BUBBLE_ACTIVITY_LOG_EXPIRATION = 600
  31. def redis_set(name, value, ex):
  32. REDIS.set(name, value, nx=True, ex=ex)
  33. REDIS.set(name, value, xx=True, ex=ex)
  34. def bubble_log(message):
  35. print(str(datetime.datetime.time(datetime.datetime.now()))+': ' + message, file=sys.stderr)
  36. def bubble_activity_log(client_addr, server_addr, event, data):
  37. key = BUBBLE_ACTIVITY_LOG_PREFIX + str(time.time() * 1000.0) + '_' + str(uuid.uuid4())
  38. value = json.dumps({
  39. 'source': 'mitmproxy',
  40. 'client_addr': client_addr,
  41. 'server_addr': server_addr,
  42. 'event': event,
  43. 'data': data
  44. })
  45. bubble_log('bubble_activity_log: setting '+key+' = '+value)
  46. redis_set(key, value, BUBBLE_ACTIVITY_LOG_EXPIRATION)
  47. pass
  48. def bubble_passthru(remote_addr, addr, fqdn):
  49. headers = {
  50. 'X-Forwarded-For': remote_addr,
  51. 'Accept' : 'application/json',
  52. 'Content-Type': 'application/json'
  53. }
  54. try:
  55. data = {
  56. 'addr': str(addr),
  57. 'fqdn': str(fqdn),
  58. 'remoteAddr': remote_addr
  59. }
  60. response = requests.post('http://127.0.0.1:'+bubble_port+'/api/filter/passthru', headers=headers, json=data)
  61. return response.ok
  62. except Exception as e:
  63. bubble_log('bubble_passthru API call failed: '+repr(e))
  64. traceback.print_exc()
  65. return False
  66. def bubble_matchers(req_id, remote_addr, flow, host):
  67. headers = {
  68. 'X-Forwarded-For': remote_addr,
  69. 'Accept' : 'application/json',
  70. 'Content-Type': 'application/json'
  71. }
  72. if HEADER_USER_AGENT not in flow.request.headers:
  73. bubble_log('bubble_matchers: no User-Agent header, setting to UNKNOWN')
  74. user_agent = 'UNKNOWN'
  75. else:
  76. user_agent = flow.request.headers[HEADER_USER_AGENT]
  77. if HEADER_REFERER not in flow.request.headers:
  78. bubble_log('bubble_matchers: no Referer header, setting to NONE')
  79. referer = 'NONE'
  80. else:
  81. try:
  82. referer = flow.request.headers[HEADER_REFERER].encode().decode()
  83. except Exception as e:
  84. bubble_log('bubble_matchers: error parsing Referer header: '+repr(e))
  85. referer = 'NONE'
  86. try:
  87. data = {
  88. 'requestId': req_id,
  89. 'fqdn': host,
  90. 'uri': flow.request.path,
  91. 'userAgent': user_agent,
  92. 'referer': referer,
  93. 'remoteAddr': remote_addr
  94. }
  95. response = requests.post('http://127.0.0.1:'+bubble_port+'/api/filter/matchers/'+req_id, headers=headers, json=data)
  96. if response.ok:
  97. return response.json()
  98. bubble_log('bubble_matchers response not OK, returning empty matchers array: '+str(response.status_code)+' / '+repr(response.text))
  99. except Exception as e:
  100. bubble_log('bubble_matchers API call failed: '+repr(e))
  101. traceback.print_exc()
  102. return None
  103. def add_flow_ctx(flow, name, value):
  104. if not hasattr(flow, 'bubble_ctx'):
  105. flow.bubble_ctx = {}
  106. flow.bubble_ctx[name] = value
  107. def get_flow_ctx(flow, name):
  108. if not hasattr(flow, 'bubble_ctx'):
  109. return None
  110. if not name in flow.bubble_ctx:
  111. return None
  112. return flow.bubble_ctx[name]