tatsuhiro-t / spdylay

The experimental SPDY protocol version 2, 3 and 3.1 implementation in C
http://tatsuhiro-t.github.io/spdylay/
MIT License
602 stars 103 forks source link

shrpx forward proxy support? #31

Closed nutinshell closed 11 years ago

nutinshell commented 12 years ago

I tried to use shrpx to forward proxy traffic, but without success. Backend is a Squid forward HTTP proxy, shrpx turn it into a SPDY proxy which Chrome browser supported.

tatsuhiro-t commented 12 years ago

Use -b option to specify Squid address and port. If you get error from Shrpx, then use -L INFO and see the log. When Shrpx could not connect to the backend, it will log the event.

nutinshell commented 12 years ago

Yes, I used -b for squid proxy, Stud works fine with squid forward proxy.

Shrpx doesn't work, the error like:

[INFO] Accepted connection. fd=7 (shrpx_listen_handler.cc, line 90) [INFO] Upstream connected. handler 0xbef1f0 (shrpx_client_handler.cc, line 91) [INFO] Upstream negotiated next protocol: spdy/2 (shrpx_client_handler.cc, line 176) [INFO] Upstream network error (shrpx_client_handler.cc, line 76) [INFO] Deleting ClientHandler 0xbef1f0 (shrpx_client_handler.cc, line 121) [INFO] Deleted (shrpx_client_handler.cc, line 136)

tatsuhiro-t commented 12 years ago

There was network error between client and Shrpx. Shrpx did not connect to squid. One possible reason of network error in this stage is that client refused to connect because certificate is invalid (self-signed). What client are you using?

nutinshell commented 12 years ago

The client is Chrome. The cert is validated, from startssl.org which works fine with Squid https_port or Stud. I tried this morning it complains the error like: Timeout, but now it seems the error like: net::ERR_PROXY_CERTIFICATE_INVALID, so weird.

tatsuhiro-t commented 12 years ago

If you set shrpx address in chrome's proxy setting, it does not work. Shrpx is just like Stud with SPDY. You need to enter Shrpx address in the URI bar to connect the site.

nutinshell commented 12 years ago

But by using Stud, it actually works with Chrome SSL proxy setting :) Chrome support SPDY/SSL proxy type.

tatsuhiro-t commented 12 years ago

Hmm, so it seems I misunderstood the stud's ability. The fact is that Shrpx cannot be used as SPDY/SSL proxy.

nutinshell commented 12 years ago

Oh, so sorry to hear that. If Shrpx can do it, that would be cool to have fast SPDY proxy.

tatsuhiro-t commented 12 years ago

It turns out that Shrpx can be used as ssl proxy but only allows http proxy requests (I think stud is in this situation too). To support https and spdy traffic, we just add CONNECT method handling. CONNECT request in spdy is just one big stream, sending DATA frame back and forth. Adding that support is not big deal. 2012/07/10 2:08 "nutinshell" < reply@reply.github.com

:

Oh, so sorry to hear that. If Shrpx can do it, that would be cool to have fast SPDY proxy.


Reply to this email directly or view it on GitHub: https://github.com/tatsuhiro-t/spdylay/issues/31#issuecomment-6852857

nutinshell commented 12 years ago

Stud can handle both http and https traffic very well, in fact, stud just terminates the ssl proxy and forward http/https traffic to Squid.

tatsuhiro-t commented 12 years ago

Ok, forget my previous post. I just mixed apache and squid backends.

If squid is back, I think shrpx should work as ssl proxy in the current form, well, theoretically. The thing is I have never tested shrpx with this configuration. I will test it tonight and report back here. 2012/07/10 13:04 "nutinshell" < reply@reply.github.com

:

Stud can handle both http and https traffic very well, in fact, stud just terminates the ssl proxy and forward http/https traffic to Squid.


Reply to this email directly or view it on GitHub: https://github.com/tatsuhiro-t/spdylay/issues/31#issuecomment-6866453

tatsuhiro-t commented 12 years ago

Tested. It turns out that I need to fix several portion of the code to make Shrpx SSL/SPDY proxy. I'm working on this.

tatsuhiro-t commented 12 years ago

I finally made shrpx act like SSL/SPDY proxy. Use -s or --spdy-proxy option to enable SSL/SPDY proxy mode. I tested several web sites and it worked fine so far.

nutinshell commented 12 years ago

It works! I'll keep testing it and do some performance bench test with Stud. Thanks again to bring this cool stuff.

nutinshell commented 12 years ago

Will you consider to add a SPDY "clinet mode" to shrpx for bench testing or other purpose? Stud have it and this is some explanations: https://github.com/bumptech/stud/pull/79

tatsuhiro-t commented 12 years ago

I just read the thread, but I am not clear how the client mode works.. Does it accept non-secure HTTP connection and forward encrypted connection to the backend?

nutinshell commented 12 years ago

It may work like this graph:

user(uses 127.0.0.1:1111 as http proxy) <-> shrpx (client mode, -f 127.0.0.1,1111 -b aaa.com,2222) <-spdy secure tunnel-> shrpx ( server mode, -f aaa.com,2222 -b squidproxy,port) <-> http proxy

Similar like Stunnel server side and client side, but in SPDY.

tatsuhiro-t commented 12 years ago

Thank you. Now I understood the client mode.

nutinshell commented 12 years ago

:) cool, I will do a bench test when client mode implemented, but it seems still lack of sessions cache.

tatsuhiro-t commented 12 years ago

Session caching is now enabled for across workers.

nutinshell commented 12 years ago

In proxy mode, when use the spdy proxy in Chrome at the first time, e.g, reboot and relaunch Chrome, it will take a long time to open the webpage via spdy proxy, then it becomes normal, Stud SSL proxy has no this issue.

tatsuhiro-t commented 12 years ago

It takes 10 seconds for my Linux box. I'll check tomorrow that if Shrpx is also slow without SPDY.

tatsuhiro-t commented 12 years ago

I tested node-spdyproxy. It also takes several seconds when reboot and first launch Chrome. If SPDY proxy is slow compared to normal https proxy, then I think Chrome needs longer initialization time for SPDY. Anyway, first launch of Chrome is very slow.

peteroconnor commented 12 years ago

A forward spdy proxy will be very very useful.

I have been looking a server software that can take advantage of the Chrome SSL proxy feature. I haven't found a single one!

Node-spdy proxy works beautifully, except having a memory problem that haven't been sorted out.

Squid has removed the spdy feature out of its dev pipeline. Nginx and jetty only work as a reverse spdy proxy.

If spdylay can add this feature, it will be very nice.

tatsuhiro-t commented 12 years ago

You can use shrpx in spdylay as Chrome SSL proxy with Squid backend. Use -s option to enable SSL proxy mode.

peteroconnor commented 12 years ago

Thanks for the tip. Are there man-in-the-middle problems for https traffics in this setting?

tatsuhiro-t commented 12 years ago

In Shrpx, HTTPS traffic uses HTTP CONNECT tunneling as with the usual proxy server, so there is no MITM problem.

peteroconnor commented 12 years ago

It works very nicely.

nutinshell commented 12 years ago

Hi, any update on https://github.com/tatsuhiro-t/spdylay/issues/31#issuecomment-6905046 ? just want to bring up a SPDY tunnel between two shrpx points(server and client mode).

tatsuhiro-t commented 12 years ago

No progress at the moment.

tatsuhiro-t commented 12 years ago

I'm now working on client-mode.

tatsuhiro-t commented 12 years ago

I added --client-mode option.

nutinshell commented 12 years ago

Great works. I found a issue in client-mode, when access http proxy directly in client mode like: open client-mode's host:httpport in browser, it should return 404 or 407 status code from proxy, but not 503 shrpx server error.

tatsuhiro-t commented 12 years ago

Does the backend http proxy support SPDY? Client mode only speaks SPDY to the backend. What does your configuration look like?

nutinshell commented 12 years ago

SPDY proxy created by shrpx: shrpx -b 127.0.0.1,8888 -f x.x.x.x,9999 -s -D -n 2 -c 1000 cert.key cert.crt HTTP proxy created by shrpx(client-mode): shrpx --client-mode -b x.x.x.x,9999 -f 127.0.0.1,3128 -D -n 2 -c 1000

When request to 127.0.0.1:3128, curl -I 127.0.0.1:3128, it should return 407 status code from server side's proxy server, such as squid, not 503.

tatsuhiro-t commented 12 years ago

I think client mode cannot be used with proxy server. If we request http://localhost/foo to client-mode shrpx, it will finally forward to the last proxy squid. Then squid is trying to request http://localhost/foo, which creates loop.

nutinshell commented 12 years ago

Yes, any request to client-mode shrpx, it forward to squid proxy, exactly, A GET request to test the proxy should return http 407(you can test it by open squid host:port in browser), this is the client-mode shrpx should return I think.

tatsuhiro-t commented 12 years ago

I got 400 when opening squid host:port in browser. I think it is because I did not setup authentication. I think the difference of 4xx and 5xx is that how request-line is sent to squid. When opening squid host:port from browser, squid gets the following request line:

GET / HTTP/1.1

On the other hand, though spdy-proxy, it correctly sends request-line for the proxy:

GET http://x.x.x.x/ HTTP/1.1

Squid responds differently for these cases and it reflects the response status.

nutinshell commented 12 years ago

Test by shrpx-client<->shrpx-proxy-server curl -I 127.0.0.1:8888

HTTP/1.1 503 Service Unavailable Content-Type: text/html; charset=iso-8859-1 Date: Sun, 18 Nov 2012 18:09:21 GMT Via: 1.1 shrpx, 1.1 shrpx

Test by stud-client<->stud-proxy-server curl -I 127.0.0.1:9999

HTTP/1.0 400 Bad Request Server: squid Mime-Version: 1.0 Date: Sun, 18 Nov 2012 18:10:01 GMT Content-Type: text/html Content-Length: 3773 X-Squid-Error: ERR_INVALID_URL 0 Vary: Accept-Language Content-Language: en

stud do correctly return 400 from squid, I believe which is right.

tatsuhiro-t commented 12 years ago

OK, I got the same result with you. The problem is that --spdy-proxy option always modifies request line to the absolute URI before sending backend proxy and it causes 503 response because "GET https://..." is not supported.

Try without --spdy-proxy option. I got same result with stud without --spdy-proxy.

nutinshell commented 12 years ago

OK, --spdy-proxy works for it.

Here comes an other issue, no SPDY site(like https://twitter.com or https://www.google.com) could be open via client-side proxy, weird.

tatsuhiro-t commented 12 years ago

Are you using client-mode <-> spdy-proxy <-> squid <-> google.com? I fixed this issue. Meanwhile, I'm working on reducing SPDY connections. The idea is that share the same SPDY connection with connections in the same thread.

nutinshell commented 12 years ago

Yes, the issue fixed, but intro a new bug, all http request return 404...

tatsuhiro-t commented 12 years ago

I can use client-mode <-> spdy-proxy <-> squid with chrome without problem. client-mode <-> spdyd works fine too with HTTP link. Pull the latest changes, I made shared SPDY connections.

nutinshell commented 12 years ago

shrpx -b squid -f X,16677 -D -n 2 -c 1000 --ciphers RC4 cert.key cert.crt (server) shrpx --client-mode -f 127.0.0.1,8888 -b X,16677 -D -n 2 -c 1000 --ciphers RC4

Use 127.0.0.1:8888 as proxy, all http pages return 404, what's the possible problem I met?

tatsuhiro-t commented 12 years ago

I think you need -s in the second server. Without that, shrpx does not alter SPDY request path to the path squid understands.

tatsuhiro-t commented 12 years ago

It may be confusing with my previous comment, but if you want to use client mode and 2nd shrpx, you need -s in the second server.

nutinshell commented 12 years ago

Yes, I tried -s to let proxy work, but it will fail haproxy's healthy check, because GET 127.0.0.1:8888 return 503, so I remove -s like you said in https://github.com/tatsuhiro-t/spdylay/issues/31#issuecomment-10489474 , it worked around for me for some time.

You should consider to let GET request return 4XX code from remote squid, this is what stud does.

tatsuhiro-t commented 12 years ago

This is a problem of how chrome sends the HTTP request to the proxy in SPDY. I explain why we cannot 4XX status code in shrpx SPDY proxy configuration.

For plain HTTP, HTTP request to the proxy is something like this:

GET http://example.org HTTP/1.1
host: example.org

And proxy can recognize this is the request for the proxy by looking absolute URI in request line.

On the other hand, chrome sends HTTP request to the proxy in SPDY:

:host example.org
:path /
:schme http
:version HTTP/1.1

This is completely the same with HTTP request for non-proxy Web server. Therefore, SPDY proxy has to make a choice to decide this is proxy request or not. In Shrpx, --spdy-proxy is given, it assumes this is the proxy request and construct HTTP request to the backend squid like this:

GET http://example.org HTTP/1.1
host: example.org

This is how spdy-proxy works.

If --spdy-proxy is not given, shrpx creates HTTP request like this:

GET / HTTP/1.1
host example.org

See the difference of the request URI.

Why does stud configuration return 404? This is because stud just forwards HTTP request headers unaltered. So if you sends HTTP request:

GET / HTTP/1.1
host: 127.0.0.1:8888

Then, stud chain forwards it to squid. Squid sees the request path is not absolute URI, so it returns 400 bad request.

tatsuhiro-t commented 12 years ago

That said, I should consider to add another option to make client mode a proxy explicitly so that we can check request URI and if it is not absolute, return 400 status code. I think it is necessary to stop loop when non proxy request is issued. 2012/11/21 3:11 "nutinshell" notifications@github.com:

Yes, I tried -s to let proxy work, but it will fail haproxy's healthy check, because GET 127.0.0.1:8888 return 503, so I remove -s like you said in #31https://github.com/tatsuhiro-t/spdylay/issues/31#issuecomment-10489474, it worked around for me for some time.

You should consider to let GET request return 4XX code from remote squid, this is what stud does.

— Reply to this email directly or view it on GitHubhttps://github.com/tatsuhiro-t/spdylay/issues/31#issuecomment-10565887.