Re: Setting listen address of HAProxy as HTTP-Header?

2009-07-28 Thread Maik Broemme
Hi,

Willy Tarreau  wrote:
> On Tue, Jul 28, 2009 at 11:30:09AM +0200, Maik Broemme wrote:
> > Hi,
> > 
> > Willy Tarreau  wrote:
> > > Hi Maik,
> > > 
> > > On Tue, Jul 28, 2009 at 12:31:23AM +0200, Maik Broemme wrote:
> > > > Hi,
> > > > 
> > > > is it possible to set the listen address of HAProxy as an HTTP-Request
> > > > Header? For example if you have HAProxys running on multiple servers and
> > > > balance the requests to multiple backend servers, which have a NAT 
> > > > router
> > > > between HAProxys and backend servers, it would be very nice to have a
> > > > header like 'X-Forward-Via' or 'X-Forward-From'. Did someone know if
> > > > this is possible?
> > > 
> > > you have two possibilities :
> > > 
> > >   - you know each one of your haproxy servers, so you configure them
> > > to simply add a Via header (using reqadd with their name). Eg:
> > > 
> > >  reqadd Via:\ haproxy1
> > > 
> > 
> > Well this isn't enough, because I need the ip address.
> > 
> > >   - you just want to forward the address the client connected to,
> > > which should match the listen address when there's only one
> > > listen address. Then you can enable "option originalto" which
> > > you contributed, and get this IP address in the "x-original-to"
> > > header.
> > > 
> > 
> > Well this would be enough, if I won't use HAProxy as transparent proxy.
> > On the system running HAProxy, I will redirect the connections to
> > HAProxy with iptables and HAProxy itself will forward them to a SQUID
> > farm. Between HAProxys and the SQUIDs are some NAT-Router. The SQUID
> > itself uses some proprietary extension which relies on the IP from which
> > the HTTP connection comes.
> > 
> >   - 'X-Forward-For' gives me the client address. (Client)
> >   - 'X-Original-To' gives me the original destination address. (Webserver)
> > 
> > If HAProxy is transparent between both, what gives me that address? :)
> > 
> > PS: I have contributed the 'X-Original-To' patch, but in that setup it
> > won't help me. It wouldn't be much work, so I can also contribute a
> > patch for it.
> 
> Well, I'm a bit confused then. Which IP address would you want to see in
> your header then ?
> 

The ip address which HAProxy will use for its own outgoing connection as
source address. In a transparent HAProxy setup this isn't the original
destination address (X-Original-To)

> Willy
> 

--Maik



Re: Setting listen address of HAProxy as HTTP-Header?

2009-07-28 Thread Maik Broemme
Hi,

Willy Tarreau  wrote:
> Hi Maik,
> 
> On Tue, Jul 28, 2009 at 12:31:23AM +0200, Maik Broemme wrote:
> > Hi,
> > 
> > is it possible to set the listen address of HAProxy as an HTTP-Request
> > Header? For example if you have HAProxys running on multiple servers and
> > balance the requests to multiple backend servers, which have a NAT router
> > between HAProxys and backend servers, it would be very nice to have a
> > header like 'X-Forward-Via' or 'X-Forward-From'. Did someone know if
> > this is possible?
> 
> you have two possibilities :
> 
>   - you know each one of your haproxy servers, so you configure them
> to simply add a Via header (using reqadd with their name). Eg:
> 
>  reqadd Via:\ haproxy1
> 

Well this isn't enough, because I need the ip address.

>   - you just want to forward the address the client connected to,
> which should match the listen address when there's only one
> listen address. Then you can enable "option originalto" which
> you contributed, and get this IP address in the "x-original-to"
> header.
> 

Well this would be enough, if I won't use HAProxy as transparent proxy.
On the system running HAProxy, I will redirect the connections to
HAProxy with iptables and HAProxy itself will forward them to a SQUID
farm. Between HAProxys and the SQUIDs are some NAT-Router. The SQUID
itself uses some proprietary extension which relies on the IP from which
the HTTP connection comes.

  - 'X-Forward-For' gives me the client address. (Client)
  - 'X-Original-To' gives me the original destination address. (Webserver)

If HAProxy is transparent between both, what gives me that address? :)

PS: I have contributed the 'X-Original-To' patch, but in that setup it
won't help me. It wouldn't be much work, so I can also contribute a
patch for it.

> Hoping this helps,
> Willy
> 

--Maik



Setting listen address of HAProxy as HTTP-Header?

2009-07-27 Thread Maik Broemme
Hi,

is it possible to set the listen address of HAProxy as an HTTP-Request
Header? For example if you have HAProxys running on multiple servers and
balance the requests to multiple backend servers, which have a NAT router
between HAProxys and backend servers, it would be very nice to have a
header like 'X-Forward-Via' or 'X-Forward-From'. Did someone know if
this is possible?

--Maik



Re: [PATCH] Fix 'tcp-request content [accept|reject] if condition' parser for missing 'if'.

2009-05-13 Thread Maik Broemme
Hi,

Willy Tarreau  wrote:
> On Wed, May 13, 2009 at 11:50:07AM +0200, Maik Broemme wrote:
> 
> I don't get you. You mean that simply omitting the "if" between "reject" and
> "cond" is not returned as an error, that's it ? If so, yes I agree that it
> would be better that it yells here. Since I copy-pasted the parser from other
> rules (use_backend, block, redirect, ...) the same problem should be present
> everywhere.
> 

Yes exactly, if the "if" word is missing the result is non-working.
Nothing more and nothing less.

> OK, so it's clearly a matter of not reporting that an unknown word is
> present where only {empty, "if", "unless") are accepted. I'll look into
> that.
> 

Many thanks.

> BTW, you can simplify your rules by using two things :
> 
> either you make only one ACL :
>   acl localnet dst 192.168.0.0/16 172.16.0.0/12 10.0.0.0/8
>   tcp-request content reject if localnet
> 
> or you can keep your 3 ACLs but group them into one rule :
> 
>   acl localnet-1 dst 192.168.0.0/16
>   acl localnet-2 dst 172.16.0.0/12
>   acl localnet-3 dst 10.0.0.0/8
>   tcp-request content reject if localnet-1 or localnet-2 or localnet-3
> 

Many thanks too, didn't know that it is working so too.

> Regards,
> Willy
> 

--Maik



Re: TCP traffic multiplexing as balance algorithm?

2009-05-13 Thread Maik Broemme
Hi,

Benoit  wrote:
> Maik Broemme a écrit :
> > Hi,
> >   
> >
> > Multiplex means traffic duplication. If you have multiple server
> > configuration options in one listen group, the incoming traffic is
> > sent to all servers.
> >   
> 
> Hum, i'm sorry but no, multiplexing is not duplication. In fact it's
> more like the opposite,
> it's the process of combining multiple data stream into one (long descr.
> here: http://en.wikipedia.org/wiki/Multiplexing)

Sorry multiplexing was the wrong word for it, I rellay talk about
duplication.

> >
> > tcpdump is not perfect in that case, because it has to run the hole time
> > you want to duplicate the traffic and sent it to server1 and server2.
> >   
> So let's say you pacth haproxy and he duplicate traffic to two servers
> and is able to forget
> data from one (the dev/test one) and keep the other (the prod one).
> 
> How will haproxy been able to react to the different responses/timing
> from each servers ?
> Let's say you duplicate MX traffic, with the test server being used to
> validate a new configuration
> to keep away spammers (simple example).
> Let's say both server are able to answer at the exact same time or
> aren't too frisky about having the answer
> before the question, when the prod server will accept the mail message
> and start listinening from it's main
> part the other could have rejected it, however he still will receive the
> main part, while not expecting it,
> which depending of the implementation could lead to troubles, like if
> the originating mail server try to
>  send another mail using the same connection.
> 

I am thinking about the timing issues, my guess is to add a option for
the duplicate balance algorithm, lets say 'async' or 'sync'. In 'async'
state haproxy will send traffic to dev/test and only take care of
response from dev, regardless if test respond or not. Later answer from
test will be dropped by haproxy. In 'sync' state the haproxy will wait
until dev/test has answered and send the answer from dev to client.

For short:

  - async will drop everything from test, regardless of answer
time and send everything to test regardless if it is expected or
not.

  - sync will drop everything from test, but wait until it has answered.

There will be - for sure - not much scenarios were you need such
feature.

> 
> This is a very simple example and most MX implementation could react
> correctly but that's not the case of
> everything
> 
> 

--Maik



Re: [PATCH] Fix 'tcp-request content [accept|reject] if condition' parser for missing 'if'.

2009-05-13 Thread Maik Broemme
Hi,

Willy Tarreau  wrote:
> Hi Maik,
> 
> On Tue, May 12, 2009 at 01:36:46AM +0200, Maik Broemme wrote:
> > Hi,
> > 
> > attached is a patch which fixes a configuration mistake regarding the
> > 'tcp-request' option. If you have the following in your configuration
> > file:
> > 
> > acl localnet dst 10.0.0.0/8
> > tcp-request content reject if localnet
> > 
> > This will work fine, but if you change the 'tcp-request' line and remove
> > the 'if' haproxy-1.3.17 will segfault, I think the following changelog
> > entry in 1.3.18 addresses this problem:
> > 
> > [BUG] fix parser crash on unconditional tcp content rules
> 
> yes precisely.
> 
> > But now in 1.3.18 the default behaviour is a bit weird. If you remove
> > the 'if' statement the haproxy will reject every connection, regardless
> > of matching to 'localnet' or not and the configuration seems to be valid,
> > but which is definetly not what expected.
> 
> I can't reproduce the issue here. For me, what happens is the right thing :
> 
>   - the following config rejects everything :
> 
> tcp-request content reject
> 
>   - the following config rejects everything which was not accepted :
> 
> tcp-request content accept if 
> tcp-request content reject
> 
>   - the following config rejects only everything which matches the condition :
> 
> tcp-request content reject if 
> 
> The second case above was precisely what led me to discover the segfault
> bug, which was introduced in 1.3.17 with the refinement of the config
> warnings. But the behaviour has not changed since 1.3.16.
> 

You have missed the non-working case. :-)

  - the following config seems to be ok, but didn't work as expected.

tcp-request content reject 

This is just because of the missing 'if' and in 1.3.17 this missing 'if'
result in a crash. A crash isn't better, but in case of crash you know
that something was misconfigured.

> > I have changed this to the following behaviour: If nothing is specified
> > after accept or reject the default condition will apply (like source and
> > documentation says) and if there is some parameter after accept or
> > reject it has to be 'if' or 'unless' anything else will result in:
> > 
> > [ALERT] 131/012555 (27042) : parsing [/etc/haproxy/haproxy.cfg:94] :
> > 'tcp-request content reject' expects 'if', 'unless' or nothing, but
> > found 'localnet'
> > [ALERT] 131/012555 (27042) : Error reading configuration file :
> > /etc/haproxy/haproxy.cfg
> > 
> > I think this is much more accurate. At least it took me some time to
> > verify why the hell my configuration file is valid, but did not work as
> > expected. :)
> 
> in fact not, that's precisely what I don't want. To workaround the bug
> I encountered, I had to write that :
> 
> tcp-request content accept if 
> tcp-request content reject if TRUE
> 
> That's pretty annoying. All conditionnal actions support either
> "if/unless cond" or inconditional execution if no condition is
> specified.
> 
> Are you sure your config was OK ? Can you post the example which
> causes you trouble ? Maybe your example is right and the doc is
> wrong ;-)
> 

Sure I have attached the file. If you remove the 'if' in the
'tcp-request' the config file is ok, haproxy starts but every request
from everywhere is dropped.

> Regards,
> Willy
> 

--Maik
# global configuration section.
global
maxconn 32768
chroot  /var/lib/haproxy
userhaproxy
group   haproxy
daemon
quiet

# default configuration and timeouts.
defaults
log global
retries 10
maxconn 32768
timeout connect 60s
timeout server  60s
timeout client  60s
timeout queue   60s
timeout tarpit  60s

# service and balance configuration.
listen  client-filter   10.0.1.7:10080
modehttp
cookie  SERVERID nocache
balance roundrobin
acl localnet-1 dst 192.168.0.0/16
acl localnet-2 dst 172.16.0.0/12
acl localnet-3 dst 10.0.0.0/8
tcp-request content reject if localnet-1
tcp-request content reject if localnet-2
tcp-request content reject if localnet-3
option  forwardfor header X-Forwarded-For
option  originalto header X-Original-To
option  httpclose

Re: TCP traffic multiplexing as balance algorithm?

2009-05-13 Thread Maik Broemme
Hi,

Willy Tarreau  wrote:
> Hi Maik,
> 
> On Tue, May 12, 2009 at 01:57:47AM +0200, Maik Broemme wrote:
> > Hi,
> > 
> > I have a small question. Did someone know if it is possible to do simple
> > traffic multiplexing with HAProxy? Maybe I am missing it somehow, but
> > want to ask on the list before creating a patch for it.
> 
> what do you call "traffic multiplexing" ? From your description below, I
> failed to understand what it consists in.
> 

Multiplex means traffic duplication. If you have multiple server
configuration options in one listen group, the incoming traffic is
sent to all servers.

> > Just to answer the real-world scenario question. TCP multiplexing can be
> > very useful for debugging backend servers or doing a simple logging and
> > passive traffic dumping.
> > 
> > There are two major ideas of implementing it:
> > 
> >   - 1:N (Active / Passive)
> >   - 1:N (Active / Active)
> > 
> > Well active means that request is going to destination and response back
> > to client and passive means that only request is going to the destination.
> > In configuration it could look like:
> > 
> > listen  smtp-filter 127.0.0.1:25
> > modetcp
> > balance multiplex
> > server  smtp1 10.0.0.5:25
> > server  smtp2 10.0.0.6:25
> > 
> > The active / active would be very hard to implement, tcp stream
> > synchronisation would be a pain and I think no one will really need
> > this, but active / passive is a very useful feature.
> > 
> > In my environment it is often so, that developers need access to real
> > traffic data to debug (in the example above) their developed smtp
> > software. Is anyone else missing such functionality? :)
> 
> Access to real data is solved with tcpdump or logs, I don't see what
> your load-balancing method will bring here.
> 

tcpdump is not perfect in that case, because it has to run the hole time
you want to duplicate the traffic and sent it to server1 and server2.

> > --Maik
> 
> Regards,
> Willy
> 

--Maik



TCP traffic multiplexing as balance algorithm?

2009-05-11 Thread Maik Broemme
Hi,

I have a small question. Did someone know if it is possible to do simple
traffic multiplexing with HAProxy? Maybe I am missing it somehow, but
want to ask on the list before creating a patch for it.

Just to answer the real-world scenario question. TCP multiplexing can be
very useful for debugging backend servers or doing a simple logging and
passive traffic dumping.

There are two major ideas of implementing it:

  - 1:N (Active / Passive)
  - 1:N (Active / Active)

Well active means that request is going to destination and response back
to client and passive means that only request is going to the destination.
In configuration it could look like:

listen  smtp-filter 127.0.0.1:25
modetcp
balance multiplex
server  smtp1 10.0.0.5:25
server  smtp2 10.0.0.6:25

The active / active would be very hard to implement, tcp stream
synchronisation would be a pain and I think no one will really need
this, but active / passive is a very useful feature.

In my environment it is often so, that developers need access to real
traffic data to debug (in the example above) their developed smtp
software. Is anyone else missing such functionality? :)

--Maik



[PATCH] Fix 'tcp-request content [accept|reject] if condition' parser for missing 'if'.

2009-05-11 Thread Maik Broemme
Hi,

attached is a patch which fixes a configuration mistake regarding the
'tcp-request' option. If you have the following in your configuration
file:

acl localnet dst 10.0.0.0/8
tcp-request content reject if localnet

This will work fine, but if you change the 'tcp-request' line and remove
the 'if' haproxy-1.3.17 will segfault, I think the following changelog
entry in 1.3.18 addresses this problem:

[BUG] fix parser crash on unconditional tcp content rules

But now in 1.3.18 the default behaviour is a bit weird. If you remove
the 'if' statement the haproxy will reject every connection, regardless
of matching to 'localnet' or not and the configuration seems to be valid,
but which is definetly not what expected.

I have changed this to the following behaviour: If nothing is specified
after accept or reject the default condition will apply (like source and
documentation says) and if there is some parameter after accept or
reject it has to be 'if' or 'unless' anything else will result in:

[ALERT] 131/012555 (27042) : parsing [/etc/haproxy/haproxy.cfg:94] :
'tcp-request content reject' expects 'if', 'unless' or nothing, but
found 'localnet'
[ALERT] 131/012555 (27042) : Error reading configuration file :
/etc/haproxy/haproxy.cfg

I think this is much more accurate. At least it took me some time to
verify why the hell my configuration file is valid, but did not work as
expected. :)

--Maik
diff -Nur haproxy-1.3.18/src/proto_tcp.c 
haproxy-1.3.18-tcp-request-condition-fix/src/proto_tcp.c
--- haproxy-1.3.18/src/proto_tcp.c  2009-05-10 20:27:47.0 +0200
+++ haproxy-1.3.18-tcp-request-condition-fix/src/proto_tcp.c2009-05-12 
01:25:48.0 +0200
@@ -509,6 +509,13 @@
pol = ACL_COND_IF;
else if (!strcmp(args[3], "unless"))
pol = ACL_COND_UNLESS;
+   else {
+   if (args[3][0] != '\0') {
+   snprintf(err, errlen, "'%s %s %s' expects 'if', 
'unless' or nothing, but found '%s'",
+args[0], args[1], args[2], args[3]);
+   return -1;
+   }
+   }
 
/* Note: we consider "if TRUE" when there is no condition */
if (pol != ACL_COND_NONE &&


Re: A patch for haproxy-1.3.17 which add X-Original-Dst header.

2009-05-08 Thread Maik Broemme
Hi,

many thanks Willy, I have still found a line which was missing in the
patch. In 'src/cfgparse.c' around line 677 there are the default values
set. I missed the following line:

curproxy->except_to = defproxy.except_to;

Just to set the default values if they will be - maybe - changed in
future versions. So please add it before adding the patch. :)

I have also another question: I am preparing a patch for setting
multiple except values to X-Forward-For and X-Original-To, because I am
still missing this feature. Am I right that it isn't possible in the
current version or did i miss something in documentation?

Willy Tarreau  wrote:
> Hi Maik,
> 
> OK the patch looks fine, I've merged it.
> 
> Thanks!
> Willy
> 

--Maik



Re: A patch for haproxy-1.3.17 which add X-Original-Dst header.

2009-04-17 Thread Maik Broemme
Hi,

Maik Broemme  wrote:
> Hi,
> 
> Maik Broemme  wrote:
> > Hi,
> > 
> > I have attached a patch which will add on every http request a new
> > header 'X-Original-Dst'. If you have HAProxy running in transparent mode
> > with a big number of SQUID servers behind it, it is very nice to have
> > the original destination ip as a common header to make decisions based
> > on it.
> > 
> > The whole thing is configurable with a new option 'originaldst'. I have
> > updated the sourcecode as well as the documentation. The 'haproxy-en.txt'
> > and 'haproxy-fr.txt' files are untouched, due to lack of my french
> > language knowledge. ;)
> > 
> > Also the patch adds this header for IPv4 only. I haven't any IPv6 test
> > environment running here and don't know if getsockopt() with SO_ORIGINAL_DST
> > will work on IPv6. If someone knows it and wants to test it I can modify
> > the diff. Feel free to ask me questions or things which should be changed. 
> > :)
> > 
> 
> I have attached a new diff, because the first one has two issues:
> 
>   - The except ip addresses for X-Original-Dst header were matched
> against 'except_net' instead of 'except_dst' which was wrong.
> 
>   - The except ip addresses for X-Original-Dst header were matched
> against the netmask of 'except_mask' which is only valid for
> 'except_net'. I have added a new netmask value 'except_mask_dst'
> to fix that.
> 

okay attached is now the final version, there were no new features or
enhancements. I only renamed it from 'X-Original-Dst' to 'X-Original-To'
because it is a common practice to name it so. For example Postfix does
it in a mail header with the same name.

> > --Maik
> 
> --Maik

--Maik
diff -Nur haproxy-1.3.17/doc/architecture.txt 
haproxy-1.3.17-x-original-to/doc/architecture.txt
--- haproxy-1.3.17/doc/architecture.txt 2009-03-29 15:26:57.0 +0200
+++ haproxy-1.3.17-x-original-to/doc/architecture.txt   2009-04-17 
18:41:58.0 +0200
@@ -128,6 +128,15 @@
 option httpclose
 option forwardfor
 
+ - if the application needs to log the original destination IP, use the
+   "originalto" option which will add an "X-Original-To" header with the
+   original destination IP address. You must also use "httpclose" to ensure
+   that you will rewrite every requests and not only the first one of each
+   session :
+
+option httpclose
+option originalto
+
The web server will have to be configured to use this header instead.
For example, on apache, you can use LogFormat for this :
 
diff -Nur haproxy-1.3.17/doc/configuration.txt 
haproxy-1.3.17-x-original-to/doc/configuration.txt
--- haproxy-1.3.17/doc/configuration.txt2009-03-29 15:26:57.0 
+0200
+++ haproxy-1.3.17-x-original-to/doc/configuration.txt  2009-04-17 
18:44:02.0 +0200
@@ -599,6 +599,7 @@
 [no] option dontlognull X  X X -
 [no] option forceclose  X  - X X
 option forwardfor   X  X X X
+option originalto   X  X X X
 [no] option http_proxy  X  X X X
 option httpchk  X  - X X
 [no] option httpclose   X  X X X
@@ -2038,6 +2039,65 @@
   See also : "option httpclose"
 
 
+option originalto [ except  ] [ header  ]
+  Enable insertion of the X-Original-To header to requests sent to servers
+  May be used in sections :   defaults | frontend | listen | backend
+ yes   |yes   |   yes  |   yes
+  Arguments :
+ is an optional argument used to disable this option for sources
+  matching 
+an optional argument to specify a different "X-Original-To"
+  header name.  
+
+  Since HAProxy can work in transparent mode, every request from a client can
+  be redirected to the proxy and HAProxy itself can proxy every request to a
+  complex SQUID environment and the destination host from SO_ORIGINAL_DST will
+  be lost. This is annoying when you want access rules based on destination ip
+  addresses. To solve this problem, a new HTTP header "X-Original-To" may be
+  added by HAProxy to all requests sent to the server. This header contains a
+  value representing the original destination IP address. Since this must be
+  configured to always use the last occurrence of this header only. Note that
+  only the last occurrence of the header must be used, since it is really
+  possible that the client has already brought one.
+
+  The keyword "header" may be used to supply a different header na

Re: [PATCH] Added 'option inject' for mode 'tcp'

2009-04-17 Thread Maik Broemme
Hi,

Willy Tarreau  wrote:
> Hi Maik,
> 
> On Fri, Apr 17, 2009 at 04:29:11AM +0200, Maik Broemme wrote:
> > Hi,
> > 
> > attached is a patch which adds a new option to HAProxy called 'inject'
> > for the mode 'tcp'. In the current version of this patch you can only
> > add data at the beginning of the session. I think this is very useful -
> > at least for me it is. :))
> 
> There are interesting concepts here it seems, eventhough some parts still
> seem a bit confusing to me. I'll review that in depth this week-end. Could
> you give us a few hints about what type of real-world usage you make of
> such a feature ? I certainly can understand the ability to insert a client's
> IP in TCP data, but I'm not sure what purpose returning data to the client
> will serve.
> 

Well i can give you small example for what it would be useful (I haven't
any better example yet. :))

  - Client -> HAProxy

>> EHLO localhost.localdomain

  - HAProxy -> Server

>> EHLO localhost.localdomain

  - Server -> HAProxy

<< 250-mydomain.de Hello localhost.localdomain [127.0.0.1]
<< 250-SIZE 52428800
<< 250-PIPELINING
<< 250-AUTH PLAIN LOGIN

  - HAProxy -> Client

<< 250-mydomain.de Hello localhost.localdomain [127.0.0.1]
<< 250-SIZE 13107200
<< 250-AUTH PLAIN

Well I don't want to write a full content inspection based on every
protocol, but in general you could do some small rewrites with it and
change or capabilities of services to match clients capabilities.

> Also, I don't think this should be set as an "option". Options tend to be
> just flags, eventhough some of them are slightly more. Once we figure out
> a more general usage, we will probably find a new keyword family for such
> a feature ;-)
> 

I thought the same at least this is very unbeautiful:

  if (!strcmp(args[2], "req")) {
  curproxy->listen->analysers |= AN_REQ_INJECT;
  } else if (!strcmp(args[2], "rsp")) {

Well I also have a version of the patch which adds it as a mode 'inject'
and add two new files src/proto_inject.c and include/proto/proto_inject.h
What do you think about it?

> Regards,
> Willy
> 

--Maik



[PATCH] Added 'option inject' for mode 'tcp'

2009-04-16 Thread Maik Broemme
Hi,

attached is a patch which adds a new option to HAProxy called 'inject'
for the mode 'tcp'. In the current version of this patch you can only
add data at the beginning of the session. I think this is very useful -
at least for me it is. :))

The configuration syntax is the following (I will update the documentation
with a more recent patch):

  optioninject req 1 forwardfor
  optioninject req 2 data "EHLO localhost.localdomain"
  optioninject req 3 data "GET / HTTP/1.1"
  optioninject rsp 1 data "500 Service Unavailable"

There are still some things open which I want to add later. If someone
has ideas about things which should be implemented, feel free to reply. :)

  - remove code duplication.
* X-Forward-For, X-Original-Dst in src/cfgparse.c and src/proto_tcp.c,
  maybe src/proto_http.c

  - add support for inject data on response.
* currently it works only on request.

  - add session injection based on request or response.
* currently injection only works at the beginning of request and first
  response.

  - modify session information based on regular expression for request
or response.
* currently this isn't possible.

This will make it possible to inject data at every time of the session
without knowing the underlying protocol. The attached patch is very basic,
but I send it in that early stage, to get some feedback if it is a feature
for HAProxy or not. Comments are welcome. :) Also it should be possible to
transfer some very minimalistic html pages like:

  optioninject rsp 1 data ""
  optioninject rsp 2 data ""
  optioninject rsp 3 data "Error"
  optioninject rsp 4 data ""
  optioninject rsp 5 data "Access denied"
  optioninject rsp 6 data "

For example: With a later version of this patch it is possible to create a
service named 'smtp-mail-me' and at connect via telnet it can do the
following:

  >> EHLO localhost.localdomain
  << 250-mydomain.de Hello localhost.localdomain [127.0.0.1]
  << 250-SIZE 52428800
  << 250-PIPELINING
  >> AUTH PLAIN XX==
  << 235 Authentication succeeded
  >> MAIL FROM:
  << 250 Ok
  >> RCPT TO:
  << 250 Accepted
  >> DATA
  >> ...
  >> .
  << 250 Ok id=1LudBO-SQ-Qa
  >> QUIT

Every other text-based protocol can be handled in such case too. I want to
mention that I don't know exactly how the timeout handling is done in
HAProxy. The source is very anoying to me there, some hints would be nice. :)

--Maik
diff -Nur haproxy-1.3.17/include/proto/proto_tcp.h 
haproxy-1.3.17-tcp-inject/include/proto/proto_tcp.h
--- haproxy-1.3.17/include/proto/proto_tcp.h2009-03-29 15:26:57.0 
+0200
+++ haproxy-1.3.17-tcp-inject/include/proto/proto_tcp.h 2009-04-17 
02:37:44.0 +0200
@@ -33,6 +33,7 @@
 void tcpv6_add_listener(struct listener *listener);
 int tcp_bind_listener(struct listener *listener, char *errmsg, int errlen);
 int tcp_inspect_request(struct session *s, struct buffer *req);
+int tcp_inject_request(struct session *s, struct buffer *req);
 
 #endif /* _PROTO_PROTO_TCP_H */
 
diff -Nur haproxy-1.3.17/include/types/buffers.h 
haproxy-1.3.17-tcp-inject/include/types/buffers.h
--- haproxy-1.3.17/include/types/buffers.h  2009-03-29 15:26:57.0 
+0200
+++ haproxy-1.3.17-tcp-inject/include/types/buffers.h   2009-04-17 
02:37:44.0 +0200
@@ -111,6 +111,7 @@
 #define AN_REQ_HTTP_TARPIT  0x0008  /* wait for end of HTTP tarpit */
 #define AN_RTR_HTTP_HDR 0x0010  /* inspect HTTP response headers */
 #define AN_REQ_UNIX_STATS   0x0020  /* process unix stats socket 
request */
+#define AN_REQ_INJECT   0x0040  /* inject header lines into tcp 
session */
 
 /* describes a chunk of string */
 struct chunk {
diff -Nur haproxy-1.3.17/src/cfgparse.c haproxy-1.3.17-tcp-inject/src/cfgparse.c
--- haproxy-1.3.17/src/cfgparse.c   2009-03-29 15:26:57.0 +0200
+++ haproxy-1.3.17-tcp-inject/src/cfgparse.c2009-04-17 04:12:18.0 
+0200
@@ -1604,6 +1604,78 @@
}
}
}
+   else if (!strcmp(args[1], "inject")) {
+   int cur_arg;
+
+   /* inject x-forwarded-for field at the beginning of tcp 
session. */
+   curproxy->options |= PR_O_FWDFOR;
+
+   free(curproxy->fwdfor_hdr_name);
+   curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
+   curproxy->fwdfor_hdr_len  = strlen(DEF_XFORWARDFOR_HDR);
+
+   /* next argument must be "req" or "rep" */
+   if (!strcmp(args[2], "req")) {
+   curproxy->listen->analysers |= AN_REQ_INJECT;
+   } else if (!strcmp(args[2], "rsp")) {
+// TODO: implement it
+   Alert("parsing [%s:%d] : '%s %s %s' not yet 
implemented.\n",
+  

Re: A patch for haproxy-1.3.17 which add X-Original-Dst header.

2009-04-15 Thread Maik Broemme
Hi,

Maik Broemme  wrote:
> Hi,
> 
> I have attached a patch which will add on every http request a new
> header 'X-Original-Dst'. If you have HAProxy running in transparent mode
> with a big number of SQUID servers behind it, it is very nice to have
> the original destination ip as a common header to make decisions based
> on it.
> 
> The whole thing is configurable with a new option 'originaldst'. I have
> updated the sourcecode as well as the documentation. The 'haproxy-en.txt'
> and 'haproxy-fr.txt' files are untouched, due to lack of my french
> language knowledge. ;)
> 
> Also the patch adds this header for IPv4 only. I haven't any IPv6 test
> environment running here and don't know if getsockopt() with SO_ORIGINAL_DST
> will work on IPv6. If someone knows it and wants to test it I can modify
> the diff. Feel free to ask me questions or things which should be changed. :)
> 

I have attached a new diff, because the first one has two issues:

  - The except ip addresses for X-Original-Dst header were matched
against 'except_net' instead of 'except_dst' which was wrong.

  - The except ip addresses for X-Original-Dst header were matched
against the netmask of 'except_mask' which is only valid for
'except_net'. I have added a new netmask value 'except_mask_dst'
to fix that.

> --Maik

--Maik
diff -Nur haproxy-1.3.17/doc/architecture.txt 
haproxy-1.3.17-x-original-dst/doc/architecture.txt
--- haproxy-1.3.17/doc/architecture.txt 2009-03-29 15:26:57.0 +0200
+++ haproxy-1.3.17-x-original-dst/doc/architecture.txt  2009-04-15 
04:34:08.0 +0200
@@ -128,6 +128,15 @@
 option httpclose
 option forwardfor
 
+ - if the application needs to log the original destination IP, use the
+   "originaldst" option which will add an "X-Original-Dst" header with the
+   original destination IP address. You must also use "httpclose" to ensure
+   that you will rewrite every requests and not only the first one of each
+   session :
+
+option httpclose
+option originaldst
+
The web server will have to be configured to use this header instead.
For example, on apache, you can use LogFormat for this :
 
diff -Nur haproxy-1.3.17/doc/configuration.txt 
haproxy-1.3.17-x-original-dst/doc/configuration.txt
--- haproxy-1.3.17/doc/configuration.txt2009-03-29 15:26:57.0 
+0200
+++ haproxy-1.3.17-x-original-dst/doc/configuration.txt 2009-04-15 
04:30:21.0 +0200
@@ -599,6 +599,7 @@
 [no] option dontlognull X  X X -
 [no] option forceclose  X  - X X
 option forwardfor   X  X X X
+option originaldst  X  X X X
 [no] option http_proxy  X  X X X
 option httpchk  X  - X X
 [no] option httpclose   X  X X X
@@ -2038,6 +2039,65 @@
   See also : "option httpclose"
 
 
+option originaldst [ except  ] [ header  ]
+  Enable insertion of the X-Original-Dst header to requests sent to servers
+  May be used in sections :   defaults | frontend | listen | backend
+ yes   |yes   |   yes  |   yes
+  Arguments :
+ is an optional argument used to disable this option for sources
+  matching 
+an optional argument to specify a different "X-Original-Dst"
+  header name.  
+
+  Since HAProxy can work in transparent mode, every request from a client can
+  be redirected to the proxy and HAProxy itself can proxy every request to a
+  complex SQUID environment and the destination host from SO_ORIGINAL_DST will
+  be lost. This is annoying when you want access rules based on destination ip
+  addresses. To solve this problem, a new HTTP header "X-Original-Dst" may be
+  added by HAProxy to all requests sent to the server. This header contains a
+  value representing the original destination IP address. Since this must be
+  configured to always use the last occurrence of this header only. Note that
+  only the last occurrence of the header must be used, since it is really
+  possible that the client has already brought one.
+
+  The keyword "header" may be used to supply a different header name to 
replace 
+  the default "X-Original-Dst". This can be useful where you might already
+  have a "X-Original-Dst" header from a different application, and you need
+  preserve it. Also if your backend server doesn't use the "X-Original-Dst"
+  header and requires different one.
+
+  Sometimes, a same HAProxy instance may be shared between a direct client
+  access and a reverse-proxy access (for instance when an SSL reverse-proxy is
+  used to decr

A patch for haproxy-1.3.17 which add X-Original-Dst header.

2009-04-14 Thread Maik Broemme
Hi,

I have attached a patch which will add on every http request a new
header 'X-Original-Dst'. If you have HAProxy running in transparent mode
with a big number of SQUID servers behind it, it is very nice to have
the original destination ip as a common header to make decisions based
on it.

The whole thing is configurable with a new option 'originaldst'. I have
updated the sourcecode as well as the documentation. The 'haproxy-en.txt'
and 'haproxy-fr.txt' files are untouched, due to lack of my french
language knowledge. ;)

Also the patch adds this header for IPv4 only. I haven't any IPv6 test
environment running here and don't know if getsockopt() with SO_ORIGINAL_DST
will work on IPv6. If someone knows it and wants to test it I can modify
the diff. Feel free to ask me questions or things which should be changed. :)

--Maik
diff -Nur haproxy-1.3.17/doc/architecture.txt 
haproxy-1.3.17-x-original-dst/doc/architecture.txt
--- haproxy-1.3.17/doc/architecture.txt 2009-03-29 15:26:57.0 +0200
+++ haproxy-1.3.17-x-original-dst/doc/architecture.txt  2009-04-15 
04:34:08.0 +0200
@@ -128,6 +128,15 @@
 option httpclose
 option forwardfor
 
+ - if the application needs to log the original destination IP, use the
+   "originaldst" option which will add an "X-Original-Dst" header with the
+   original destination IP address. You must also use "httpclose" to ensure
+   that you will rewrite every requests and not only the first one of each
+   session :
+
+option httpclose
+option originaldst
+
The web server will have to be configured to use this header instead.
For example, on apache, you can use LogFormat for this :
 
diff -Nur haproxy-1.3.17/doc/configuration.txt 
haproxy-1.3.17-x-original-dst/doc/configuration.txt
--- haproxy-1.3.17/doc/configuration.txt2009-03-29 15:26:57.0 
+0200
+++ haproxy-1.3.17-x-original-dst/doc/configuration.txt 2009-04-15 
04:30:21.0 +0200
@@ -599,6 +599,7 @@
 [no] option dontlognull X  X X -
 [no] option forceclose  X  - X X
 option forwardfor   X  X X X
+option originaldst  X  X X X
 [no] option http_proxy  X  X X X
 option httpchk  X  - X X
 [no] option httpclose   X  X X X
@@ -2038,6 +2039,65 @@
   See also : "option httpclose"
 
 
+option originaldst [ except  ] [ header  ]
+  Enable insertion of the X-Original-Dst header to requests sent to servers
+  May be used in sections :   defaults | frontend | listen | backend
+ yes   |yes   |   yes  |   yes
+  Arguments :
+ is an optional argument used to disable this option for sources
+  matching 
+an optional argument to specify a different "X-Original-Dst"
+  header name.  
+
+  Since HAProxy can work in transparent mode, every request from a client can
+  be redirected to the proxy and HAProxy itself can proxy every request to a
+  complex SQUID environment and the destination host from SO_ORIGINAL_DST will
+  be lost. This is annoying when you want access rules based on destination ip
+  addresses. To solve this problem, a new HTTP header "X-Original-Dst" may be
+  added by HAProxy to all requests sent to the server. This header contains a
+  value representing the original destination IP address. Since this must be
+  configured to always use the last occurrence of this header only. Note that
+  only the last occurrence of the header must be used, since it is really
+  possible that the client has already brought one.
+
+  The keyword "header" may be used to supply a different header name to 
replace 
+  the default "X-Original-Dst". This can be useful where you might already
+  have a "X-Original-Dst" header from a different application, and you need
+  preserve it. Also if your backend server doesn't use the "X-Original-Dst"
+  header and requires different one.
+
+  Sometimes, a same HAProxy instance may be shared between a direct client
+  access and a reverse-proxy access (for instance when an SSL reverse-proxy is
+  used to decrypt HTTPS traffic). It is possible to disable the addition of the
+  header for a known source address or network by adding the "except" keyword
+  followed by the network address. In this case, any source IP matching the
+  network will not cause an addition of this header. Most common uses are with
+  private networks or 127.0.0.1.
+
+  This option may be specified either in the frontend or in the backend. If at
+  least one of them uses it, the header will be added. Note that the backend's
+  setting of the header subargument takes precedence over the frontend's if
+  both are defined.
+
+  It is important to note that as long as HAProxy does not support keep-alive
+  connections, only the first request of a connection will receive the header.
+