Przeglądaj źródła

support device security level in mitmproxy

tags/v0.12.2
Jonathan Cobb 4 lat temu
rodzic
commit
552c833153
12 zmienionych plików z 216 dodań i 173 usunięć
  1. +3
    -0
      bubble-server/src/main/java/bubble/dao/device/DeviceDAO.java
  2. +3
    -3
      bubble-server/src/main/java/bubble/model/device/DeviceSecurityLevel.java
  3. +2
    -2
      bubble-server/src/main/java/bubble/resources/app/AppSitesResource.java
  4. +1
    -1
      bubble-server/src/main/java/bubble/resources/app/AppsResource.java
  5. +2
    -1
      bubble-server/src/main/java/bubble/resources/stream/ReverseProxyResource.java
  6. +3
    -1
      bubble-server/src/main/java/bubble/server/listener/NodeInitializerListener.java
  7. +5
    -101
      bubble-server/src/main/java/bubble/service/cloud/DeviceIdService.java
  8. +131
    -0
      bubble-server/src/main/java/bubble/service/cloud/StandardDeviceIdService.java
  9. +22
    -0
      bubble-server/src/main/java/bubble/service_dbfilter/DbFilterDeviceIdService.java
  10. +2
    -3
      bubble-server/src/main/resources/message_templates/en_US/server/post_auth/ResourceMessages.properties
  11. +1
    -1
      bubble-server/src/main/resources/packer/roles/algo/tasks/main.yml
  12. +41
    -60
      bubble-server/src/main/resources/packer/roles/mitmproxy/files/bubble_passthru.py

+ 3
- 0
bubble-server/src/main/java/bubble/dao/device/DeviceDAO.java Wyświetl plik

@@ -12,6 +12,7 @@ import bubble.model.cloud.BubbleNetwork;
import bubble.model.device.BubbleDeviceType;
import bubble.model.device.Device;
import bubble.server.BubbleConfiguration;
import bubble.service.cloud.DeviceIdService;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.criterion.Order;
import org.springframework.beans.factory.annotation.Autowired;
@@ -34,6 +35,7 @@ public class DeviceDAO extends AccountOwnedEntityDAO<Device> {
@Autowired private BubbleConfiguration configuration;
@Autowired private AccountDAO accountDAO;
@Autowired private AppDataDAO dataDAO;
@Autowired private DeviceIdService deviceIdService;

@Override public Order getDefaultSortOrder() { return ORDER_CTIME_ASC; }

@@ -90,6 +92,7 @@ public class DeviceDAO extends AccountOwnedEntityDAO<Device> {
}
final Device updated = super.update(device);
ensureSpareDevice(device.getAccount(), device.getNetwork(), true);
deviceIdService.setDeviceSecurityLevel(updated);
return updated;
}



+ 3
- 3
bubble-server/src/main/java/bubble/model/device/DeviceSecurityLevel.java Wyświetl plik

@@ -6,10 +6,10 @@ import static bubble.ApiConstants.enumFromString;

public enum DeviceSecurityLevel {

// disabled, // todo: when we can identify client IP in dnscrypt-proxy, this setting will disabled DNS domain blocking
basic,
maximum,
standard,
maximum;
basic,
disabled;

@JsonCreator public static DeviceSecurityLevel fromString (String v) { return enumFromString(DeviceSecurityLevel.class, v); }



+ 2
- 2
bubble-server/src/main/java/bubble/resources/app/AppSitesResource.java Wyświetl plik

@@ -6,10 +6,10 @@ package bubble.resources.app;

import bubble.dao.app.AppSiteDAO;
import bubble.model.account.Account;
import bubble.model.app.config.AppDataDriver;
import bubble.model.app.config.AppDataView;
import bubble.model.app.AppSite;
import bubble.model.app.BubbleApp;
import bubble.model.app.config.AppDataDriver;
import bubble.model.app.config.AppDataView;
import bubble.model.device.Device;
import bubble.resources.account.AccountOwnedTemplateResource;
import bubble.service.cloud.DeviceIdService;


+ 1
- 1
bubble-server/src/main/java/bubble/resources/app/AppsResource.java Wyświetl plik

@@ -5,9 +5,9 @@
package bubble.resources.app;

import bubble.model.account.Account;
import bubble.model.app.BubbleApp;
import bubble.model.app.config.AppDataDriver;
import bubble.model.app.config.AppDataView;
import bubble.model.app.BubbleApp;
import bubble.model.device.Device;
import bubble.service.cloud.DeviceIdService;
import lombok.extern.slf4j.Slf4j;


+ 2
- 1
bubble-server/src/main/java/bubble/resources/stream/ReverseProxyResource.java Wyświetl plik

@@ -35,7 +35,8 @@ import static org.cobbzilla.util.daemon.ZillaRuntime.die;
import static org.cobbzilla.util.daemon.ZillaRuntime.empty;
import static org.cobbzilla.util.http.HttpContentTypes.CONTENT_TYPE_ANY;
import static org.cobbzilla.util.json.JsonUtil.json;
import static org.cobbzilla.wizard.resources.ResourceUtil.*;
import static org.cobbzilla.wizard.resources.ResourceUtil.invalidEx;
import static org.cobbzilla.wizard.resources.ResourceUtil.userPrincipal;

@Path(PROXY_ENDPOINT)
@Service @Slf4j


+ 3
- 1
bubble-server/src/main/java/bubble/server/listener/NodeInitializerListener.java Wyświetl plik

@@ -14,6 +14,7 @@ import bubble.model.cloud.BubbleNode;
import bubble.model.cloud.CloudService;
import bubble.server.BubbleConfiguration;
import bubble.service.boot.SelfNodeService;
import bubble.service.cloud.DeviceIdService;
import bubble.service.cloud.NetworkMonitorService;
import bubble.service.stream.AppPrimerService;
import lombok.extern.slf4j.Slf4j;
@@ -107,7 +108,7 @@ public class NodeInitializerListener extends RestServerLifecycleListenerBase<Bub
}
}

// ensure default devices exist, cert_validation_host is set, and apps are primed
// ensure default devices exist, cert_validation_host is set, apps are primed and device security levels are set
if (thisNode != null) {
final BubbleNetwork thisNetwork = c.getThisNetwork();
if (thisNetwork != null && thisNetwork.getInstallType() == AnsibleInstallType.node) {
@@ -119,6 +120,7 @@ public class NodeInitializerListener extends RestServerLifecycleListenerBase<Bub
for (Account a : accountDAO.findAll()) {
c.getBean(DeviceDAO.class).ensureSpareDevice(a.getUuid(), thisNode.getNetwork(), false);
}
c.getBean(DeviceIdService.class).initDeviceSecurityLevels();
}
}



+ 5
- 101
bubble-server/src/main/java/bubble/service/cloud/DeviceIdService.java Wyświetl plik

@@ -1,113 +1,17 @@
/**
* Copyright (c) 2020 Bubble, Inc. All rights reserved.
* For personal (non-commercial) use, see license: https://getbubblenow.com/bubble-license/
*/
package bubble.service.cloud;

import bubble.dao.account.AccountDAO;
import bubble.dao.device.DeviceDAO;
import bubble.model.device.Device;
import bubble.server.BubbleConfiguration;
import lombok.extern.slf4j.Slf4j;
import org.cobbzilla.util.collection.ExpirationMap;
import org.cobbzilla.util.io.FileUtil;
import org.cobbzilla.util.io.FilenamePrefixFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import static bubble.ApiConstants.HOME_DIR;
import static java.util.concurrent.TimeUnit.MINUTES;
import static org.cobbzilla.util.daemon.ZillaRuntime.*;
import static org.cobbzilla.wizard.resources.ResourceUtil.invalidEx;
import static org.cobbzilla.wizard.server.RestServerBase.reportError;
public interface DeviceIdService {

@Service @Slf4j
public class DeviceIdService {
Device findDeviceByIp(String ip);

public static final File WG_DEVICES_DIR = new File(HOME_DIR, "wg_devices");
List<String> findIpsByDevice(String deviceUuid);

public static final String IP_FILE_PREFIX = "ip_";
public static final FilenamePrefixFilter IP_FILE_FILTER = new FilenamePrefixFilter(IP_FILE_PREFIX);
void initDeviceSecurityLevels();

public static final String DEVICE_FILE_PREFIX = "device_";

@Autowired private DeviceDAO deviceDAO;
@Autowired private BubbleConfiguration configuration;
@Autowired private AccountDAO accountDAO;

private final Map<String, Device> deviceCache = new ExpirationMap<>(MINUTES.toMillis(10));

public Device findDeviceByIp (String ipAddr) {

if (!WG_DEVICES_DIR.exists()) {
if (configuration.testMode()) return findTestDevice(ipAddr);
reportError("findDeviceByIp: err.deviceDir.notFound");
return null;
}

return deviceCache.computeIfAbsent(ipAddr, ip -> {
try {
// try the simple case first
final File ipFile = new File(WG_DEVICES_DIR, "ip_" + ip);
if (ipFile.exists() && ipFile.length() > 0) {
final String deviceUuid = FileUtil.toString(ipFile).trim();
return deviceDAO.findByUuid(deviceUuid);
}

// walk through each ip file, finding one whose name semantically matches the given IP
// this may be required for IPv6 since there can be multiple string representation of the same IP
final String[] ipFiles = WG_DEVICES_DIR.list(IP_FILE_FILTER);
if (ipFiles == null || ipFile.length() == 0) return null;

final InetAddress addr = InetAddress.getByName(ip);
for (String f : ipFiles) {
try {
if (InetAddress.getByName(f.substring(IP_FILE_PREFIX.length())).equals(addr)) {
final String deviceUuid = FileUtil.toString(new File(WG_DEVICES_DIR, f)).trim();
return deviceDAO.findByUuid(deviceUuid);
}
} catch (Exception e) {
log.warn("findDeviceByIp("+ip+"): error handling IP file: "+f+": "+shortError(e));
}
}
log.warn("findDeviceByIp("+ip+"): no devices found for IP: "+ip);
return null;

} catch (IOException e) {
return die("findDeviceByIp("+ip+") error: "+e, e);
}
});
}

public List<String> findIpsByDevice(String deviceUuid) {
if (!WG_DEVICES_DIR.exists()) throw invalidEx("err.deviceDir.notFound");
final File deviceFile = new File(WG_DEVICES_DIR, DEVICE_FILE_PREFIX+deviceUuid);
if (!deviceFile.exists() || deviceFile.length() == 0) return Collections.emptyList();
try {
return FileUtil.toStringList(deviceFile);
} catch (IOException e) {
return die("findIpsByDevice("+deviceUuid+") error: "+e, e);
}
}

private Device findTestDevice(String ipAddr) {
final String adminUuid = accountDAO.getFirstAdmin().getUuid();
final List<Device> adminDevices = deviceDAO.findByAccount(adminUuid);
if (empty(adminDevices)) {
log.warn("findDeviceByIp("+ipAddr+") test mode and no admin devices, returning dummy device");
return new Device().setAccount(adminUuid).setName("dummy");
} else {
log.warn("findDeviceByIp("+ipAddr+") test mode, returning and possibly initializing first admin device");
final Device device = adminDevices.get(0);
return device.uninitialized() ? deviceDAO.update(device.initTotpKey()) : device;
}
}
void setDeviceSecurityLevel(Device device);

}

+ 131
- 0
bubble-server/src/main/java/bubble/service/cloud/StandardDeviceIdService.java Wyświetl plik

@@ -0,0 +1,131 @@
/**
* Copyright (c) 2020 Bubble, Inc. All rights reserved.
* For personal (non-commercial) use, see license: https://getbubblenow.com/bubble-license/
*/
package bubble.service.cloud;

import bubble.dao.account.AccountDAO;
import bubble.dao.device.DeviceDAO;
import bubble.model.device.Device;
import bubble.server.BubbleConfiguration;
import lombok.extern.slf4j.Slf4j;
import org.cobbzilla.util.collection.ExpirationMap;
import org.cobbzilla.util.io.FileUtil;
import org.cobbzilla.util.io.FilenamePrefixFilter;
import org.cobbzilla.wizard.cache.redis.RedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import static bubble.ApiConstants.HOME_DIR;
import static java.util.concurrent.TimeUnit.MINUTES;
import static org.cobbzilla.util.daemon.ZillaRuntime.*;
import static org.cobbzilla.wizard.resources.ResourceUtil.invalidEx;
import static org.cobbzilla.wizard.server.RestServerBase.reportError;

@Service @Slf4j
public class StandardDeviceIdService implements DeviceIdService {

public static final File WG_DEVICES_DIR = new File(HOME_DIR, "wg_devices");

public static final String IP_FILE_PREFIX = "ip_";
public static final FilenamePrefixFilter IP_FILE_FILTER = new FilenamePrefixFilter(IP_FILE_PREFIX);

public static final String DEVICE_FILE_PREFIX = "device_";

// used in dnscrypt-proxy and mitmproxy to check device security level
public static final String REDIS_KEY_DEVICE_SECURITY_LEVEL_PREFIX = "bubble_device_security_level_";

@Autowired private DeviceDAO deviceDAO;
@Autowired private AccountDAO accountDAO;
@Autowired private RedisService redis;
@Autowired private BubbleConfiguration configuration;

private final Map<String, Device> deviceCache = new ExpirationMap<>(MINUTES.toMillis(10));

@Override public Device findDeviceByIp (String ipAddr) {

if (!WG_DEVICES_DIR.exists()) {
if (configuration.testMode()) return findTestDevice(ipAddr);
reportError("findDeviceByIp: err.deviceDir.notFound");
return null;
}

return deviceCache.computeIfAbsent(ipAddr, ip -> {
try {
// try the simple case first
final File ipFile = new File(WG_DEVICES_DIR, "ip_" + ip);
if (ipFile.exists() && ipFile.length() > 0) {
final String deviceUuid = FileUtil.toString(ipFile).trim();
return deviceDAO.findByUuid(deviceUuid);
}

// walk through each ip file, finding one whose name semantically matches the given IP
// this may be required for IPv6 since there can be multiple string representation of the same IP
final String[] ipFiles = WG_DEVICES_DIR.list(IP_FILE_FILTER);
if (ipFiles == null || ipFile.length() == 0) return null;

final InetAddress addr = InetAddress.getByName(ip);
for (String f : ipFiles) {
try {
if (InetAddress.getByName(f.substring(IP_FILE_PREFIX.length())).equals(addr)) {
final String deviceUuid = FileUtil.toString(new File(WG_DEVICES_DIR, f)).trim();
return deviceDAO.findByUuid(deviceUuid);
}
} catch (Exception e) {
log.warn("findDeviceByIp("+ip+"): error handling IP file: "+f+": "+shortError(e));
}
}
log.warn("findDeviceByIp("+ip+"): no devices found for IP: "+ip);
return null;

} catch (IOException e) {
return die("findDeviceByIp("+ip+") error: "+e, e);
}
});
}

@Override public List<String> findIpsByDevice(String deviceUuid) {
if (!WG_DEVICES_DIR.exists()) throw invalidEx("err.deviceDir.notFound");
final File deviceFile = new File(WG_DEVICES_DIR, DEVICE_FILE_PREFIX+deviceUuid);
if (!deviceFile.exists() || deviceFile.length() == 0) return Collections.emptyList();
try {
return FileUtil.toStringList(deviceFile);
} catch (IOException e) {
return die("findIpsByDevice("+deviceUuid+") error: "+e, e);
}
}

@Override public void initDeviceSecurityLevels() {
for (Device device : deviceDAO.findAll()) {
if (device.uninitialized()) continue;
setDeviceSecurityLevel(device);
}
}

@Override public void setDeviceSecurityLevel(Device device) {
for (String ip : findIpsByDevice(device.getUuid())) {
redis.set_plaintext(REDIS_KEY_DEVICE_SECURITY_LEVEL_PREFIX+ip, device.getSecurityLevel().name());
}
}

private Device findTestDevice(String ipAddr) {
final String adminUuid = accountDAO.getFirstAdmin().getUuid();
final List<Device> adminDevices = deviceDAO.findByAccount(adminUuid);
if (empty(adminDevices)) {
log.warn("findDeviceByIp("+ipAddr+") test mode and no admin devices, returning dummy device");
return new Device().setAccount(adminUuid).setName("dummy");
} else {
log.warn("findDeviceByIp("+ipAddr+") test mode, returning and possibly initializing first admin device");
final Device device = adminDevices.get(0);
return device.uninitialized() ? deviceDAO.update(device.initTotpKey()) : device;
}
}

}

+ 22
- 0
bubble-server/src/main/java/bubble/service_dbfilter/DbFilterDeviceIdService.java Wyświetl plik

@@ -0,0 +1,22 @@
package bubble.service_dbfilter;

import bubble.model.device.Device;
import bubble.service.cloud.DeviceIdService;
import org.springframework.stereotype.Service;

import java.util.List;

import static org.cobbzilla.util.daemon.ZillaRuntime.notSupported;

@Service
public class DbFilterDeviceIdService implements DeviceIdService {

@Override public Device findDeviceByIp(String ip) { return notSupported("findDeviceByIp"); }

@Override public List<String> findIpsByDevice(String deviceUuid) { return notSupported("findIpsByDevice"); }

@Override public void initDeviceSecurityLevels() { notSupported("initDeviceSecurityLevels"); }

@Override public void setDeviceSecurityLevel(Device device) { notSupported("setDeviceSecurityLevel"); }

}

+ 2
- 3
bubble-server/src/main/resources/message_templates/en_US/server/post_auth/ResourceMessages.properties Wyświetl plik

@@ -501,9 +501,8 @@ device_security_level_standard=Standard
device_security_level_standard_description=Standard protection. Unrecognized traffic is allowed. VPN apps enabled.
device_security_level_basic=Basic
device_security_level_basic_description=Basic protection. Unrecognized traffic is allowed. VPN apps disabled.
# todo: when we can identify client IP in dnscrypt-proxy, this setting will disabled DNS domain blocking
#device_security_level_disabled=Disabled
#device_security_level_disabled_description=No protection. Unrecognized traffic is allowed. VPN apps disabled.
device_security_level_disabled=Off
device_security_level_disabled_description=No protection. Unrecognized traffic is allowed. VPN apps disabled.

# Cert types
message_os_uninitialized=Uninitialized


+ 1
- 1
bubble-server/src/main/resources/packer/roles/algo/tasks/main.yml Wyświetl plik

@@ -13,7 +13,7 @@
get_url:
url: https://github.com/getbubblenow/bubble-dist/raw/master/algo/master.zip
dest: /tmp/algo.zip
checksum: sha256:357e613833385626e88564c97f0b5726f49686c33a774be9a7766bd1a1249915
checksum: sha256:5a4e72d9671a38ff3ce9b5d6724c05222b343ddc408d690f1f511577d2673122

- name: Unzip algo master.zip
unarchive:


+ 41
- 60
bubble-server/src/main/resources/packer/roles/mitmproxy/files/bubble_passthru.py Wyświetl plik

@@ -33,26 +33,22 @@ import subprocess

REDIS_DNS_PREFIX = 'bubble_dns_'
REDIS_PASSTHRU_PREFIX = 'bubble_passthru_'
REDIS_CLIENT_CERT_STATUS_PREFIX = 'bubble_cert_status_'
REDIS_KEY_DEVICE_SECURITY_LEVEL_PREFIX = 'bubble_device_security_level_' # defined in StandardDeviceIdService
REDIS_PASSTHRU_DURATION = 60 * 60 # 1 hour timeout on passthru

REDIS = redis.Redis(host='127.0.0.1', port=6379, db=0)

FORCE_PASSTHRU = {'passthru': True}

cert_validation_host = None
local_ips = None


def get_ip_cert_status(client_addr):
status = REDIS.get(REDIS_CLIENT_CERT_STATUS_PREFIX+client_addr)
if status is None:
return None
enabled = status.decode() == "True"
return enabled


def set_ip_cert_status(client_addr, enabled):
REDIS.set(REDIS_CLIENT_CERT_STATUS_PREFIX+client_addr, str(enabled))
bubble_log('set_ip_cert_status: set '+client_addr+' = '+str(enabled))
def get_device_security_level(client_addr):
level = REDIS.get(REDIS_KEY_DEVICE_SECURITY_LEVEL_PREFIX+client_addr)
if level is None:
return 'maximum'
return level.decode()


def get_local_ips():
@@ -64,17 +60,6 @@ def get_local_ips():
return local_ips


def get_cert_validation_host():
global cert_validation_host
if cert_validation_host is None:
cert_validation_host = REDIS.get('certValidationHost')
if cert_validation_host is not None:
cert_validation_host = cert_validation_host.decode()
# bubble_log('get_cert_validation_host: initialized to '+cert_validation_host)
# bubble_log('get_cert_validation_host: returning '+cert_validation_host)
return cert_validation_host


def passthru_cache_prefix(client_addr, server_addr):
return REDIS_PASSTHRU_PREFIX + client_addr + '_' + server_addr

@@ -103,29 +88,15 @@ class TlsFeedback(TlsLayer):
fqdns = fqdns_for_addr(server_address)
try:
super(TlsFeedback, self)._establish_tls_with_client()
if fqdns and get_cert_validation_host() in fqdns:
# bubble_log('_establish_tls_with_client: TLS success for '+repr(server_address)+', enabling SSL interception for client '+client_address)
set_ip_cert_status(client_address, True)

except TlsProtocolException as e:
cache_key = passthru_cache_prefix(client_address, server_address)
bubble_log('_establish_tls_with_client: TLS error for '+repr(server_address)+', enabling passthru for client '+client_address+' with cache_key='+cache_key)
if fqdns and get_cert_validation_host() in fqdns:
set_ip_cert_status(client_address, False)
else:
redis_set(cache_key, json.dumps({'fqdns': fqdns, 'addr': server_address, 'passthru': True}), ex=REDIS_PASSTHRU_DURATION)
redis_set(cache_key, json.dumps({'fqdns': fqdns, 'addr': server_address, 'passthru': True}), ex=REDIS_PASSTHRU_DURATION)
raise e


def check_bubble_passthru(client_addr, addr, fqdns):
cert_status = get_ip_cert_status(client_addr)

if cert_status is not None and not cert_status:
bubble_log('check_bubble_passthru: returning True because cert_status for '+client_addr+' was False')
return {'fqdns': fqdns, 'addr': addr, 'passthru': True}
else:
bubble_log('check_bubble_passthru: request is NOT for cert_validation_host: '+cert_validation_host+", it is for one of fqdn="+repr(fqdns)+", checking bubble_passthru...")

passthru = bubble_passthru(client_addr, addr, fqdns)
if passthru is None or passthru:
bubble_log('check_bubble_passthru: bubble_passthru returned '+repr(passthru)+' for FQDN/addr '+repr(fqdns)+'/'+repr(addr)+', returning True')
@@ -139,9 +110,6 @@ def should_passthru(client_addr, addr, fqdns):
if addr in get_local_ips():
# bubble_log('should_passthru: local ip is always passthru: '+addr)
return {'fqdns': fqdns, 'addr': addr, 'passthru': True}
else:
# bubble_log('should_passthru: addr ('+addr+') is not a local ip: '+repr(get_local_ips()))
pass

cache_key = passthru_cache_prefix(client_addr, addr)
prefix = 'should_passthru: ip='+repr(addr)+' (fqdns='+repr(fqdns)+') cache_key='+cache_key+': '
@@ -163,25 +131,38 @@ def should_passthru(client_addr, addr, fqdns):

def next_layer(next_layer):
if isinstance(next_layer, TlsLayer) and next_layer._client_tls:
client_address = next_layer.client_conn.address[0]
server_address = next_layer.server_conn.address[0]
client_addr = next_layer.client_conn.address[0]
server_addr = next_layer.server_conn.address[0]

fqdns = fqdns_for_addr(server_address)
validation_host = get_cert_validation_host()
if fqdns and validation_host in fqdns:
bubble_log('next_layer: never passing thru (always getting feedback) for cert_validation_host='+validation_host)
next_layer.__class__ = TlsFeedback
fqdns = fqdns_for_addr(server_addr)
no_fqdns = fqdns is None or len(fqdns) == 0
security_level = get_device_security_level(client_addr)
if server_addr in get_local_ips():
bubble_log('next_layer: enabling passthru for LOCAL server='+server_addr+' regardless of security_level='+security_level+' for client='+client_addr)
passthru = FORCE_PASSTHRU

elif security_level == 'disabled' or security_level == 'basic':
bubble_log('next_layer: enabling passthru for server='+server_addr+' because security_level='+security_level+' for client='+client_addr)
passthru = FORCE_PASSTHRU

elif security_level == 'standard' and no_fqdns:
bubble_log('next_layer: enabling passthru for server='+server_addr+' because no FQDN found and security_level='+security_level+' for client='+client_addr)
passthru = FORCE_PASSTHRU

elif security_level == 'maximum' and no_fqdns:
bubble_log('next_layer: disabling passthru (no TlsFeedback) for server='+server_addr+' because no FQDN found and security_level='+security_level+' for client='+client_addr)
return

else:
bubble_log('next_layer: checking should_passthru for client_address='+client_address)
passthru = should_passthru(client_address, server_address, fqdns)
if passthru is None or passthru['passthru']:
# bubble_log('next_layer: TLS passthru for ' + repr(next_layer.server_conn.address))
if passthru is not None and 'fqdns' in passthru:
bubble_activity_log(client_address, server_address, 'tls_passthru', passthru['fqdns'])
next_layer_replacement = RawTCPLayer(next_layer.ctx, ignore=True)
next_layer.reply.send(next_layer_replacement)
else:
# bubble_log('next_layer: NO PASSTHRU (getting feedback) for client_address='+client_address+', server_address='+server_address)
bubble_activity_log(client_address, server_address, 'tls_intercept', passthru['fqdns'])
next_layer.__class__ = TlsFeedback
bubble_log('next_layer: checking should_passthru for server='+server_addr+', client='+client_addr+' with security_level='+security_level)
passthru = should_passthru(client_addr, server_addr, fqdns)
if passthru is None or passthru['passthru']:
bubble_log('next_layer: enabling passthru for ' + repr(next_layer.server_conn.address))
bubble_activity_log(client_addr, server_addr, 'tls_passthru', fqdns)
next_layer_replacement = RawTCPLayer(next_layer.ctx, ignore=True)
next_layer.reply.send(next_layer_replacement)
else:
bubble_log('next_layer: disabling passthru (with TlsFeedback) for client_addr='+client_addr+', server_addr='+server_addr)
bubble_activity_log(client_addr, server_addr, 'tls_intercept', fqdns)
next_layer.__class__ = TlsFeedback

Ładowanie…
Anuluj
Zapisz