(Ab)using OpenVPN to make two unrealiable Internet connections act asone reliable connection (Failure #1)

Got packet loss? Got two or more connections? Got server somewhere to route packets thru?



I tried few different approaches until finally coming up with version that works. Let’s start with non-working attempts so you know what NOT to do. As these tricks I tried might be useful in some other scenarios I wanted to still post them. Here’s my first failed attempt.

1. Using 'tc' with mirred and munge actions.

Create dummy interface which will be used as route for packets we want to duplicate. In this example to-be-duplicated destination net is 172.16.0.0/24.
# modprobe dummy
# ifconfig dummy0 172.17.172.17 netmask 255.255.255.255 up
# route add -net 172.16.0.0 netmask 255.255.255.0 dev dummy0

Clone any packets sent via dummy0 to eth1 and eth2.
# tc qdisc add dev dummy0 root handle 1: prio
# tc qdisc add dev dummy0 ingress
# tc filter add dev dummy0 protocol ip prio 23 u32 \
  match ip src 0.0.0.0/0 flowid 1: \
  action mirred \
  egress mirror dev eth1 \
  pipe \
  action mirred \
  egress redirect dev eth2


Edit source and destination macs on outgoing packets to match intended destination and local adapter address on eth1/eth2.
# tc qdisc add dev eth1 handle 1: root prio
# tc filter add dev eth1 parent 1: protocol ip prio 10 u32 \
  match ip src 0.0.0.0/0 flowid 1: \
  action pedit \
  munge offset -14 u16 set 0x000c \
  munge offset -12 u32 set 0x29d880cc \
  munge offset -8 u32 set 0x000c293e \
  munge offset -4 u16 set 0x28fd

# tc qdisc add dev eth2 handle 1: root prio
# tc filter add dev eth2 parent 1: protocol ip prio 10 u32 \
  match ip src 0.0.0.0/0 flowid 1: \
  action pedit \
  munge offset -14 u16 set 0x000c \
  munge offset -12 u32 set 0x29d880d6 \
  munge offset -8 u32 set 0x000c293e \
  munge offset -4 u16 set 0x2807

# offset -14 = dstmac, first 2 bytes (00:0c:29:d8:80:d6 --> 0x000c)
# offset -12 = dstmac, last 4 bytes (00:0c:29:d8:80:d6 --> 0x29d880d6)
# offset -8 = srcmac, first 4 bytes (00:0c:29:3e:28:07 --> 0x000c293e)
# offset -8 = srcmac, last 2 bytes (00:0c:29:3e:28:07 --> 0x2807)

Since these packets don't travel via regular NAT chains we can't fix source IP with iptables. You can try to do it with tc. Example below changes source IP to 10.10.1.1 (0x0a0a0101, offset 12) and also fixes packet checksums.
# tc qdisc add dev eth1 handle 1: root prio
# tc filter add dev eth1 parent 1: protocol ip prio 10 u32 \
  match ip src 0.0.0.0/0 flowid 1: \
  action pedit \
  munge offset -14 u16 set 0x000c \
  munge offset -12 u32 set 0x29d880cc \
  munge offset -8 u32 set 0x000c293e \
  munge offset -4 u16 set 0x28fd \
  munge offset 12 u32 set 0x0A0A0101 \
  pipe \
  csum ip and udp and tcp


Well that approach doesn't work. Outgoing traffic is ok, but apart from ICMP kernel really don't like packets coming back. Don't know why but given how ugly way to do what we want that is I'm happy it failed.

See next post for how I failed again or go straight to working solution.

Comments