On Tue, Oct 06, 2009 at 11:22:11PM +0300, Imre Oolberg wrote:
> Hallo!
>
> I have used carp ip-stealth balancing for only pass and block rules with
> two openbsd 4.5 firewalls and https server quite successfully, like this
Hi,
finally someone who got IP balancing to work :)
>
> to isp router is firewalls' default gw
>
> |--carp0--| carp0: 192.168.1.170
> _|_ _|_
> FW1 | | | | FW2
> |___| |___|
> |--carp1--| carp1: 10.0.1.193
> | |
> ----|-------|---------|------|---
> | |
> _|_ _|_
> | | 10.0.1.200:443 | | 10.0.1.199:80
> |___| https server |___| http server
>
> Carp interfaces are created with definitions like this (on the other
> firewall 1:100,2:0 -> 1:0,2:100)
>
> inet 192.168.1.170 255.255.255.248 192.168.1.175 carpnodes \
> 1:100,2:0 balancing ip-stealth pass xxx carpdev em0
> inet 10.0.1.193 255.255.255.240 10.0.1.207 carpnodes \
> 3:100,4:0 balancing ip-stealth pass yyy carpdev em1
>
> And the problem arrives when i add second server (http) and trying to
> use rdr rules rewriting ip address, essential rules are
>
> rdr on $ext_if inet proto tcp to 10.0.1.199 port 8080 tag TO_HTTP \
> -> 10.0.1.199 port 80
> rdr on $ext_if inet proto tcp to 10.0.1.200 port 80 tag TO_HTTP \
> -> 10.0.1.199 port 80
Carp IP balancing does its load distribution with a simple hash
over the source and destination IP address.
So in general doing any sort of address rewrite (nat, rdr)
can mess things up, because the return packet will be handled
by the other node.
And stateful filtering and asymmetric routing are not good friends.
However, in your case there might be a workaround.
The carp hash function does a: (src ^ dst) % number_of_nodes
to decide which node accepts the packet.
Since you only have 2 nodes, it is all just a matter of an
odd or even result.
If you change your https servers' IP to an odd one (eg 10.0.1.201)
your rdr rule would become:
rdr on $ext_if inet proto tcp to 10.0.1.201 port 80 tag TO_HTTP \
-> 10.0.1.199 port 80
This way, the packet hash after the rdr will be equal to the
one before.
> pass in quick on $ext_if inet tagged TO_HTTP
> pass in quick on $ext_if inet proto tcp to 10.0.1.200 port 443 \
> tag TO_HTTP
> pass out quick on $int_if inet tagged TO_HTTP
>
> So the problem is i cant figure out why first rdr works and the second
> rdr does not.
The first one only rewrites the tcp port, not the IP address.
HTH,
Marco