diff --git a/mitmproxy/addons/tlsconfig.py b/mitmproxy/addons/tlsconfig.py index 2df6cf0c3..a05d63598 100644 --- a/mitmproxy/addons/tlsconfig.py +++ b/mitmproxy/addons/tlsconfig.py @@ -34,6 +34,10 @@ def alpn_select_callback(conn: SSL.Connection, options: List[bytes]) -> Any: http2 = app_data["http2"] if server_alpn and server_alpn in options: return server_alpn + if server_alpn == b"": + # We do have a server connection, but the remote server refused to negotiate a protocol: + # We need to mirror this on the client connection. + return SSL.NO_OVERLAPPING_PROTOCOLS http_alpns = tls.HTTP_ALPNS if http2 else tls.HTTP1_ALPNS for alpn in options: # client sends in order of preference, so we are nice and respect that. if alpn in http_alpns: diff --git a/test/mitmproxy/addons/test_tlsconfig.py b/test/mitmproxy/addons/test_tlsconfig.py index 3a0e012a2..885b9410f 100644 --- a/test/mitmproxy/addons/test_tlsconfig.py +++ b/test/mitmproxy/addons/test_tlsconfig.py @@ -30,6 +30,10 @@ def test_alpn_select_callback(): # Test no overlap assert tlsconfig.alpn_select_callback(conn, [b"qux", b"quux"]) == SSL.NO_OVERLAPPING_PROTOCOLS + # Test that we don't select an ALPN if the server refused to select one. + conn.set_app_data(tlsconfig.AppData(server_alpn=b"", http2=True)) + assert tlsconfig.alpn_select_callback(conn, [b"http/1.1"]) == SSL.NO_OVERLAPPING_PROTOCOLS + here = Path(__file__).parent