def test_close(kresd_sock, query_before): """Establish a connection and wait for timeout from kresd.""" if query_before: utils.ping_alive(kresd_sock) time.sleep(utils.MAX_TIMEOUT) with utils.expect_kresd_close(): utils.ping_alive(kresd_sock)
def test_tls_selfsigned_cert(kresd_tt, sock_family): """Use TLS with a self signed certificate.""" sock, dest = kresd_tt.stream_socket(sock_family, tls=True) ctx = utils.make_ssl_context(verify_location=kresd_tt.tls_cert_path) ssock = ctx.wrap_socket(sock, server_hostname='transport-test-server.com') ssock.connect(dest) utils.ping_alive(ssock)
def test_long_lived(kresd_sock, duration, delay): """Establish and keep connection alive for longer than maximum timeout.""" utils.ping_alive(kresd_sock) end_time = time.time() + duration while time.time() < end_time: time.sleep(delay) utils.ping_alive(kresd_sock)
def test_tls_no_cert(kresd, sock_family): """Use TLS without certificates.""" sock, dest = kresd.stream_socket(sock_family, tls=True) ctx = utils.make_ssl_context(insecure=True) ssock = ctx.wrap_socket(sock) ssock.connect(dest) utils.ping_alive(ssock)
def test_query_flood_close(make_kresd_sock): """Flood resolver with queries and close the connection.""" buff = flood_buffer(10000) sock1 = make_kresd_sock() sock1.sendall(buff) sock1.close() sock2 = make_kresd_sock() utils.ping_alive(sock2)
def test_prefix_cuts_message(kresd_sock, datalen, send_query): """Prefix is shorter than the DNS message.""" wire, _ = utils.prepare_wire() assert datalen < len(wire) invalid_buff = utils.prepare_buffer(wire, datalen) send_query(kresd_sock, invalid_buff) # buffer breaks parsing of TCP stream with utils.expect_kresd_close(): utils.ping_alive(kresd_sock)
def connect(kresd, ctx, sf, session=None): sock, dest = kresd.stream_socket(sf, tls=True) ssock = ctx.wrap_socket(sock, server_hostname='transport-test-server.com', session=session) ssock.connect(dest) new_session = ssock.session assert new_session.has_ticket assert ssock.session_reused == (session is not None) utils.ping_alive(ssock) ssock.close() return new_session
def test_conn_flood(tmpdir, sock_func_name): def create_sockets(make_sock, nsockets): sockets = [] next_ping = time.time() + 4 # less than tcp idle timeout / 2 while True: additional_sockets = 0 while time.time() < next_ping: nsock_to_init = min(100, nsockets - len(sockets)) if not nsock_to_init: return sockets sockets.extend([make_sock() for _ in range(nsock_to_init)]) additional_sockets += nsock_to_init # large number of connections can take a lot of time to open # send some valid data to avoid TCP idle timeout for already open sockets next_ping = time.time() + 4 for s in sockets: utils.ping_alive(s) # break when no more than 20% additional sockets are created if additional_sockets / len(sockets) < 0.2: return sockets max_num_of_open_files = resource.getrlimit( resource.RLIMIT_NOFILE)[0] - RESERVED_NOFILE nsockets = min(max_num_of_open_files, MAX_SOCKETS) # create kresd instance with verbose=False ip = '127.0.0.1' ip6 = '::1' with Kresd(tmpdir, ip=ip, ip6=ip6, verbose=False) as kresd: make_sock = getattr(kresd, sock_func_name) # function for creating sockets sockets = create_sockets(make_sock, nsockets) print("\nEstablished {} connections".format(len(sockets))) print("Start sending data") for i in range(MAX_ITERATIONS): for s in sockets: utils.ping_alive(s) print("Iteration {} done...".format(i)) print("Close connections") for s in sockets: s.close() # check in kresd is alive print("Check upstream is still alive") sock = make_sock() utils.ping_alive(sock) print("OK!")
def test_slow_lorris(kresd_sock, query_before): """Simulate slow-lorris attack by sending byte after byte with delays in between.""" if query_before: utils.ping_alive(kresd_sock) buff, _ = utils.get_msgbuff() end_time = time.time() + utils.MAX_TIMEOUT with utils.expect_kresd_close(): for i in range(len(buff)): b = buff[i:i+1] kresd_sock.send(b) if time.time() > end_time: break time.sleep(1)
def test_prefix_trailing_garbage(kresd_sock, glength, query_before): """Send messages with trailing garbage (its length included in prefix).""" if query_before: utils.ping_alive(kresd_sock) for _ in range(10): wire, msgid = utils.prepare_wire() wire += utils.get_garbage(glength) buff = utils.prepare_buffer(wire) kresd_sock.sendall(buff) answer = utils.receive_parse_answer(kresd_sock) assert answer.id == msgid time.sleep(0.1)
def test_oob(kresd, sock_func_name): """TCP out-of-band (urgent) data must not crash resolver.""" make_sock = getattr(kresd, sock_func_name) sock = make_sock() msg_buff, msgid = utils.get_msgbuff() sock.sendall(msg_buff, socket.MSG_OOB) try: msg_answer = utils.receive_parse_answer(sock) assert msg_answer.id == msgid except ConnectionError: pass # TODO kresd responds with TCP RST, this should be fixed # check kresd is alive sock2 = make_sock() utils.ping_alive(sock2)
def test_query_flood_garbage(make_kresd_sock, glength, gcount, delay, query_before): """Flood resolver with prefixed garbage.""" sock1 = make_kresd_sock() if query_before: utils.ping_alive(sock1) gbuff = utils.get_prefixed_garbage(glength) buff = gbuff * gcount end_time = time.time() + utils.MAX_TIMEOUT with utils.expect_kresd_close(rst_ok=True): # connection must be closed while time.time() < end_time: sock1.sendall(buff) time.sleep(delay) sock2 = make_kresd_sock() utils.ping_alive(sock2) # resolver must stay alive
def create_sockets(make_sock, nsockets): sockets = [] next_ping = time.time() + 4 # less than tcp idle timeout / 2 while True: additional_sockets = 0 while time.time() < next_ping: nsock_to_init = min(100, nsockets - len(sockets)) if not nsock_to_init: return sockets sockets.extend([make_sock() for _ in range(nsock_to_init)]) additional_sockets += nsock_to_init # large number of connections can take a lot of time to open # send some valid data to avoid TCP idle timeout for already open sockets next_ping = time.time() + 4 for s in sockets: utils.ping_alive(s) # break when no more than 20% additional sockets are created if additional_sockets / len(sockets) < 0.2: return sockets
def test_query_flood_no_recv(make_kresd_sock): """Flood resolver with queries but don't read any data.""" # A use-case for TCP_USER_TIMEOUT socket option? See RFC 793 and RFC 5482 # It seems it doesn't works as expected. libuv doesn't return any error # (neither on uv_write() call, not in the callback) when kresd sends answers, # so kresd can't recognize that client didn't read any answers. At a certain # point, kresd stops receiving queries from the client (whilst client keep # sending) and closes connection due to timeout. buff = flood_buffer(10000) sock1 = make_kresd_sock() end_time = time.time() + utils.MAX_TIMEOUT with utils.expect_kresd_close(rst_ok=True): # connection must be closed while time.time() < end_time: sock1.sendall(buff) time.sleep(0.5) sock2 = make_kresd_sock() utils.ping_alive(sock2) # resolver must stay alive