About the Site

This weblog is edited and run by members of reallyenglish, a company offering a total English learning solution based in London, Beijing, Shanghai and Tokyo. Visit our corporate site to know more about what we do.

Notes are posted by members from various cultural and geographical backgrounds, and the topics range from education, business and international communication to software development, the internet culture, and more.

Staff

Masatomo Nakano http://twitter.com/masatomon /m/mt-static/support/assets_c/userpics/userpic-2-100x100.png simonl davida jeremyw Go Kameda gavin b No name tomoyukis

 

Recent Comments

  • Tomoyuki Sakurai: we've been using vether(4) successfully since 4.7. http://old.nabble.com/kernel-6318:-arp-cache-problem-bridge%284%29-with-vether%284%29-td27635451.html (the bug read more
  • RofR: Hi everyone Where about to setup serveral OBSD 4.9 or read more
  • Tomoyuki Sakurai: the above configuration has been working fine since 4.6. read more
  • Jean Aumont: Hi Tomoyuki, If you capture the packets with tcpdump and read more
  • Tomoyuki Sakurai: you will not see OSPF packets on physical interface. > read more
  • Jean Aumont: Hi everyone, I have been trying to pass OSPF in read more
  • Anonymous: without any other information, all i can say is doing read more
  • Jean Aumont: I have a similar set-up, but my 2 end points read more
  • illouca: thank you for the patch !! read more
  • Go Kameda: Glad to hear that - im afraid i cannot really read more

December 2009 Archives

Almost all serious project require redundancy, reallyenglish is no exception. carp(4), developed by OpenBSD project, is a free implementation of VRRP, which is patented by Cisco. carp(4) has load balancing based on L2 and L3, but here, I'm going to focus on its fail over feature.

            | 192.168.100.254/24
     .------+------.
 vr0 |         vr0 |
 .---+---. vr3 .---+---.
 | core1 +-----+ core2 |
 `---+---'     `---+---'
 vr1 |          vr1|
     `------+------'
            | 192.168.200.254/24

Firstly, enable IPv4 forwarding. Also, enable preemption to failover all carp interfaces altogether when one interface fails.

# sysctl net.inet.ip.forwarding=1
# echo net.inet.ip.forwarding=1 >> /etc/sysctl.conf
# sysctl net.inet.carp.preempt=1
# echo net.inet.carp.preempt=1 >> /etc/sysctl.conf

Using carp(4) is fairly simple. Here is what hostname.if(5) looks like.

/etc/hostname.vr0:     up
/etc/hostname.vr1:     up
/etc/hostname.vr3:     inet 172.16.0.1/30
/etc/hostname.carp0:   192.168.100.254 vhid 1 carpdev vr0 pass mypass
/etc/hostname.carp1:   192.168.200.254 vhid 2 carpdev vr1 pass mypass
/etc/hostname.pfsync0: syncdev vr3

Bring up the interfaces. You can also use ifconfig(8), but I always prefer startup script to make sure that the configuration will not be lost.

# sh /etc/netstart vr0
# sh /etc/netstart vr1
# sh /etc/netstart vr3
# sh /etc/netstart carp0
# sh /etc/netstart carp1
# sh /etc/netstart pfync0

If you insists on using ifconfig(8):

# ifconfig vr0 up
# ifconfig vr1 up
# ifconfig vr3 inet 172.16.0.1/30
# ifconfig carp0 create
# ifconfig carp1 create
# ifconfig carp0 192.168.100.254 vhid 1 carpdev vr0 pass mypass
# ifconfig carp1 192.168.200.254 vhid 2 carpdev vr0 pass mypass
# ifconfig pfsync0 syncdev vr3

Repeat almost same configuration on core2. The difference is each carp interface has advskew keyword and vr3 for pfsync device has different IP address. A router with higher advskew value becomes slave.

/etc/hostname.vr3:     inet 172.16.0.2/30
/etc/hostname.carp0: 192.168.100.254 vhid 1 carpdev vr0 pass mypass advskew 100
/etc/hostname.carp1: 192.168.200.254 vhid 2 carpdev vr1 pass mypass advskew 100

Now you have redundant firewalls. Easy!

As explained in the earlier entry, we use OSPF for internal routing. How do I establish OSPF neighbor? Because ospfd(8) cannot be enabled actively on carp'ed interface, you need real interface that connects OSPF cloud and core routers. Additionally, real interface cannot preempt carp interface. That means when the real interface fails, you cannot failover. To workaround this problem, you need two OSPF-enabled routers and two links on each core. Things get messy from now on.

                                     carp0
           udav1   vr1    sis0      /
-----.      .------.     .-------. / 
     +------+  r1  +-----+ core1 |<
     |      `------'     `-------' \
     |     udav0|vr2\   / sis1  \   \
     |          |    \ /         \   carp1
OSPF |          |     X        pfsync0
     |          |    / \         /   carp0
     |     udav0|vr1/   \ sis0  /   /
     |      .------.     .-------. / 
     +------|  r2  +-----+ core2 |<
-----'      `------'     `-------' \
           udav1   vr2     sis1     \
                                     carp1

In this setup, when one of the link from core to OSPF cloud fails, traffic will be routed via the link between r1 and r2. When carp'ed interface fails, preemption kicks in and ospfd(8) on core1 will remove the routes and r1 will not route traffic to core1. claudio@, one of "the networking guy" in OpenBSD admitted it's not optimal. Hopefully, it will be fixed in the future release.

ALIX 2D3 board, which is used as r1 and r2, has only three ports. And one port is used for diskless boot in this testing. So, i added two USB ethernet adopters, deteced as udav(4). Make sure the right patch goes to the right port. Each link between the routers has a /30 subnet. If confused, draw a diagram on paper.

Let's enable OSPF on all interface on every router, but not on real interfaces used for carp. ospfd.conf(5) looks like:

# core1 and core2
auth-type crypt
auth-md 1 "mypass"
auth-md-keyid 1

area 0.0.0.0 {
  # link to r1/r2
  interface sis0 { metric 10 }
  interface sis1 { metric 20 }
  # you can omit "passive" on carp interface. it's always passive anyway
  interface carp1 { passive }
  interface carp0 { passive }
}

# r1 and r2
auth-type crypt
auth-md 1 "mypass"
auth-md-keyid 1

area 0.0.0.0 {
  # link to core
  interface vr1 { metric 10 }
  interface vr2 { metric 20 }
  interface udav0 { }
  interface udav1 { }
}

Run ospfd(8) on every router. The output of ospfctl(8) on core1 looks like this.

# ospfctl sh int
Interface   Address            State  HelloTimer Linkstate  Uptime    nc  ac
carp0       192.168.100.254/24 DOWN   -          master     00:00:00   0   0
carp1       192.168.200.254/24 DOWN   -          master     00:00:00   0   0
sis1        192.168.0.5/30     BCKUP  00:00:00   active     1d06h19m   1   1
sis0        192.168.0.1/30     BCKUP  00:00:00   active     1d06h19m   1   1

# ospfctl sh ne
ID              Pri State        DeadTime Address         Iface     Uptime
172.16.254.202  10  FULL/DR      00:00:33 192.168.0.6     sis1      1d06h20m
172.16.254.201  1   FULL/DR      00:00:32 192.168.0.2     sis0      1d06h20m

Now the fun (and boring) part. While pinging from a host in OSPF cloud to the other end of core, pull out the cable randomly. You can shutdown one of the router, too. Nothing should happen, other than normal ping output. If it doesn't work, tcpdump(8) is your friend. You can manually fail over the master by:

# ifconfig -g carp carpdemote 10

This setup requires no additional package and works out of the box. If you need more redundancy, i.e. redundancy at application level, than this setup, OpenBSD also provides relayd(8). If you need redundant DHCP servers, modified version of dhcpd(8) has synchronization support. OpenBSD makes redundant networking fairly easy.

Happy redundancy!