Re: About the SPOE
On Wed, Jul 24, 2024 at 03:48:15PM +0200, Christopher Faulet wrote: > As announced, the SPOE was finally refactored. This new SPOE will be shipped > with the 3.1-dev4. It is a full rewrite of the engine, based on a dedicated > SPOP multiplexer. It means a "spop" proxy mode, used for SPOE backends, was > added. It is now the default mode for backends used by SPOE engines. "mode > spop" can be explicitly specified, but otherwise, the mode is detected > during post-parsing. So, these backends cannot be mixed for a raw TCP usage. > > Thanks to this refactoring, SPOP connections are now properly reused, > similarly to HTTP connections. So, it is now possible to properly balance > connections when several servers are configured. The management of IDLE > connections used on HTTP backends is used for SPOP connections. It is a huge > improvement compared to what was performed by hand with the pool of SPOE > applets. In addition to these, what's important to understand is that previously, connections were load-balanced between agents while now it's messages. Thus the control is much finer. For example "balance leastconn" can make some sense for always sending a request to the least loaded agent; "balance hash var(ptxn.XXX)" can make sense as well to perform some affinity and improve context reuse on the backend, and so on. It's never easy to enumerate all possibilities offered by switching from per-connection processing to per-request processing, but it's basically the same as we gained long ago by switching from forwarding SSL as raw TCP connections and later decoding SSL to process each individual request! That's why I second Christopher regarding this quest for testers. It's possible some will feel that something tiny is missing to achieve a great step forward in their use cases, it'd better be expressed early ;-) Willy
Re: About the SPOE
Le 28/03/2024 à 18:14, Christopher Faulet a écrit : Thanks Lokesh, Abhijeet and Aleksandar for your feedback. This truly help us. Thanks too to Pierre and Mattia for their feedback on the request mirroring. Rest assured that we take this into account in our reflections. After some internal discussions and also regarding to feedback we had internally, we've decided to invest some time to rewrite the engine for the 3.1. A feature request was created to keep the conversation going (https://github.com/haproxy/haproxy/issues/2502). But to sum up, the idea is to rethink the engine to make it simpler. Of course, the engine will be based on recent core features. But features will also be reduced to remain maintainable. Among other things, the asynchronous mode will be removed because it is far too complex and most probably unused. It is clearly an over-designed feature. Then we will not invest time on the payload streaming support. This feature is pretty complex to implement and this is mainly why we never made the current SPOE evolved. Let's be reasonable this time. This will probably influence the design. For people who have invested time in SPOAs development, the protocol will be kept compatible. The purpose here is to rewrite the engine itself. So it is above all internal to HAProxy. For the 3.0, the warning about the SPOE will be changed to notify users some configuration changes should be expected in future versions. Some other small changes should be expected for the 3.0. But the heavy lifting will be performed on the 3.1. Of course, it is still a subject under discussion. The above issue is here to collect ideas for the next steps but also for more long term features. Feel free to feed it. Hi, As announced, the SPOE was finally refactored. This new SPOE will be shipped with the 3.1-dev4. It is a full rewrite of the engine, based on a dedicated SPOP multiplexer. It means a "spop" proxy mode, used for SPOE backends, was added. It is now the default mode for backends used by SPOE engines. "mode spop" can be explicitly specified, but otherwise, the mode is detected during post-parsing. So, these backends cannot be mixed for a raw TCP usage. Thanks to this refactoring, SPOP connections are now properly reused, similarly to HTTP connections. So, it is now possible to properly balance connections when several servers are configured. The management of IDLE connections used on HTTP backends is used for SPOP connections. It is a huge improvement compared to what was performed by hand with the pool of SPOE applets. In parallel, the notion of child and parent streams was added. In this context, the SPOE stream, used to exchange messages with SPOA is the child while the main stream is the parent. The child stream is created by the parent stream to perform some processing for its parent. In addition, it is possible from a child stream to retrieve variables of the parent stream. This feature can be used to perform some processing in the child stream based on properties of the parent stream. The first and probably the main usage is to apply stickiness rules in a child stream based on info from the parent stream. dedicated scopes was added to retrieve parent variables (psess, ptxn, preq and pres). Here is a very simple example: frontend front-http bind *:8889 tcp-request content set-var(txn.client_src) src filter spoe engine ip-reputation config /spoe-ip-reputation.conf http-request send-spoe-group ip-reputation check-client-ip http-response set-header X-Ip-Score %[var(sess.iprep.ip_score)] default_backend back-http backend back-http server www 127.0.0.1:8000 backend iprep-backend mode spop timeout server 10s stick-table type ip size 200k expire 30m stick on var(ptxn.client_src) server iprep-srv1 127.0.0.1:12345 server iprep-srv2 127.0.0.1:12345 server iprep-srv3 127.0.0.1:12345 server iprep-srv4 127.0.0.1:12345 With this configuration, SPOP sessions are sticky on servers based on the client source address. The configuration manual was updated accordingly. Check it for details. About other changes, the fragmentation support and the asynchronous mode were removed. Without the streaming feature, the fragmentation is just useless. And the asynchronous mode is overkill and just incompatible with the new architecture. Following SPOE parameters were also removed and are silently ignored when found in SPOE configuration: maxconnrate, maxerrrate, max-waiting-frames, timeout hello and timeout idle. SPOE log format was adapted because several info no longer exist. The first and main step is finished. But there are some missing parts. For instance, connection closures are a bit dirty for now because the internal API must evolve a bit first. This will be achieved before the 3.1 release. Stats regarding the SPOE must be enriched. Some parameters must be added (in configuration and
Re: [SPOE] an error was triggered during the resources allocation.
Le 10/07/2024 à 09:02, Maciej Zdeb a écrit : Hi, I've tested this patch and it looks very promising - no errors so far. I will deploy it tomorrow on a larger scale. Thanks Christopher! Thanks ! I will merge it. -- Christopher Faulet
Re: [SPOE] an error was triggered during the resources allocation.
Hi, I've tested this patch and it looks very promising - no errors so far. I will deploy it tomorrow on a larger scale. Thanks Christopher! Kind regards, wt., 9 lip 2024 o 08:43 Christopher Faulet napisał(a): > Le 05/07/2024 à 12:57, Maciej Zdeb a écrit : > > Hi, > > I'm using haproxy version 2.8.9 and noticed strange behavior of the SPOE > engine. > > I see many logs like below. From what I managed to investigate, the > error with > > value 2 is defined as SPOE_CTX_ERR_RES (an error was triggered during > the > > resources allocation) and this particular error is set only in > > spoe_queue_context function. > > > > So probably there is an issue with that logic of creating applets, but > I'm > > unable to understand what is wrong with it. I don't have any limits in > spoe > > configuration so it should not be the cause. > > > > /* Check if we need to create a new SPOE applet or not. */ > > if (agent->rt[tid].processing < agent->rt[tid].idles || > > agent->rt[tid].processing < > > read_freq_ctr(&agent->rt[tid].processing_per_sec)) > > goto end; > > > > SPOE_PRINTF(stderr, "%d.%06d [SPOE/%-15s] %s: stream=%p" > > " - try to create new SPOE appctx\n", > > (int)date.tv_sec, (int)date.tv_usec, agent->id, > __FUNCTION__, > > ctx->strm); > > > > spoe_create_appctx(conf); > > > >end: > > /* The only reason to return an error is when there is no > applet */ > > if (LIST_ISEMPTY(&agent->rt[tid].applets)) { > > ctx->status_code = SPOE_CTX_ERR_RES; > > return -1; > > } > > Hi Maciej, > > Thanks for the report and sorry for the delay :/ > > I guess here the issue is that there are applets but not on the current > thread. > The following patch should fix the issue. Could you confirm it really > fixes your > issue ? it can safely be applied on the 2.8.9 or 2.8-HEAD. > > FYI, I'm working on the SPOE refactoring. I hope the first version will be > available soon for testing. > > -- > Christopher Faulet >
Re: [SPOE] an error was triggered during the resources allocation.
Le 05/07/2024 à 12:57, Maciej Zdeb a écrit : Hi, I'm using haproxy version 2.8.9 and noticed strange behavior of the SPOE engine. I see many logs like below. From what I managed to investigate, the error with value 2 is defined as SPOE_CTX_ERR_RES (an error was triggered during the resources allocation) and this particular error is set only in spoe_queue_context function. So probably there is an issue with that logic of creating applets, but I'm unable to understand what is wrong with it. I don't have any limits in spoe configuration so it should not be the cause. /* Check if we need to create a new SPOE applet or not. */ if (agent->rt[tid].processing < agent->rt[tid].idles || agent->rt[tid].processing < read_freq_ctr(&agent->rt[tid].processing_per_sec)) goto end; SPOE_PRINTF(stderr, "%d.%06d [SPOE/%-15s] %s: stream=%p" " - try to create new SPOE appctx\n", (int)date.tv_sec, (int)date.tv_usec, agent->id, __FUNCTION__, ctx->strm); spoe_create_appctx(conf); end: /* The only reason to return an error is when there is no applet */ if (LIST_ISEMPTY(&agent->rt[tid].applets)) { ctx->status_code = SPOE_CTX_ERR_RES; return -1; } Hi Maciej, Thanks for the report and sorry for the delay :/ I guess here the issue is that there are applets but not on the current thread. The following patch should fix the issue. Could you confirm it really fixes your issue ? it can safely be applied on the 2.8.9 or 2.8-HEAD. FYI, I'm working on the SPOE refactoring. I hope the first version will be available soon for testing. -- Christopher Faulet From 884bf036923119a762e26703c0b430f13aa58611 Mon Sep 17 00:00:00 2001 From: Christopher Faulet Date: Tue, 9 Jul 2024 08:24:05 +0200 Subject: [PATCH] BUG/MEDIUM: spoe: Be sure to create a SPOE applet if none on the current thread When a message is queued, waiting to be processed by a SPOE applet, there are some heuristic to know if a new applet must be created or not. There are 2 conditions to skip the applet creation: 1 - if there are enough idle applets on the current thread, or, 2 - if the processing rate on the current thread is high enough to handle this new message In the 2nd case, there is a flaw when the number of processed messages falls to zero while the processing rate is still greater than zero. In that case, we will skip the SPOE applet creation without taking care to check there is at least one applet on the current thread. So now, the conditions above to skip the SPOE applet creation are only evaluated if there is at least one applet on the current thread. This patch must be backported to every stable versions. --- src/flt_spoe.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/flt_spoe.c b/src/flt_spoe.c index f565e962d..0b35b7eed 100644 --- a/src/flt_spoe.c +++ b/src/flt_spoe.c @@ -2090,8 +2090,9 @@ spoe_queue_context(struct spoe_context *ctx) struct spoe_appctx *spoe_appctx; /* Check if we need to create a new SPOE applet or not. */ - if (agent->rt[tid].processing < agent->rt[tid].idles || - agent->rt[tid].processing < read_freq_ctr(&agent->rt[tid].processing_per_sec)) + if (!LIST_ISEMPTY(&agent->rt[tid].applets) && + (agent->rt[tid].processing < agent->rt[tid].idles || + agent->rt[tid].processing < read_freq_ctr(&agent->rt[tid].processing_per_sec))) goto end; SPOE_PRINTF(stderr, "%d.%06d [SPOE/%-15s] %s: stream=%p" -- 2.45.1
[SPOE] an error was triggered during the resources allocation.
Hi, I'm using haproxy version 2.8.9 and noticed strange behavior of the SPOE engine. I see many logs like below. From what I managed to investigate, the error with value 2 is defined as SPOE_CTX_ERR_RES (an error was triggered during the resources allocation) and this particular error is set only in spoe_queue_context function. So probably there is an issue with that logic of creating applets, but I'm unable to understand what is wrong with it. I don't have any limits in spoe configuration so it should not be the cause. /* Check if we need to create a new SPOE applet or not. */ if (agent->rt[tid].processing < agent->rt[tid].idles || agent->rt[tid].processing < read_freq_ctr(&agent->rt[tid].processing_per_sec)) goto end; SPOE_PRINTF(stderr, "%d.%06d [SPOE/%-15s] %s: stream=%p" " - try to create new SPOE appctx\n", (int)date.tv_sec, (int)date.tv_usec, agent->id, __FUNCTION__, ctx->strm); spoe_create_appctx(conf); end: /* The only reason to return an error is when there is no applet */ if (LIST_ISEMPTY(&agent->rt[tid].applets)) { ctx->status_code = SPOE_CTX_ERR_RES; return -1; } Jul 5 12:42:29 haproxy: SPOE: [agent] sid=704430 st=2 -1/-1/-1/-1/0 42/43 0/1 3431/89801 Jul 5 12:42:29 haproxy: SPOE: [agent] sid=704436 st=2 -1/-1/-1/-1/0 42/43 0/1 3432/89802 Jul 5 12:42:29 haproxy: SPOE: [agent] sid=704447 st=2 -1/-1/-1/-1/0 42/43 0/1 3433/89805 Jul 5 12:42:29 haproxy: SPOE: [agent] sid=704470 st=2 -1/-1/-1/-1/0 42/43 0/1 3434/89809 Jul 5 12:42:29 haproxy: SPOE: [agent] sid=704539 st=2 -1/-1/-1/-1/0 41/43 0/2 3435/89821 Jul 5 12:42:29 haproxy: SPOE: [agent] sid=704797 st=2 -1/-1/-1/-1/0 42/43 0/1 3436/89847 Jul 5 12:42:29 haproxy: SPOE: [agent] sid=704834 st=2 -1/-1/-1/-1/0 43/43 0/0 3437/89849 Jul 5 12:42:29 haproxy: SPOE: [agent] sid=704953 st=2 -1/-1/-1/-1/0 43/43 0/0 3438/89864 Jul 5 12:42:29 haproxy: SPOE: [agent] sid=705002 st=2 -1/-1/-1/-1/0 43/44 1/0 3439/89867 Jul 5 12:42:29 haproxy: SPOE: [agent] sid=705003 st=2 -1/-1/-1/-1/0 43/44 1/0 3440/89868 Jul 5 12:42:29 haproxy: SPOE: [agent] sid=705152 st=2 -1/-1/-1/-1/0 40/44 0/4 3441/89882 Jul 5 12:42:29 haproxy: SPOE: [agent] sid=705203 st=2 -1/-1/-1/-1/0 43/44 0/1 3442/89890 Jul 5 12:42:29 haproxy: SPOE: [agent] sid=705214 st=2 -1/-1/-1/-1/0 43/44 0/1 3443/89891 Jul 5 12:42:29 haproxy: SPOE: [agent] sid=705327 st=2 -1/-1/-1/-1/0 40/44 0/4 3444/89900 Jul 5 12:42:29 haproxy: SPOE: [agent] sid=705347 st=2 -1/-1/-1/-1/0 44/44 0/0 3445/89905 Jul 5 12:42:29 haproxy: SPOE: [agent] sid=705457 st=2 -1/-1/-1/-1/0 42/42 0/0 3446/89922 Jul 5 12:42:29 haproxy: SPOE: [agent] sid=705642 st=2 -1/-1/-1/-1/0 42/42 0/0 3447/89943 Kind regards, Maciej Zdeb
Re: Update for https://github.com/haproxy/wiki/wiki/SPOE:-Stream-Processing-Offloading-Engine
On Mon, Apr 15, 2024 at 10:18:19AM +0200, Aleksandar Lazic wrote: > Hi. > > The "https://github.com/criteo/haproxy-spoe-go"; is archived since Nov 7, > 2023 and there is a fork from that repo https://github.com/go-spop/spoe > Can we add this info to the wiki page? > > There is also a rust implementation > https://github.com/vkill/haproxy-spoa-example which could be added. > > If it's possible then would I add this by my self. > Thanks Aleks, I add them both on the page, and set criteo's one as unmaintained. -- William Lallemand
Update for https://github.com/haproxy/wiki/wiki/SPOE:-Stream-Processing-Offloading-Engine
Hi. The "https://github.com/criteo/haproxy-spoe-go"; is archived since Nov 7, 2023 and there is a fork from that repo https://github.com/go-spop/spoe Can we add this info to the wiki page? There is also a rust implementation https://github.com/vkill/haproxy-spoa-example which could be added. If it's possible then would I add this by my self. Regards Alex
Re: About the SPOE
Thanks Lokesh, Abhijeet and Aleksandar for your feedback. This truly help us. Thanks too to Pierre and Mattia for their feedback on the request mirroring. Rest assured that we take this into account in our reflections. After some internal discussions and also regarding to feedback we had internally, we've decided to invest some time to rewrite the engine for the 3.1. A feature request was created to keep the conversation going (https://github.com/haproxy/haproxy/issues/2502). But to sum up, the idea is to rethink the engine to make it simpler. Of course, the engine will be based on recent core features. But features will also be reduced to remain maintainable. Among other things, the asynchronous mode will be removed because it is far too complex and most probably unused. It is clearly an over-designed feature. Then we will not invest time on the payload streaming support. This feature is pretty complex to implement and this is mainly why we never made the current SPOE evolved. Let's be reasonable this time. This will probably influence the design. For people who have invested time in SPOAs development, the protocol will be kept compatible. The purpose here is to rewrite the engine itself. So it is above all internal to HAProxy. For the 3.0, the warning about the SPOE will be changed to notify users some configuration changes should be expected in future versions. Some other small changes should be expected for the 3.0. But the heavy lifting will be performed on the 3.1. Of course, it is still a subject under discussion. The above issue is here to collect ideas for the next steps but also for more long term features. Feel free to feed it. Regards, -- Christopher Faulet
About the SPOE
Hi list, We have a few usages of SPOE, mainly: * HTTP traffic mirroring. It's being discussed on GH, more details here: https://github.com/haproxy/haproxy/issues/2471#issuecomment-2007261494 * authentication (because we used to have 2 auth methods and it helped developing one backend to handle them both). I guess if one provide pure SSO/OAuth2/OIDC it can be handled natively nowadays with all the converters that have been added (also seen that multiple official blogposts have been published on the topic). We also envisaged SPOE to offload some heavy filtering workload, especially to separate the ownership of components (one spoa could have been owned and deployed by ). As long as there's a sort of equivalent of SPOE in the long-run, we're not shocked that this comes to be deprecated. -- Pierre
Re: About the SPOE
Hi Lokesh, On Tue, Mar 26, 2024 at 12:10:53AM +, Lokesh Jindal wrote: > Hey Willy > > Resending this email in case you missed the last one. Let me know if you had > any follow up questions/comments. > I saw https://github.com/haproxy/haproxy/issues/2502 created by Christopher - > looking forward to discussion on that issue. Sorry for the delay, yes I had a quick look but last week was full of meetings here and I'm slowly trying to catch up with the lag, I'm even late on -dev6 :-( Back on this soon. There could be good news from our side given that some of the meetings were precisely about all of this ;-) Stay tuned, Willy
Re: About the SPOE
Hey Willy Resending this email in case you missed the last one. Let me know if you had any follow up questions/comments. I saw https://github.com/haproxy/haproxy/issues/2502 created by Christopher - looking forward to discussion on that issue. - Lokesh From: Lokesh Jindal Date: Monday, March 18, 2024 at 4:55 PM To: Willy Tarreau Cc: Abhijeet Rastogi , Christopher Faulet , haproxy@formilux.org , Aleksandar Lazic Subject: Re: About the SPOE Hey Willy Please see my response inline below. - Lokesh From: Willy Tarreau Date: Monday, March 18, 2024 at 4:08 AM To: Lokesh Jindal Cc: Abhijeet Rastogi , Christopher Faulet , haproxy@formilux.org , Aleksandar Lazic Subject: Re: About the SPOE Hi Lokesh, Abhijeet, Alex, First, thanks for jumping into this thread, the purpose of the deprecation is in a big part to try to collect the requirements of possibly existing users. Mind you that the rare times we hear about SPOE is only because of problems, so it's difficult to figure what to keep and what to cut from the existing design. More on that below: On Fri, Mar 15, 2024 at 05:15:14PM +, Lokesh Jindal wrote: > Hey Christopher > > Adding to what my colleague, Abhijeet, said. > > > 1. We plan to ramp traffic to HAProxy very soon where we will heavily rely > on SPOA. In our testing, we are satisfied with SPOE in terms of > performance. The flexibility to write SPOA in any language not only allows > us to handle "complex use cases" like connecting to non-http downstreams, > but also helps in observability - metrics and logging. Interesting, the initial internal e-mail in 2016 that ignited the SPOE design was driven from the same observations: in web environments it's quite rare to find developers who are at ease with system-level languages, yet they are the ones most likely to request to extend the proxy. For this reason we wanted to offer the possibility to call code written in other languages. In addition it was estimated that the ability to connect to the agent over the network and using secure connections was absolutely essential. It brings the ability to scale the processing engine without adding more LB nodes, and even to offload that to another DC, infrastructure or even to delegate it to a 3rd party. [Lokesh]: One of our major flows requires us to connect to couchbase for every request. Today, we are running one HAProxy process + one golang SPOA process on every host of the reverse proxy layer. This keeps the setup simple and avoids making a network call for HAProxy-SPOA communication, reducing latency. We have a couple of other flows where the SPOA connects to HTTP services for things like SSO, some type of cookie renewal, etc. These are not as latency sensitive as the flow mentioned above. Further, we anticipate the interaction of SPOA with these external services will change often – how we parse the http response from the services, how we make the request to these services, addition of new calls to services, etc. In these cases, the SPOA will give us ability to develop features fast. Among the use cases which immediately came to mind were authentication, database accesses, name resolution, "remote maps", request classification, IP reputation, etc. In addition we thought that limiting ourselves to short request/responses like this was probably limiting and that it would have been useful to support streaming so that we could implement image recompression, caching, WAFs etc. The first PoC implementation that was merged in version 1.7 lacked the streaming abilities, and it's still the current implementation. It took a while before we received feedback on it, since then caching was implemented, the demand for image recompression is close to non-existing, and WAFs users have well accommodated to dealing with extra layers by now it seems. So basically we're left with something ultra-complex that deals with short request-responses most of the time, and that suffers from the initial design which was way bigger than the use cases. [Lokesh]: I think this applies to us, as explained in my comment above. > 2. What is the best alternative to SPOE? I don't know yet, and the purpose of this deprecation precisely is to engage discussion with users. One could think about various HTTP-based protocols for which it is easier to implement a server, some gRPC maybe, possibly even a stripped-down version of the SPOP protocol if we figure that everyone is running on a reasonable subset that's much easier to deal with than the whole stuff we have now. > Two options that we are aware of > - Write fetchers/converters in lua or write filters in other languages > using the Lua API. In your experience, how do they compare to SPOE in terms > of: > * Performance > * Fault isolation The benefits of SPOE as you've found, clearly are in terms of flexibility as i
Re: About the SPOE
Hey Willy Please see my response inline below. - Lokesh From: Willy Tarreau Date: Monday, March 18, 2024 at 4:08 AM To: Lokesh Jindal Cc: Abhijeet Rastogi , Christopher Faulet , haproxy@formilux.org , Aleksandar Lazic Subject: Re: About the SPOE Hi Lokesh, Abhijeet, Alex, First, thanks for jumping into this thread, the purpose of the deprecation is in a big part to try to collect the requirements of possibly existing users. Mind you that the rare times we hear about SPOE is only because of problems, so it's difficult to figure what to keep and what to cut from the existing design. More on that below: On Fri, Mar 15, 2024 at 05:15:14PM +, Lokesh Jindal wrote: > Hey Christopher > > Adding to what my colleague, Abhijeet, said. > > > 1. We plan to ramp traffic to HAProxy very soon where we will heavily rely > on SPOA. In our testing, we are satisfied with SPOE in terms of > performance. The flexibility to write SPOA in any language not only allows > us to handle "complex use cases" like connecting to non-http downstreams, > but also helps in observability - metrics and logging. Interesting, the initial internal e-mail in 2016 that ignited the SPOE design was driven from the same observations: in web environments it's quite rare to find developers who are at ease with system-level languages, yet they are the ones most likely to request to extend the proxy. For this reason we wanted to offer the possibility to call code written in other languages. In addition it was estimated that the ability to connect to the agent over the network and using secure connections was absolutely essential. It brings the ability to scale the processing engine without adding more LB nodes, and even to offload that to another DC, infrastructure or even to delegate it to a 3rd party. [Lokesh]: One of our major flows requires us to connect to couchbase for every request. Today, we are running one HAProxy process + one golang SPOA process on every host of the reverse proxy layer. This keeps the setup simple and avoids making a network call for HAProxy-SPOA communication, reducing latency. We have a couple of other flows where the SPOA connects to HTTP services for things like SSO, some type of cookie renewal, etc. These are not as latency sensitive as the flow mentioned above. Further, we anticipate the interaction of SPOA with these external services will change often – how we parse the http response from the services, how we make the request to these services, addition of new calls to services, etc. In these cases, the SPOA will give us ability to develop features fast. Among the use cases which immediately came to mind were authentication, database accesses, name resolution, "remote maps", request classification, IP reputation, etc. In addition we thought that limiting ourselves to short request/responses like this was probably limiting and that it would have been useful to support streaming so that we could implement image recompression, caching, WAFs etc. The first PoC implementation that was merged in version 1.7 lacked the streaming abilities, and it's still the current implementation. It took a while before we received feedback on it, since then caching was implemented, the demand for image recompression is close to non-existing, and WAFs users have well accommodated to dealing with extra layers by now it seems. So basically we're left with something ultra-complex that deals with short request-responses most of the time, and that suffers from the initial design which was way bigger than the use cases. [Lokesh]: I think this applies to us, as explained in my comment above. > 2. What is the best alternative to SPOE? I don't know yet, and the purpose of this deprecation precisely is to engage discussion with users. One could think about various HTTP-based protocols for which it is easier to implement a server, some gRPC maybe, possibly even a stripped-down version of the SPOP protocol if we figure that everyone is running on a reasonable subset that's much easier to deal with than the whole stuff we have now. > Two options that we are aware of > - Write fetchers/converters in lua or write filters in other languages > using the Lua API. In your experience, how do they compare to SPOE in terms > of: > * Performance > * Fault isolation The benefits of SPOE as you've found, clearly are in terms of flexibility as it allows to scale the number of analysers independently on the number of LBs, and it almost makes problems almost unnoticeable. For example, if your code relied on unstable 3rd party libraries, crashing your SPOA doesn't bring down the whole proxy. Similarly in terms of added latency, all the latency is in the external component, the rest of the traffic is not affected as it would be by placing some heavy processing directly inside the haproxy proces
Re: About the SPOE
Hi Lokesh, Abhijeet, Alex, First, thanks for jumping into this thread, the purpose of the deprecation is in a big part to try to collect the requirements of possibly existing users. Mind you that the rare times we hear about SPOE is only because of problems, so it's difficult to figure what to keep and what to cut from the existing design. More on that below: On Fri, Mar 15, 2024 at 05:15:14PM +, Lokesh Jindal wrote: > Hey Christopher > > Adding to what my colleague, Abhijeet, said. > > > 1. We plan to ramp traffic to HAProxy very soon where we will heavily rely > on SPOA. In our testing, we are satisfied with SPOE in terms of > performance. The flexibility to write SPOA in any language not only allows > us to handle "complex use cases" like connecting to non-http downstreams, > but also helps in observability - metrics and logging. Interesting, the initial internal e-mail in 2016 that ignited the SPOE design was driven from the same observations: in web environments it's quite rare to find developers who are at ease with system-level languages, yet they are the ones most likely to request to extend the proxy. For this reason we wanted to offer the possibility to call code written in other languages. In addition it was estimated that the ability to connect to the agent over the network and using secure connections was absolutely essential. It brings the ability to scale the processing engine without adding more LB nodes, and even to offload that to another DC, infrastructure or even to delegate it to a 3rd party. Among the use cases which immediately came to mind were authentication, database accesses, name resolution, "remote maps", request classification, IP reputation, etc. In addition we thought that limiting ourselves to short request/responses like this was probably limiting and that it would have been useful to support streaming so that we could implement image recompression, caching, WAFs etc. The first PoC implementation that was merged in version 1.7 lacked the streaming abilities, and it's still the current implementation. It took a while before we received feedback on it, since then caching was implemented, the demand for image recompression is close to non-existing, and WAFs users have well accommodated to dealing with extra layers by now it seems. So basically we're left with something ultra-complex that deals with short request-responses most of the time, and that suffers from the initial design which was way bigger than the use cases. > 2. What is the best alternative to SPOE? I don't know yet, and the purpose of this deprecation precisely is to engage discussion with users. One could think about various HTTP-based protocols for which it is easier to implement a server, some gRPC maybe, possibly even a stripped-down version of the SPOP protocol if we figure that everyone is running on a reasonable subset that's much easier to deal with than the whole stuff we have now. > Two options that we are aware of > - Write fetchers/converters in lua or write filters in other languages > using the Lua API. In your experience, how do they compare to SPOE in terms > of: > * Performance > * Fault isolation The benefits of SPOE as you've found, clearly are in terms of flexibility as it allows to scale the number of analysers independently on the number of LBs, and it almost makes problems almost unnoticeable. For example, if your code relied on unstable 3rd party libraries, crashing your SPOA doesn't bring down the whole proxy. Similarly in terms of added latency, all the latency is in the external component, the rest of the traffic is not affected as it would be by placing some heavy processing directly inside the haproxy process. > 3. As Abhijeet said, can you share a list of issues with SPOE that make it > hard to maintain? On the top of my head I can enumerate a few: - the load balancing is integraly reimplemented at the SPOE level between applets - the load balancing is affected by the support of response-less messages, which prevent haproxy from having an estimate of the server's load, which means that an algo such as leastconn would not make sense in such a condition - the idle connections management is integraly reimplemented at the SPOE level using applets as well. An idle SPOE connection is in fact a full application-layer stream with one applet on one side and a connection on the other side. These cannot be migrated between threads, which require even more complex stream-to-stream thread-safe communication mechanisms and synchronisation. - it's possible to receive a response on a different connection than the one that saw the request. This adds complexity in the matching request lookup, needs for extra synchronisation so that the other stream doesn
Re: About the SPOE
Hi. On 2024-03-15 (Fr.) 15:09, Christopher Faulet wrote: Hi all, It was evoked on the ML by Willy and mentioned in few issues on GH. It is now official. The SPOE was marked as deprecated for the 3.0. It is not a pleasant announce because it is always an admission of failure to remove a feature. Sadly, this filter should be refactored to work properly. It was implemented as a functional PoC for the 1.7 and since then, no time was invest to improve it and make it truly maintainable in time. Worst, other parts of HAProxy evolved, especially applets part, making maintenance ever more expensive. We must be realistic on the subject, there was no real adoption on the SPOE and this partly explains why no time was invest on it. So we are really sorry for users relying on it. But we cannot continue in this direction. The 3.0 is be an LTS version. It means the SPOE will still be maintained on this version and lower ones for 5 years. On the 3.1, it will be marked as unmaintained and possibly removed if an alternative solution is implemented. It remains few months before the 3.0 release to change our mind. Maybe this announce will be an electroshock to give it a new lease of life. Otherwise it is time to find an alternative solution based on an existing protocol. For all 3.0 users, there is now a warning if a SPOE filter is configured. But there is also a global option to silent it. To do so, "expose-deprecated-directives" must be added in the global section. Now we are open to discussion on this subject. Let us know your feeling and if you have any suggestion, we will be happy to talk about it. As I fully understand this step it would he very helpful to have a filter which have the possibility to run some tasks outside of HAProxy in async way. There was a short discussion, in the past, about the future of filters https://www.mail-archive.com/haproxy@formilux.org/msg44164.html maybe there are some Ideas which can be reused. From my point of view would be a http-filter (1,2,!3 imho), with all the pros and cons, one of the best way for a filter, because this protocol is so widely used and a lot of knowledge could be reused. One of the biggest benefit is also that, even in Enterprise environments, could this filter be used as this protocol is able to run across a proxy. FCGI is also another option as it's already part of the Filter chain :-). I don't know too much about grpc but maybe this protocol could also be used as filter ¯\_(ツ)_/¯. Lua-API with some external Daemons could be also used to move the workload out of HAProxy. From my point of view, what ever solution is chosen the Idea behind the SPOE should be kept because it's a good concept to scale the filters outside of HAProxy. I see a lot of possibilities here the main point is always how much work it it to maintain the filter chain. Regards, Jm2c Regards Alex
Re: About the SPOE
Hey Christopher Adding to what my colleague, Abhijeet, said. 1. We plan to ramp traffic to HAProxy very soon where we will heavily rely on SPOA. In our testing, we are satisfied with SPOE in terms of performance. The flexibility to write SPOA in any language not only allows us to handle “complex use cases” like connecting to non-http downstreams, but also helps in observability – metrics and logging. 2. What is the best alternative to SPOE? Two options that we are aware of – Write fetchers/converters in lua or write filters in other languages using the Lua API. In your experience, how do they compare to SPOE in terms of: * Performance * Fault isolation 3. As Abhijeet said, can you share a list of issues with SPOE that make it hard to maintain? Be it SPOE or an alternate solution that allows us to handle complex use cases with good performance, fault isolation (as much as possible) and observability, we will be happy to help develop/maintain it. - Lokesh From: Abhijeet Rastogi Date: Friday, March 15, 2024 at 8:23 AM To: Christopher Faulet Cc: haproxy@formilux.org Subject: Re: About the SPOE Hi Christopher, Thank you for starting the discussion here. >Worst, other parts of HAProxy evolved, especially applets part, making maintenance ever more expensive. Can we elaborate on what makes maintenance expensive? >We must be realistic on the subject, there was no real adoption on the SPOE and this partly explains why no time was invest on it. My company primarily uses SPOE in cases where we've to connect with non-http downstreams, for example, connecting to the data layer (Couchbase etc) that makes the proxy stateless. Other uses-cases are SSO implementation etc. We are a new user to HAproxy, with multi-million QPS on HAproxy already, and we've plans to ramp multiples of that in the coming year or two. >Now we are open to discussion on this subject. Let us know your feeling and if you have any suggestion, we will be happy to talk about it. Our goal at my company has been to not modify HAproxy core and still add features to it without running in the same memory space as HAproxy for safety. Of course, we use config DSL and lua as much as possible, but it falls short in terms of writing complex business logic. (non-http downstreams etc). If it's not SPOE, what is a true replacement? With my limited knowledge, not a true replacement though, maybe lua filter API and then write these complex in-flight operations in Rust? With the learnings from today, what would be the ideal way to replace it, considering we had engineers to maintain it? Slightly off-topic, SPOE has its flaws too though. One of our use-cases is to stream (kafka) HTTP traffic information (cookies, request data etc) in an efficient fashion and we actually did not use SPOE as the cost to exchange information was too high. In this particular case, we ended up streaming data via txn/req variables to logs instead (ring buffer). Thanks, Abhijeet On Fri, Mar 15, 2024 at 7:10 AM Christopher Faulet wrote: > > Hi all, > > It was evoked on the ML by Willy and mentioned in few issues on GH. It is now > official. The SPOE was marked as deprecated for the 3.0. It is not a pleasant > announce because it is always an admission of failure to remove a feature. > Sadly, this filter should be refactored to work properly. It was implemented > as > a functional PoC for the 1.7 and since then, no time was invest to improve it > and make it truly maintainable in time. Worst, other parts of HAProxy evolved, > especially applets part, making maintenance ever more expensive. > > We must be realistic on the subject, there was no real adoption on the SPOE > and > this partly explains why no time was invest on it. So we are really sorry for > users relying on it. But we cannot continue in this direction. > > The 3.0 is be an LTS version. It means the SPOE will still be maintained on > this > version and lower ones for 5 years. On the 3.1, it will be marked as > unmaintained and possibly removed if an alternative solution is implemented. > > It remains few months before the 3.0 release to change our mind. Maybe this > announce will be an electroshock to give it a new lease of life. Otherwise it > is > time to find an alternative solution based on an existing protocol. > > For all 3.0 users, there is now a warning if a SPOE filter is configured. But > there is also a global option to silent it. To do so, > "expose-deprecated-directives" must be added in the global section. > > Now we are open to discussion on this subject. Let us know your feeling and if > you have any suggestion, we will be happy to talk about it. > > Regards, > -- > Christopher Faulet > -- Cheers, Abhijeet (https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fabhi.host%2
Re: About the SPOE
Hi Christopher, Thank you for starting the discussion here. >Worst, other parts of HAProxy evolved, especially applets part, making maintenance ever more expensive. Can we elaborate on what makes maintenance expensive? >We must be realistic on the subject, there was no real adoption on the SPOE and this partly explains why no time was invest on it. My company primarily uses SPOE in cases where we've to connect with non-http downstreams, for example, connecting to the data layer (Couchbase etc) that makes the proxy stateless. Other uses-cases are SSO implementation etc. We are a new user to HAproxy, with multi-million QPS on HAproxy already, and we've plans to ramp multiples of that in the coming year or two. >Now we are open to discussion on this subject. Let us know your feeling and if you have any suggestion, we will be happy to talk about it. Our goal at my company has been to not modify HAproxy core and still add features to it without running in the same memory space as HAproxy for safety. Of course, we use config DSL and lua as much as possible, but it falls short in terms of writing complex business logic. (non-http downstreams etc). If it's not SPOE, what is a true replacement? With my limited knowledge, not a true replacement though, maybe lua filter API and then write these complex in-flight operations in Rust? With the learnings from today, what would be the ideal way to replace it, considering we had engineers to maintain it? Slightly off-topic, SPOE has its flaws too though. One of our use-cases is to stream (kafka) HTTP traffic information (cookies, request data etc) in an efficient fashion and we actually did not use SPOE as the cost to exchange information was too high. In this particular case, we ended up streaming data via txn/req variables to logs instead (ring buffer). Thanks, Abhijeet On Fri, Mar 15, 2024 at 7:10 AM Christopher Faulet wrote: > > Hi all, > > It was evoked on the ML by Willy and mentioned in few issues on GH. It is now > official. The SPOE was marked as deprecated for the 3.0. It is not a pleasant > announce because it is always an admission of failure to remove a feature. > Sadly, this filter should be refactored to work properly. It was implemented > as > a functional PoC for the 1.7 and since then, no time was invest to improve it > and make it truly maintainable in time. Worst, other parts of HAProxy evolved, > especially applets part, making maintenance ever more expensive. > > We must be realistic on the subject, there was no real adoption on the SPOE > and > this partly explains why no time was invest on it. So we are really sorry for > users relying on it. But we cannot continue in this direction. > > The 3.0 is be an LTS version. It means the SPOE will still be maintained on > this > version and lower ones for 5 years. On the 3.1, it will be marked as > unmaintained and possibly removed if an alternative solution is implemented. > > It remains few months before the 3.0 release to change our mind. Maybe this > announce will be an electroshock to give it a new lease of life. Otherwise it > is > time to find an alternative solution based on an existing protocol. > > For all 3.0 users, there is now a warning if a SPOE filter is configured. But > there is also a global option to silent it. To do so, > "expose-deprecated-directives" must be added in the global section. > > Now we are open to discussion on this subject. Let us know your feeling and if > you have any suggestion, we will be happy to talk about it. > > Regards, > -- > Christopher Faulet > -- Cheers, Abhijeet (https://abhi.host)
About the SPOE
Hi all, It was evoked on the ML by Willy and mentioned in few issues on GH. It is now official. The SPOE was marked as deprecated for the 3.0. It is not a pleasant announce because it is always an admission of failure to remove a feature. Sadly, this filter should be refactored to work properly. It was implemented as a functional PoC for the 1.7 and since then, no time was invest to improve it and make it truly maintainable in time. Worst, other parts of HAProxy evolved, especially applets part, making maintenance ever more expensive. We must be realistic on the subject, there was no real adoption on the SPOE and this partly explains why no time was invest on it. So we are really sorry for users relying on it. But we cannot continue in this direction. The 3.0 is be an LTS version. It means the SPOE will still be maintained on this version and lower ones for 5 years. On the 3.1, it will be marked as unmaintained and possibly removed if an alternative solution is implemented. It remains few months before the 3.0 release to change our mind. Maybe this announce will be an electroshock to give it a new lease of life. Otherwise it is time to find an alternative solution based on an existing protocol. For all 3.0 users, there is now a warning if a SPOE filter is configured. But there is also a global option to silent it. To do so, "expose-deprecated-directives" must be added in the global section. Now we are open to discussion on this subject. Let us know your feeling and if you have any suggestion, we will be happy to talk about it. Regards, -- Christopher Faulet
Re: SPOE
On 2023-06-15 22:11, Sander Klein wrote: Hi, Is there a way to filter which URL's go through SPOE and which are just handled directly in a single frontend? I can't seem to find it in the documentantion. I'm currently on HAProxy 2.6.14. Right after I mailed this I read SPOE.txt a bit better and saw you can influence it with for instance on-http-request and HAProxy ACLs. So, I think I can figure it out ;-) Greets, Sander
SPOE
Hi, Is there a way to filter which URL's go through SPOE and which are just handled directly in a single frontend? I can't seem to find it in the documentantion. I'm currently on HAProxy 2.6.14. Regards, Sander Klein
Re: [2.4.22] Segmentation fault when using spoe + disabled keyword
Awesome, thanks! czw., 11 maj 2023 o 09:38 Christopher Faulet napisał(a): > Le 5/9/23 à 14:29, Maciej Zdeb a écrit : > > Hi Christopher, > > no problem. :) Yes I'm using the same spoe backend for multiple > frontends. This > > is my spoe configuration: > > > > [abc] > > > > spoe-agent abc-agent > >messages check-abc > >register-var-names x_abc_request_headers x_headers x_abc_response body > >option var-prefix abc > >option set-on-error error > >option set-total-time total_time > >timeout hello 100ms > >timeout idle 41s > >timeout processing 50ms > >use-backend spoe-abc > > > > spoe-message check-abc > >args Key=str("123") Key2=str("Haproxy")... > >acl route_to_abc path_beg -f /etc/haproxy/configs/acl/path_begin.lst > >event on-frontend-http-request if route_to_abc > > > > Thanks ! I'm able to reproduce the issue. > > SPOE filters for disabled proxies are released during startup but pattern > expressions may be shared between filters. So if the disabled proxy is > defined > first, it is an issue because these expressions are released while they > are > still used by other filters. > > I pushed a fix in 2.8-DEV. It will be backported to all stable versions. > As a > workaround, the disabled proxies must not be the first ones defined. > > -- > Christopher Faulet > >
Re: [2.4.22] Segmentation fault when using spoe + disabled keyword
Le 5/9/23 à 14:29, Maciej Zdeb a écrit : Hi Christopher, no problem. :) Yes I'm using the same spoe backend for multiple frontends. This is my spoe configuration: [abc] spoe-agent abc-agent messages check-abc register-var-names x_abc_request_headers x_headers x_abc_response body option var-prefix abc option set-on-error error option set-total-time total_time timeout hello 100ms timeout idle 41s timeout processing 50ms use-backend spoe-abc spoe-message check-abc args Key=str("123") Key2=str("Haproxy")... acl route_to_abc path_beg -f /etc/haproxy/configs/acl/path_begin.lst event on-frontend-http-request if route_to_abc Thanks ! I'm able to reproduce the issue. SPOE filters for disabled proxies are released during startup but pattern expressions may be shared between filters. So if the disabled proxy is defined first, it is an issue because these expressions are released while they are still used by other filters. I pushed a fix in 2.8-DEV. It will be backported to all stable versions. As a workaround, the disabled proxies must not be the first ones defined. -- Christopher Faulet
Re: [2.4.22] Segmentation fault when using spoe + disabled keyword
Hi Christopher, no problem. :) Yes I'm using the same spoe backend for multiple frontends. This is my spoe configuration: [abc] spoe-agent abc-agent messages check-abc register-var-names x_abc_request_headers x_headers x_abc_response body option var-prefix abc option set-on-error error option set-total-time total_time timeout hello 100ms timeout idle 41s timeout processing 50ms use-backend spoe-abc spoe-message check-abc args Key=str("123") Key2=str("Haproxy")... acl route_to_abc path_beg -f /etc/haproxy/configs/acl/path_begin.lst event on-frontend-http-request if route_to_abc wt., 9 maj 2023 o 09:14 Christopher Faulet napisał(a): > Le 5/2/23 à 13:58, Maciej Zdeb a écrit : > > Hi, > > I'm experiencing a segmentation fault caused by adding "disabled" > > (http://docs.haproxy.org/2.4/configuration.html#4-disabled > > <http://docs.haproxy.org/2.4/configuration.html#4-disabled>) to the > frontend > > section of haproxy configuration file. That frontend does not handle any > traffic > > yet. > > > > The "disabled" keyword was used on other frontends on the same HAProxy > instance > > before without any issue. The difference is that this time it was added > to > > frontend with spoe filter. This probably causes a crash when processing > requests > > on a different heavily used frontend (also spoe enabled). > > > > It crashes after 2-10s under production traffic. I couldn't replicate it > with a > > synthetic test, however I have a coredump and packages with HAProxy > binary and > > debug symbols. > > > > (gdb) bt > > #0 __pthread_kill_implementation (no_tid=0, signo=6, > threadid=140527117211200) > > at ./nptl/pthread_kill.c:44 > > #1 __pthread_kill_internal (signo=6, threadid=140527117211200) at > > ./nptl/pthread_kill.c:78 > > #2 __GI___pthread_kill (threadid=140527117211200, signo=signo@entry=6) > at > > ./nptl/pthread_kill.c:89 > > #3 0x7fcf0881a476 in __GI_raise (sig=sig@entry=6) at > > ../sysdeps/posix/raise.c:26 > > #4 0x7fcf088007f3 in __GI_abort () at ./stdlib/abort.c:79 > > #5 0x558f48524feb in ha_panic () at src/debug.c:333 > > #6 0x558f486be1af in wdt_handler (sig=14, si=0x7fcf04e4d3f0, > > arg=0x7fcf04e4d2c0) at src/wdt.c:122 > > #7 > > #8 0x558f48469895 in pattern_exec_match (head=0x558f69fe67b8, > > smp=0x7fcf04e4e080, fill=0) at src/pattern.c:2498 > > #9 0x558f485a0bf2 in acl_exec_cond (cond=0x558f69fe69a0, > px=0x558f69f67cf0, > > sess=0x7fce50243cd0, strm=0x7fce5020a4b0, opt=6) at src/acl.c:1123 > > #10 0x558f483b5eea in spoe_encode_message (s=0x7fce5020a4b0, > > ctx=0x7fce5026ddf0, msg=0x558f69fe2650, dir=0, buf=0x7fcf04e4e1b0, > > end=0x7fce502a627c "") at src/flt_spoe.c:2185 > > #11 0x558f483b6259 in spoe_encode_messages (s=0x7fce5020a4b0, > > ctx=0x7fce5026ddf0, messages=0x558f69fe23a0, dir=0, type=1) at > src/flt_spoe.c:2285 > > #12 0x558f483b75a4 in spoe_process_messages (s=0x7fce5020a4b0, > > ctx=0x7fce5026ddf0, messages=0x558f69fe23a0, dir=0, type=1) at > src/flt_spoe.c:2726 > > #13 0x558f483b79d0 in spoe_process_event (s=0x7fce5020a4b0, > > ctx=0x7fce5026ddf0, ev=SPOE_EV_ON_HTTP_REQ_FE) at src/flt_spoe.c:2842 > > #14 0x558f483b8eeb in spoe_chn_pre_analyze (s=0x7fce5020a4b0, > > filter=0x7fce5025c920, chn=0x7fce5020a4c0, an_bit=16) at > src/flt_spoe.c:3324 > > #15 0x558f48549976 in flt_pre_analyze (s=0x7fce5020a4b0, > chn=0x7fce5020a4c0, > > an_bit=16) at src/filters.c:764 > > #16 0x558f4836aaff in process_stream (t=0x7fce50242f30, > > context=0x7fce5020a4b0, state=260) at src/stream.c:1918 > > #17 0x558f4857aa3c in run_tasks_from_lists (budgets=0x7fcf04e4e5a0) > at > > src/task.c:597 > > #18 0x558f4857b485 in process_runnable_tasks () at src/task.c:838 > > #19 0x558f484d0eb5 in run_poll_loop () at src/haproxy.c:2630 > > #20 0x558f484d1423 in run_thread_poll_loop (data=0x5) at > src/haproxy.c:2805 > > #21 0x7fcf0886cb43 in start_thread (arg=) at > > ./nptl/pthread_create.c:442 > > #22 0x7fcf088fea00 in clone3 () at > ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81 > > > > haproxy -vv > > HAProxy version 2.4.22-f8e3218 2023/02/14 - https://haproxy.org/ > > <https://haproxy.org/> > > Status: long-term supported branch - will stop receiving fixes around Q2 > 2026. > > Known bugs: http://www.haproxy.org/bugs/bugs-2.4.22.html > > <http://www.haproxy.org/bugs/bugs-2.4.22.html> > > Running on: Linux 5.15.0-69-generic #76-Ubuntu SMP Fri Mar 17 17:19:29 >
Re: [2.4.22] Segmentation fault when using spoe + disabled keyword
Le 5/2/23 à 13:58, Maciej Zdeb a écrit : Hi, I'm experiencing a segmentation fault caused by adding "disabled" (http://docs.haproxy.org/2.4/configuration.html#4-disabled <http://docs.haproxy.org/2.4/configuration.html#4-disabled>) to the frontend section of haproxy configuration file. That frontend does not handle any traffic yet. The "disabled" keyword was used on other frontends on the same HAProxy instance before without any issue. The difference is that this time it was added to frontend with spoe filter. This probably causes a crash when processing requests on a different heavily used frontend (also spoe enabled). It crashes after 2-10s under production traffic. I couldn't replicate it with a synthetic test, however I have a coredump and packages with HAProxy binary and debug symbols. (gdb) bt #0 __pthread_kill_implementation (no_tid=0, signo=6, threadid=140527117211200) at ./nptl/pthread_kill.c:44 #1 __pthread_kill_internal (signo=6, threadid=140527117211200) at ./nptl/pthread_kill.c:78 #2 __GI___pthread_kill (threadid=140527117211200, signo=signo@entry=6) at ./nptl/pthread_kill.c:89 #3 0x7fcf0881a476 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26 #4 0x7fcf088007f3 in __GI_abort () at ./stdlib/abort.c:79 #5 0x558f48524feb in ha_panic () at src/debug.c:333 #6 0x558f486be1af in wdt_handler (sig=14, si=0x7fcf04e4d3f0, arg=0x7fcf04e4d2c0) at src/wdt.c:122 #7 #8 0x558f48469895 in pattern_exec_match (head=0x558f69fe67b8, smp=0x7fcf04e4e080, fill=0) at src/pattern.c:2498 #9 0x558f485a0bf2 in acl_exec_cond (cond=0x558f69fe69a0, px=0x558f69f67cf0, sess=0x7fce50243cd0, strm=0x7fce5020a4b0, opt=6) at src/acl.c:1123 #10 0x558f483b5eea in spoe_encode_message (s=0x7fce5020a4b0, ctx=0x7fce5026ddf0, msg=0x558f69fe2650, dir=0, buf=0x7fcf04e4e1b0, end=0x7fce502a627c "") at src/flt_spoe.c:2185 #11 0x558f483b6259 in spoe_encode_messages (s=0x7fce5020a4b0, ctx=0x7fce5026ddf0, messages=0x558f69fe23a0, dir=0, type=1) at src/flt_spoe.c:2285 #12 0x558f483b75a4 in spoe_process_messages (s=0x7fce5020a4b0, ctx=0x7fce5026ddf0, messages=0x558f69fe23a0, dir=0, type=1) at src/flt_spoe.c:2726 #13 0x558f483b79d0 in spoe_process_event (s=0x7fce5020a4b0, ctx=0x7fce5026ddf0, ev=SPOE_EV_ON_HTTP_REQ_FE) at src/flt_spoe.c:2842 #14 0x558f483b8eeb in spoe_chn_pre_analyze (s=0x7fce5020a4b0, filter=0x7fce5025c920, chn=0x7fce5020a4c0, an_bit=16) at src/flt_spoe.c:3324 #15 0x558f48549976 in flt_pre_analyze (s=0x7fce5020a4b0, chn=0x7fce5020a4c0, an_bit=16) at src/filters.c:764 #16 0x558f4836aaff in process_stream (t=0x7fce50242f30, context=0x7fce5020a4b0, state=260) at src/stream.c:1918 #17 0x558f4857aa3c in run_tasks_from_lists (budgets=0x7fcf04e4e5a0) at src/task.c:597 #18 0x558f4857b485 in process_runnable_tasks () at src/task.c:838 #19 0x558f484d0eb5 in run_poll_loop () at src/haproxy.c:2630 #20 0x558f484d1423 in run_thread_poll_loop (data=0x5) at src/haproxy.c:2805 #21 0x7fcf0886cb43 in start_thread (arg=) at ./nptl/pthread_create.c:442 #22 0x7fcf088fea00 in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81 haproxy -vv HAProxy version 2.4.22-f8e3218 2023/02/14 - https://haproxy.org/ <https://haproxy.org/> Status: long-term supported branch - will stop receiving fixes around Q2 2026. Known bugs: http://www.haproxy.org/bugs/bugs-2.4.22.html <http://www.haproxy.org/bugs/bugs-2.4.22.html> Running on: Linux 5.15.0-69-generic #76-Ubuntu SMP Fri Mar 17 17:19:29 UTC 2023 x86_64 Build options : TARGET = linux-glibc CPU = generic CC = cc CFLAGS = -O0 -g -Wall -Wextra -Wdeclaration-after-statement -fwrapv -Wno-unused-label -Wno-sign-compare -Wno-unused-parameter -Wno-clobbered -Wno-missing-field-initializers -Wtype-limits -Wshift-negative-value -Wshift-overflow=2 -Wduplicated-cond -Wnull-dereference -DMAX_SESS_STKCTR=12 OPTIONS = USE_PCRE2=1 USE_PCRE2_JIT=1 USE_GETADDRINFO=1 USE_OPENSSL=1 USE_LUA=1 USE_ZLIB=1 USE_DL=1 USE_PROMEX=1 DEBUG = Feature list : -51DEGREES +ACCEPT4 +BACKTRACE -CLOSEFROM +CPU_AFFINITY +CRYPT_H -DEVICEATLAS +DL +EPOLL -EVPORTS +FUTEX +GETADDRINFO -KQUEUE +LIBCRYPT +LINUX_SPLICE +LINUX_TPROXY +LUA -MEMORY_PROFILING +NETFILTER +NS -OBSOLETE_LINKER +OPENSSL -OT -PCRE +PCRE2 +PCRE2_JIT -PCRE_JIT +POLL +PRCTL -PRIVATE_CACHE -PROCCTL +PROMEX -PTHREAD_PSHARED -QUIC +RT -SLZ -STATIC_PCRE -STATIC_PCRE2 -SYSTEMD +TFO +THREAD +THREAD_DUMP +TPROXY -WURFL +ZLIB Default settings : bufsize = 16384, maxrewrite = 1024, maxpollevents = 200 Built with multi-threading support (MAX_THREADS=64, default=4). Built with OpenSSL version : OpenSSL 1.1.1t 7 Feb 2023 Running on OpenSSL version : OpenSSL 1.1.1t 7 Feb 2023 OpenSSL library supports TLS extensions : yes OpenSSL library supports SNI : yes OpenSSL library supports : TLSv1.0 TLSv1.1 TLSv1.2 TLSv1.3 Built with Lua version : Lua 5.3.5
[2.4.22] Segmentation fault when using spoe + disabled keyword
Hi, I'm experiencing a segmentation fault caused by adding "disabled" ( http://docs.haproxy.org/2.4/configuration.html#4-disabled) to the frontend section of haproxy configuration file. That frontend does not handle any traffic yet. The "disabled" keyword was used on other frontends on the same HAProxy instance before without any issue. The difference is that this time it was added to frontend with spoe filter. This probably causes a crash when processing requests on a different heavily used frontend (also spoe enabled). It crashes after 2-10s under production traffic. I couldn't replicate it with a synthetic test, however I have a coredump and packages with HAProxy binary and debug symbols. (gdb) bt #0 __pthread_kill_implementation (no_tid=0, signo=6, threadid=140527117211200) at ./nptl/pthread_kill.c:44 #1 __pthread_kill_internal (signo=6, threadid=140527117211200) at ./nptl/pthread_kill.c:78 #2 __GI___pthread_kill (threadid=140527117211200, signo=signo@entry=6) at ./nptl/pthread_kill.c:89 #3 0x7fcf0881a476 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26 #4 0x7fcf088007f3 in __GI_abort () at ./stdlib/abort.c:79 #5 0x558f48524feb in ha_panic () at src/debug.c:333 #6 0x558f486be1af in wdt_handler (sig=14, si=0x7fcf04e4d3f0, arg=0x7fcf04e4d2c0) at src/wdt.c:122 #7 #8 0x558f48469895 in pattern_exec_match (head=0x558f69fe67b8, smp=0x7fcf04e4e080, fill=0) at src/pattern.c:2498 #9 0x558f485a0bf2 in acl_exec_cond (cond=0x558f69fe69a0, px=0x558f69f67cf0, sess=0x7fce50243cd0, strm=0x7fce5020a4b0, opt=6) at src/acl.c:1123 #10 0x558f483b5eea in spoe_encode_message (s=0x7fce5020a4b0, ctx=0x7fce5026ddf0, msg=0x558f69fe2650, dir=0, buf=0x7fcf04e4e1b0, end=0x7fce502a627c "") at src/flt_spoe.c:2185 #11 0x558f483b6259 in spoe_encode_messages (s=0x7fce5020a4b0, ctx=0x7fce5026ddf0, messages=0x558f69fe23a0, dir=0, type=1) at src/flt_spoe.c:2285 #12 0x558f483b75a4 in spoe_process_messages (s=0x7fce5020a4b0, ctx=0x7fce5026ddf0, messages=0x558f69fe23a0, dir=0, type=1) at src/flt_spoe.c:2726 #13 0x558f483b79d0 in spoe_process_event (s=0x7fce5020a4b0, ctx=0x7fce5026ddf0, ev=SPOE_EV_ON_HTTP_REQ_FE) at src/flt_spoe.c:2842 #14 0x558f483b8eeb in spoe_chn_pre_analyze (s=0x7fce5020a4b0, filter=0x7fce5025c920, chn=0x7fce5020a4c0, an_bit=16) at src/flt_spoe.c:3324 #15 0x558f48549976 in flt_pre_analyze (s=0x7fce5020a4b0, chn=0x7fce5020a4c0, an_bit=16) at src/filters.c:764 #16 0x558f4836aaff in process_stream (t=0x7fce50242f30, context=0x7fce5020a4b0, state=260) at src/stream.c:1918 #17 0x558f4857aa3c in run_tasks_from_lists (budgets=0x7fcf04e4e5a0) at src/task.c:597 #18 0x558f4857b485 in process_runnable_tasks () at src/task.c:838 #19 0x558f484d0eb5 in run_poll_loop () at src/haproxy.c:2630 #20 0x558f484d1423 in run_thread_poll_loop (data=0x5) at src/haproxy.c:2805 #21 0x7fcf0886cb43 in start_thread (arg=) at ./nptl/pthread_create.c:442 #22 0x7fcf088fea00 in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81 haproxy -vv HAProxy version 2.4.22-f8e3218 2023/02/14 - https://haproxy.org/ Status: long-term supported branch - will stop receiving fixes around Q2 2026. Known bugs: http://www.haproxy.org/bugs/bugs-2.4.22.html Running on: Linux 5.15.0-69-generic #76-Ubuntu SMP Fri Mar 17 17:19:29 UTC 2023 x86_64 Build options : TARGET = linux-glibc CPU = generic CC = cc CFLAGS = -O0 -g -Wall -Wextra -Wdeclaration-after-statement -fwrapv -Wno-unused-label -Wno-sign-compare -Wno-unused-parameter -Wno-clobbered -Wno-missing-field-initializers -Wtype-limits -Wshift-negative-value -Wshift-overflow=2 -Wduplicated-cond -Wnull-dereference -DMAX_SESS_STKCTR=12 OPTIONS = USE_PCRE2=1 USE_PCRE2_JIT=1 USE_GETADDRINFO=1 USE_OPENSSL=1 USE_LUA=1 USE_ZLIB=1 USE_DL=1 USE_PROMEX=1 DEBUG = Feature list : -51DEGREES +ACCEPT4 +BACKTRACE -CLOSEFROM +CPU_AFFINITY +CRYPT_H -DEVICEATLAS +DL +EPOLL -EVPORTS +FUTEX +GETADDRINFO -KQUEUE +LIBCRYPT +LINUX_SPLICE +LINUX_TPROXY +LUA -MEMORY_PROFILING +NETFILTER +NS -OBSOLETE_LINKER +OPENSSL -OT -PCRE +PCRE2 +PCRE2_JIT -PCRE_JIT +POLL +PRCTL -PRIVATE_CACHE -PROCCTL +PROMEX -PTHREAD_PSHARED -QUIC +RT -SLZ -STATIC_PCRE -STATIC_PCRE2 -SYSTEMD +TFO +THREAD +THREAD_DUMP +TPROXY -WURFL +ZLIB Default settings : bufsize = 16384, maxrewrite = 1024, maxpollevents = 200 Built with multi-threading support (MAX_THREADS=64, default=4). Built with OpenSSL version : OpenSSL 1.1.1t 7 Feb 2023 Running on OpenSSL version : OpenSSL 1.1.1t 7 Feb 2023 OpenSSL library supports TLS extensions : yes OpenSSL library supports SNI : yes OpenSSL library supports : TLSv1.0 TLSv1.1 TLSv1.2 TLSv1.3 Built with Lua version : Lua 5.3.5 Built with the Prometheus exporter as a service Built with network namespace support. Built with zlib version : 1.2.11 Running on zlib version : 1.2.11 Compression algorithms supported : identity("identity"), deflate("deflate"),
spoe - capturing & mirroring traffic
I'd like to capture & mirror HTTP traffic for a few days, to capture some truly representative load generating traffic. https://www.haproxy.com/blog/haproxy-traffic-mirroring-for-real-world-testing/ There seem to be a few general options: - use spoe & spoa-mirror - some bpf/tcpdump powered capture & replay tool spoa-mirror in general is more interesting as we can take care of TLS termination and get all the haproxy goodness, but it seems not to be maintained. Is anybody aware of alternatives using the SPOE engine? BTW I have found goreplay which looks very nice for BPF style capture, but having the full filtering & acl power of haproxy is definitely a better option. https://github.com/haproxytech/spoa-mirror https://goreplay./org/ A+ Dave
Re: New .NET SPOE Library
On Thu, Jun 2, 2022 at 10:00 PM Sébastien Crocquesel < s.crocque...@inulogic.com> wrote: > Dear all, > > I create a .NET Library to build SPOP agent and release it under MIT > Licence. The library is happily used in production for more than 2 years > now and serve more than 10K req/s per agent node. > > I would be pleased if it can be referenced on the spoe wiki page with > other current implementations. > > You may find more information at > https://github.com/inulogic/HAProxy.StreamProcessingOffload.AgentFramework > > > Best regards, > Sebastien > > Hi Sebastien! Thx a lot for your contribution! I just updated the wiki page: https://github.com/haproxy/wiki/wiki/SPOE:-Stream-Processing-Offloading-Engine Baptiste
New .NET SPOE Library
Dear all, I create a .NET Library to build SPOP agent and release it under MIT Licence. The library is happily used in production for more than 2 years now and serve more than 10K req/s per agent node. I would be pleased if it can be referenced on the spoe wiki page with other current implementations. You may find more information at https://github.com/inulogic/HAProxy.StreamProcessingOffload.AgentFramework Best regards, Sebastien
Re: Weird behavior of spoe between http and https requests
Le 6/11/21 à 8:22 PM, Aleksandar Lazic a écrit : Hi. On 11.06.21 18:07, Aleksandar Lazic wrote: Hi. I use haproxy 2.4 with this fe config. ``` global log stdout format raw daemon daemon maxconn 2 stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners stats timeout 30s tune.ssl.default-dh-param 2048 # Default SSL material locations ca-base /etc/ssl/certs crt-base /etc/ssl/private # See https://ssl-config.mozilla.org/#server=haproxy&version=2.1&config=old&openssl=1.1.1d&guideline=5.4 ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256 ssl-default-bind-options no-tls-tickets ssl-min-ver TLSv1.0 ssl-default-server-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA ssl-default-server-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256 ssl-default-server-options no-tls-tickets ssl-min-ver TLSv1.0 defaults http log global mode http retry-on all-retryable-errors option forwardfor option redispatch option http-ignore-probes option httplog option dontlognull option log-health-checks option socket-stats timeout connect 5s timeout client 50s timeout server 50s http-reuse safe errorfile 400 /etc/haproxy/errors/400.http errorfile 403 /etc/haproxy/errors/403.http errorfile 408 /etc/haproxy/errors/408.http errorfile 500 /etc/haproxy/errors/500.http errorfile 502 /etc/haproxy/errors/502.http errorfile 503 /etc/haproxy/errors/503.http errorfile 504 /etc/haproxy/errors/504.http frontend http-in bind *:80 mode http unique-id-format %rt http-request set-var(sess.my_fe_path) path http-request set-var(sess.my_fe_src) src http-request set-var(sess.my_fe_referer) req.hdr(Referer) http-request set-var(sess.my_fe_requestedhost) req.hdr(Host) # define the spoe agents filter spoe engine agent-on-http-req config /etc/haproxy/spoe-url.conf filter spoe engine agent-on-http-res config /etc/haproxy/spoe-url.conf frontend https-in bind :::443 v4v6 alpn h2,http/1.1 ssl ca-file /etc/haproxy/letsencryptauthorityx3.pem crt /etc/ssl/haproxy/ unique-id-format %rt http-request set-var(sess.my_fe_path) path http-request set-var(sess.my_fe_src) src http-request set-var(sess.my_fe_referer) req.hdr(Referer) http-request set-var(sess.my_fe_requestedhost) req.hdr(Host) # define the spoe agents filter spoe engine agent-on-http-req config /etc/haproxy/spoe-url.conf filter spoe engine agent-on-http-res config /etc/haproxy/spoe-url.conf ``` And with this spoe config. ``` [agent-on-http-req] spoe-agent agent-on-http-req log global messages agent-on-http-req option var-prefix feevents timeout hello 2s timeout idle 2m timeout processing 1s use-backend agent-on-http-req spoe-message agent-on-http-req args my_path=path my_src=src my_referer=req.hdr(Referer) my_sid=unique-id my_req_host=req.hdr(Host) event on-frontend-http-request [agent-on-http-res] spoe-agent agent-on-http-res log global messages agent-on-http-res option var-prefix feevents timeout hello 2s timeout idle 2m timeout processing 1s use-backend agent-on-http-res spoe-message agent-on-http-res args my_path=var(sess.my_fe_path) my_src=src my_referer=var(sess.my_fe_referer) my_sid=unique-id my_req_host=var(sess.my_fe_requestedhost) event on-http-response ``` Now when I make a http request I get all values and args. ``` Jun 11 16:01:01 reggata-001 spoe-url[112969]: 2021/06/11 16:01:01 Msg Name :agent-on-http-req: Jun 11
Re: Weird behavior of spoe between http and https requests
Hi. On 11.06.21 18:07, Aleksandar Lazic wrote: Hi. I use haproxy 2.4 with this fe config. ``` global log stdout format raw daemon daemon maxconn 2 stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners stats timeout 30s tune.ssl.default-dh-param 2048 # Default SSL material locations ca-base /etc/ssl/certs crt-base /etc/ssl/private # See https://ssl-config.mozilla.org/#server=haproxy&version=2.1&config=old&openssl=1.1.1d&guideline=5.4 ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256 ssl-default-bind-options no-tls-tickets ssl-min-ver TLSv1.0 ssl-default-server-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA ssl-default-server-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256 ssl-default-server-options no-tls-tickets ssl-min-ver TLSv1.0 defaults http log global mode http retry-on all-retryable-errors option forwardfor option redispatch option http-ignore-probes option httplog option dontlognull option log-health-checks option socket-stats timeout connect 5s timeout client 50s timeout server 50s http-reuse safe errorfile 400 /etc/haproxy/errors/400.http errorfile 403 /etc/haproxy/errors/403.http errorfile 408 /etc/haproxy/errors/408.http errorfile 500 /etc/haproxy/errors/500.http errorfile 502 /etc/haproxy/errors/502.http errorfile 503 /etc/haproxy/errors/503.http errorfile 504 /etc/haproxy/errors/504.http frontend http-in bind *:80 mode http unique-id-format %rt http-request set-var(sess.my_fe_path) path http-request set-var(sess.my_fe_src) src http-request set-var(sess.my_fe_referer) req.hdr(Referer) http-request set-var(sess.my_fe_requestedhost) req.hdr(Host) # define the spoe agents filter spoe engine agent-on-http-req config /etc/haproxy/spoe-url.conf filter spoe engine agent-on-http-res config /etc/haproxy/spoe-url.conf frontend https-in bind :::443 v4v6 alpn h2,http/1.1 ssl ca-file /etc/haproxy/letsencryptauthorityx3.pem crt /etc/ssl/haproxy/ unique-id-format %rt http-request set-var(sess.my_fe_path) path http-request set-var(sess.my_fe_src) src http-request set-var(sess.my_fe_referer) req.hdr(Referer) http-request set-var(sess.my_fe_requestedhost) req.hdr(Host) # define the spoe agents filter spoe engine agent-on-http-req config /etc/haproxy/spoe-url.conf filter spoe engine agent-on-http-res config /etc/haproxy/spoe-url.conf ``` And with this spoe config. ``` [agent-on-http-req] spoe-agent agent-on-http-req log global messages agent-on-http-req option var-prefix feevents timeout hello 2s timeout idle 2m timeout processing 1s use-backend agent-on-http-req spoe-message agent-on-http-req args my_path=path my_src=src my_referer=req.hdr(Referer) my_sid=unique-id my_req_host=req.hdr(Host) event on-frontend-http-request [agent-on-http-res] spoe-agent agent-on-http-res log global messages agent-on-http-res option var-prefix feevents timeout hello 2s timeout idle 2m timeout processing 1s use-backend agent-on-http-res spoe-message agent-on-http-res args my_path=var(sess.my_fe_path) my_src=src my_referer=var(sess.my_fe_referer) my_sid=unique-id my_req_host=var(sess.my_fe_requestedhost) event on-http-response ``` Now when I make a http request I get all values and args. ``` Jun 11 16:01:01 reggata-001 spoe-url[112969]: 2021/06/11 16:01:01 Msg Name :agent-on-http-req: Jun 11 16:01:01 reggata-001 spoe-url[112969]: 2021/06/11 16:01:01 Msg Count :5: Jun 11 16:01:01 reggata-001 spoe-url[112969]: 202
Weird behavior of spoe between http and https requests
Hi. I use haproxy 2.4 with this fe config. ``` global log stdout format raw daemon daemon maxconn 2 stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners stats timeout 30s tune.ssl.default-dh-param 2048 # Default SSL material locations ca-base /etc/ssl/certs crt-base /etc/ssl/private # See https://ssl-config.mozilla.org/#server=haproxy&version=2.1&config=old&openssl=1.1.1d&guideline=5.4 ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256 ssl-default-bind-options no-tls-tickets ssl-min-ver TLSv1.0 ssl-default-server-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA ssl-default-server-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256 ssl-default-server-options no-tls-tickets ssl-min-ver TLSv1.0 defaults http log global mode http retry-on all-retryable-errors option forwardfor option redispatch option http-ignore-probes option httplog option dontlognull option log-health-checks option socket-stats timeout connect 5s timeout client 50s timeout server 50s http-reuse safe errorfile 400 /etc/haproxy/errors/400.http errorfile 403 /etc/haproxy/errors/403.http errorfile 408 /etc/haproxy/errors/408.http errorfile 500 /etc/haproxy/errors/500.http errorfile 502 /etc/haproxy/errors/502.http errorfile 503 /etc/haproxy/errors/503.http errorfile 504 /etc/haproxy/errors/504.http frontend http-in bind *:80 mode http unique-id-format %rt http-request set-var(sess.my_fe_path) path http-request set-var(sess.my_fe_src) src http-request set-var(sess.my_fe_referer) req.hdr(Referer) http-request set-var(sess.my_fe_requestedhost) req.hdr(Host) # define the spoe agents filter spoe engine agent-on-http-req config /etc/haproxy/spoe-url.conf filter spoe engine agent-on-http-res config /etc/haproxy/spoe-url.conf frontend https-in bind :::443 v4v6 alpn h2,http/1.1 ssl ca-file /etc/haproxy/letsencryptauthorityx3.pem crt /etc/ssl/haproxy/ unique-id-format %rt http-request set-var(sess.my_fe_path) path http-request set-var(sess.my_fe_src) src http-request set-var(sess.my_fe_referer) req.hdr(Referer) http-request set-var(sess.my_fe_requestedhost) req.hdr(Host) # define the spoe agents filter spoe engine agent-on-http-req config /etc/haproxy/spoe-url.conf filter spoe engine agent-on-http-res config /etc/haproxy/spoe-url.conf ``` And with this spoe config. ``` [agent-on-http-req] spoe-agent agent-on-http-req log global messages agent-on-http-req option var-prefix feevents timeout hello 2s timeout idle 2m timeout processing 1s use-backend agent-on-http-req spoe-message agent-on-http-req args my_path=path my_src=src my_referer=req.hdr(Referer) my_sid=unique-id my_req_host=req.hdr(Host) event on-frontend-http-request [agent-on-http-res] spoe-agent agent-on-http-res log global messages agent-on-http-res option var-prefix feevents timeout hello 2s timeout idle 2m timeout processing 1s use-backend agent-on-http-res spoe-message agent-on-http-res args my_path=var(sess.my_fe_path) my_src=src my_referer=var(sess.my_fe_referer) my_sid=unique-id my_req_host=var(sess.my_fe_requestedhost) event on-http-response ``` Now when I make a http request I get all values and args. ``` Jun 11 16:01:01 reggata-001 spoe-url[112969]: 2021/06/11 16:01:01 Msg Name :agent-on-http-req: Jun 11 16:01:01 reggata-001 spoe-url[112969]: 2021/06/11 16:01:01 Msg Count :5: Jun 11 16:01:01 reggata-001 spoe-url[112969]: 2021/06/11 16:01:01 Arg Name :my_path: Jun 11 16:01:01 reggata-001 spoe-url[112969]: 2021/06/11 16:01:01 Arg Value :/test:
Re: ring buffer + spoe = segfault
Great, thanks for the update. :) W dniu pt., 19.02.2021 o 18:06 Christopher Faulet napisał(a): > Le 19/02/2021 à 09:31, Maciej Zdeb a écrit : > > Hi, > > > > By accident I discovered that when enabling logging with line "log > > ring@spoe-ring local2" in SPOE immediate segmentation fault occurs. > > > > Steps to reproduce (configuration files attached): > > > > # execute spoa-server from contrib directory: > > ./spoa -d -p 8080 > > > > # execute haproxy: > > haproxy -f haproxy.cfg > > > > # trigger: > > curl http://localhost:8000 <http://localhost:8000> > > > > > > # haproxy -v > > HA-Proxy version 2.2.5-34b2b10 2020/11/05 - https://haproxy.org/ > > <https://haproxy.org/> > > Status: long-term supported branch - will stop receiving fixes around Q2 > 2025. > > Known bugs: http://www.haproxy.org/bugs/bugs-2.2.5.html > > <http://www.haproxy.org/bugs/bugs-2.2.5.html> > > Running on: Linux 4.15.0-54-generic #58-Ubuntu SMP Mon Jun 24 10:55:24 > UTC 2019 > > x86_64 > > > > Kind regards, > > Maciej > > Maciej, > > I pushed a fix (https://github.com/haproxy/haproxy/commit/1d7d0f8). Not > backported yet. > > Thanks ! > -- > Christopher Faulet >
Re: ring buffer + spoe = segfault
Le 19/02/2021 à 09:31, Maciej Zdeb a écrit : Hi, By accident I discovered that when enabling logging with line "log ring@spoe-ring local2" in SPOE immediate segmentation fault occurs. Steps to reproduce (configuration files attached): # execute spoa-server from contrib directory: ./spoa -d -p 8080 # execute haproxy: haproxy -f haproxy.cfg # trigger: curl http://localhost:8000 <http://localhost:8000> # haproxy -v HA-Proxy version 2.2.5-34b2b10 2020/11/05 - https://haproxy.org/ <https://haproxy.org/> Status: long-term supported branch - will stop receiving fixes around Q2 2025. Known bugs: http://www.haproxy.org/bugs/bugs-2.2.5.html <http://www.haproxy.org/bugs/bugs-2.2.5.html> Running on: Linux 4.15.0-54-generic #58-Ubuntu SMP Mon Jun 24 10:55:24 UTC 2019 x86_64 Kind regards, Maciej Maciej, I pushed a fix (https://github.com/haproxy/haproxy/commit/1d7d0f8). Not backported yet. Thanks ! -- Christopher Faulet
Re: ring buffer + spoe = segfault
Le 19/02/2021 à 09:31, Maciej Zdeb a écrit : Hi, By accident I discovered that when enabling logging with line "log ring@spoe-ring local2" in SPOE immediate segmentation fault occurs. Steps to reproduce (configuration files attached): # execute spoa-server from contrib directory: ./spoa -d -p 8080 # execute haproxy: haproxy -f haproxy.cfg # trigger: curl http://localhost:8000 <http://localhost:8000> # haproxy -v HA-Proxy version 2.2.5-34b2b10 2020/11/05 - https://haproxy.org/ <https://haproxy.org/> Status: long-term supported branch - will stop receiving fixes around Q2 2025. Known bugs: http://www.haproxy.org/bugs/bugs-2.2.5.html <http://www.haproxy.org/bugs/bugs-2.2.5.html> Running on: Linux 4.15.0-54-generic #58-Ubuntu SMP Mon Jun 24 10:55:24 UTC 2019 x86_64 Kind regards, Maciej Maciej, Thanks for the report. Indeed, there is no post parsing resolution in the SPOE to find the sink corresponding to the ring buffer. It also fails on the 2.4-dev. I'll fix it soon. -- Christopher Faulet
ring buffer + spoe = segfault
Hi, By accident I discovered that when enabling logging with line "log ring@spoe-ring local2" in SPOE immediate segmentation fault occurs. Steps to reproduce (configuration files attached): # execute spoa-server from contrib directory: ./spoa -d -p 8080 # execute haproxy: haproxy -f haproxy.cfg # trigger: curl http://localhost:8000 # haproxy -v HA-Proxy version 2.2.5-34b2b10 2020/11/05 - https://haproxy.org/ Status: long-term supported branch - will stop receiving fixes around Q2 2025. Known bugs: http://www.haproxy.org/bugs/bugs-2.2.5.html Running on: Linux 4.15.0-54-generic #58-Ubuntu SMP Mon Jun 24 10:55:24 UTC 2019 x86_64 Kind regards, Maciej spoa-server.spoe.conf Description: Binary data haproxy.cfg Description: Binary data
Re: [PATCH] CLEANUP: spoe: fix typo on `var_check_arg` comment
On Tue, Jan 05, 2021 at 11:14:58AM +0100, William Dauchy wrote: > there was an extra `s` added to the `var_check_arg` function Merged, thank you William. Willy
[PATCH] CLEANUP: spoe: fix typo on `var_check_arg` comment
there was an extra `s` added to the `var_check_arg` function Signed-off-by: William Dauchy --- src/flt_spoe.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/flt_spoe.c b/src/flt_spoe.c index 45370fee6..bfd6f4fbf 100644 --- a/src/flt_spoe.c +++ b/src/flt_spoe.c @@ -4178,7 +4178,7 @@ parse_spoe_flt(char **args, int *cur_arg, struct proxy *px, arg.type = ARGT_STR; arg.data.str.area = trash.area; arg.data.str.data = trash.data; - arg.data.str.size = 0; /* Set it to 0 to not release it in vars_check_args() */ + arg.data.str.size = 0; /* Set it to 0 to not release it in vars_check_arg() */ if (!vars_check_arg(&arg, err)) { memprintf(err, "SPOE agent '%s': failed to register variable %s.%s (%s)", curagent->id, curagent->var_pfx, curagent->var_on_error, *err); @@ -4195,7 +4195,7 @@ parse_spoe_flt(char **args, int *cur_arg, struct proxy *px, arg.type = ARGT_STR; arg.data.str.area = trash.area; arg.data.str.data = trash.data; - arg.data.str.size = 0; /* Set it to 0 to not release it in vars_check_args() */ + arg.data.str.size = 0; /* Set it to 0 to not release it in vars_check_arg() */ if (!vars_check_arg(&arg, err)) { memprintf(err, "SPOE agent '%s': failed to register variable %s.%s (%s)", curagent->id, curagent->var_pfx, curagent->var_t_process, *err); @@ -4212,7 +4212,7 @@ parse_spoe_flt(char **args, int *cur_arg, struct proxy *px, arg.type = ARGT_STR; arg.data.str.area = trash.area; arg.data.str.data = trash.data; - arg.data.str.size = 0; /* Set it to 0 to not release it in vars_check_args() */ + arg.data.str.size = 0; /* Set it to 0 to not release it in vars_check_arg() */ if (!vars_check_arg(&arg, err)) { memprintf(err, "SPOE agent '%s': failed to register variable %s.%s (%s)", curagent->id, curagent->var_pfx, curagent->var_t_process, *err); @@ -4418,7 +4418,7 @@ parse_spoe_flt(char **args, int *cur_arg, struct proxy *px, arg.type = ARGT_STR; arg.data.str.area = trash.area; arg.data.str.data = trash.data; - arg.data.str.size = 0; /* Set it to 0 to not release it in vars_check_args() */ + arg.data.str.size = 0; /* Set it to 0 to not release it in vars_check_arg() */ if (!vars_check_arg(&arg, err)) { memprintf(err, "SPOE agent '%s': failed to register variable %s.%s (%s)", curagent->id, curagent->var_pfx, vph->name, *err); -- 2.29.2
Re: [PATCH] BUG/MINOR: spoe: correction of setting bits for analyzer
Le 19/06/2020 à 22:21, Miroslav Zagorac a écrit : Hello everyone, somehow it seems to me that this is a bug when setting bits for the channel analyzer in the spoe filter.. in this case the attached patch can be applied. I adjusted the commit message to add a short description and info about the backports. Now merged, thank you ! -- Christopher Faulet
[PATCH] BUG/MINOR: spoe: correction of setting bits for analyzer
Hello everyone, somehow it seems to me that this is a bug when setting bits for the channel analyzer in the spoe filter.. in this case the attached patch can be applied. -- Zaga What can change the nature of a man? >From 5bbed897105cafb49cc1cf8676497a7f86ea9947 Mon Sep 17 00:00:00 2001 From: Miroslav Zagorac Date: Fri, 19 Jun 2020 22:17:17 +0200 Subject: [PATCH] BUG/MINOR: spoe: correction of setting bits for analyzer --- src/flt_spoe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/flt_spoe.c b/src/flt_spoe.c index 49d7466ae..4790f5945 100644 --- a/src/flt_spoe.c +++ b/src/flt_spoe.c @@ -3187,7 +3187,7 @@ spoe_start_analyze(struct stream *s, struct filter *filter, struct channel *chn) ctx->flags |= SPOE_CTX_FL_CLI_CONNECTED; } else { - if (filter->pre_analyzers & SPOE_EV_ON_TCP_RSP) + if (filter->pre_analyzers & AN_RES_INSPECT) chn->analysers |= AN_RES_INSPECT; if (ctx->flags & SPOE_CTX_FL_SRV_CONNECTED) -- 2.20.1
Re: [PATCH] BUG/MEDIUM: spoe: Use unique engine_id for all agents in all scopes
Le 18/03/2020 à 04:21, Kevin Zhu a écrit : Hi Christopher Can you please test the config files I attached in this mail, HAProxy version 2.1.3 And you can add some debug code like SPOE_PRINTF in function spoe_init_per_thread to print engin_ids of every agent in every proxy. Then you can see the engine_id is duplicated. The patch I attached in prev mail is worked, but I agree better to have a lock. Hi Kevin, Ok I understand now how you hit the bug. You use the same engine in 2 different frontends. Of course, it is totally valid. And there is indeed a bug here. And in fact, it reveals a design problem. First, I confirm on 2.x versions, it should already be fixed by side effect. As I said, a new thread-safe and process-safe PRNG was implemented. Now, a specific state is chosen for each process child after the fork. The fix will be part of the next releases. For the 1.9, It is annoying because each spoe engine will reset the random state with the same seed. With 2 spoe engines, it may be reset by the second one on the first thread while it is used to generate IDs of the first one on other threads. The problem exists for completely different engines. If you use more than one engine, you may hit the bug. So, the spoe_init_per_thread() callback function is definitely the wrong place to reset the random state. It must be done just after the fork, in the child process. About your patch, on the 1.9 (or the version 2.1.3) with several threads, you may have the same engine ID for different threads, with just one engine. To convince you, replace nbproc by nbthread in your configuration and add a delay between the HA_ATOMIC_LOAD and the HA_ATOMIC_STORE. This will increase the probability to have duplicated engine IDs. I'll try to push a fix for the 1.9. But I'm busy on another task for now. For 2.x versions, you may use the last snapshots to have the fix. -- Christopher Faulet
Re: [PATCH] BUG/MEDIUM: spoe: Use unique engine_id for all agents in all scopes
Le 13/03/2020 à 08:02, Kevin Zhu a écrit : Hi again In version 2.1.3: When config spoe engine proxys > 1, the function "srandom" will run more than one times, it will make some engine_id duplicated, and the SPOA is group SPOP connections by engine_id when option async is on, the ack will reply to the wrong SPOE. This patch should backport to 2.0 and 1.9. Hi, Sorry, but your patch does not fix the bug. First, for 2.x, recent changes to implement a thread-safe and process-safe PRNG seem to make this patch useless. For the version 1.9, the problem is not to run srandom() multiple times because it is executed only once per process, for the first thread. But the spoe_init_per_thread() callback function is not necessarily called for the first thread first. So an engine ID may be generated for a thread before calling srandom(). This way it is possible to have same ID for several threads on different process. AFAIK, the bug should only be possible when nbproc and nbthread are mixed. In your patch, srandom() may be called multiple times for the same process because the init variable may be seen to 0 by several threads. So it is possible to reset the random seed before generating an engine ID. This way, several threads may have the same engine ID for the same process. Unfortunately, to fix the bug, we have to synchronize the threads to be sure only one thread runs srandom() before generating any engine ID. So, we must have a lock. Another solution is to call srandom() just after the fork of a process. -- Christopher Faulet
Re: [PATCH] BUG/MEDIUM: spoe: dup agent's engine_id string from trash.area
Le 13/03/2020 à 07:54, Kevin Zhu a écrit : Hi The agent's engine_id forgot to dup from trash, all engine_ids point to the same address "&trash.area", the engine_id changed at run time and will double-free when release agents and trash. Kevin Thanks, now applied ! -- Christopher Faulet
[PATCH] BUG/MEDIUM: spoe: Use unique engine_id for all agents in all scopes
Hi again In version 2.1.3: When config spoe engine proxys > 1, the function "srandom" will run more than one times, it will make some engine_id duplicated, and the SPOA is group SPOP connections by engine_id when option async is on, the ack will reply to the wrong SPOE. This patch should backport to 2.0 and 1.9. My pleasure Kevin From 512e4aca8e3ffd57fb3f12581ede6d8e8d624319 Mon Sep 17 00:00:00 2001 From: Kevin Zhu Date: Fri, 13 Mar 2020 14:40:46 +0800 Subject: [PATCH] BUG/MEDIUM: spoe: Use unique engine_id for all agents in all scopes When config spoe engine proxys > 1, the function "srandom" will run more than one times, it will make some engine_id duplicated, and the SPOA is group SPOP connections by engine_id when option async is on, the ack will reply to the wrong SPOE. --- src/flt_spoe.c | 7 +-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/flt_spoe.c b/src/flt_spoe.c index 930ac8d..2181138 100644 --- a/src/flt_spoe.c +++ b/src/flt_spoe.c @@ -3118,14 +3118,17 @@ spoe_init_per_thread(struct proxy *p, struct flt_conf *fconf) { struct spoe_config *conf = fconf->conf; struct spoe_agent *agent = conf->agent; + static int init = 0; - /* Use a != seed per process */ - if (relative_pid > 1 && tid == 0) + if (HA_ATOMIC_LOAD(&init) == 0) { + HA_ATOMIC_STORE(&init, 1); srandom(now_ms * pid); + } agent->rt[tid].engine_id = generate_pseudo_uuid(); if (agent->rt[tid].engine_id == NULL) return -1; + return 0; } -- 2.7.4
[PATCH] BUG/MEDIUM: spoe: dup agent's engine_id string from trash.area
Hi The agent's engine_id forgot to dup from trash, all engine_ids point to the same address "&trash.area", the engine_id changed at run time and will double-free when release agents and trash. Kevin From 674ba1e318cb561a1650db98030e12939e604171 Mon Sep 17 00:00:00 2001 From: Kevin Zhu Date: Fri, 13 Mar 2020 10:39:51 +0800 Subject: [PATCH] BUG/MEDIUM: spoe: dup agent's engine_id string from trash.area The agent's engine_id forgot to dup from trash, all engine_ids point to the same address "&trash.area", the engine_id changed at run time and will double free when release agents and trash. --- src/flt_spoe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/flt_spoe.c b/src/flt_spoe.c index df080d8..57c2246 100644 --- a/src/flt_spoe.c +++ b/src/flt_spoe.c @@ -258,7 +258,7 @@ static char * generate_pseudo_uuid() { ha_generate_uuid(&trash); - return trash.area; + return my_strndup(trash.area, trash.data); } -- 2.7.4
Re: BUG/MEDIUM: spoe: engine-id is necessary if not health check
Le 17/09/2019 à 11:11, Christopher Faulet a écrit : Le 16/09/2019 à 03:40, Kevin Zhu a écrit : Sorry Crhistopher, have you look at this mail ?😁 On Mon, 2 Sep 2019 at 16:11, Kevin Zhu mailto:ip0...@gmail.com>> wrote: Hi Christopher SPOE engine-id is all same when nbproc is more than 1, the clients all group under same engine, and same stream-id and frame-id frames may come at same time. So we alway need engine-id to identify client's and frames. Best Regards Hi Kevin, Don't be sorry. I was busy when received your mail and after I forgot to review it. So, thanks for the reminder. There are 2 parts in your patch. First, about the SPOE engine-id when there is more than 1 process, you're right. The engine-id is the same for all instances and it's a problem. But if we are fixing this part, we might as well fix it for the threads too. For now, the Async mode does not work with several threads just because of the engine-id. It is pretty easy to fix, thus I will do it too. Then, about the mandatory nature of the engine-id, I'm disagree. For 2 reasons. First, because health-checks does not provide it. Second, because it is only required for the async mode. We can imagine to not send it when this mode is explicitly disabled. From the protocol point of view, I prefer to keep it optional. I can amend your patch to get only part to generate a different engine-id per process if you are ok. Then I'll do a fix to have a different engine-id per-thread too and always allow the async mode. Hi Kevin, I've finally found some time to push the patches. I will backport it soon. Thanks ! -- Christopher Faulet
Re: BUG/MEDIUM: spoe: engine-id is necessary if not health check
Le 16/09/2019 à 03:40, Kevin Zhu a écrit : Sorry Crhistopher, have you look at this mail ?😁 On Mon, 2 Sep 2019 at 16:11, Kevin Zhu <mailto:ip0...@gmail.com>> wrote: Hi Christopher SPOE engine-id is all same when nbproc is more than 1, the clients all group under same engine, and same stream-id and frame-id frames may come at same time. So we alway need engine-id to identify client's and frames. Best Regards Hi Kevin, Don't be sorry. I was busy when received your mail and after I forgot to review it. So, thanks for the reminder. There are 2 parts in your patch. First, about the SPOE engine-id when there is more than 1 process, you're right. The engine-id is the same for all instances and it's a problem. But if we are fixing this part, we might as well fix it for the threads too. For now, the Async mode does not work with several threads just because of the engine-id. It is pretty easy to fix, thus I will do it too. Then, about the mandatory nature of the engine-id, I'm disagree. For 2 reasons. First, because health-checks does not provide it. Second, because it is only required for the async mode. We can imagine to not send it when this mode is explicitly disabled. From the protocol point of view, I prefer to keep it optional. I can amend your patch to get only part to generate a different engine-id per process if you are ok. Then I'll do a fix to have a different engine-id per-thread too and always allow the async mode. -- Christopher Faulet
Re: BUG/MEDIUM: spoe: engine-id is necessary if not health check
Sorry Crhistopher, have you look at this mail ?😁 On Mon, 2 Sep 2019 at 16:11, Kevin Zhu wrote: > Hi Christopher > > SPOE engine-id is all same when nbproc is more than 1, the clients all > group under same engine, and same stream-id and frame-id frames may come > at > same time. So we alway need engine-id to identify client's and frames. > Best Regards >
BUG/MEDIUM: spoe: engine-id is necessary if not health check
Hi Christopher SPOE engine-id is all same when nbproc is more than 1, the clients all group under same engine, and same stream-id and frame-id frames may come at same time. So we alway need engine-id to identify client's and frames. Best Regards From caedabe336897704b4da39818ac7d226c7b8a9db Mon Sep 17 00:00:00 2001 From: Kevin Zhu Date: Mon, 2 Sep 2019 13:45:34 +0800 Subject: [PATCH] BUG/MEDIUM: spoe: engine-id is necessary if not health check SPOE engine-id is all same when nbproc is more than 1, the clients all group under same engine, and same stream-id and frame-id frames may come at same time. So we alway need engine-id to identify client's and frames. --- doc/SPOE.txt | 8 src/flt_spoe.c | 35 +-- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/doc/SPOE.txt b/doc/SPOE.txt index 19f00ad..dd8f920 100644 --- a/doc/SPOE.txt +++ b/doc/SPOE.txt @@ -932,6 +932,10 @@ Following items are mandatory in the KV-LIST: This a comma-separated list of capabilities supported by HAProxy. Spaces must be ignored, if any. + * "engine-id" + +This is a uniq string that identify a SPOE engine. + Following optional items can be added in the KV-LIST: * "healthcheck" @@ -939,10 +943,6 @@ Following optional items can be added in the KV-LIST: If this item is set to TRUE, then the HAPROXY-HELLO frame is sent during a SPOE health check. When set to FALSE, this item can be ignored. - * "engine-id" - - This is a uniq string that identify a SPOE engine. - To finish the HELLO handshake, the agent must return an AGENT-HELLO frame with its supported SPOP version, the lower value between its maximum size allowed for a frame and the HAProxy one and capabilities it supports. If an error diff --git a/src/flt_spoe.c b/src/flt_spoe.c index b8323f6..06ceeae 100644 --- a/src/flt_spoe.c +++ b/src/flt_spoe.c @@ -267,7 +267,7 @@ generate_pseudo_uuid() return NULL; if (!init) { - srand(now_ms); + srand(now_ms + pid); init = 1; } @@ -457,17 +457,18 @@ spoe_prepare_hahello_frame(struct appctx *appctx, char *frame, size_t size) if (spoe_encode_buffer(chk->area, chk->data, &p, end) == -1) goto too_big; - /* (optionnal) "engine-id" K/V item, if present */ - if (agent != NULL && agent->engine_id != NULL) { - sz = SLEN(ENGINE_ID_KEY); - if (spoe_encode_buffer(ENGINE_ID_KEY, sz, &p, end) == -1) - goto too_big; + /* "engine-id" K/V item */ + sz = SLEN(ENGINE_ID_KEY); + if (spoe_encode_buffer(ENGINE_ID_KEY, sz, &p, end) == -1) + goto too_big; - *p++ = SPOE_DATA_T_STR; + *p++ = SPOE_DATA_T_STR; + if (agent != NULL) { sz = strlen(agent->engine_id); if (spoe_encode_buffer(agent->engine_id, sz, &p, end) == -1) goto too_big; - } + } else if (spoe_encode_buffer(NULL, 0, &p, end) == -1) + goto too_big; return (p - frame); @@ -3111,6 +3112,21 @@ spoe_check(struct proxy *px, struct flt_conf *fconf) return 0; } +/* Initializes the SPOE filter for a proxy for a specific thread. + * Returns a negative value if an error occurs. */ +static int +spoe_init_per_thread(struct proxy *p, struct flt_conf *fconf) +{ + struct spoe_agent *agent = ((struct spoe_config*)fconf->conf)->agent; + if (agent->engine_id == NULL) + agent->engine_id = generate_pseudo_uuid(); + + if (agent->engine_id == NULL) + return -1; + + return 0; +} + /** * Hooks attached to a stream */ @@ -3309,6 +3325,7 @@ struct flt_ops spoe_ops = { .init = spoe_init, .deinit = spoe_deinit, .check = spoe_check, + .init_per_thread = spoe_init_per_thread, /* Handle start/stop of SPOE */ .attach = spoe_start, @@ -4177,8 +4194,6 @@ parse_spoe_flt(char **args, int *cur_arg, struct proxy *px, } curagent->var_pfx = strdup(curagent->id); } - if (curagent->engine_id == NULL) - curagent->engine_id = generate_pseudo_uuid(); if (curagent->var_on_error) { struct arg arg; -- 2.7.4
Re: Proof of concept SPOE based SSO solution
On Fri, Jul 5, 2019 at 11:12 AM Andrew Heberle wrote: > Hi All, > > I have put together a Go based proof of concept SPOE agent that also > implements a SAML 2 Service Provider (SP) in order to do "SSO" in > HAProxy. > > The code is located here: > > https://gitlab.com/andrewheberle/go-http-auth-sso > > The basic process is that SPOA is used to check if the user is logged > in or not and then based on the set variables you can make decisions > via "http-request" rules. > > This originally started out without the SPOE part and was using the > Lua http-auth-request script > (https://github.com/TimWolla/haproxy-auth-request), however with the > release of the Go SPOE package > (https://github.com/Aestek/haproxy-connect/tree/master/spoe) I rewrote > it based on that. > > Our use case is to have the SP pointed to a IdP in Azure so we can do > single-sign-on to Office 365 and we have "http-request" rules in place > to set some custom headers that our application uses for > authentication/authorisation. These are set based on the variables > that come back from the SPOA, which come from the claims in the > authentication process. > > Hopefully this is of some use to people. > > Any feedback and constructive criticism is welcome. > > -- > Andrew Heberle > > Thanks for sharing Andrew! Cheers, Igor
Re: question about spoe doc
Hi. Am 05.07.2019 um 15:28 schrieb Christopher Faulet: > Le 03/07/2019 à 11:03, Aleksandar Lazic a écrit : >> Hi. >> >> in the spoe doc in section **2.5. Example** are the following lines. >> >> ``` >> 620 spoe-message get-ip-reputation >> 621 args ip=src >> 622 event on-client-session if ! { src -f >> /etc/haproxy/whitelist.lst } >> ``` >> >> As far as I understood the doc in line `496 args [name=] ...` right >> could be the check also against `ip` not only `src`? >> >> git links: >> >> http://git.haproxy.org/?p=haproxy-1.8.git;a=blob;f=doc/SPOE.txt;h=9602df95dacc3aa5f6fa9154c0cf3f2a3f4ed092;hb=HEAD >> >> >> http://git.haproxy.org/?p=haproxy.git;a=blob;f=doc/SPOE.txt;h=19f00ad98d51f155494b47e680f14d6973dd91bb;hb=HEAD >> > > Sorry, I don't understand the question. "src" is a sample fetch. "ip" is just > a > label. It may be use by the agent to match arguments. It could be a way to > pass > arguments in any order and rely on their names instead of their positions. > > Hope it helps :) Yes, thank you. I thought that "ip" can be used for testing, but as it is only a label it's not possible to use it similar as "src". Best regads aleks
Re: question about spoe doc
Le 03/07/2019 à 11:03, Aleksandar Lazic a écrit : Hi. in the spoe doc in section **2.5. Example** are the following lines. ``` 620 spoe-message get-ip-reputation 621 args ip=src 622 event on-client-session if ! { src -f /etc/haproxy/whitelist.lst } ``` As far as I understood the doc in line `496 args [name=] ...` right could be the check also against `ip` not only `src`? git links: http://git.haproxy.org/?p=haproxy-1.8.git;a=blob;f=doc/SPOE.txt;h=9602df95dacc3aa5f6fa9154c0cf3f2a3f4ed092;hb=HEAD http://git.haproxy.org/?p=haproxy.git;a=blob;f=doc/SPOE.txt;h=19f00ad98d51f155494b47e680f14d6973dd91bb;hb=HEAD Sorry, I don't understand the question. "src" is a sample fetch. "ip" is just a label. It may be use by the agent to match arguments. It could be a way to pass arguments in any order and rely on their names instead of their positions. Hope it helps :) -- Christopher Faulet
Proof of concept SPOE based SSO solution
Hi All, I have put together a Go based proof of concept SPOE agent that also implements a SAML 2 Service Provider (SP) in order to do "SSO" in HAProxy. The code is located here: https://gitlab.com/andrewheberle/go-http-auth-sso The basic process is that SPOA is used to check if the user is logged in or not and then based on the set variables you can make decisions via "http-request" rules. This originally started out without the SPOE part and was using the Lua http-auth-request script (https://github.com/TimWolla/haproxy-auth-request), however with the release of the Go SPOE package (https://github.com/Aestek/haproxy-connect/tree/master/spoe) I rewrote it based on that. Our use case is to have the SP pointed to a IdP in Azure so we can do single-sign-on to Office 365 and we have "http-request" rules in place to set some custom headers that our application uses for authentication/authorisation. These are set based on the variables that come back from the SPOA, which come from the claims in the authentication process. Hopefully this is of some use to people. Any feedback and constructive criticism is welcome. -- Andrew Heberle
question about spoe doc
Hi. in the spoe doc in section **2.5. Example** are the following lines. ``` 620 spoe-message get-ip-reputation 621 args ip=src 622 event on-client-session if ! { src -f /etc/haproxy/whitelist.lst } ``` As far as I understood the doc in line `496 args [name=] ...` right could be the check also against `ip` not only `src`? git links: http://git.haproxy.org/?p=haproxy-1.8.git;a=blob;f=doc/SPOE.txt;h=9602df95dacc3aa5f6fa9154c0cf3f2a3f4ed092;hb=HEAD http://git.haproxy.org/?p=haproxy.git;a=blob;f=doc/SPOE.txt;h=19f00ad98d51f155494b47e680f14d6973dd91bb;hb=HEAD Regards Aleks
Re: [PATCH 5/9] BUG/MINOR: spoe: Fix memory leak if failing to allocate memory
Le 23/06/2019 à 22:10, Tim Duesterhus a écrit : Technically harmless, but it annoys clang analyzer. This bug was introduced in 336d3ef0e77192582c98b3c578927a529ceadd9b. This fix should be backported to HAProxy 1.9+. --- src/flt_spoe.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/flt_spoe.c b/src/flt_spoe.c index f20b2640b..4e48aa95c 100644 --- a/src/flt_spoe.c +++ b/src/flt_spoe.c @@ -3751,6 +3751,7 @@ cfg_parse_spoe_agent(const char *file, int linenum, char **args, int kwm) goto out; } if ((vph->name = strdup(args[cur_arg])) == NULL) { + free(vph); ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum); err_code |= ERR_ALERT | ERR_ABORT; goto out; Thanks, merged now. -- Christopher Faulet
[PATCH 5/9] BUG/MINOR: spoe: Fix memory leak if failing to allocate memory
Technically harmless, but it annoys clang analyzer. This bug was introduced in 336d3ef0e77192582c98b3c578927a529ceadd9b. This fix should be backported to HAProxy 1.9+. --- src/flt_spoe.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/flt_spoe.c b/src/flt_spoe.c index f20b2640b..4e48aa95c 100644 --- a/src/flt_spoe.c +++ b/src/flt_spoe.c @@ -3751,6 +3751,7 @@ cfg_parse_spoe_agent(const char *file, int linenum, char **args, int kwm) goto out; } if ((vph->name = strdup(args[cur_arg])) == NULL) { + free(vph); ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum); err_code |= ERR_ALERT | ERR_ABORT; goto out; -- 2.21.0
Re: BUG/MEDIUM: spoe: arg len encoded in previous frag frame but len changed
Le 26/04/2019 à 08:26, Kevin Zhu a écrit : Hi here I'm come again : ) Fragmented arg will do fetch at every encode time, each fetch may get different result if SMP_F_MAY_CHANGE, for example the fetch , but the length already encoded in first fragment of the frame, that will cause SPOA decode failed and waste resources. Good catch. The fix was merged in upstream and backported to 1.9 and 1.8. Thanks, -- Christopher Faulet
BUG/MEDIUM: spoe: arg len encoded in previous frag frame but len changed
Hi here I'm come again : ) Fragmented arg will do fetch at every encode time, each fetch may get different result if SMP_F_MAY_CHANGE, for example the fetch , but the length already encoded in first fragment of the frame, that will cause SPOA decode failed and waste resources. Best regards From 342258c94fbe8ed146e8490fb80a2a7c40cb9075 Mon Sep 17 00:00:00 2001 From: Kevin Zhu Date: Fri, 26 Apr 2019 14:00:01 +0800 Subject: [PATCH] BUG/MEDIUM: spoe: arg len encoded in previous frag frame but len changed Fragmented arg will do fetch at every encode time, each fetch may get different result if SMP_F_MAY_CHANGE, for example res.payload, but the length already encoded in first fragment of the frame, that will cause SPOA decode failed and waste resources. --- include/proto/spoe.h | 7 --- include/types/spoe.h | 1 + src/flt_spoe.c | 3 ++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/include/proto/spoe.h b/include/proto/spoe.h index e5b3b4b..86328ad 100644 --- a/include/proto/spoe.h +++ b/include/proto/spoe.h @@ -121,7 +121,7 @@ spoe_decode_buffer(char **buf, char *end, char **str, uint64_t *len) * many bytes has been encoded. If <*off> is zero at the end, it means that all * data has been encoded. */ static inline int -spoe_encode_data(struct sample *smp, unsigned int *off, char **buf, char *end) +spoe_encode_data(unsigned int *len, struct sample *smp, unsigned int *off, char **buf, char *end) { char *p = *buf; int ret; @@ -185,15 +185,16 @@ spoe_encode_data(struct sample *smp, unsigned int *off, char **buf, char *end) end); if (ret == -1) return -1; +*len = chk->data; } else { /* The sample has been fragmented, encode remaining data */ -ret = MIN(chk->data - *off, end - p); +ret = MIN(*len - *off, end - p); memcpy(p, chk->area + *off, ret); p += ret; } /* Now update <*off> */ - if (ret + *off != chk->data) + if (ret + *off != *len) *off += ret; else *off = 0; diff --git a/include/types/spoe.h b/include/types/spoe.h index a744cd7..0ab5d5a 100644 --- a/include/types/spoe.h +++ b/include/types/spoe.h @@ -323,6 +323,7 @@ struct spoe_context { struct spoe_message *curmsg; /* SPOE message from which to resume encoding */ struct spoe_arg *curarg; /* SPOE arg in from which to resume encoding */ unsigned int curoff; /* offset in from which to resume encoding */ + unsigned int len; /* length of need to be encode, for SMP_F_MAY_CHANGE data */ unsigned int flags; /* SPOE_FRM_FL_* */ } frag_ctx; /* Info about fragmented frames, valid on if SPOE_CTX_FL_FRAGMENTED is set */ diff --git a/src/flt_spoe.c b/src/flt_spoe.c index 63d40a6..b1a8788 100644 --- a/src/flt_spoe.c +++ b/src/flt_spoe.c @@ -2182,6 +2182,7 @@ spoe_encode_message(struct stream *s, struct spoe_context *ctx, list_for_each_entry(arg, &msg->args, list) { ctx->frag_ctx.curarg = arg; ctx->frag_ctx.curoff = UINT_MAX; + ctx->frag_ctx.curlen = 0; encode_argument: if (ctx->frag_ctx.curoff != UINT_MAX) @@ -2196,7 +2197,7 @@ spoe_encode_message(struct stream *s, struct spoe_context *ctx, /* Fetch the argument value */ smp = sample_process(s->be, s->sess, s, dir|SMP_OPT_FINAL, arg->expr, NULL); - ret = spoe_encode_data(smp, &ctx->frag_ctx.curoff, buf, end); + ret = spoe_encode_data(&ctx->frag_ctx.len, smp, &ctx->frag_ctx.curoff, buf, end); if (ret == -1 || ctx->frag_ctx.curoff) goto too_big; } -- 2.7.4
Re: [PATCH] BUG/MAJOR: spoe: spoe_context shouldn't queue again if fragment send
Le 20/04/2019 à 12:15, Kevin Zhu a écrit : Hi I think there forgot check if the spoe_context already has fragment msg send before spoe_queue_context, it will segment fault in spoe_release_appctx. This bug is already fixed, in the upstream (3e86cec05) and HAProxy 1.9 (c3468fe1d). However, it has not been backported yet in HAProxy 1.8. Thanks, -- Christopher Faulet
Re: [PATCH] BUG/MAJOR: spoe: Rollback frequency counter to sending_rate
Le 13/04/2019 à 09:53, Kevin Zhu a écrit : The processing is really difficult to be smaller than processing_per_sec, and most msg will create a new applet, but there are already have a lot idle applets waiting for work. and the result is that the most applets is not reused. This patch should be backported to 1.9. Hi Kevin, The frequency counter was added to be more accurate and avoid creating new applets to often. So, bugs are always possible of course. but first, I'd prefer to understand what you experienced before reverting this part. I assume this patch is an attempt to fix your FDs issue on HAProxy 1.9. -- Christopher Faulet
[PATCH] BUG/MAJOR: spoe: spoe_context shouldn't queue again if fragment send
Hi I think there forgot check if the spoe_context already has fragment msg send before spoe_queue_context, it will segment fault in spoe_release_appctx. Best regards. From 437775b6f4a611324348746e1e673cb9d024c1b0 Mon Sep 17 00:00:00 2001 From: Kevin Zhu Date: Sat, 20 Apr 2019 17:45:21 +0800 Subject: [PATCH] BUG/MAJOR: spoe: spoe_context shouldn't queue again if fragment send If spoe_context already has fragment msg send, queue it to sending_queue again the other appctx will sent the msg, it will segment fault in function spoe_release_appctx. This patch should be backported to 1.9 --- src/flt_spoe.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/flt_spoe.c b/src/flt_spoe.c index 0f72de8..3420540 100644 --- a/src/flt_spoe.c +++ b/src/flt_spoe.c @@ -2682,8 +2682,9 @@ spoe_process_messages(struct stream *s, struct spoe_context *ctx, goto end; if (!ret) goto skip; - if (spoe_queue_context(ctx) < 0) - goto end; + if (ctx->spoe_appctx == NULL) + if (spoe_queue_context(ctx) < 0) +goto end; ctx->state = SPOE_CTX_ST_SENDING_MSGS; } -- 2.7.4
[PATCH] BUG/MAJOR: spoe: Rollback frequency counter to sending_rate
The processing is really difficult to be smaller than processing_per_sec, and most msg will create a new applet, but there are already have a lot idle applets waiting for work. and the result is that the most applets is not reused. This patch should be backported to 1.9. Best regards. From cad58af8ee953b97ab5b9d9e7551823890e3da6c Mon Sep 17 00:00:00 2001 From: Kevin Zhu Date: Sat, 13 Apr 2019 15:28:54 +0800 Subject: [PATCH] BUG/MAJOR: spoe: Rollback frequency counter to sending_rate The processing is really difficult to be smaller than processing_per_sec, and most msg will create a new applet, but there are already have a lot idle applets waiting for work. and the result is that the most applets is not reused. This patch should be backported to 1.9. --- include/types/spoe.h | 3 +-- src/flt_spoe.c | 30 +++--- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/include/types/spoe.h b/include/types/spoe.h index a744cd7..7b6a9fb 100644 --- a/include/types/spoe.h +++ b/include/types/spoe.h @@ -265,8 +265,7 @@ struct spoe_agent { /* running info */ struct { unsigned intframe_size; /* current maximum frame size, only used to encode messages */ - unsigned intprocessing; - struct freq_ctr processing_per_sec; + unsigned int sending_rate; struct freq_ctr conn_per_sec; /* connections per second */ struct freq_ctr err_per_sec;/* connetion errors per second */ diff --git a/src/flt_spoe.c b/src/flt_spoe.c index b820710..514b466 100644 --- a/src/flt_spoe.c +++ b/src/flt_spoe.c @@ -1728,7 +1728,7 @@ spoe_handle_processing_appctx(struct appctx *appctx) } if (active_s || active_r) { - update_freq_ctr(&agent->rt[tid].processing_per_sec, active_s); + agent->rt[tid].sending_rate += active_s; SPOE_APPCTX(appctx)->task->expire = tick_add_ifset(now_ms, agent->timeout.idle); } @@ -2041,8 +2041,7 @@ spoe_queue_context(struct spoe_context *ctx) struct spoe_appctx *spoe_appctx; /* Check if we need to create a new SPOE applet or not. */ - if (!eb_is_empty(&agent->rt[tid].idle_applets) && - agent->rt[tid].processing < read_freq_ctr(&agent->rt[tid].processing_per_sec)) + if (!eb_is_empty(&agent->rt[tid].idle_applets) && agent->rt[tid].sending_rate) goto end; SPOE_PRINTF(stderr, "%d.%06d [SPOE/%-15s] %s: stream=%p" @@ -2096,18 +2095,21 @@ spoe_queue_context(struct spoe_context *ctx) return -1; } - /* Add the SPOE context in the sending queue */ + /* Add the SPOE context in the sending queue and update all running + * info */ LIST_ADDQ(&agent->rt[tid].sending_queue, &ctx->list); + if (agent->rt[tid].sending_rate) + agent->rt[tid].sending_rate--; _HA_ATOMIC_ADD(&agent->counters.nb_sending, 1); spoe_update_stat_time(&ctx->stats.tv_request, &ctx->stats.t_request); ctx->stats.tv_queue = now; SPOE_PRINTF(stderr, "%d.%06d [SPOE/%-15s] %s: stream=%p" " - Add stream in sending queue" - " - applets=%u - idles=%u - processing=%u\n", + " - applets=%u - idles=%u - sending_rate=%u\n", (int)now.tv_sec, (int)now.tv_usec, agent->id, __FUNCTION__, ctx->strm, agent->counters.applets, agent->counters.idles, - agent->rt[tid].processing); + agent->rt[tid].sending_rate); /* Finally try to wakeup an IDLE applet. */ if (!eb_is_empty(&agent->rt[tid].idle_applets)) { @@ -2549,14 +2551,13 @@ spoe_handle_processing_error(struct stream *s, struct spoe_agent *agent, } static inline int -spoe_start_processing(struct spoe_agent *agent, struct spoe_context *ctx, int dir) +spoe_start_processing(struct spoe_context *ctx, int dir) { /* If a process is already started for this SPOE context, retry * later. */ if (ctx->flags & SPOE_CTX_FL_PROCESS) return 0; - agent->rt[tid].processing++; ctx->stats.tv_start = now; ctx->stats.tv_request = now; ctx->stats.t_request = -1; @@ -2593,7 +2594,6 @@ spoe_stop_processing(struct spoe_agent *agent, struct spoe_context *ctx) } /* Reset the flag to allow next processing */ - agent->rt[tid].processing--; ctx->flags &= ~(SPOE_CTX_FL_PROCESS|SPOE_CTX_FL_FRAGMENTED); /* Reset processing timer */ @@ -2659,7 +2659,7 @@ spoe_process_messages(struct stream *s, struct spoe_context *ctx, s->task->expire = tick_first((tick_is_expired(s->task->expire, now_ms) ? 0 : s->task->expire), ctx->process_exp); } - ret = spoe_start_processing(agent, ctx, dir); + ret = spoe_start_processing(ctx, dir); if (!ret) goto out; @@ -2745,7 +2745,7 @@ spoe_process_group(struct stream *s, struct spoe_context *ctx, ret = spoe_process_messages(s, ctx, &group->messages, dir, SPOE_MSGS_BY_GROUP); if (ret && ctx->stats.t_process != -1) { SPOE_PRINT
[PATCH] MINOR: Fix a typo in a warning message in the spoe subsystem
Hi, This patch fixes a typo in a user-facing message of the spoe subsystem. Thanks, Joseph From 1a241dfc448fd7c6358809b340b89a93177f85ff Mon Sep 17 00:00:00 2001 From: Joseph Herlant Date: Thu, 15 Nov 2018 13:49:02 -0800 Subject: [PATCH] MINOR: Fix a typo in a warning message in the spoe subsystem Fix a typo in a user-facing message of the spoe subsystem. --- src/flt_spoe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/flt_spoe.c b/src/flt_spoe.c index 2dd26fda..457ecf8f 100644 --- a/src/flt_spoe.c +++ b/src/flt_spoe.c @@ -3974,7 +3974,7 @@ cfg_parse_spoe_message(const char *file, int linenum, char **args, int kwm) else if (!strcmp(args[1], spoe_event_str[SPOE_EV_ON_HTTP_RSP])) curmsg->event = SPOE_EV_ON_HTTP_RSP; else { - ha_alert("parsing [%s:%d] : unkown event '%s'.\n", + ha_alert("parsing [%s:%d] : unknown event '%s'.\n", file, linenum, args[1]); err_code |= ERR_ALERT | ERR_FATAL; goto out; -- 2.19.1
[PATCH] CLEANUP: Fix typos in the spoe subsystem
Hi, This patch fixes typos in the code comments of the spoe subsystem. Thanks, Joseph From 20610f5c7ee2eaca0de501cc0aab696a21671b75 Mon Sep 17 00:00:00 2001 From: Joseph Herlant Date: Thu, 15 Nov 2018 13:46:49 -0800 Subject: [PATCH] CLEANUP: Fix typos in the spoe subsystem Fix typos in the code comments of the spoe subsystem. --- include/proto/spoe.h | 4 ++-- src/flt_spoe.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/proto/spoe.h b/include/proto/spoe.h index b6c4ee2c..e5b3b4b2 100644 --- a/include/proto/spoe.h +++ b/include/proto/spoe.h @@ -61,7 +61,7 @@ spoe_encode_buffer(const char *str, size_t len, char **buf, char *end) /* Encode a buffer, possibly partially. It does the same thing than * 'spoe_encode_buffer', but if there is not enough space, it does not fail. * On success, it returns the number of copied bytes and <*buf> is moved after - * the encoded value. If an error occured, it returns -1. */ + * the encoded value. If an error occurred, it returns -1. */ static inline int spoe_encode_frag_buffer(const char *str, size_t len, char **buf, char *end) { @@ -113,7 +113,7 @@ spoe_decode_buffer(char **buf, char *end, char **str, uint64_t *len) /* Encode a typed data using value in . On success, it returns the number * of copied bytes and <*buf> is moved after the encoded value. If an error - * occured, it returns -1. + * occurred, it returns -1. * * If the value is too big to be encoded, depending on its type, then encoding * failed or the value is partially encoded. Only strings and binaries can be diff --git a/src/flt_spoe.c b/src/flt_spoe.c index cd0b88a9..2dd26fda 100644 --- a/src/flt_spoe.c +++ b/src/flt_spoe.c @@ -383,7 +383,7 @@ spoe_str_to_vsn(const char *str, size_t len) } /* Encode the HELLO frame sent by HAProxy to an agent. It returns the number of - * encoded bytes in the frame on success, 0 if an encoding error occured and -1 + * encoded bytes in the frame on success, 0 if an encoding error occurred and -1 * if a fatal error occurred. */ static int spoe_prepare_hahello_frame(struct appctx *appctx, char *frame, size_t size) @@ -2179,14 +2179,14 @@ spoe_encode_message(struct stream *s, struct spoe_context *ctx, if (ctx->frag_ctx.curoff != UINT_MAX) goto encode_arg_value; - /* Encode the arguement name as a string. It can by NULL */ + /* Encode the argument name as a string. It can by NULL */ if (spoe_encode_buffer(arg->name, arg->name_len, buf, end) == -1) goto too_big; ctx->frag_ctx.curoff = 0; encode_arg_value: - /* Fetch the arguement value */ + /* Fetch the argument value */ smp = sample_process(s->be, s->sess, s, dir|SMP_OPT_FINAL, arg->expr, NULL); ret = spoe_encode_data(smp, &ctx->frag_ctx.curoff, buf, end); if (ret == -1 || ctx->frag_ctx.curoff) -- 2.19.1
Re: SPOE and modsecurity contrib Failed to decode HELLO frame
Hi. Am 17.08.2018 um 11:36 schrieb Павел.: > > I'm solved it. > > The installed version and the source version should be the same :) That's it ;-) Best regards Aleks > Пятница, 17 августа 2018, 14:08 +06:00 от Aleksandar Lazic > : > > Hi. > > Am 16.08.2018 um 11:00 schrieb Павел.: > > > > HI all! I'm compile modsec as described in the instructions > > contib/modsec/README, but have the next errors: > > Which version of haproxy and this contib do you use? > There was some changes recently. > > http://www.haproxy.org/download/1.8/src/CHANGELOG > 2018/06/22 : 1.8.10 > > Regards > Aleks > > > # /usr/local/bin/modsecurity -n 4 -d -f > /etc/haproxy/waf/modsecurity.conf > > 1534409877.286475 [00] ModSecurity for nginx (STABLE)/2.9.2 > > (http://www.modsecurity.org/) configured. > > 1534409877.286555 [00] ModSecurity: APR compiled version="1.4.8"; loaded > > version="1.4.8" > > 1534409877.286577 [00] ModSecurity: PCRE compiled version="8.32 "; > loaded > > version="8.32 2012-11-30" > > 1534409877.286593 [00] ModSecurity: YAJL compiled version="2.0.4" > > 1534409877.286610 [00] ModSecurity: LIBXML compiled version="2.9.1" > > 1534409877.286723 [00] ModSecurity: StatusEngine call: > > "2.9.2,nginx,1.4.8/1.4.8,8.32/8.32 > > 2012-11-30,(null),2.9.1,4c3b0f175f079eaa4dd15b6eaef7a8207e809bb8" > > 1534409877.494433 [00] ModSecurity: StatusEngine call successfully > sent. For > > more information visit: http://status.modsecurity.org/ > > 1534409877.495333 [00] Worker 01 initialized > > 1534409877.495453 [01] Worker ready to process client messages > > 1534409877.495499 [00] Worker 02 initialized > > 1534409877.495514 [02] Worker ready to process client messages > > 1534409877.495767 [00] Worker 03 initialized > > 1534409877.495817 [03] Worker ready to process client messages > > 1534409877.495925 [00] Worker 04 initialized > > 1534409877.495958 [00] Server is ready [fragmentation=false - > pipelining=false - > > async=false - debug=true - max-frame-size=16384] > > 1534409877.495961 [04] Worker ready to process client messages > > 1534409881.192419 [00] <1> New Client connection accepted and assigned > to > worker 01 > > 1534409881.192511 [01] <1> read_frame_cb > > 1534409881.192596 [01] <1> New Frame of 129 bytes received > > 1534409881.192606 [01] <1> Decode HAProxy HELLO frame > > 1534409881.192613 [01] Failed to decode HELLO frame > > 1534409881.192617 [01] <1> Encode Agent DISCONNECT frame > > 1534409881.192626 [01] <1> Disconnect status code : 10 > > 1534409881.192630 [01] <1> Disconnect message : fragmentation not > supported > > 1534409881.192648 [01] <1> write_frame_cb > > 1534409881.192689 [01] <1> Frame of 58 bytes send > > 1534409881.192695 [01] <1> Release client > > 1534409882.497134 [01] 0 clients connected > > 1534409882.497174 [02] 0 clients connected > > 1534409882.497197 [04] 0 clients connected > > 1534409882.497185 [03] 0 clients connected > > ^C1534409885.480782 [00] Stopping the server > > > > Has anyone encountered a similar one? > > > > -- > > Павел.
Re: SPOE and modsecurity contrib Failed to decode HELLO frame
Hi. Am 16.08.2018 um 11:00 schrieb Павел.: > > HI all! I'm compile modsec as described in the instructions > contib/modsec/README, but have the next errors: Which version of haproxy and this contib do you use? There was some changes recently. http://www.haproxy.org/download/1.8/src/CHANGELOG 2018/06/22 : 1.8.10 Regards Aleks > # /usr/local/bin/modsecurity -n 4 -d -f /etc/haproxy/waf/modsecurity.conf > 1534409877.286475 [00] ModSecurity for nginx (STABLE)/2.9.2 > (http://www.modsecurity.org/) configured. > 1534409877.286555 [00] ModSecurity: APR compiled version="1.4.8"; loaded > version="1.4.8" > 1534409877.286577 [00] ModSecurity: PCRE compiled version="8.32 "; loaded > version="8.32 2012-11-30" > 1534409877.286593 [00] ModSecurity: YAJL compiled version="2.0.4" > 1534409877.286610 [00] ModSecurity: LIBXML compiled version="2.9.1" > 1534409877.286723 [00] ModSecurity: StatusEngine call: > "2.9.2,nginx,1.4.8/1.4.8,8.32/8.32 > 2012-11-30,(null),2.9.1,4c3b0f175f079eaa4dd15b6eaef7a8207e809bb8" > 1534409877.494433 [00] ModSecurity: StatusEngine call successfully sent. For > more information visit: http://status.modsecurity.org/ > 1534409877.495333 [00] Worker 01 initialized > 1534409877.495453 [01] Worker ready to process client messages > 1534409877.495499 [00] Worker 02 initialized > 1534409877.495514 [02] Worker ready to process client messages > 1534409877.495767 [00] Worker 03 initialized > 1534409877.495817 [03] Worker ready to process client messages > 1534409877.495925 [00] Worker 04 initialized > 1534409877.495958 [00] Server is ready [fragmentation=false - > pipelining=false - > async=false - debug=true - max-frame-size=16384] > 1534409877.495961 [04] Worker ready to process client messages > 1534409881.192419 [00] <1> New Client connection accepted and assigned to > worker 01 > 1534409881.192511 [01] <1> read_frame_cb > 1534409881.192596 [01] <1> New Frame of 129 bytes received > 1534409881.192606 [01] <1> Decode HAProxy HELLO frame > 1534409881.192613 [01] Failed to decode HELLO frame > 1534409881.192617 [01] <1> Encode Agent DISCONNECT frame > 1534409881.192626 [01] <1> Disconnect status code : 10 > 1534409881.192630 [01] <1> Disconnect message : fragmentation not supported > 1534409881.192648 [01] <1> write_frame_cb > 1534409881.192689 [01] <1> Frame of 58 bytes send > 1534409881.192695 [01] <1> Release client > 1534409882.497134 [01] 0 clients connected > 1534409882.497174 [02] 0 clients connected > 1534409882.497197 [04] 0 clients connected > 1534409882.497185 [03] 0 clients connected > ^C1534409885.480782 [00] Stopping the server > > Has anyone encountered a similar one? > > -- > Павел.
SPOE and modsecurity contrib Failed to decode HELLO frame
HI all! I'm compile modsec as described in the instructions contib/modsec/README, but have the next errors: # /usr/local/bin/modsecurity -n 4 -d -f /etc/haproxy/waf/modsecurity.conf 1534409877.286475 [00] ModSecurity for nginx (STABLE)/2.9.2 (http://www.modsecurity.org/) configured. 1534409877.286555 [00] ModSecurity: APR compiled version="1.4.8"; loaded version="1.4.8" 1534409877.286577 [00] ModSecurity: PCRE compiled version="8.32 "; loaded version="8.32 2012-11-30" 1534409877.286593 [00] ModSecurity: YAJL compiled version="2.0.4" 1534409877.286610 [00] ModSecurity: LIBXML compiled version="2.9.1" 1534409877.286723 [00] ModSecurity: StatusEngine call: "2.9.2,nginx,1.4.8/1.4.8,8.32/8.32 2012-11-30,(null),2.9.1,4c3b0f175f079eaa4dd15b6eaef7a8207e809bb8" 1534409877.494433 [00] ModSecurity: StatusEngine call successfully sent. For more information visit: http://status.modsecurity.org/ 1534409877.495333 [00] Worker 01 initialized 1534409877.495453 [01] Worker ready to process client messages 1534409877.495499 [00] Worker 02 initialized 1534409877.495514 [02] Worker ready to process client messages 1534409877.495767 [00] Worker 03 initialized 1534409877.495817 [03] Worker ready to process client messages 1534409877.495925 [00] Worker 04 initialized 1534409877.495958 [00] Server is ready [fragmentation=false - pipelining=false - async=false - debug=true - max-frame-size=16384] 1534409877.495961 [04] Worker ready to process client messages 1534409881.192419 [00] <1> New Client connection accepted and assigned to worker 01 1534409881.192511 [01] <1> read_frame_cb 1534409881.192596 [01] <1> New Frame of 129 bytes received 1534409881.192606 [01] <1> Decode HAProxy HELLO frame 1534409881.192613 [01] Failed to decode HELLO frame 1534409881.192617 [01] <1> Encode Agent DISCONNECT frame 1534409881.192626 [01] <1> Disconnect status code : 10 1534409881.192630 [01] <1> Disconnect message : fragmentation not supported 1534409881.192648 [01] <1> write_frame_cb 1534409881.192689 [01] <1> Frame of 58 bytes send 1534409881.192695 [01] <1> Release client 1534409882.497134 [01] 0 clients connected 1534409882.497174 [02] 0 clients connected 1534409882.497197 [04] 0 clients connected 1534409882.497185 [03] 0 clients connected ^C1534409885.480782 [00] Stopping the server Has anyone encountered a similar one? -- Павел.
Re: [PATCH] MAJOR: spoe: upgrade the SPOP version to 2.0 and remove the support for 1.0
Hi Christopher, On Mon, Jun 04, 2018 at 02:52:31PM +0200, Christopher Faulet wrote: > Here is a patch to change the SPOP version. It follows the commit c4dcaff3 > ("BUG/MEDIUM: spoe: Flags are not encoded in network order") in order to > make sure no incompatible agent will be used with HAProxy. To do so, the > SPOP 1.0 is no more supported. Now merged, thank you. While I hate to perform such breaking changes, here we're already facing a broken situation so I agree that it's better to benefit from the moment where the only existing SPOAs are those located in the contrib/ directory and fix the issue once for all, to ensure nobody accidently starts to develop an outdated version that will break once heavily deployed. Thanks, Willy
[PATCH] MAJOR: spoe: upgrade the SPOP version to 2.0 and remove the support for 1.0
Hi, Here is a patch to change the SPOP version. It follows the commit c4dcaff3 ("BUG/MEDIUM: spoe: Flags are not encoded in network order") in order to make sure no incompatible agent will be used with HAProxy. To do so, the SPOP 1.0 is no more supported. Thanks, -- Christopher Faulet >From 0c68fe1a07f81d5c0c69c959cdceb447369620e7 Mon Sep 17 00:00:00 2001 From: Christopher Faulet Date: Thu, 31 May 2018 14:56:42 +0200 Subject: [PATCH] MAJOR: spoe: upgrade the SPOP version to 2.0 and remove the support for 1.0 The commit c4dcaff3 ("BUG/MEDIUM: spoe: Flags are not encoded in network order") introduced an incompatibility with older agents. So the major version of the SPOP is increased to make the situation unambiguous. And because before the fix, the protocol is buggy, the support of the version 1.0 is removed to be sure to not continue to support buggy agents. the agents in the contrib folder (spoa_example, modsecurity and mod_defender) are also updated to announce the SPOP version 2.0. So, to be clear, from the patch, connections to agents announcing the SPOP version 1.0 will be rejected. This patch must be backported in 1.8. --- contrib/mod_defender/spoa.c | 2 +- contrib/modsecurity/spoa.c | 2 +- contrib/spoa_example/spoa.c | 2 +- src/flt_spoe.c | 5 +++-- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/contrib/mod_defender/spoa.c b/contrib/mod_defender/spoa.c index 1191260a..34b24f49 100644 --- a/contrib/mod_defender/spoa.c +++ b/contrib/mod_defender/spoa.c @@ -43,7 +43,7 @@ #define CONNECTION_BACKLOG 10 #define NUM_WORKERS10 #define MAX_FRAME_SIZE 16384 -#define SPOP_VERSION "1.0" +#define SPOP_VERSION "2.0" #define SLEN(str) (sizeof(str)-1) diff --git a/contrib/modsecurity/spoa.c b/contrib/modsecurity/spoa.c index cbabcb29..18ef1d24 100644 --- a/contrib/modsecurity/spoa.c +++ b/contrib/modsecurity/spoa.c @@ -48,7 +48,7 @@ #define CONNECTION_BACKLOG 10 #define NUM_WORKERS10 #define MAX_FRAME_SIZE 16384 -#define SPOP_VERSION "1.0" +#define SPOP_VERSION "2.0" #define SLEN(str) (sizeof(str)-1) diff --git a/contrib/spoa_example/spoa.c b/contrib/spoa_example/spoa.c index 71a36f07..d7486a41 100644 --- a/contrib/spoa_example/spoa.c +++ b/contrib/spoa_example/spoa.c @@ -43,7 +43,7 @@ #define CONNECTION_BACKLOG 10 #define NUM_WORKERS10 #define MAX_FRAME_SIZE 16384 -#define SPOP_VERSION "1.0" +#define SPOP_VERSION "2.0" #define SLEN(str) (sizeof(str)-1) diff --git a/src/flt_spoe.c b/src/flt_spoe.c index a16932bf..ae751ce2 100644 --- a/src/flt_spoe.c +++ b/src/flt_spoe.c @@ -314,12 +314,13 @@ struct spoe_version { /* All supported versions */ static struct spoe_version supported_versions[] = { - {"1.0", 1000, 1000}, + /* 1.0 is now unsupported because of a bug about frame's flags*/ + {"2.0", 2000, 2000}, {NULL, 0, 0} }; /* Comma-separated list of supported versions */ -#define SUPPORTED_VERSIONS_VAL "1.0" +#define SUPPORTED_VERSIONS_VAL "2.0" /* Convert a string to a SPOE version value. The string must follow the format * "MAJOR.MINOR". It will be concerted into the integer (1000 * MAJOR + MINOR). -- 2.17.0
Re: Use acl on spoe events
> Em 27 de mai de 2018, à(s) 14:51, Joao Morais > escreveu: > >> Em 27 de mai de 2018, à(s) 12:02, Daniel Corbett >> escreveu: >> >> Hello Joao, >> >> On 05/26/2018 05:54 PM, Joao Morais wrote: >>> >>> There is no difference if I use acl like the example above, or use the `if >>> {...}` syntax or remove the acl at all, my modsecurity agent always receive >>> a new connection despite of the host I’m using. >>> >>> Is there a way to use a spoe filter only if some l7 conditions match? >> >> This appears to have been fixed in 1.9-dev with this commit: >> >> https://git.haproxy.org/?p=haproxy.git;a=commitdiff;h=333694d7715952a9610a3e6f00807eaf5edd209a;hp=336d3ef0e77192582c98b3c578927a529ceadd9b > > Hi Daniel, I can confirm this fixes my 1.8.9 deployment, thanks! > > Is there any plan to backport to 1.8? .. ~jm
Re: Use acl on spoe events
> Em 27 de mai de 2018, à(s) 12:02, Daniel Corbett > escreveu: > > Hello Joao, > > On 05/26/2018 05:54 PM, Joao Morais wrote: >> >> There is no difference if I use acl like the example above, or use the `if >> {...}` syntax or remove the acl at all, my modsecurity agent always receive >> a new connection despite of the host I’m using. >> >> Is there a way to use a spoe filter only if some l7 conditions match? > > This appears to have been fixed in 1.9-dev with this commit: > > https://git.haproxy.org/?p=haproxy.git;a=commitdiff;h=333694d7715952a9610a3e6f00807eaf5edd209a;hp=336d3ef0e77192582c98b3c578927a529ceadd9b Hi Daniel, I can confirm this fixes my 1.8.9 deployment, thanks! Is there any plan to backport to 1.8? > > Thanks, > -- Daniel ~jm
Re: Use acl on spoe events
Hello Joao, On 05/26/2018 05:54 PM, Joao Morais wrote: There is no difference if I use acl like the example above, or use the `if {...}` syntax or remove the acl at all, my modsecurity agent always receive a new connection despite of the host I’m using. Is there a way to use a spoe filter only if some l7 conditions match? This appears to have been fixed in 1.9-dev with this commit: https://git.haproxy.org/?p=haproxy.git;a=commitdiff;h=333694d7715952a9610a3e6f00807eaf5edd209a;hp=336d3ef0e77192582c98b3c578927a529ceadd9b Thanks, -- Daniel
Use acl on spoe events
Hi list, I’m trying to filter spoe events using acl, no success atm. This is the relevant part of my configuration: === /etc/haproxy/haproxy.cfg === frontend bar ... filter spoe engine modsecurity config /etc/haproxy/spoe-modsecurity.conf http-request deny if { var(txn.modsec.code) -m int gt 0 } ... backend spoe-modsecurity mode tcp server modsec-spoa1 127.0.0.1:12345 === /etc/haproxy/spoe-modsecurity.conf [modsecurity] spoe-agent modsecurity-agent messages check-request option var-prefix modsec timeout hello 100ms timeout idle30s timeout processing 1s use-backend spoe-modsecurity spoe-message check-request aclhost_my.domain req.hdr(host) my.domain args unique-id method path query req.ver req.hdrs_bin req.body_size req.body event on-frontend-http-request if host_my.domain There is no difference if I use acl like the example above, or use the `if {...}` syntax or remove the acl at all, my modsecurity agent always receive a new connection despite of the host I’m using. Is there a way to use a spoe filter only if some l7 conditions match? ~jm
Re: SPOE and modsecurity contrib
On Sun, May 20, 2018 at 10:59:02AM -0400, Daniel Corbett wrote: > While I haven't been able to get 'tcp-request content reject' to work with > this configuration -- I am able to get 'http-request deny' to work: > > http-request deny if { var(txn.modsec.code) -m int gt 0 } This is expected. The "tcp-request content" rules are evaluated before HTTP rules, hence before the filters as well. Thus here the rule says that it will reject the request based on a variable that holds its initial value and never had a chance to be modified yet. Unfortunately there is little we can do to detect this better, except improving the doc and providing better config examples. Willy
Re: SPOE and modsecurity contrib
> Em 20 de mai de 2018, à(s) 11:59, Daniel Corbett > escreveu: > > Hello Joao, > > While I haven't been able to get 'tcp-request content reject' to work with > this configuration -- I am able to get 'http-request deny' to work: > > http-request deny if { var(txn.modsec.code) -m int gt 0 } > > Regarding txn.modsec.code -- I have been able to reproduce the > "txn.modsec.code=-101" and "set variable code=4294967195" when crs-setup.conf > / crs.setup.conf.example is missing the following SecDefaultAction lines: > > SecDefaultAction "phase:1,log,auditlog,deny,status:403" > SecDefaultAction "phase:2,log,auditlog,deny,status:403" > > When those are in place -- I receive the following in logs: > > The txn.modsec.code is: 403 > > Please let me know if that solves it for you. > Hi Daniel, yes, now everything makes a lot of sense - and it’s working. Including the fact that `4294967195(uint32) == -101(int32)` and that I need to read a lot more about how ModSecurity works. Thanks! > > Thanks, > —- Daniel > ~jm
Re: SPOE and modsecurity contrib
Hello Joao, While I haven't been able to get 'tcp-request content reject' to work with this configuration -- I am able to get 'http-request deny' to work: http-request deny if { var(txn.modsec.code) -m int gt 0 } Regarding txn.modsec.code -- I have been able to reproduce the "txn.modsec.code=-101" and "set variable code=4294967195" when crs-setup.conf / crs.setup.conf.example is missing the following SecDefaultAction lines: SecDefaultAction "phase:1,log,auditlog,deny,status:403" SecDefaultAction "phase:2,log,auditlog,deny,status:403" When those are in place -- I receive the following in logs: The txn.modsec.code is: 403 Please let me know if that solves it for you. Thanks, -- Daniel
SPOE and modsecurity contrib
Hi list, I'm playing with SPOE and modsecurity contrib from HAProxy 1.8.9. I've a couple of doubts and issues that I'll describe just below my config and some loggings: = haproxy.conf listen my-front log 127.0.0.1:514 format rfc5424 local0 timeout client 5s timeout connect 5s timeout server 5s mode http bind :8080 log-format "The txn.modsec.code is: %[var(txn.modsec.code)]" filter spoe engine modsecurity config /tmp/haproxy/spoe-modsecurity.conf tcp-request content reject if { var(txn.modsec.code) -m int gt 0 } server local 192.168.95.102:8000 backend spoe-modsecurity mode tcp timeout connect 5s timeout server 3m server iprep1 127.0.0.1:12345 - = spoe-modsecurity.conf [modsecurity] spoe-agent modsecurity-agent messagescheck-request option var-prefix modsec timeout hello 100ms timeout idle30s timeout processing 1s use-backend spoe-modsecurity spoe-message check-request args unique-id method path query req.ver req.hdrs_bin req.body_size req.body event on-frontend-http-request - modsecurity SPOA is logging whenever I make a request to HAProxy so apparently it's working as expected: =log 1 -- curl -I localhost:8080?ref=abc 1526747591.637257 [01] Process SPOE Message 'check-request' 1526747591.638333 [01] Encode Agent ACK frame 1526747591.638867 [01] STREAM-ID=0 - FRAME-ID=1 1526747591.638887 [01] Add action : set variable code=4294967195 - =log 2 -- curl -I 127.0.0.1:8080?ref=abc 1526741757.670146 [01] Process SPOE Message 'check-request' 1526741757.671956 [00] [client 127.0.0.1] ModSecurity: Warning. Pattern match "^[\\d.:]+$" at REQUEST_HEADERS:Host. [file "/owasp-modsecurity-crs-3.0.2/rules/REQUEST-920-PROTOCOL-ENFORCEMENT.conf"] [line "810"] [id "920350"] [rev "2"] [msg "Host header is a numeric IP address"] [data "127.0.0.1:8080"] [severity "WARNING"] [ver "OWASP_CRS/3.0.0"] [maturity "9"] [accuracy "9"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-protocol"] [tag "OWASP_CRS/PROTOCOL_VIOLATION/IP_HOST"] [tag "WASCTC/WASC-21"] [tag "OWASP_TOP_10/A7"] [tag "PCI/6.5.10"] [hostname "8ae61a5f0c2e"] [uri "http://127.0.0.1:8080/";] [unique_id ""] 1526741757.672306 [01] Encode Agent ACK frame 1526741757.672333 [01] STREAM-ID=12 - FRAME-ID=1 1526741757.672351 [01] Add action : set variable code=4294967195 - =log 3 -- curl -I 127.0.0.1:8080?ref=/../etc/passwd 1526741728.786700 [00] [client 127.0.0.1] ModSecurity: Warning. Matched phrase "etc/passwd" at ARGS:ref. [file "/owasp-modsecurity-crs-3.0.2/rules/REQUEST-932-APPLICATION-ATTACK-RCE.conf"] [line "448"] [id "932160"] [rev "1"] [msg "Remote Command Execution: Unix Shell Code Found"] [data "Matched Data: etc/passwd found within ARGS:ref: /etc/passwd"] [severity "CRITICAL"] [ver "OWASP_CRS/3.0.0"] [maturity "1"] [accuracy "8"] [tag "application-multi"] [tag "language-shell"] [tag "platform-unix"] [tag "attack-rce"] [tag "OWASP_CRS/WEB_ATTACK/COMMAND_INJECTION"] [tag "WASCTC/WASC-31"] [tag "OWASP_TOP_10/A1"] [tag "PCI/6.5.2"] [hostname "8ae61a5f0c2e"] [uri "http://127.0.0.1:8080/";] [unique_id ""] ... 1526741728.787814 [01] Add action : set variable code=4294967195 - Running modsecurity with: -d -n 1 -f /tmp/haproxy/modsec.conf My environment is a `haproxy:alpine` container with all the stuff needed to compile both modsecurity and it's SPOA contrib. The doc used was `haproxy-1.8.9/contrib/modsecurity/README`. Now a couple of doubts: * If I `curl -v 127.0.0.1:12345` I can see a connection being opened on modsecurity and `curl` waits for something it could understand. If I ctrl+C `curl`, modsecurity starts an endless loop and use almost 100% of one CPU. I'm aware modsecurity SPOA speaks SPOP instead of HTTP, but perhaps something could be improved since this could also happen eg on a network failure. * The `set variable code=` on logs has always the same value `4294967195` despite what modsecurity found. * A `log-format "%[var(txn.modsec.code)]"` logs always the same value `-101` despite what modsecurity found. * Perhaps a specific HAProxy doubt here: `tcp-request content reject` never rejects a request even changing `gt` to `lt` or `eq`. Changing the acl to `!{...}` the connection is always rejected despite of the operator. ~jm
Re: SPOE patchs
On Fri, May 18, 2018 at 02:58:44PM +0200, Christopher Faulet wrote: > And because this is Friday and the sun shines, 2 more patches to do some > cleanup in the SPOE. Because it's Friday and the sun shines, they were merged. thanks, Willy
Re: SPOE patchs
Le 18/05/2018 à 14:53, Christopher Faulet a écrit : Le 18/05/2018 à 12:38, Thierry FOURNIER a écrit : Hi, In attachment two patches for SPOE. The first fix an error message, and the second fix a mistake in the protocol. Thanks Thierry for these patches. Here are fixes for the SPOAs modsecurity and mod_defender. And because this is Friday and the sun shines, 2 more patches to do some cleanup in the SPOE. Thanks -- Christopher Faulet >From 78bb0889c45e5ffecfd693787823f32b9a5e90cf Mon Sep 17 00:00:00 2001 From: Christopher Faulet Date: Fri, 6 Apr 2018 11:34:12 +0200 Subject: [PATCH 1/2] CLEANUP: spoe: Remove unused variables the agent structure applets_act and applets_idle were used for debugging purpose. Now, these values are part of the agent's counters. --- include/types/spoe.h | 4 src/flt_spoe.c | 12 ++-- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/include/types/spoe.h b/include/types/spoe.h index c01a03ef..2f13d375 100644 --- a/include/types/spoe.h +++ b/include/types/spoe.h @@ -265,10 +265,6 @@ struct spoe_agent { /* running info */ struct { unsigned intframe_size; /* current maximum frame size, only used to encode messages */ -#if defined(DEBUG_SPOE) || defined(DEBUG_FULL) - unsigned intapplets_act;/* # of applets alive at a time */ - unsigned intapplets_idle; /* # of applets in the state SPOE_APPCTX_ST_IDLE */ -#endif unsigned intprocessing; struct freq_ctr processing_per_sec; diff --git a/src/flt_spoe.c b/src/flt_spoe.c index 4e27c63b..f96a94f3 100644 --- a/src/flt_spoe.c +++ b/src/flt_spoe.c @@ -1239,7 +1239,6 @@ spoe_release_appctx(struct appctx *appctx) __FUNCTION__, appctx); /* Remove applet from the list of running applets */ - SPOE_DEBUG_STMT(agent->rt[tid].applets_act--); HA_ATOMIC_SUB(&agent->counters.applets, 1); HA_SPIN_LOCK(SPOE_APPLET_LOCK, &agent->rt[tid].lock); if (!LIST_ISEMPTY(&spoe_appctx->list)) { @@ -1252,7 +1251,6 @@ spoe_release_appctx(struct appctx *appctx) if (appctx->st0 != SPOE_APPCTX_ST_END) { if (appctx->st0 == SPOE_APPCTX_ST_IDLE) { eb32_delete(&spoe_appctx->node); - SPOE_DEBUG_STMT(agent->rt[tid].applets_idle--); HA_ATOMIC_SUB(&agent->counters.idles, 1); } @@ -1437,7 +1435,6 @@ spoe_handle_connecting_appctx(struct appctx *appctx) default: /* HELLO handshake is finished, set the idle timeout and * add the applet in the list of running applets. */ - SPOE_DEBUG_STMT(agent->rt[tid].applets_idle++); HA_ATOMIC_ADD(&agent->counters.idles, 1); appctx->st0 = SPOE_APPCTX_ST_IDLE; SPOE_APPCTX(appctx)->node.key = 0; @@ -1725,7 +1722,6 @@ spoe_handle_processing_appctx(struct appctx *appctx) } if (appctx->st0 == SPOE_APPCTX_ST_PROCESSING && SPOE_APPCTX(appctx)->cur_fpa < agent->max_fpa) { - SPOE_DEBUG_STMT(agent->rt[tid].applets_idle++); HA_ATOMIC_ADD(&agent->counters.idles, 1); appctx->st0 = SPOE_APPCTX_ST_IDLE; eb32_insert(&agent->rt[tid].idle_applets, &SPOE_APPCTX(appctx)->node); @@ -1889,7 +1885,6 @@ spoe_handle_appctx(struct appctx *appctx) goto switchstate; case SPOE_APPCTX_ST_IDLE: - SPOE_DEBUG_STMT(agent->rt[tid].applets_idle--); HA_ATOMIC_SUB(&agent->counters.idles, 1); eb32_delete(&SPOE_APPCTX(appctx)->node); if (stopping && @@ -2007,7 +2002,6 @@ spoe_create_appctx(struct spoe_config *conf) HA_SPIN_LOCK(SPOE_APPLET_LOCK, &conf->agent->rt[tid].lock); LIST_ADDQ(&conf->agent->rt[tid].applets, &SPOE_APPCTX(appctx)->list); HA_SPIN_UNLOCK(SPOE_APPLET_LOCK, &conf->agent->rt[tid].lock); - SPOE_DEBUG_STMT(conf->agent->rt[tid].applets_act++); HA_ATOMIC_ADD(&conf->agent->counters.applets, 1); task_wakeup(SPOE_APPCTX(appctx)->task, TASK_WOKEN_INIT); @@ -2099,9 +2093,9 @@ spoe_queue_context(struct spoe_context *ctx) SPOE_PRINTF(stderr, "%d.%06d [SPOE/%-15s] %s: stream=%p" " - Add stream in sending queue" - " - applets_act=%u - applets_idle=%u - processing=%u\n", + " - applets=%u - idles=%u - processing=%u\n", (int)now.tv_sec, (int)now.tv_usec, agent->id, __FUNCTION__, - ctx->strm, agent->rt[tid].applets_act, agent->rt[tid].applets_idle, + ctx->strm, agent->counters.applets, agent->counters.idles, agent->rt[tid].processing); /* Finally try to wakeup an IDLE applet. */ @@ -3358,8 +3352,6 @@ cfg_parse_spoe_agent(const char *file, int linenum, char **args, int kwm) } for (i = 0; i < global.nbthread; ++i) { curagent->rt[i].frame_size = curagent->max_frame_size; - SPOE_DEBUG_STMT(curagent->rt[i].applets_act = 0); - SPOE_DEBUG_STMT(curagent->rt[i].applets_idle = 0); curagent->rt[i].processing = 0; LIST_INIT(&curagent->rt[i].a
Re: SPOE patchs
Le 18/05/2018 à 12:38, Thierry FOURNIER a écrit : Hi, In attachment two patches for SPOE. The first fix an error message, and the second fix a mistake in the protocol. Thanks Thierry for these patches. Here are fixes for the SPOAs modsecurity and mod_defender. -- Christopher Faulet >From 444e432df47b77a635296d85fb6673f60b92bef7 Mon Sep 17 00:00:00 2001 From: Christopher Faulet Date: Fri, 18 May 2018 14:38:56 +0200 Subject: [PATCH 1/2] BUG/MEDIUM: contrib/mod_defender: Use network order to encode/decode flags A recent fix on the SPOE revealed a mismatch between the SPOE specification and the mod_defender implementation on the way flags are encoded or decoded. They must be exchanged using the network bytes order and not the host one. Be careful though, this patch breaks the compatiblity with HAProxy SPOE before commit c4dcaff3 ("BUG/MEDIUM: spoe: Flags are not encoded in network order"). --- contrib/mod_defender/spoa.c | 7 +++ 1 file changed, 7 insertions(+) diff --git a/contrib/mod_defender/spoa.c b/contrib/mod_defender/spoa.c index c4e15bb4..1191260a 100644 --- a/contrib/mod_defender/spoa.c +++ b/contrib/mod_defender/spoa.c @@ -460,6 +460,7 @@ handle_hahello(struct spoe_frame *frame) /* Retrieve flags */ memcpy((char *)&(frame->flags), p, 4); + frame->flags = ntohl(frame->flags); p += 4; /* Fragmentation is not supported for HELLO frame */ @@ -567,6 +568,7 @@ handle_hadiscon(struct spoe_frame *frame) /* Retrieve flags */ memcpy((char *)&(frame->flags), p, 4); + frame->flags = ntohl(frame->flags); p += 4; /* Fragmentation is not supported for DISCONNECT frame */ @@ -648,6 +650,7 @@ handle_hanotify(struct spoe_frame *frame) /* Retrieve flags */ memcpy((char *)&(frame->flags), p, 4); + frame->flags = ntohl(frame->flags); p += 4; /* Fragmentation is not supported */ @@ -710,6 +713,7 @@ handle_hafrag(struct spoe_frame *frame) /* Retrieve flags */ memcpy((char *)&(frame->flags), p, 4); + frame->flags = ntohl(frame->flags); p+= 4; /* Read the stream-id and frame-id */ @@ -772,6 +776,7 @@ prepare_agenthello(struct spoe_frame *frame) *p++ = SPOE_FRM_T_AGENT_HELLO; /* Set flags */ + flags = htonl(flags); memcpy(p, (char *)&flags, 4); p += 4; @@ -853,6 +858,7 @@ prepare_agentdicon(struct spoe_frame *frame) *p++ = SPOE_FRM_T_AGENT_DISCON; /* Set flags */ + flags = htonl(flags); memcpy(p, (char *)&flags, 4); p += 4; @@ -900,6 +906,7 @@ prepare_agentack(struct spoe_frame *frame) *p++ = SPOE_FRM_T_AGENT_ACK; /* Set flags */ + flags = htonl(flags); memcpy(p, (char *)&flags, 4); p += 4; -- 2.14.3 >From d424c222e690cf93075ba2f94911cb557218b521 Mon Sep 17 00:00:00 2001 From: Christopher Faulet Date: Fri, 18 May 2018 14:46:32 +0200 Subject: [PATCH 2/2] BUG/MEDIUM: contrib/modsecurity: Use network order to encode/decode flags A recent fix on the SPOE revealed a mismatch between the SPOE specification and the modsecurity implementation on the way flags are encoded or decoded. They must be exchanged using the network bytes order and not the host one. Be careful though, this patch breaks the compatiblity with HAProxy SPOE before commit c4dcaff3 ("BUG/MEDIUM: spoe: Flags are not encoded in network order"). --- contrib/modsecurity/spoa.c | 7 +++ 1 file changed, 7 insertions(+) diff --git a/contrib/modsecurity/spoa.c b/contrib/modsecurity/spoa.c index 506ff824..ab3e8b2b 100644 --- a/contrib/modsecurity/spoa.c +++ b/contrib/modsecurity/spoa.c @@ -465,6 +465,7 @@ handle_hahello(struct spoe_frame *frame) /* Retrieve flags */ memcpy((char *)&(frame->flags), p, 4); + frame->flags = ntohl(frame->flags); p += 4; /* Fragmentation is not supported for HELLO frame */ @@ -572,6 +573,7 @@ handle_hadiscon(struct spoe_frame *frame) /* Retrieve flags */ memcpy((char *)&(frame->flags), p, 4); + frame->flags = ntohl(frame->flags); p += 4; /* Fragmentation is not supported for DISCONNECT frame */ @@ -653,6 +655,7 @@ handle_hanotify(struct spoe_frame *frame) /* Retrieve flags */ memcpy((char *)&(frame->flags), p, 4); + frame->flags = ntohl(frame->flags); p += 4; /* Fragmentation is not supported */ @@ -715,6 +718,7 @@ handle_hafrag(struct spoe_frame *frame) /* Retrieve flags */ memcpy((char *)&(frame->flags), p, 4); + frame->flags = ntohl(frame->flags); p+= 4; /* Read the stream-id and frame-id */ @@ -777,6 +781,7 @@ prepare_agenthello(struct spoe_frame *frame) *p++ = SPOE_FRM_T_AGENT_HELLO; /* Set flags */ + flags = htonl(flags); memcpy(p, (char *)&flags, 4); p += 4; @@ -858,6 +863,7 @@ prepare_agentdicon(struct spoe_frame *frame) *p++ = SPOE_FRM_T_AGENT_DISCON; /* Set flags */ + flags = htonl(flags); memcpy(p, (char *)&flags, 4); p += 4; @@ -905,6 +911,7 @@ prepare_agentack(struct spoe_frame *frame) *p++ = SPOE_FRM_T_AGENT_ACK; /* Set flags */ + flags = htonl(flags); memcpy(p, (char *)&flags, 4); p += 4; -- 2.14.3
Re: SPOE patchs
On Fri, May 18, 2018 at 12:38:07PM +0200, Thierry FOURNIER wrote: > Hi, > > In attachment two patches for SPOE. > The first fix an error message, and the second fix a mistake in the protocol. Thank you, now applied, Willy
SPOE patchs
Hi, In attachment two patches for SPOE. The first fix an error message, and the second fix a mistake in the protocol. BR, Thierry >From c0274215ed91e90e127bda790b785b698fb149e7 Mon Sep 17 00:00:00 2001 From: Thierry FOURNIER Date: Thu, 10 May 2018 16:41:26 +0200 Subject: [PATCH 1/3] BUG/MINOR: spoe: Mistake in error message about SPOE configuration The announced accepted chars are "[a-zA-Z_-.]", but the real accepted alphabet is "[a-zA-Z0-9_.]". Numbers are supported and "-" is not supported. This patch should be backported to 1.8 and 1.7 --- src/flt_spoe.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/flt_spoe.c b/src/flt_spoe.c index 6ac48fc7d..cc6c55e29 100644 --- a/src/flt_spoe.c +++ b/src/flt_spoe.c @@ -3535,7 +3535,7 @@ cfg_parse_spoe_agent(const char *file, int linenum, char **args, int kwm) tmp = args[2]; while (*tmp) { if (!isalnum(*tmp) && *tmp != '_' && *tmp != '.') { - ha_alert("parsing [%s:%d]: '%s %s' only supports [a-zA-Z_-.] chars.\n", + ha_alert("parsing [%s:%d]: '%s %s' only supports [a-zA-Z0-9_.] chars.\n", file, linenum, args[0], args[1]); err_code |= ERR_ALERT | ERR_FATAL; goto out; @@ -3569,7 +3569,7 @@ cfg_parse_spoe_agent(const char *file, int linenum, char **args, int kwm) tmp = args[2]; while (*tmp) { if (!isalnum(*tmp) && *tmp != '_' && *tmp != '.') { - ha_alert("parsing [%s:%d]: '%s %s' only supports [a-zA-Z_-.] chars.\n", + ha_alert("parsing [%s:%d]: '%s %s' only supports [a-zA-Z0-9_.] chars.\n", file, linenum, args[0], args[1]); err_code |= ERR_ALERT | ERR_FATAL; goto out; @@ -3593,7 +3593,7 @@ cfg_parse_spoe_agent(const char *file, int linenum, char **args, int kwm) tmp = args[2]; while (*tmp) { if (!isalnum(*tmp) && *tmp != '_' && *tmp != '.') { - ha_alert("parsing [%s:%d]: '%s %s' only supports [a-zA-Z_-.] chars.\n", + ha_alert("parsing [%s:%d]: '%s %s' only supports [a-zA-Z0-9_.] chars.\n", file, linenum, args[0], args[1]); err_code |= ERR_ALERT | ERR_FATAL; goto out; @@ -3617,7 +3617,7 @@ cfg_parse_spoe_agent(const char *file, int linenum, char **args, int kwm) tmp = args[2]; while (*tmp) { if (!isalnum(*tmp) && *tmp != '_' && *tmp != '.') { - ha_alert("parsing [%s:%d]: '%s %s' only supports [a-zA-Z_-.] chars.\n", + ha_alert("parsing [%s:%d]: '%s %s' only supports [a-zA-Z0-9_.] chars.\n", file, linenum, args[0], args[1]); err_code |= ERR_ALERT | ERR_FATAL; goto out; -- 2.16.3 >From 67d525fec42cd9739a093d0e53415b5209d1ee4e Mon Sep 17 00:00:00 2001 From: Thierry FOURNIER Date: Fri, 18 May 2018 12:25:39 +0200 Subject: [PATCH 3/3] BUG/MEDIUM: spoe: Flags are not encoded in network order The flags are direct copy of the "unsigned int" in the network stream, so the stream contains a 32 bits field encoded with the host endian. - This is not reliable for stream betwen different architecture host - For x86, the bits doesn't correspond to the documentation. This patch add some precision in the documentation and put the bitfield in the stream usig network butes order. Warning: this patch can break compatibility with existing agents. This patch should be backported in all version supporing SPOE Original network capture: 12:28:16.181343 IP 127.0.0.1.46782 > 127.0.0.1.12345: Flags [P.], seq 134:168, ack 59, win 342, options [nop,nop,TS val 2855241281 ecr 2855241281], length 34 0x: 4500 0056 6b94 4000 4006 d10b 7f00 0001 E..Vk.@.@... 0x0010: 7f00 0001 b6be 3039 a3d1 ee54 7d61 d6f7 ..09...T}a.. 0x0020: 8018 0156 fe4a 0101 080a aa2f 8641 ...V.J.../.A 0x0030: aa2f 8641 001e 0301 010f ./.A ^^ 0x0040: 6368 6563 6b2d 636c 6965 6e74 2d69 7001 check-client-ip. 0x0050: 0006 7f00 0001 .. Fixed network capture: 12:24:26.948165 IP 127.0.0.1.46706 > 127.0.0.1.12345: Flags [P.], seq 4066280627:4066280661, ack 3148908096, win 342, options [nop,nop,TS val 2855183972 ecr 2855177690], length 34 0x: 4500 0056 0538 4000 4006 3768 7f00 0001 E..V.8@.@.7h 0x0010: 7f00 0001 b672 3039 f25e 84b3 bbb0 8640 .r09.^.@ 0x0020: 8018 0156 fe4a 0101 080a aa2e a664 ...V.J.d 0x0030: aa2e 8dda 001e 0300 0114 010f ^^ 0x0040: 6368 6563 6b2d 636c 6965 6e74 2d69 7001 check-client
[PATCH] Badd SPOE message
Hi List and Christopher, A little patch in attachment. I tagged it as BUG because the bahavior doesn't correspond to the error message and I read the code to understand the problem. So, it is very minor, and maybe I would be classed as DOC ? br, Thierry >From b8051783f6133b31cb3d0474ad542ab859d27853 Mon Sep 17 00:00:00 2001 From: Thierry FOURNIER Date: Thu, 10 May 2018 16:41:26 +0200 Subject: [PATCH] BUG/MINOR: spoe: Mistake in error message about SPOE configuration The announced accepted chars are "[a-zA-Z_-.]", but the real accepted alphabet is "[a-zA-Z0-9_.]". Numbers are supported and "-" is not supported. This patch should be backported to 1.8 and 1.7 --- src/flt_spoe.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/flt_spoe.c b/src/flt_spoe.c index 6ac48fc7d..cc6c55e29 100644 --- a/src/flt_spoe.c +++ b/src/flt_spoe.c @@ -3535,7 +3535,7 @@ cfg_parse_spoe_agent(const char *file, int linenum, char **args, int kwm) tmp = args[2]; while (*tmp) { if (!isalnum(*tmp) && *tmp != '_' && *tmp != '.') { - ha_alert("parsing [%s:%d]: '%s %s' only supports [a-zA-Z_-.] chars.\n", + ha_alert("parsing [%s:%d]: '%s %s' only supports [a-zA-Z0-9_.] chars.\n", file, linenum, args[0], args[1]); err_code |= ERR_ALERT | ERR_FATAL; goto out; @@ -3569,7 +3569,7 @@ cfg_parse_spoe_agent(const char *file, int linenum, char **args, int kwm) tmp = args[2]; while (*tmp) { if (!isalnum(*tmp) && *tmp != '_' && *tmp != '.') { - ha_alert("parsing [%s:%d]: '%s %s' only supports [a-zA-Z_-.] chars.\n", + ha_alert("parsing [%s:%d]: '%s %s' only supports [a-zA-Z0-9_.] chars.\n", file, linenum, args[0], args[1]); err_code |= ERR_ALERT | ERR_FATAL; goto out; @@ -3593,7 +3593,7 @@ cfg_parse_spoe_agent(const char *file, int linenum, char **args, int kwm) tmp = args[2]; while (*tmp) { if (!isalnum(*tmp) && *tmp != '_' && *tmp != '.') { - ha_alert("parsing [%s:%d]: '%s %s' only supports [a-zA-Z_-.] chars.\n", + ha_alert("parsing [%s:%d]: '%s %s' only supports [a-zA-Z0-9_.] chars.\n", file, linenum, args[0], args[1]); err_code |= ERR_ALERT | ERR_FATAL; goto out; @@ -3617,7 +3617,7 @@ cfg_parse_spoe_agent(const char *file, int linenum, char **args, int kwm) tmp = args[2]; while (*tmp) { if (!isalnum(*tmp) && *tmp != '_' && *tmp != '.') { - ha_alert("parsing [%s:%d]: '%s %s' only supports [a-zA-Z_-.] chars.\n", + ha_alert("parsing [%s:%d]: '%s %s' only supports [a-zA-Z0-9_.] chars.\n", file, linenum, args[0], args[1]); err_code |= ERR_ALERT | ERR_FATAL; goto out; -- 2.16.3
[PATCH 2/4] CLEANUP: spoe: Remove unused label retry
This removes the retry labels from spoe_send_frame and spoe_recv_frame which are unused since d5216d474d69856a282e4443f180af2093a80d6c, which is unreleased, but was backported to haproxy 1.8 as f13f3a4babdb1ce23a7e982c765704bca728111a. --- src/flt_spoe.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/flt_spoe.c b/src/flt_spoe.c index 8694b07a7..a53795861 100644 --- a/src/flt_spoe.c +++ b/src/flt_spoe.c @@ -1125,7 +1125,6 @@ spoe_send_frame(struct appctx *appctx, char *buf, size_t framesz) ret = ci_putblk(si_ic(si), buf, framesz+4); if (ret <= 0) { if ((ret == -3 && si_ic(si)->buf == &buf_empty) || ret == -1) { - retry: si_applet_cant_put(si); return 1; /* retry */ } @@ -1156,7 +1155,6 @@ spoe_recv_frame(struct appctx *appctx, char *buf, size_t framesz) } if (ret <= 0) { if (ret == 0) { - retry: return 1; /* retry */ } SPOE_APPCTX(appctx)->status_code = SPOE_FRM_ERR_IO; -- 2.16.1
Re: Opinion about blog post of SPOE
Hi Christopher. Am 17-02-2017 10:41, schrieb Christopher Faulet: Le 16/02/2017 à 12:41, Aleksandar Lazic a écrit : Do you think that there will be also big changes in the protocol? No not really. The protocol should remain mostly unchanged. In fact, except new "capabilities", there are no big changes. And these capabilities will only influence how frames will be exchanged between HAProxy and SPOAs. With the current version, when a frame is sent to an agent, the connection is "locked", waiting the acknowledgment from the agent and cannot be used to handle another frame. So connections are underused and you need to have more opened connections than necessary. With the next version, it will be possible to multiplex frames on connections. It will also be possible to send fragmented frames to agent when the payload size exceeds the frame size. However, it will not possible to receive such kind of frames in HAProxy for now. Thank you for the detailed answer. Best regards Aleks
Re: Opinion about blog post of SPOE
Le 16/02/2017 à 12:41, Aleksandar Lazic a écrit : Do you think that there will be also big changes in the protocol? No not really. The protocol should remain mostly unchanged. In fact, except new "capabilities", there are no big changes. And these capabilities will only influence how frames will be exchanged between HAProxy and SPOAs. With the current version, when a frame is sent to an agent, the connection is "locked", waiting the acknowledgment from the agent and cannot be used to handle another frame. So connections are underused and you need to have more opened connections than necessary. With the next version, it will be possible to multiplex frames on connections. It will also be possible to send fragmented frames to agent when the payload size exceeds the frame size. However, it will not possible to receive such kind of frames in HAProxy for now. -- Christopher Faulet
Re: Opinion about blog post of SPOE
Hi Christopher. Am 16-02-2017 10:18, schrieb Christopher Faulet: Le 15/02/2017 à 02:43, Aleksandar Lazic a écrit : Hi. Due to the fact that I like this SPOE I have started to write about it ;-) https://me2digital.online/2017/02/15/haproxy-1-7-feature-spoe/ Is the concept displayed correct in the picture? Are the data (tcp, http-header, http-body) quoted when HAProxy send it to the SPOEA? I'm interested to create a spoea for https://modsecurity.org/ do anyone else see a need for this? Hi Aleks, Nice to see someone interested by the SPOE and by implementing a service using it. Your picture is correct. Thank you for the confirmation. The protocol used to communicate with agents (the SPOP) is a binary protocol. So data are not quoted. Ah okay. About the modsecurity, it is definitely a good candidate for a SPOA. Note that for now, it is not possible to send all the HTTP request (Header + Body). With the option "http-buffer-request", you could handle simple/small requests. But it will not work for chunked or too big payloads. Thanks for info. For now, I'm working on SPOE improvements. The current version is an "experimental" version with many flaws and limited features. But the payload filtering is definitely on the roadmap (without deadline however). This requires changes in the HTTP parser, so it is a bit tricky. And new sample fetches need to be added. So there is still a lot of work before you can implement a fully functional WAF. But I'm on it and all help/suggestion/remarks are welcome :) Well due to the implementation of http/2 I'm sure the will be also some changes in the HTTP parser ;-). Do you think that there will be also big changes in the protocol? Cheers Aleks
Re: Opinion about blog post of SPOE
Le 15/02/2017 à 02:43, Aleksandar Lazic a écrit : Hi. Due to the fact that I like this SPOE I have started to write about it ;-) https://me2digital.online/2017/02/15/haproxy-1-7-feature-spoe/ Is the concept displayed correct in the picture? Are the data (tcp, http-header, http-body) quoted when HAProxy send it to the SPOEA? I'm interested to create a spoea for https://modsecurity.org/ do anyone else see a need for this? Hi Aleks, Nice to see someone interested by the SPOE and by implementing a service using it. Your picture is correct. The protocol used to communicate with agents (the SPOP) is a binary protocol. So data are not quoted. About the modsecurity, it is definitely a good candidate for a SPOA. Note that for now, it is not possible to send all the HTTP request (Header + Body). With the option "http-buffer-request", you could handle simple/small requests. But it will not work for chunked or too big payloads. For now, I'm working on SPOE improvements. The current version is an "experimental" version with many flaws and limited features. But the payload filtering is definitely on the roadmap (without deadline however). This requires changes in the HTTP parser, so it is a bit tricky. And new sample fetches need to be added. So there is still a lot of work before you can implement a fully functional WAF. But I'm on it and all help/suggestion/remarks are welcome :) -- Christopher Faulet
Opinion about blog post of SPOE
Hi. Due to the fact that I like this SPOE I have started to write about it ;-) https://me2digital.online/2017/02/15/haproxy-1-7-feature-spoe/ Is the concept displayed correct in the picture? Are the data (tcp, http-header, http-body) quoted when HAProxy send it to the SPOEA? I'm interested to create a spoea for https://modsecurity.org/ do anyone else see a need for this? Best regards Aleks
Re: [PATCH] BUG: spoe: Fix parsing of SPOE actions in ACK frames
On Thu, Nov 24, 2016 at 09:00:51PM +0100, Christopher Faulet wrote: > New patch attached. thanks. Applied now, thanks! Willy
Re: [PATCH] BUG: spoe: Fix parsing of SPOE actions in ACK frames
Le 24/11/2016 à 19:50, Willy Tarreau a écrit : Hi Christopher, On Thu, Nov 24, 2016 at 03:06:13PM +0100, Christopher Faulet wrote: >From 7ed3c2942d57ea2ddfc8973cce9cc1c94bca01da Mon Sep 17 00:00:00 2001 From: Christopher Faulet Date: Thu, 24 Nov 2016 14:53:22 +0100 Subject: [PATCH] BUG: spoe: Fix parsing of SPOE actions in ACK frames X-Bogosity: Ham, tests=bogofilter, spamicity=0.00, version=1.2.4 For "SET-VAR" actions, data was not correctly parsed. 'idx' variable was not correctly updated when the 3rd argument was parsed. Are you sure your patch is correct ? I think it's bogus : diff --git a/src/flt_spoe.c b/src/flt_spoe.c index 0b722b6..8227140 100644 --- a/src/flt_spoe.c +++ b/src/flt_spoe.c @@ -2017,7 +2017,7 @@ process_spoe_actions(struct stream *s, struct spoe_context *ctx, goto skip; memset(&smp, 0, sizeof(smp)); smp_set_owner(&smp, s->be, s->sess, s, dir|SMP_OPT_FINAL); - if (decode_spoe_data(p+idx, p+size, &smp) == -1) + if ((idx += decode_spoe_data(p+idx, p+size, &smp)) == -1) goto skip; The only case it will work is when idx = 0 before decoding, which doesn't really look like the only case you're interested in. I guess you wanted to do this instead : - if (decode_spoe_data(p+idx, p+size, &smp) == -1) + ret = decode_spoe_data(p+idx, p+size, &smp); + if (ret == -1) goto skip; + idx += ret; Am I wrong ? That's the reason why I hate assignments in "if" conditions, half of the time they are bogus, the other half they make the reader scratch his head wondering if it's bogus or intended :-) Ah of course you're right ! too tired... New patch attached. thanks. -- Christopher >From 1b46491bf93c76602122ea5814c42fdcfbf2d816 Mon Sep 17 00:00:00 2001 From: Christopher Faulet Date: Thu, 24 Nov 2016 14:53:22 +0100 Subject: [PATCH] BUG: spoe: Fix parsing of SPOE actions in ACK frames X-Bogosity: Ham, tests=bogofilter, spamicity=0.00, version=1.2.4 For "SET-VAR" actions, data was not correctly parsed. 'idx' variable was not correctly updated when the 3rd argument was parsed. --- src/flt_spoe.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/flt_spoe.c b/src/flt_spoe.c index 0b722b6..776848e 100644 --- a/src/flt_spoe.c +++ b/src/flt_spoe.c @@ -2017,8 +2017,10 @@ process_spoe_actions(struct stream *s, struct spoe_context *ctx, goto skip; memset(&smp, 0, sizeof(smp)); smp_set_owner(&smp, s->be, s->sess, s, dir|SMP_OPT_FINAL); -if (decode_spoe_data(p+idx, p+size, &smp) == -1) + +if ((i = decode_spoe_data(p+idx, p+size, &smp)) == -1) goto skip; +idx += i; SPOE_PRINTF(stderr, "%d.%06d [SPOE/%-15s] %s: stream=%p" " - set-var '%s.%s.%.*s'\n", -- 2.7.4
Re: [PATCH] BUG: spoe: Fix parsing of SPOE actions in ACK frames
Hi Christopher, On Thu, Nov 24, 2016 at 03:06:13PM +0100, Christopher Faulet wrote: > >From 7ed3c2942d57ea2ddfc8973cce9cc1c94bca01da Mon Sep 17 00:00:00 2001 > From: Christopher Faulet > Date: Thu, 24 Nov 2016 14:53:22 +0100 > Subject: [PATCH] BUG: spoe: Fix parsing of SPOE actions in ACK frames > X-Bogosity: Ham, tests=bogofilter, spamicity=0.00, version=1.2.4 > > For "SET-VAR" actions, data was not correctly parsed. 'idx' variable was not > correctly updated when the 3rd argument was parsed. Are you sure your patch is correct ? I think it's bogus : > diff --git a/src/flt_spoe.c b/src/flt_spoe.c > index 0b722b6..8227140 100644 > --- a/src/flt_spoe.c > +++ b/src/flt_spoe.c > @@ -2017,7 +2017,7 @@ process_spoe_actions(struct stream *s, struct > spoe_context *ctx, > goto skip; > memset(&smp, 0, sizeof(smp)); > smp_set_owner(&smp, s->be, s->sess, s, > dir|SMP_OPT_FINAL); > - if (decode_spoe_data(p+idx, p+size, &smp) == -1) > + if ((idx += decode_spoe_data(p+idx, p+size, > &smp)) == -1) > goto skip; The only case it will work is when idx = 0 before decoding, which doesn't really look like the only case you're interested in. I guess you wanted to do this instead : - if (decode_spoe_data(p+idx, p+size, &smp) == -1) + ret = decode_spoe_data(p+idx, p+size, &smp); + if (ret == -1) goto skip; + idx += ret; Am I wrong ? That's the reason why I hate assignments in "if" conditions, half of the time they are bogus, the other half they make the reader scratch his head wondering if it's bogus or intended :-) Willy
[PATCH] BUG: spoe: Fix parsing of SPOE actions in ACK frames
Hi, Here is a small bug fix on SPOE filter. -- Christopher >From 7ed3c2942d57ea2ddfc8973cce9cc1c94bca01da Mon Sep 17 00:00:00 2001 From: Christopher Faulet Date: Thu, 24 Nov 2016 14:53:22 +0100 Subject: [PATCH] BUG: spoe: Fix parsing of SPOE actions in ACK frames X-Bogosity: Ham, tests=bogofilter, spamicity=0.00, version=1.2.4 For "SET-VAR" actions, data was not correctly parsed. 'idx' variable was not correctly updated when the 3rd argument was parsed. --- src/flt_spoe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/flt_spoe.c b/src/flt_spoe.c index 0b722b6..8227140 100644 --- a/src/flt_spoe.c +++ b/src/flt_spoe.c @@ -2017,7 +2017,7 @@ process_spoe_actions(struct stream *s, struct spoe_context *ctx, goto skip; memset(&smp, 0, sizeof(smp)); smp_set_owner(&smp, s->be, s->sess, s, dir|SMP_OPT_FINAL); -if (decode_spoe_data(p+idx, p+size, &smp) == -1) +if ((idx += decode_spoe_data(p+idx, p+size, &smp)) == -1) goto skip; SPOE_PRINTF(stderr, "%d.%06d [SPOE/%-15s] %s: stream=%p" -- 2.7.4