1

I'm tryng to use nghttpd server to test HTTP/2.0. To start it i'm using:

sudo nghttpd --push=/test=/test1.png,/test2.pcapng,/test2.txt,/test3.png  --no-tls --workers=3  --early-response  -v  80.

In my CWD i've got the push files. In another terminal, i type:

telnet localhost 80

And everything seems ok, since i have this output in the first terminal

[id=1] [ 11.893] send SETTINGS frame <length=6, flags=0x00, stream_id=0>
      (niv=1)
      [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[id=1] [ 21.898] send GOAWAY frame <length=8, flags=0x00, stream_id=0>
      (last_stream_id=0, error_code=SETTINGS_TIMEOUT(0x04), opaque_data(0)=[])

The problems occur when i try an (any type of) HTTP GET with the second terminal:

telnet localhost 80
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
GET /test HTTP/2.0
Connection closed by foreign host.

In my first terminal i get this output

[id=1] [314.531] closed

How can i solve this?

2 Answers2

1

HTTP/2 is a binary protocol, and you cannot use telnet like you could with HTTP/1.1.

You want to read carefully the HTTP/2 specification that describes that the HTTP/2 protocol is binary and requires to compress HTTP headers using HPACK. These two things combined make very difficult to use telnet and manual input to the socket; the usual way to interact with HTTP/2 server is to use HTTP/2 client tools.

Such client tools include nghttp itself and, among others, curl.

Community
  • 1
  • 1
sbordet
  • 16,856
  • 1
  • 50
  • 45
  • I solved using curl forcing http2 (after installing libcurl), but i would like to build and send a frame by myself maybe using nc or telnet if possible – Lorenzo Epifani Jun 07 '18 at 09:56
  • It is possible, just that you have to write binary data and you have to figure out the HPACK encoding for the request line and headers by yourself - it's some work but doable. Perhaps it's best that you use a tool to send a request, capture the network trace with `tcpdump` or similar, and then replay the bytes captured with `nc` or `telnet`. – sbordet Jun 07 '18 at 10:32
1

Little more elaboration: the HTTP/2 server sends control frames like MAGICand SETTINGS (this includes information like Max Concurrent Streams and Initial Window Size) and the server does not honor the client until these are acknowledged by the client (in a SETTINGS frame as well).

Telnet just establishes the TCP connection and then waits for the user to issue next packets.

Without seeing these control frames in couple of seconds, the server closes the connection in couple of seconds.

This is in accordance to RFC 7540, section 6.5.3:

If the sender of a SETTINGS frame does not receive an acknowledgement within a reasonable amount of time, it MAY issue a connection error (Section 5.4.1) of type SETTINGS_TIMEOUT.

This is the log of nghttpd (running in verbose mode) when I connected via Telnet:

[id=2] [ 34.645] send SETTINGS frame <length=6, flags=0x00, stream_id=0>
          (niv=1)
          [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[id=2] [ 44.654] send GOAWAY frame <length=8, flags=0x00, stream_id=0>
          (last_stream_id=0, error_code=SETTINGS_TIMEOUT(0x04), opaque_data(0)=[])
[id=2] [ 44.654] closed

In fact, in your question lies the answer, only that you printed the log of nghttpd server in parts. The server sent GOAWAY frame 10 seconds after sending the SETTINGS frame and closed the TCP connection.

Soumya Kanti
  • 1,429
  • 1
  • 17
  • 28
  • I'm just reading the RFC 7540. Since nghttpd is a testing server, i can customize its requirement in order to estabilsh a connection with an empty SETTINGS frame (0-7 parameter it says, empty i mean with 0 paramenters) with the ack set. I'm working on this now. **Is the ack supposed to be in the TCP envelope? Is there a way to see an example frame?** I'm tryng to google it but i cannot find anything. I'm tryng to use wireshark to see an example of response in a HTTP/2 communication, but is impossible because the traffic is encrypted(TLS) – Lorenzo Epifani Jun 07 '18 at 09:23
  • You can run nghttp2 over h2c. `$ nghttpd -a 127.0.0.1 --no-tls -d ./htdoc 8080` – Soumya Kanti Jun 07 '18 at 12:31