@@ -12,14 +12,14 @@ import static org.cobbzilla.util.daemon.ZillaRuntime.empty; | |||
public class FilterConnCheckRequest { | |||
@Getter @Setter private String addr; | |||
public boolean hasAddr() { return !empty(addr); } | |||
@Getter @Setter private String clientAddr; | |||
public boolean hasClientAddr() { return !empty(clientAddr); } | |||
@Getter @Setter private String serverAddr; | |||
public boolean hasServerAddr() { return !empty(serverAddr); } | |||
@Getter @Setter private String[] fqdns; | |||
public boolean hasFqdns() { return !empty(fqdns); } | |||
public boolean hasFqdn(String f) { return hasFqdns() && ArrayUtils.contains(fqdns, f); } | |||
@Getter @Setter private String remoteAddr; | |||
public boolean hasRemoteAddr() { return !empty(remoteAddr); } | |||
} |
@@ -26,6 +26,7 @@ import bubble.service.block.BlockStatsService; | |||
import bubble.service.block.BlockStatsSummary; | |||
import bubble.service.boot.SelfNodeService; | |||
import bubble.service.device.DeviceService; | |||
import bubble.service.device.FlexRouterInfo; | |||
import bubble.service.device.StandardFlexRouterService; | |||
import bubble.service.stream.ConnectionCheckResponse; | |||
import bubble.service.stream.StandardRuleEngineService; | |||
@@ -149,7 +150,7 @@ public class FilterHttpResource { | |||
@Context ContainerRequest request, | |||
FilterConnCheckRequest connCheckRequest) { | |||
final String prefix = "checkConnection: "; | |||
if (connCheckRequest == null || !connCheckRequest.hasAddr() || !connCheckRequest.hasRemoteAddr()) { | |||
if (connCheckRequest == null || !connCheckRequest.hasServerAddr() || !connCheckRequest.hasClientAddr()) { | |||
if (log.isDebugEnabled()) log.debug(prefix+"invalid connCheckRequest, returning forbidden"); | |||
return forbidden(); | |||
} | |||
@@ -160,12 +161,12 @@ public class FilterHttpResource { | |||
if (isLocalIp) { | |||
// if it is for our host or net name, passthru | |||
if (connCheckRequest.hasFqdns() && (connCheckRequest.hasFqdn(getThisNode().getFqdn()) || connCheckRequest.hasFqdn(getThisNetwork().getNetworkDomain()))) { | |||
if (log.isDebugEnabled()) log.debug(prefix + "returning passthru for LOCAL fqdn/addr=" + arrayToString(connCheckRequest.getFqdns()) + "/" + connCheckRequest.getAddr()); | |||
if (log.isDebugEnabled()) log.debug(prefix + "returning passthru for LOCAL fqdn/addr=" + arrayToString(connCheckRequest.getFqdns()) + "/" + connCheckRequest.getServerAddr()); | |||
return ok(ConnectionCheckResponse.passthru); | |||
} | |||
} | |||
final String vpnAddr = connCheckRequest.getRemoteAddr(); | |||
final String vpnAddr = connCheckRequest.getClientAddr(); | |||
final Device device = deviceService.findDeviceByIp(vpnAddr); | |||
if (device == null) { | |||
if (log.isDebugEnabled()) log.debug(prefix+"device not found for IP "+vpnAddr+", returning not found"); | |||
@@ -181,14 +182,14 @@ public class FilterHttpResource { | |||
} | |||
if (isLocalIp) { | |||
final boolean showStats = showStats(accountUuid, connCheckRequest.getAddr(), connCheckRequest.getFqdns()); | |||
final boolean showStats = showStats(accountUuid, connCheckRequest.getServerAddr(), connCheckRequest.getFqdns()); | |||
final DeviceSecurityLevel secLevel = device.getSecurityLevel(); | |||
if (showStats && secLevel.supportsRequestModification()) { | |||
// allow it for now | |||
if (log.isDebugEnabled()) log.debug(prefix + "returning noop (showStats=true, secLevel="+secLevel+") for LOCAL fqdn/addr=" + arrayToString(connCheckRequest.getFqdns()) + "/" + connCheckRequest.getAddr()); | |||
if (log.isDebugEnabled()) log.debug(prefix + "returning noop (showStats=true, secLevel="+secLevel+") for LOCAL fqdn/addr=" + arrayToString(connCheckRequest.getFqdns()) + "/" + connCheckRequest.getServerAddr()); | |||
return ok(ConnectionCheckResponse.noop); | |||
} else { | |||
if (log.isDebugEnabled()) log.debug(prefix + "returning block (showStats="+showStats+", secLevel="+secLevel+") for LOCAL fqdn/addr=" + arrayToString(connCheckRequest.getFqdns()) + "/" + connCheckRequest.getAddr()); | |||
if (log.isDebugEnabled()) log.debug(prefix + "returning block (showStats="+showStats+", secLevel="+secLevel+") for LOCAL fqdn/addr=" + arrayToString(connCheckRequest.getFqdns()) + "/" + connCheckRequest.getServerAddr()); | |||
return ok(ConnectionCheckResponse.block); | |||
} | |||
} | |||
@@ -207,17 +208,17 @@ public class FilterHttpResource { | |||
if (connCheckRequest.hasFqdns()) { | |||
final String[] fqdns = connCheckRequest.getFqdns(); | |||
for (String fqdn : fqdns) { | |||
checkResponse = ruleEngine.checkConnection(account, device, retained, connCheckRequest.getAddr(), fqdn); | |||
checkResponse = ruleEngine.checkConnection(account, device, retained, connCheckRequest.getServerAddr(), fqdn); | |||
if (checkResponse != ConnectionCheckResponse.noop) { | |||
if (log.isDebugEnabled()) log.debug(prefix + "found " + checkResponse + " (breaking) for fqdn/addr=" + fqdn + "/" + connCheckRequest.getAddr()); | |||
if (log.isDebugEnabled()) log.debug(prefix + "found " + checkResponse + " (breaking) for fqdn/addr=" + fqdn + "/" + connCheckRequest.getServerAddr()); | |||
break; | |||
} | |||
} | |||
if (log.isDebugEnabled()) log.debug(prefix+"returning "+checkResponse+" for fqdns/addr="+Arrays.toString(fqdns)+"/"+ connCheckRequest.getAddr()); | |||
if (log.isDebugEnabled()) log.debug(prefix+"returning "+checkResponse+" for fqdns/addr="+Arrays.toString(fqdns)+"/"+ connCheckRequest.getServerAddr()); | |||
return ok(checkResponse); | |||
} else { | |||
if (log.isDebugEnabled()) log.debug(prefix+"returning noop for NO fqdns, addr="+connCheckRequest.getAddr()); | |||
if (log.isDebugEnabled()) log.debug(prefix+"returning noop for NO fqdns, addr="+connCheckRequest.getServerAddr()); | |||
return ok(ConnectionCheckResponse.noop); | |||
} | |||
} | |||
@@ -228,7 +229,7 @@ public class FilterHttpResource { | |||
} | |||
private boolean isForLocalIp(FilterConnCheckRequest connCheckRequest) { | |||
return connCheckRequest.hasAddr() && getConfiguredIps().contains(connCheckRequest.getAddr()); | |||
return connCheckRequest.hasServerAddr() && getConfiguredIps().contains(connCheckRequest.getServerAddr()); | |||
} | |||
private boolean isForLocalIp(FilterMatchersRequest matchersRequest) { | |||
@@ -631,16 +632,24 @@ public class FilterHttpResource { | |||
return ok(summary); | |||
} | |||
@GET @Path(EP_FLEX_ROUTERS+"/{requestId}") | |||
public Response getFlexRouters(@Context Request req, | |||
@Context ContainerRequest ctx, | |||
@PathParam("requestId") String requestId) { | |||
final FilterSubContext filterCtx = new FilterSubContext(req, requestId); | |||
final FilterHttpRequest request = filterCtx.request; | |||
final DeviceStatus deviceStatus = deviceService.getDeviceStatus(request.getDevice().getUuid()); | |||
@GET @Path(EP_FLEX_ROUTERS) | |||
public Response getFlexRouter(@Context Request req, | |||
@Context ContainerRequest ctx) { | |||
final String vpnIp = getRemoteAddr(req); | |||
final Device device = deviceService.findDeviceByIp(vpnIp); | |||
if (device == null) { | |||
log.warn("getFlexRouters: device not found: "+vpnIp); | |||
return ok(Collections.emptySet()); | |||
} | |||
if (log.isDebugEnabled()) log.debug("getFlexRouters: finding routers for vpnIp="+vpnIp); | |||
final DeviceStatus deviceStatus = deviceService.getDeviceStatus(device.getUuid()); | |||
final String publicIp = deviceStatus.getIp(); | |||
final String vpnIp = request.getMatchersResponse().getRequest().getClientAddr(); | |||
return ok(flexRouterService.selectClosestRouter(request.getAccount().getUuid(), vpnIp, publicIp)); | |||
Collection<FlexRouterInfo> routers = flexRouterService.selectClosestRouter(device.getAccount(), vpnIp, publicIp); | |||
if (log.isDebugEnabled()) log.debug("getFlexRouters: found router(s) for vpnIp="+vpnIp+": "+json(routers)); | |||
if (routers.isEmpty()) return ok(Collections.emptySet()); | |||
return ok(routers.iterator().next().initAuth()); | |||
} | |||
@POST @Path(EP_LOGS+"/{requestId}") | |||
@@ -3,25 +3,32 @@ package bubble.service.device; | |||
import bubble.cloud.geoLocation.GeoLocation; | |||
import bubble.model.device.DeviceStatus; | |||
import bubble.model.device.FlexRouter; | |||
import lombok.EqualsAndHashCode; | |||
import com.fasterxml.jackson.annotation.JsonIgnore; | |||
import lombok.Getter; | |||
import lombok.Setter; | |||
import lombok.ToString; | |||
import static bubble.model.device.DeviceStatus.NO_DEVICE_STATUS; | |||
import static org.cobbzilla.util.json.JsonUtil.COMPACT_MAPPER; | |||
import static org.cobbzilla.util.json.JsonUtil.json; | |||
@EqualsAndHashCode(of="port") @ToString | |||
@ToString | |||
public class FlexRouterInfo { | |||
@Getter private final String vpnIp; | |||
@Getter private final int port; | |||
@Getter private final DeviceStatus deviceStatus; | |||
@JsonIgnore @Getter private final FlexRouter router; | |||
@JsonIgnore @Getter private final DeviceStatus deviceStatus; | |||
@Getter @Setter private String auth; | |||
public FlexRouterInfo (FlexRouter router, DeviceStatus deviceStatus) { | |||
this.vpnIp = router.getIp(); | |||
this.port = router.getPort(); | |||
this.router = router; | |||
this.deviceStatus = deviceStatus; | |||
} | |||
@JsonIgnore public String getVpnIp () { return router.getIp(); } | |||
@JsonIgnore public int getPort () { return router.getPort(); } | |||
public String getProxyUrl () { return router.proxyBaseUri(); } | |||
public boolean hasGeoLocation () { return hasDeviceStatus() && deviceStatus.getLocation() != null && deviceStatus.getLocation().hasLatLon(); } | |||
public boolean hasNoGeoLocation () { return !hasGeoLocation(); } | |||
@@ -35,4 +42,12 @@ public class FlexRouterInfo { | |||
public boolean hasIp () { return hasDeviceStatus() && deviceStatus.hasIp(); } | |||
public String ip () { return hasIp() ? deviceStatus.getIp() : null; } | |||
public FlexRouterInfo initAuth () { auth = json(router.pingObject(), COMPACT_MAPPER); return this; } | |||
@Override public int hashCode() { return getPort(); } | |||
@Override public boolean equals(Object obj) { | |||
return obj instanceof FlexRouterInfo && ((FlexRouterInfo) obj).getPort() == getPort(); | |||
} | |||
} |
@@ -13,14 +13,19 @@ public class FlexRouterProximityComparator implements Comparator<FlexRouterInfo> | |||
private final String preferredIp; | |||
@Override public int compare(FlexRouterInfo r1, FlexRouterInfo r2) { | |||
if (r1.getVpnIp().equals(preferredIp)) { | |||
return Integer.MIN_VALUE; | |||
} | |||
if (r2.getVpnIp().equals(preferredIp)) { | |||
return Integer.MAX_VALUE; | |||
} | |||
// if preferred ip matches, that takes precedence over everything | |||
if (r1.getVpnIp().equals(preferredIp)) return Integer.MIN_VALUE; | |||
if (r2.getVpnIp().equals(preferredIp)) return Integer.MAX_VALUE; | |||
// if a router has no location info, it goes last | |||
if (r1.hasNoGeoLocation()) return Integer.MAX_VALUE; | |||
if (r2.hasNoGeoLocation()) return Integer.MIN_VALUE; | |||
// if WE have no location info, just compare ports (we choose randomly) | |||
if (geoLocation == null) return r1.getPort() - r2.getPort(); | |||
// compare distances. if they are equals, just compare ports (we choose randomly) | |||
final double distance1 = r1.distance(geoLocation); | |||
final double distance2 = r2.distance(geoLocation); | |||
final int delta = (int) (1000.0d * (distance1 - distance2)); | |||
@@ -141,7 +141,7 @@ public class StandardFlexRouterService extends SimpleDaemon implements FlexRoute | |||
public Set<FlexRouterInfo> selectClosestRouter (String accountUuid, String publicIp, String vpnIp) { | |||
if (log.isDebugEnabled()) log.debug("selectClosestRouter: publicIp="+publicIp+", vpnIp="+vpnIp); | |||
final GeoLocation geoLocation = geoService.locate(accountUuid, publicIp); | |||
final GeoLocation geoLocation = publicIp == null ? null : geoService.locate(accountUuid, publicIp); | |||
final Collection<FlexRouterInfo> values = activeRouters.values(); | |||
switch (values.size()) { | |||
case 0: return Collections.emptySet(); | |||
@@ -12,6 +12,7 @@ import subprocess | |||
import time | |||
import traceback | |||
import uuid | |||
from http import HTTPStatus | |||
from netaddr import IPAddress, IPNetwork | |||
from bubble_vpn4 import wireguard_network_ipv4 | |||
from bubble_vpn6 import wireguard_network_ipv6 | |||
@@ -24,6 +25,7 @@ HEADER_USER_AGENT = 'User-Agent' | |||
HEADER_CONTENT_SECURITY_POLICY = 'Content-Security-Policy' | |||
HEADER_REFERER = 'Referer' | |||
HEADER_FILTER_PASSTHRU = 'X-Bubble-Passthru' | |||
HEADER_FLEX_AUTH = 'X-Bubble-Flex-Auth' | |||
CTX_BUBBLE_MATCHERS = 'X-Bubble-Matchers' | |||
CTX_BUBBLE_ABORT = 'X-Bubble-Abort' | |||
@@ -55,6 +57,10 @@ VPN_IP6_CIDR = IPNetwork(wireguard_network_ipv6) | |||
parse_host_header = re.compile(r"^(?P<host>[^:]+|\[.+\])(?::(?P<port>\d+))?$") | |||
def status_reason(status_code): | |||
return HTTPStatus(status_code).phrase | |||
def redis_set(name, value, ex): | |||
REDIS.set(name, value, nx=True, ex=ex) | |||
REDIS.set(name, value, xx=True, ex=ex) | |||
@@ -75,7 +81,7 @@ def bubble_activity_log(client_addr, server_addr, event, data): | |||
pass | |||
def bubble_conn_check(remote_addr, addr, fqdns, security_level): | |||
def bubble_conn_check(client_addr, server_addr, fqdns, security_level): | |||
if debug_capture_fqdn and fqdns: | |||
for f in debug_capture_fqdn: | |||
if f in fqdns: | |||
@@ -84,15 +90,15 @@ def bubble_conn_check(remote_addr, addr, fqdns, security_level): | |||
return 'noop' | |||
headers = { | |||
'X-Forwarded-For': remote_addr, | |||
'Accept' : 'application/json', | |||
'X-Forwarded-For': client_addr, | |||
'Accept': 'application/json', | |||
'Content-Type': 'application/json' | |||
} | |||
try: | |||
data = { | |||
'addr': str(addr), | |||
'serverAddr': str(server_addr), | |||
'fqdns': fqdns, | |||
'remoteAddr': remote_addr | |||
'clientAddr': client_addr | |||
} | |||
response = requests.post('http://127.0.0.1:'+bubble_port+'/api/filter/check', headers=headers, json=data) | |||
if response.ok: | |||
@@ -110,6 +116,26 @@ def bubble_conn_check(remote_addr, addr, fqdns, security_level): | |||
return None | |||
def bubble_get_flex_router(client_addr): | |||
headers = { | |||
'X-Forwarded-For': client_addr, | |||
'Accept': 'application/json' | |||
} | |||
try: | |||
response = requests.get('http://127.0.0.1:'+bubble_port+'/api/filter/flexRouters', headers=headers) | |||
if response.ok: | |||
return response.json() | |||
if bubble_log.isEnabledFor(ERROR): | |||
bubble_log.error('bubble_get_flex_routes API call failed: '+repr(response)) | |||
return None | |||
except Exception as e: | |||
if bubble_log.isEnabledFor(ERROR): | |||
bubble_log.error('bubble_get_flex_routes API call failed: '+repr(e)) | |||
traceback.print_exc() | |||
return None | |||
DEBUG_MATCHER_NAME = 'DebugCaptureMatcher' | |||
DEBUG_MATCHER = { | |||
'decision': 'match', | |||
@@ -139,7 +165,7 @@ def bubble_matchers(req_id, client_addr, server_addr, flow, host): | |||
headers = { | |||
'X-Forwarded-For': client_addr, | |||
'Accept' : 'application/json', | |||
'Accept': 'application/json', | |||
'Content-Type': 'application/json' | |||
} | |||
if HEADER_USER_AGENT not in flow.request.headers: | |||
@@ -0,0 +1,94 @@ | |||
# | |||
# Copyright (c) 2020 Bubble, Inc. All rights reserved. For personal (non-commercial) use, see license: https://getbubblenow.com/bubble-license/ | |||
# | |||
import requests | |||
from mitmproxy.net.http import headers as nheaders | |||
from bubble_api import HEADER_FLEX_AUTH, bubble_get_flex_router | |||
import logging | |||
from logging import INFO, DEBUG, WARNING, ERROR, CRITICAL | |||
bubble_log = logging.getLogger(__name__) | |||
def prepend_remainder_to_stream(remainder, raw): | |||
first = True | |||
while True: | |||
chunk = raw.read(8192) | |||
if first and chunk and len(remainder) > 0: | |||
yield remainder + chunk | |||
elif chunk: | |||
yield chunk | |||
else: | |||
break | |||
if first: | |||
first = False | |||
def set_flex_response(client_addr, flex_host, flow): | |||
if bubble_log.isEnabledFor(INFO): | |||
bubble_log.info('set_flex_response: checking for flex router for host: '+flex_host) | |||
router = bubble_get_flex_router(client_addr) | |||
if router is None or 'auth' not in router: | |||
if bubble_log.isEnabledFor(INFO): | |||
bubble_log.info('set_flex_response: no flex router for host: '+flex_host) | |||
return | |||
if bubble_log.isEnabledFor(INFO): | |||
bubble_log.info('set_flex_response: found router '+repr(router)+' for flex host: '+flex_host) | |||
# build the request | |||
url = flow.request.scheme + '://' + flex_host + flow.request.path | |||
headers = flow.request.headers | |||
headers[HEADER_FLEX_AUTH] = router['auth'] | |||
proxy_url = router['proxyUrl'] | |||
proxies = { "http": proxy_url, "https": proxy_url } | |||
# send request to flex router | |||
if bubble_log.isEnabledFor(DEBUG): | |||
bubble_log.debug('request: sending flex request for '+url+' to '+proxy_url) | |||
response = requests.request(flow.request.method, url, | |||
headers=headers, | |||
timeout=(15, 15), | |||
stream=True, | |||
data=flow.request.stream, | |||
proxies=proxies) | |||
# Parse the response, we have to do this raw to capture the full status line | |||
# Status line | |||
next_bytes = response.raw.read(16384) # enough to read all headers | |||
response_text = next_bytes.decode() | |||
lines = response_text.splitlines() | |||
status_line = lines[0] | |||
status_line_parts = status_line.split() | |||
flow.response.http_version = status_line_parts[0] | |||
flow.response.status_code = int(status_line_parts[1]) | |||
flow.response.reason = status_line_parts[2] | |||
# Headers | |||
response_headers = nheaders.Headers() | |||
end_of_headers = False | |||
lines = lines[1:] | |||
bytes_consumed = len(status_line) + 1 | |||
while True: | |||
for header_line in lines[:-1]: | |||
if header_line == '': | |||
bytes_consumed = bytes_consumed + 1 | |||
end_of_headers = True | |||
break | |||
header_parts = header_line.split(':', 1) | |||
response_headers[header_parts[0].strip()] = header_parts[1].strip() | |||
bytes_consumed = bytes_consumed + len(header_line) + 1 | |||
if end_of_headers: | |||
break | |||
next_bytes = response.raw.read(8192) | |||
next_text = lines[-1] + '\n' + next_bytes.decode() | |||
lines = next_text.splitlines() | |||
flow.response.headers = response_headers | |||
# Body -- prepend remainder left over from parsing headers | |||
remainder = next_bytes[bytes_consumed:] | |||
flow.response.stream = prepend_remainder_to_stream(remainder, response.raw) |
@@ -11,7 +11,7 @@ import traceback | |||
from mitmproxy.net.http import Headers | |||
from bubble_config import bubble_port, bubble_host_alias, debug_capture_fqdn, debug_stream_fqdn, debug_stream_uri | |||
from bubble_api import CTX_BUBBLE_MATCHERS, CTX_BUBBLE_ABORT, CTX_BUBBLE_LOCATION, BUBBLE_URI_PREFIX, \ | |||
HEADER_HEALTH_CHECK, HEALTH_CHECK_URI, \ | |||
HEADER_HEALTH_CHECK, HEALTH_CHECK_URI, status_reason, \ | |||
CTX_BUBBLE_REQUEST_ID, CTX_CONTENT_LENGTH, CTX_CONTENT_LENGTH_SENT, get_flow_ctx, add_flow_ctx, \ | |||
HEADER_USER_AGENT, HEADER_FILTER_PASSTHRU, HEADER_CONTENT_SECURITY_POLICY, REDIS, redis_set, parse_host_header | |||
@@ -196,6 +196,11 @@ def bubble_filter_response(flow): | |||
def responseheaders(flow): | |||
if bubble_log.isEnabledFor(DEBUG): | |||
bubble_log.info('flow.response.http_version='+flow.response.http_version) | |||
bubble_log.info('flow.response.status_code='+str(flow.response.status_code)) | |||
bubble_log.info('flow.response.reason='+flow.response.reason) | |||
path = flow.request.path | |||
if path and path.startswith(BUBBLE_URI_PREFIX): | |||
if path.startswith(HEALTH_CHECK_URI): | |||
@@ -205,6 +210,7 @@ def responseheaders(flow): | |||
flow.response.headers[HEADER_HEALTH_CHECK] = 'OK' | |||
flow.response.headers[HEADER_CONTENT_LENGTH] = '3' | |||
flow.response.status_code = 200 | |||
flow.response.reason = 'OK' | |||
flow.response.stream = lambda chunks: [b'OK\n'] | |||
else: | |||
uri = 'http://127.0.0.1:' + bubble_port + '/' + path[len(BUBBLE_URI_PREFIX):] | |||
@@ -232,6 +238,7 @@ def responseheaders(flow): | |||
for key, value in response.headers.items(): | |||
flow.response.headers[key] = value | |||
flow.response.status_code = response.status_code | |||
flow.response.reason = status_reason(response.status_code) | |||
flow.response.stream = lambda chunks: send_bubble_response(response) | |||
else: | |||
@@ -244,6 +251,7 @@ def responseheaders(flow): | |||
flow.response.headers = Headers() | |||
flow.response.headers[HEADER_LOCATION] = abort_location | |||
flow.response.status_code = abort_code | |||
flow.response.reason = status_reason(abort_code) | |||
flow.response.stream = lambda chunks: [] | |||
else: | |||
if HEADER_CONTENT_TYPE in flow.response.headers: | |||
@@ -254,6 +262,7 @@ def responseheaders(flow): | |||
bubble_log.info('responseheaders: aborting request with HTTP status '+str(abort_code)+', path was: '+path) | |||
flow.response.headers = Headers() | |||
flow.response.status_code = abort_code | |||
flow.response.reason = status_reason(abort_code) | |||
flow.response.stream = lambda chunks: abort_data(content_type) | |||
elif flow.response.status_code // 100 != 2: | |||
@@ -32,11 +32,11 @@ import time | |||
import uuid | |||
from mitmproxy.net.http import headers as nheaders | |||
from bubble_api import bubble_matchers, bubble_activity_log, HEALTH_CHECK_URI, REDIS, \ | |||
from bubble_api import bubble_matchers, bubble_activity_log, HEALTH_CHECK_URI, \ | |||
CTX_BUBBLE_MATCHERS, BUBBLE_URI_PREFIX, CTX_BUBBLE_ABORT, CTX_BUBBLE_LOCATION, CTX_BUBBLE_PASSTHRU, CTX_BUBBLE_REQUEST_ID, \ | |||
add_flow_ctx, parse_host_header, is_bubble_request, is_sage_request, is_not_from_vpn, is_flex_domain | |||
from bubble_config import bubble_host, bubble_host_alias | |||
from bubble_modify import bubble_filter_response | |||
from bubble_flex import set_flex_response | |||
bubble_log = logging.getLogger(__name__) | |||
@@ -246,19 +246,11 @@ class Rerouter: | |||
return host | |||
def request(self, flow): | |||
check_flex_host = self.bubble_handle_request(flow) | |||
if check_flex_host is not None: | |||
flex_host = self.bubble_handle_request(flow) | |||
if flex_host is not None: | |||
client_addr = flow.client_conn.address[0] | |||
if is_flex_domain(client_addr, check_flex_host): | |||
if bubble_log.isEnabledFor(INFO): | |||
bubble_log.info('request: check_flex_host is '+check_flex_host+' locating flex router') | |||
# select flex router | |||
# send request to flex router | |||
# set status line | |||
# populate headers | |||
# flow.response.headers = | |||
# populate body stream, ensure ".iter_content" works | |||
bubble_filter_response(flow) | |||
if is_flex_domain(client_addr, flex_host): | |||
set_flex_response(flow) | |||
addons = [Rerouter()] |