spdy-http2 / node-spdy

SPDY server on Node.js
2.81k stars 196 forks source link

Can't make HTTP2 work with koa #263

Closed felixsanz closed 8 years ago

felixsanz commented 8 years ago

Hi, i need a bit of help because this isn't working but first, a question:

It is possible to use HTTP2 without SSL/certificates? The use case is communicating with haproxy in a secure network (haproxy does SSL termination)

If it's possible, setting plain: false makes the server always return "empty reply from server"

indutny commented 8 years ago

I think for this scenario ssl: false, plain: true is what actually needed.

felixsanz commented 8 years ago

but i can't make use of HTTP2 with that. i'm using procotols: ['h2'] and even protocol: 'h2' and none work, it just sends http 1.1.

Also. plain: true why? plain is not http2 right?

plain - if defined, server will ignore NPN and ALPN data and choose whether to use spdy or plain http by looking at first data packet.

felixsanz commented 8 years ago

const options = {
  spdy: {
    protocols: ['h2'],
    plain : true,
    ssl   : false,
  },
}

const foo = spdy.createServer(options, server.callback())
  console.log(foo._spdyState) // <----------- check below
  foo.listen(process.env.PORT || 3000, () => {
    console.log('Server listening...')
  })
{ options: { protocols: [ 'h2' ], plain: true, ssl: false },
  secure: false,
  listeners: [ [Function: connectionListener] ] }
curl --http2 http://localhost:3000
curl: (52) Empty reply from server
curl -I http://localhost:3000
HTTP/1.1 200 OK
indutny commented 8 years ago

Is h2 advertised on HAProxy through ALPN?

felixsanz commented 8 years ago

@indutny at the moment i'm trying to debug node directly. as you see i'm doing curl to localhost:3000, thats the node server. haproxy is not interacting yet

indutny commented 8 years ago

Yeah, sorry about that. Just tested it myself (I don't have http2-enabled curl)

const spdy = require('./');

spdy.createServer({
  spdy:{ plain: true, ssl: false }
}, (req, res) => {
  res.end('hello');
}).listen(8000, () => {
  console.log('Listening');
});
$ h2load -p h2c http://127.0.0.1:8000/ -v -n 1000
starting benchmark...
spawning thread #0: 1 total client(s). 1000 total requests
Application protocol: h2c
progress: 10% done
progress: 20% done
progress: 30% done
progress: 40% done
progress: 50% done
progress: 60% done
progress: 70% done
progress: 80% done
progress: 90% done
progress: 100% done

finished in 1.06s, 942.01 req/s, 30.40KB/s
requests: 1000 total, 1000 started, 1000 done, 1000 succeeded, 0 failed, 0 errored, 0 timeout
status codes: 1000 2xx, 0 3xx, 0 4xx, 0 5xx
traffic: 32.27KB (33049) total, 1000B (1000) headers (space savings 90.00%), 4.88KB (5000) data
                     min         max         mean         sd        +/- sd
time for request:      599us     10.64ms      1.06ms       849us    92.70%
time for connect:      216us       216us       216us         0us   100.00%
time to 1st byte:     8.08ms      8.08ms      8.08ms         0us   100.00%
req/s           :     942.05      942.05      942.05        0.00   100.00%
indutny commented 8 years ago

Appears to be working! Does h2load work for you too?

felixsanz commented 8 years ago

It kinda works now, but it's using HTTP2? Because when i access with chrome, and i check chrome://net-internals/#http2, nothing is there related to localhost.

Something weird is h2load shows this:

  -p, --no-tls-proto=<PROTOID>
              Specify ALPN identifier of the  protocol to be used when
              accessing http URI without SSL/TLS.
              Available protocols: h2c and
              http/1.1
              Default: h2c

But chrome says:

HTTP/2 Enabled: true
SPDY/3.1 Enabled: false
Use Alternative Service: undefined
ALPN Protocols: h2,http/1.1
NPN Protocols: undefined

h2 and h2c is not the same?


I also use this extension and it's not showing me that i'm using http2. Instead it appears as if i were using http/1.1

felixsanz commented 8 years ago

If i enable ssl and disable plain, i get ERR_SSL_VERSION_OR_CIPHER_MISMATCH in chrome.

If it helps: https://gist.github.com/felixsanz/5a144aacd443be96a2f21a16e0955fa0

Here appear:

--> Testing protocols (via sockets except TLS 1.2 and SPDY/NPN)

 SSLv2      not offered (OK)
 SSLv3      not offered (OK)
 TLS 1      not offered
 TLS 1.1    not offered
 TLS 1.2    not offered (NOT ok)
 SPDY/NPN   not offered

So looks like no protocol is enabled. But anyway this is related to SSL, and i prefer to use HTTP2 without SSL (but if not possible, https is fine)

indutny commented 8 years ago

@felixsanz that's because it is running in a plain mode. This is not really a way it is supposed to be run, just something that could be used when running behind HAProxy or other load balancer.

Chrome can't really connect to it using h2 this way, though. (Unless there is some flag at chrome://flags to have a plain-text http2 connections).

Here is a link http://httpwg.org/specs/rfc7540.html#rfc.section.3.1 about differences between h2 and h2c.

indutny commented 8 years ago

@felixsanz node-spdy doesn't support running without TLS/SSL. Either balancer should be in front of it, or the TLS cert/key should be supplied to it.

Sorry!

felixsanz commented 8 years ago

So can you help with the SSL version? ERR_SSL_VERSION_OR_CIPHER_MISMATCH

indutny commented 8 years ago

Do you supply cert/key options to spdy.createServer?

felixsanz commented 8 years ago

Yes. I created a self-signed cert using this commands:

openssl genrsa -des3 -passout pass:x -out server.pass.key 2048

openssl rsa -passin pass:x -in server.pass.key -out server.key

rm server.pass.key

openssl req -new -key server.key -out server.csr

openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
indutny commented 8 years ago

Does curl -k https://127.0.0.1:3000/ work?

indutny commented 8 years ago

Ah, I see that you are using ssltest. One sec.

indutny commented 8 years ago

May I ask you to post a code sample of server instantiation that you use?

felixsanz commented 8 years ago

I always get: curl: (35) error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure

Looks like curl is trying to use ssl3 but all procotols are disabled

felixsanz commented 8 years ago

I uploaded a test repo:

mkdir spdyssl
cd spdyssl
git clone https://github.com/felixsanz/spdyssl.git .
npm install
npm run start
curl -k https://localhost:3002

Port 3002

I hope i didn't miss anything

indutny commented 8 years ago

The option name is cert, not crt. 😉 This should fix it.

felixsanz commented 8 years ago

Oh come on....... :angry:

Thanks :sob:

indutny commented 8 years ago

You're welcome.