Skip to content

Commit

Permalink
Fixes according review
Browse files Browse the repository at this point in the history
  • Loading branch information
EvgeniiMekhanik committed Dec 29, 2023
1 parent ec57089 commit ad6370f
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 87 deletions.
1 change: 1 addition & 0 deletions helpers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"prepare",
"util",
"networker",
"custom_error_page",
]

# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
File renamed without changes.
145 changes: 78 additions & 67 deletions http2_general/test_h2_block_action.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@
)

import run_config
from framework.custom_error_page import CustomErrorPageGenerator
from framework.deproxy_client import HuffmanEncoder
from framework.parameterize import param, parameterize
from helpers import analyzer, asserts, remote, tf_cfg
from helpers.custom_error_page import CustomErrorPageGenerator
from http2_general.helpers import H2Base


Expand Down Expand Up @@ -86,6 +87,11 @@ def check_fin_and_rst_in_sniffer(self, sniffer: analyzer.Sniffer) -> None:
self.assert_reset_socks(sniffer.packets)
self.assert_fin_socks(sniffer.packets)

def check_no_fin_no_rst_in_sniffer(self, sniffer: analyzer.Sniffer) -> None:
sniffer.stop()
self.assert_not_fin_socks(sniffer.packets)
self.assert_unreset_socks(sniffer.packets)

def setup_sniffer_for_attack_reply(self, client):
"""
In case of TCP segmentation and attack we can't be sure that
Expand Down Expand Up @@ -179,7 +185,7 @@ def test_block_action_error_reply(self):
],
expected_status_code="400",
)
self.assertEqual(client._last_response.body, self.ERROR_RESPONSE_BODY)
self.assertEqual(client.last_response.body, self.ERROR_RESPONSE_BODY)
self.assertFalse(client.connection_is_closed())

client.send_request(
Expand Down Expand Up @@ -214,7 +220,7 @@ def test_block_action_error_reply_with_conn_close(self):
],
expected_status_code="400",
)
self.assertEqual(client._last_response.body, self.ERROR_RESPONSE_BODY)
self.assertEqual(client.last_response.body, self.ERROR_RESPONSE_BODY)
self.assertTrue(client.wait_for_connection_close())

self.check_fin_no_rst_in_sniffer(sniffer)
Expand Down Expand Up @@ -342,12 +348,11 @@ def test_block_action_error_reply_with_conn_close_multiple_requests(self):
good_req,
]
)
client.wait_for_response(3)
self.assertTrue(client.wait_for_connection_close())

self.assertEqual(curr_responses + 1, len(client.responses))
self.assertEqual(client._last_response.status, "400")
self.assertEqual(client._last_response.body, self.ERROR_RESPONSE_BODY)
self.assertTrue(client.wait_for_connection_close())
self.assertEqual(client.last_response.status, "400")
self.assertEqual(client.last_response.body, self.ERROR_RESPONSE_BODY)

self.check_fin_no_rst_in_sniffer(sniffer)

Expand All @@ -356,84 +361,90 @@ def test_block_action_error_reply_with_conn_close_multiple_requests(self):
is closed by shutdown.
"""

def __test_block_action_error_reply_with_conn_close_frames(self, frame, expected_response=True):
@parameterize.expand(
[
param(
name="data_frame",
frame=DataFrame(stream_id=1, data=b"request body"),
expected_response=True,
),
param(
name="priority_frame",
frame=PriorityFrame(stream_id=1),
expected_response=True,
),
param(
name="rst_frame",
frame=RstStreamFrame(1),
expected_response=True,
),
param(
name="settings_frame",
frame=SettingsFrame(stream_id=0, settings={SettingCodes.INITIAL_WINDOW_SIZE: 0}),
expected_response=True,
),
param(
name="goaway_frame",
frame=GoAwayFrame(stream_id=0, last_stream_id=12, error_code=3),
expected_response=True,
),
param(
name="headers_frame",
frame=HeadersFrame(
stream_id=100,
data=HuffmanEncoder().encode(H2Base.post_request),
flags=["END_HEADERS", "END_STREAM"],
),
expected_response=True,
),
param(
name="continuation_frame",
frame=ContinuationFrame(
100,
HuffmanEncoder().encode([("header", "header_value")]),
flags={"END_HEADERS"},
),
expected_response=True,
),
param(
name="garbage",
frame=b"\x00\x0f\x0f\x0f\xff",
expected_response=False,
),
]
)
def test_block_action_error_reply_with_conn_close(self, name, frame, expected_response):
client = self.get_client("deproxy")

sniffer = self.setup_sniffer()
self.start_services_and_initiate_conn(client)
if expected_response:
self.save_must_fin_socks([client])
self.save_must_not_reset_socks([client])
else:
self.save_must_not_fin_socks([client])
self.save_must_not_reset_socks([client])

curr_responses = len(client.responses)

client.make_request(
request=[
HeaderTuple(":authority", "good.com"),
HeaderTuple(":path", "/"),
HeaderTuple(":scheme", "https"),
HeaderTuple(":method", "GET"),
HeaderTuple("Content-Type", "invalid"),
]
client.create_request(
method="GET", authority="good.com", headers=[("Content-Type", "invalid")]
)
)

client.send_bytes(frame.serialize() if isinstance(frame, Frame) else frame)
client.wait_for_response(3)

if expected_response:
self.assertEqual(curr_responses + 1, len(client.responses))
self.assertEqual(client._last_response.status, "400")
self.assertEqual(client._last_response.body, self.ERROR_RESPONSE_BODY)
self.assertTrue(client.wait_for_connection_close())
self.assertIsNotNone(client.last_response)
self.assertEqual(client.last_response.status, "400")
self.assertEqual(client.last_response.body, self.ERROR_RESPONSE_BODY)
self.check_fin_no_rst_in_sniffer(sniffer)

def test_block_action_error_reply_with_conn_close_data(self):
frame = DataFrame(stream_id=1, data=b"request body")
self.__test_block_action_error_reply_with_conn_close_frames(frame)

def test_block_action_error_reply_with_conn_close_good_priority(self):
frame = PriorityFrame(stream_id=1)
self.__test_block_action_error_reply_with_conn_close_frames(frame)

def test_block_action_error_reply_with_conn_close_rst(self):
frame = RstStreamFrame(stream_id=1)
self.__test_block_action_error_reply_with_conn_close_frames(frame)

def test_block_action_error_reply_with_conn_close_settings(self):
new_settings = dict()
new_settings[SettingCodes.INITIAL_WINDOW_SIZE] = 0
frame = SettingsFrame(0)
frame.settings = new_settings
self.__test_block_action_error_reply_with_conn_close_frames(frame)

def test_block_action_error_reply_with_conn_close_goaway(self):
frame = GoAwayFrame(0)
frame.last_stream_id = 12
frame.error_code = 3
self.__test_block_action_error_reply_with_conn_close_frames(frame)

def test_block_action_error_reply_with_conn_close_headers(self):
encoder = HuffmanEncoder()
frame = HeadersFrame(
stream_id=100,
data=encoder.encode(self.post_request),
flags=["END_HEADERS", "END_STREAM"],
)
self.__test_block_action_error_reply_with_conn_close_frames(frame)

def test_block_action_error_reply_with_conn_close_continuation(self):
encoder = HuffmanEncoder()
request_segment_2 = [("header", "header_value")]
frame = ContinuationFrame(
100,
encoder.encode(request_segment_2),
flags={"END_HEADERS"},
)
self.__test_block_action_error_reply_with_conn_close_frames(frame)

def test_block_action_error_reply_with_conn_close_garbage(self):
frame = b"\x00\x0f\x0f\x0f\xff"
self.__test_block_action_error_reply_with_conn_close_frames(frame, expected_response=False)
else:
self.assertFalse(client.wait_for_connection_close())
self.assertIsNone(client.last_response)
self.check_no_fin_no_rst_in_sniffer(sniffer)


class BlockActionH2Drop(BlockActionH2Base):
Expand Down
57 changes: 37 additions & 20 deletions http_general/test_block_action.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@

import run_config
from framework import tester
from framework.custom_error_page import CustomErrorPageGenerator
from helpers import analyzer, asserts, remote, tf_cfg
from helpers.custom_error_page import CustomErrorPageGenerator


class BlockActionBase(tester.TempestaTest, asserts.Sniffer):
Expand Down Expand Up @@ -66,6 +66,17 @@ def setup_sniffer() -> analyzer.Sniffer:
sniffer.start()
return sniffer

def check_fin_no_rst_in_sniffer(self, sniffer: analyzer.Sniffer) -> None:
sniffer.stop()
if not run_config.TCP_SEGMENTATION:
self.assert_fin_socks(sniffer.packets)
self.assert_unreset_socks(sniffer.packets)

def check_rst_no_fin_in_sniffer(self, sniffer: analyzer.Sniffer) -> None:
sniffer.stop()
self.assert_reset_socks(sniffer.packets)
self.assert_not_fin_socks(sniffer.packets)


class BlockActionReply(BlockActionBase):
ERROR_RESPONSE_BODY = ""
Expand All @@ -76,12 +87,6 @@ def setUp(self):
}
tester.TempestaTest.setUp(self)

def check_fin_and_rst_in_sniffer(self, sniffer: analyzer.Sniffer) -> None:
sniffer.stop()
if not run_config.TCP_SEGMENTATION:
self.assert_fin_socks(sniffer.packets)
self.assert_unreset_socks(sniffer.packets)

def check_last_error_response(self, client, expected_status_code):
"""
In case of TCP segmentation and attack we can't be sure that client
Expand All @@ -107,7 +112,7 @@ def test_block_action_attack_reply(self):
self.check_last_error_response(client, expected_status_code="403")

self.assertTrue(client.wait_for_connection_close())
self.check_fin_and_rst_in_sniffer(sniffer)
self.check_fin_no_rst_in_sniffer(sniffer)

def test_block_action_error_reply_with_conn_close(self):
client = self.get_client("deproxy")
Expand All @@ -121,10 +126,10 @@ def test_block_action_error_reply_with_conn_close(self):
request=f"GET / HTTP/1.1\r\nHost: good.com\r\nContent-Type: invalid\r\n\r\n",
expected_status_code="400",
)
self.assertEqual(client._last_response.body, self.ERROR_RESPONSE_BODY)
self.assertEqual(client.last_response.body, self.ERROR_RESPONSE_BODY)

self.assertTrue(client.wait_for_connection_close())
self.check_fin_and_rst_in_sniffer(sniffer)
self.check_fin_no_rst_in_sniffer(sniffer)

def test_block_action_error_reply(self):
client = self.get_client("deproxy")
Expand All @@ -138,7 +143,7 @@ def test_block_action_error_reply(self):
request=f"GET / HTTP/1.1\r\nHost: good.com\r\nX-Forwarded-For: 1.1.1.1.1.1\r\n\r\n",
expected_status_code="400",
)
self.assertEqual(client._last_response.body, self.ERROR_RESPONSE_BODY)
self.assertEqual(client.last_response.body, self.ERROR_RESPONSE_BODY)

self.assertFalse(client.connection_is_closed())

Expand Down Expand Up @@ -199,10 +204,10 @@ def test_block_action_attack_reply_not_on_req_rcv_event(self):
self.check_last_error_response(client, expected_status_code="403")

self.assertTrue(client.wait_for_connection_close())
self.check_fin_and_rst_in_sniffer(sniffer)
self.check_fin_no_rst_in_sniffer(sniffer)


class BlockActionReplyWithCustomErrorPage(BlockActionReply):
class BlockActionReplyWithCustomErrorPage(BlockActionBase):
tempesta_tmpl = """
listen 80;
srv_group default {
Expand Down Expand Up @@ -247,6 +252,23 @@ def setUp(self):
}
tester.TempestaTest.setUp(self)

def test_block_action_error_reply_with_conn_close(self):
client = self.get_client("deproxy")

sniffer = self.setup_sniffer()
self.start_all_services()
self.save_must_fin_socks([client])
self.save_must_not_reset_socks([client])

client.send_request(
request=f"GET / HTTP/1.1\r\nHost: good.com\r\nContent-Type: invalid\r\n\r\n",
expected_status_code="400",
)
self.assertEqual(client.last_response.body, self.ERROR_RESPONSE_BODY)

self.assertTrue(client.wait_for_connection_close())
self.check_fin_no_rst_in_sniffer(sniffer)


class BlockActionDrop(BlockActionBase):
def setUp(self):
Expand All @@ -255,11 +277,6 @@ def setUp(self):
}
tester.TempestaTest.setUp(self)

def check_fin_and_rst_in_sniffer(self, sniffer: analyzer.Sniffer) -> None:
sniffer.stop()
self.assert_reset_socks(sniffer.packets)
self.assert_not_fin_socks(sniffer.packets)

def test_block_action_attack_drop(self):
client = self.get_client("deproxy")

Expand All @@ -274,7 +291,7 @@ def test_block_action_attack_drop(self):

self.assertTrue(client.wait_for_connection_close())
self.assertIsNone(client.last_response)
self.check_fin_and_rst_in_sniffer(sniffer)
self.check_rst_no_fin_in_sniffer(sniffer)

def test_block_action_error_drop(self):
client = self.get_client("deproxy")
Expand All @@ -290,4 +307,4 @@ def test_block_action_error_drop(self):

self.assertTrue(client.wait_for_connection_close())
self.assertIsNone(client.last_response)
self.check_fin_and_rst_in_sniffer(sniffer)
self.check_rst_no_fin_in_sniffer(sniffer)

0 comments on commit ad6370f

Please sign in to comment.