mirror of https://github.com/Kkevsterrr/geneva
parent
5b6a3455a8
commit
de6823ba77
@ -0,0 +1,81 @@ |
||||
""" |
||||
Client |
||||
|
||||
Run by the evaluator, sends a TLS Client Hello with the ESNI extension, followed by two test packets. |
||||
""" |
||||
|
||||
import argparse |
||||
import binascii as bi |
||||
import os |
||||
import socket |
||||
import time |
||||
|
||||
socket.setdefaulttimeout(1) |
||||
|
||||
from plugins.plugin_client import ClientPlugin |
||||
|
||||
|
||||
class ESNIClient(ClientPlugin): |
||||
""" |
||||
Defines the ESNI client. |
||||
""" |
||||
name = "esni" |
||||
|
||||
def __init__(self, args): |
||||
""" |
||||
Initializes the esni client. |
||||
""" |
||||
ClientPlugin.__init__(self) |
||||
self.args = args |
||||
|
||||
@staticmethod |
||||
def get_args(command): |
||||
""" |
||||
Defines required args for this plugin |
||||
""" |
||||
super_args = ClientPlugin.get_args(command) |
||||
parser = argparse.ArgumentParser(description='ESNI Client') |
||||
|
||||
parser.add_argument('--server', action='store', help="server to connect to") |
||||
|
||||
args, _ = parser.parse_known_args(command) |
||||
args = vars(args) |
||||
|
||||
super_args.update(args) |
||||
return super_args |
||||
|
||||
def run(self, args, logger, engine=None): |
||||
""" |
||||
Try to make a forbidden GET request to the server. |
||||
""" |
||||
fitness = 0 |
||||
port = int(args["port"]) |
||||
server = args["server"] |
||||
# Client Hello with the ESNI extension |
||||
msg = b'16030103ae010003aa0303d992f9c22fbe7a7cdbc9619924bd9cc13c057f5f3da1829426cb0944292705152033c5be80af6de7633e07680125e27e3f7b80ff5e9b3cbe5278434c90b9e0e5fa0024130113031302c02bc02fcca9cca8c02cc030c00ac009c013c014009c009d002f0035000a0100033d00170000ff01000100000a000e000c001d00170018001901000101000b000201000010000e000c02683208687474702f312e310005000501000000000033006b0069001d002019570ada256d971048b34d3e9ff5607588bf10cfb6c064fc45a0fc401d9a7c470017004104ea047fd2e0fc3314de4bf03ee6205134f0d15c07f62b77625a95dc194ce8fb88cc16e53c8b400ba463915b87480b247851c095abdb0d3d5d5b14dd77dcd73750002b00050403040303000d0018001604030503060308040805080604010501060102030201002d00020101ffce016e1301001d00203652aaf122dc47dcf9fa8c37377476d050e54119adfb518f7aabd842ac97d23b00205a30e70593f57708370310ecf7054e488a62eb11e01fd059851c442d453d15c5012441910eec152c4df5ff28bf5cddb1a2e54e8595197e3dc36325145ad50a7842eb3860c8fc6ac5c1794017101365c6122abb3b81f31f5f4204eebb244252d22600734424d875948657b892d3aab3310491aff3b5126f1186bd9c321fb446cf2a41985dd206364ea28c3f8aafeafc62e039f157c3f2703a35448d2d16dcf2d5055ce58c024a5b4eb780fc5128af4ba4e90d6eef1b3cf30a5b2000448d65d6af4fffabeb91e1ed2093fdcc6ffd87ceb94429864ddb657e6316654631193fd25840e51645e1708d351140dd6eeefb80ddbaebb250b2975a1d5f291d99f89de4553d083f1b9820a3ee6976357cff433b7eb77febb3eb0db012154154d3e19b4409f8afa11aa1baeb0b7663d97f0caca2b11ed971fc574588e76a37aa4259593fe8e07fbbca27fa001c00024001002900eb00c600c07f87fafe9de4168227aeec4540f1aaeae43ff61a353f5480420ac3c33f90003fe6f501080bf04f22576a0cc1db8dc83d37b25859a81ce0277364a1794cde1c60f3b94175477beff56db7f9e2b83b31383b7d8b5da20834fb0a63d7ba2e42ad3dfa21666ed8621f34273ac5c273d7f492750e3df3bae36e398ddf83d4a7c36f639087f14eb1f7bfb2c7c0c736d69bcdbf21158c07b7088b95e5bcd08138d6b511f6492d7d93bb3729641519097b970cfeffa5882c67111dcf5d7966a1c58b4edb6e8c905a002120e47ccba37d89e4c1d979c6ef954d1cd946eff0d3119aa2b4d6411138aec74579' |
||||
try: |
||||
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) |
||||
client.settimeout(5) |
||||
client.connect((server, port)) |
||||
client.sendall(bi.unhexlify(msg)) |
||||
time.sleep(2) |
||||
client.sendall(b"test packet") |
||||
time.sleep(2) |
||||
client.sendall(b"test packet 2") |
||||
server_data = client.recv(1024) |
||||
logger.debug("Data recieved: %s", server_data.decode('utf-8', 'ignore')) |
||||
fitness += 100 |
||||
client.close() |
||||
except socket.timeout: |
||||
# Happens on connect, not sendall |
||||
logger.debug("Client: Timeout") |
||||
fitness -= 110 |
||||
except socket.error as exc: |
||||
fitness -= 100 |
||||
logger.exception("Socket error caught in client esni test.") |
||||
except Exception: |
||||
logger.exception("Exception caught in client esni test.") |
||||
fitness = -120 |
||||
finally: |
||||
logger.debug("Client finished esni test.") |
||||
return fitness * 4 |
@ -0,0 +1,102 @@ |
||||
""" |
||||
ESNI Plugin driver |
||||
|
||||
Overrides the default evaluator plugin handling so we can check if the server timed out on recv. |
||||
""" |
||||
|
||||
import argparse |
||||
import calendar |
||||
import copy |
||||
import logging |
||||
import os |
||||
import random |
||||
import socket |
||||
import sys |
||||
import tempfile |
||||
import time |
||||
import traceback |
||||
import urllib.request |
||||
|
||||
import requests |
||||
|
||||
socket.setdefaulttimeout(1) |
||||
|
||||
import actions.utils |
||||
|
||||
from plugins.plugin import Plugin |
||||
|
||||
BASEPATH = os.path.dirname(os.path.abspath(__file__)) |
||||
PROJECT_ROOT = os.path.dirname(os.path.dirname(BASEPATH)) |
||||
|
||||
|
||||
class ESNIPluginRunner(Plugin): |
||||
""" |
||||
Defines the ESNI plugin runner. |
||||
""" |
||||
name = "esni" |
||||
|
||||
def __init__(self, args): |
||||
""" |
||||
Marks this plugin as enabled |
||||
""" |
||||
self.enabled = True |
||||
|
||||
def start(self, args, evaluator, environment, ind, logger): |
||||
""" |
||||
Runs the plugins |
||||
""" |
||||
# Start the server |
||||
port = random.randint(10000, 65000) |
||||
evaluator.client_args.update({"port": port}) |
||||
evaluator.server_args.update({"port": port}) |
||||
|
||||
# If we're given a server to start, start it now |
||||
if evaluator.server_cls and not args.get("external_server"): |
||||
# If a test using TCP has been requested, switch the server to that mode |
||||
server = evaluator.start_server(evaluator.server_args, environment, logger) |
||||
evaluator.client_args.update({"server": evaluator.args["server"]}) |
||||
|
||||
fitness = evaluator.run_client(evaluator.client_args, environment, logger) |
||||
|
||||
if evaluator.server_cls and not evaluator.args["external_server"]: |
||||
evaluator.stop_server(environment, server) |
||||
|
||||
evaluator.read_fitness(ind) |
||||
|
||||
# If the engine ran on the server side, ask that it punish fitness |
||||
if evaluator.args["server_side"]: |
||||
ind.fitness = server.punish_fitness(ind.fitness, logger) |
||||
output_path = os.path.join(PROJECT_ROOT, evaluator.client_args.get("output_directory")) |
||||
fitpath = os.path.join(PROJECT_ROOT, output_path, actions.utils.FLAGFOLDER, environment["id"]) + ".fitness" |
||||
with open(fitpath, "w") as fitfile: |
||||
fitfile.write(str(ind.fitness)) |
||||
|
||||
if evaluator.server_cls and not evaluator.args["external_server"]: |
||||
logger.debug("CHECKING FOR SERVER TIMEOUT") |
||||
output_path = os.path.join(PROJECT_ROOT, evaluator.client_args.get("output_directory")) |
||||
timeout_flag = os.path.join(output_path, actions.utils.FLAGFOLDER, environment["id"]) + ".timeout" |
||||
fitpath = os.path.join(PROJECT_ROOT, output_path, actions.utils.FLAGFOLDER, environment["id"]) + ".fitness" |
||||
if os.path.exists(timeout_flag): |
||||
logger.debug("Server timeout detected") |
||||
ind.fitness = -360 |
||||
with open(fitpath, "w") as fitfile: |
||||
fitfile.write(str(ind.fitness)) |
||||
|
||||
evaluator.read_fitness(ind) |
||||
|
||||
# Log the fitness |
||||
#logger.info("[%s] Fitness %s: %s" % (ind.environment_id, str(ind.fitness), str(ind))) |
||||
|
||||
return ind.environment_id, ind.fitness |
||||
|
||||
@staticmethod |
||||
def get_args(command): |
||||
""" |
||||
Defines required global args for this plugin |
||||
""" |
||||
parser = argparse.ArgumentParser(description='ESNI plugin runner', allow_abbrev=False) |
||||
parser.add_argument('--environment-id', action='store', help="ID of the current environment") |
||||
parser.add_argument('--output-directory', action='store', help="Where to output results") |
||||
parser.add_argument('--port', action='store', type=int, help='port to use') |
||||
args, _ = parser.parse_known_args(command) |
||||
return vars(args) |
@ -0,0 +1,134 @@ |
||||
""" |
||||
ESNI Test Server |
||||
|
||||
Starts a simple TCP server, recvs data until it gets the bytes it expects from the client. |
||||
""" |
||||
import argparse |
||||
import binascii as bi |
||||
import os |
||||
import socket |
||||
|
||||
from plugins.plugin_server import ServerPlugin |
||||
import actions.utils |
||||
|
||||
|
||||
BASEPATH = os.path.dirname(os.path.abspath(__file__)) |
||||
PROJECT_ROOT = os.path.dirname(os.path.dirname(BASEPATH)) |
||||
|
||||
|
||||
class ESNIServer(ServerPlugin): |
||||
""" |
||||
Defines the ESNI client. |
||||
""" |
||||
name = "esni" |
||||
def __init__(self, args): |
||||
""" |
||||
Initializes the ESNI client. |
||||
""" |
||||
ServerPlugin.__init__(self) |
||||
|
||||
@staticmethod |
||||
def get_args(command): |
||||
""" |
||||
Defines arguments for this plugin |
||||
""" |
||||
super_args = ServerPlugin.get_args(command) |
||||
|
||||
parser = argparse.ArgumentParser(description='ESNI Test Server') |
||||
|
||||
args, _ = parser.parse_known_args(command) |
||||
args = vars(args) |
||||
super_args.update(args) |
||||
return super_args |
||||
|
||||
def run(self, args, logger): |
||||
""" |
||||
Initializes the ESNI server. |
||||
""" |
||||
logger.debug("ESNI test server initializing") |
||||
try: |
||||
port = int(args["port"]) |
||||
control_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) |
||||
# Allow socket re-use |
||||
control_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) |
||||
server_address = ('0.0.0.0', port) |
||||
logger.debug("Binding to server address 0.0.0.0:%d" % port) |
||||
control_socket.bind(server_address) |
||||
control_socket.settimeout(10) |
||||
control_socket.listen(1) |
||||
except: |
||||
logger.exception("Caught exception in esni run") |
||||
return |
||||
needed = bi.unhexlify(b'16030103ae010003aa0303d992f9c22fbe7a7cdbc9619924bd9cc13c057f5f3da1829426cb0944292705152033c5be80af6de7633e07680125e27e3f7b80ff5e9b3cbe5278434c90b9e0e5fa0024130113031302c02bc02fcca9cca8c02cc030c00ac009c013c014009c009d002f0035000a0100033d00170000ff01000100000a000e000c001d00170018001901000101000b000201000010000e000c02683208687474702f312e310005000501000000000033006b0069001d002019570ada256d971048b34d3e9ff5607588bf10cfb6c064fc45a0fc401d9a7c470017004104ea047fd2e0fc3314de4bf03ee6205134f0d15c07f62b77625a95dc194ce8fb88cc16e53c8b400ba463915b87480b247851c095abdb0d3d5d5b14dd77dcd73750002b00050403040303000d0018001604030503060308040805080604010501060102030201002d00020101ffce016e1301001d00203652aaf122dc47dcf9fa8c37377476d050e54119adfb518f7aabd842ac97d23b00205a30e70593f57708370310ecf7054e488a62eb11e01fd059851c442d453d15c5012441910eec152c4df5ff28bf5cddb1a2e54e8595197e3dc36325145ad50a7842eb3860c8fc6ac5c1794017101365c6122abb3b81f31f5f4204eebb244252d22600734424d875948657b892d3aab3310491aff3b5126f1186bd9c321fb446cf2a41985dd206364ea28c3f8aafeafc62e039f157c3f2703a35448d2d16dcf2d5055ce58c024a5b4eb780fc5128af4ba4e90d6eef1b3cf30a5b2000448d65d6af4fffabeb91e1ed2093fdcc6ffd87ceb94429864ddb657e6316654631193fd25840e51645e1708d351140dd6eeefb80ddbaebb250b2975a1d5f291d99f89de4553d083f1b9820a3ee6976357cff433b7eb77febb3eb0db012154154d3e19b4409f8afa11aa1baeb0b7663d97f0caca2b11ed971fc574588e76a37aa4259593fe8e07fbbca27fa001c00024001002900eb00c600c07f87fafe9de4168227aeec4540f1aaeae43ff61a353f5480420ac3c33f90003fe6f501080bf04f22576a0cc1db8dc83d37b25859a81ce0277364a1794cde1c60f3b94175477beff56db7f9e2b83b31383b7d8b5da20834fb0a63d7ba2e42ad3dfa21666ed8621f34273ac5c273d7f492750e3df3bae36e398ddf83d4a7c36f639087f14eb1f7bfb2c7c0c736d69bcdbf21158c07b7088b95e5bcd08138d6b511f6492d7d93bb3729641519097b970cfeffa5882c67111dcf5d7966a1c58b4edb6e8c905a002120e47ccba37d89e4c1d979c6ef954d1cd946eff0d3119aa2b4d6411138aec74579') + b'test packet' + b'test packet 2' |
||||
connection = None |
||||
try: |
||||
connection, client_address = self.get_request(control_socket) |
||||
if not connection: |
||||
logger.error("Failed to get connection") |
||||
return |
||||
data = b"" |
||||
while len(data) < len(needed): |
||||
logger.debug("Awaiting data") |
||||
d = connection.recv(256) |
||||
if not d: |
||||
break |
||||
logger.debug(b"Received: " + d) |
||||
logger.debug("Got: %d; Remaining: %d", len(data), len(needed)) |
||||
logger.debug(len(d)) |
||||
data += d |
||||
logger.debug("Got %d; Remaining: %d", len(data), len(needed)) |
||||
connection.sendall(b'ack') |
||||
assert data == needed, data |
||||
logger.debug("Successfully got all of the client's data") |
||||
|
||||
connection.close() |
||||
except socket.timeout as e: |
||||
# write to a flag file to pass back to the plugin that this strategy failed |
||||
logger.debug("Server: Connection timed out") |
||||
flagpath = os.path.join(PROJECT_ROOT, args["output_directory"], actions.utils.FLAGFOLDER, args["environment_id"]) + ".timeout" |
||||
with open(flagpath, "w") as fd: |
||||
fd.write("timeout caught") |
||||
fd.flush() |
||||
except AssertionError as exc: |
||||
logger.debug("Did not receive all data: probably a client timeout") |
||||
flagpath = os.path.join(PROJECT_ROOT, args["output_directory"], actions.utils.FLAGFOLDER, args["environment_id"]) + ".timeout" |
||||
with open(flagpath, "w") as fd: |
||||
fd.write("timeout caught") |
||||
fd.flush() |
||||
except socket.error as e: |
||||
if e.errno == 104: |
||||
logger.debug("Server: Connection RST.") |
||||
else: |
||||
logger.debug("Server: Client quit.") |
||||
except AssertionError: |
||||
logger.debug("Server: Got incorrect data. Client's packets getting dropped?") |
||||
flagpath = os.path.join(PROJECT_ROOT, args["output_directory"], actions.utils.FLAGFOLDER, args["environment_id"]) + ".timeout" |
||||
with open(flagpath, "w") as fd: |
||||
fd.write("packets dropped") |
||||
fd.flush() |
||||
|
||||
except Exception: |
||||
logger.exception("Failed during server communication.") |
||||
finally: |
||||
if connection: |
||||
connection.close() |
||||
logger.debug("Server exiting") |
||||
|
||||
def get_request(self, control_socket): |
||||
""" |
||||
Get a request from the socket. |
||||
""" |
||||
while True: |
||||
try: |
||||
sock, addr = control_socket.accept() |
||||
sock.settimeout(5) |
||||
return (sock, addr) |
||||
except socket.timeout: |
||||
pass |
||||
return (None, None) |
||||
|
||||
def stop(self): |
||||
""" |
||||
Stops this server. |
||||
""" |
||||
ServerPlugin.stop(self) |
Loading…
Reference in new issue