mike820324 / microProxy

A http/https interceptor written in pure python.
MIT License
17 stars 3 forks source link

Connecting to twitter will get RESET frame #243

Open mike820324 opened 7 years ago

mike820324 commented 7 years ago

I have notice that twitter will reject the following frame combinations as well.

If a client first sent a HEADER frame with END_HEADERS flag set, after that sent a PRIORITY frame with the same stream id, twitter server will reply with a RESET frame.

The following is the code snippets that I used

import certifi
import h2.connection
import h2.events

import errno
import socket
import ssl
import time

SERVER_NAME = 'www.twitter.com'

socket.setdefaulttimeout(2)

c = h2.connection.H2Connection()
c.initiate_connection()

ctx = ssl.create_default_context(cafile=certifi.where())
ctx.set_alpn_protocols(['h2', 'http/1.1'])
ctx.set_npn_protocols(['h2', 'http/1.1'])

s = socket.create_connection((SERVER_NAME, 443))
s = ctx.wrap_socket(s, server_hostname=SERVER_NAME)

s.sendall(c.data_to_send())

headers = [
    (':method', 'GET'),
    (':path', '/'),
    (':authority', SERVER_NAME),
    (':scheme', 'https'),
    ('user-agent', 'custom-python-script'),
]
c.send_headers(1, headers, end_stream=True)
c.prioritize(1, weight=201, depends_on=0, exclusive=False)

s.sendall(c.data_to_send())

while True:
    data = s.recv(65536 * 256)
    if not data:
        break

    try:
        events = c.receive_data(data)
        s.sendall(c.data_to_send())
    except:
        break

    for event in events:
        print(event)

Since firefox will sent a header frame with priority updated and end stream within it. Hyper-h2 will treat this into two separated events (RequestReceived, PriorityUpdated). As a result, we will first called sent_headers with priority updated and end_stream, after that calling prioritize and causing the situations.

mike820324 commented 7 years ago

B.T.W, if the above scenario is violating the RFC, there is no need to fix this and add more complexity to our code base. :)