On Tuesday, September 04, 2012 08:41:44 AM Willy Tarreau wrote: > On Mon, Sep 03, 2012 at 11:21:51PM -0700, Justin Karneges wrote: > > On Tuesday, September 04, 2012 01:37:17 AM Willy Tarreau wrote: > > > After several months of efforts by the Exceliance team, we managed to > > > rework all the buffer and connection layers in order to get SSL working > > > on both sides of HAProxy. > > > > Very cool. > > > > Since HAProxy is event-driven, is anything done to avoid expensive crypto > > operations from blocking the event loop? Maybe that is what you intend for > > "remote sockets" ? > > Exactly ! > > That said, as I've always said, the problem is not the relative cost of > crypto but the computation time. On small devices, if an operation can > take 10ms, it clearly is a problem. However on larger devices, if no > operation takes more than 100 microseconds, then the added latency is > minimal compared to system latency. That does not mean it's not a problem, > just that when you're at 100% CPU, you might still have enough scheduling > capacity to process the rest of the traffic without too much impact. > > But clearly when we can offload SSL to other processes, that will be much > better. This can already be done BTW, but you have to chain proxies. For > instance : > > global > nbproc 4 > > listen front > bind-process 1,2 > bind :443 ssl haproxy.pem > server http 127.0.0.1:8888 send-proxy > > listen http > bind-process 3 > bind 127.0.0.1:8888 accept-proxy > mode http > server back 127.0.0.1:8443 send-proxy > > listen back > bind-process 4 > bind 127.0.0.1:8443 accept-proxy > server out 192.168.0.1:443 ssl > > You see, https is accepted on processes 1 and 2, which decipher the > traffic and pass it to process 3, preserving IP information. This > process does the HTTP handling and passes the traffic to process 4 > which will re-cipher it before going to the server. > > Admittedly this is ugly and that's why we'd like to implement the > remote sockets soon, so that you can write something like this : > > listen http > bind-process 3 > bind :443 ssl haproxy.pem process 1,2 > mode http > server out 192.168.0.1:443 ssl process 4 > > Also, using socketpair() internally will be much faster and have a lower > overhead than TCP connect/accept.
Usually, the most expensive operations in TLS are the public key ones at the start of a negotiation (and possibly a renegotiation, though I'm not sure of protocol details there). However, pretty much all other TLS traffic should be fast to execute. I wonder if there is a way to differentiate these steps? This is how you'd ensure that a bunch of new https connections do not cause slowdown of existing https connections. I have tried in the past to use OpenSSL in an event-driven application in a way that does not block the event loop. This was for a local desktop application that used smart cards, where an OpenSSL call might block for 5 seconds while it hits the hardware. Since the expected number of TLS sessions in the application was small, I simply made one thread per TLS session, and funneled all results back to the event-driven main thread. Of course a thread per connection approach would not work if you want to handle thousands of connections like HAProxy. One day I wanted to go back and rewrite my code such that I could send operations to separate threads or keep them in the main thread based on a given TLS session state. This way, I could make it so only the TLS handshakes (with the expensive RSA operations and such) would need concurrency. Then the number of threads needed would be the number of expected simultaneous handshakes, which would be a far more manageable number (20?) than expected simultaneous sessions (thousands). This is not an answer for you, but just a brain dump of my thoughts on the subject. Justin

