2 ISP's - Linux Gateway Router

I have a Linux gateway with 2 ISP's,

(1) I want to route my VPN traffic through ISP1 and rest of the traffic through ISP2. When both ISP's are working fine.
(2) I want to route my VPN traffic and all other internet traffic through ISP2 if ISP1 is down.
(3) I want to route my VPN traffic and all other internet traffic through ISP1 if ISP2 is down.

I have 3 NIC's
eth0 - ISP1
eth1 - ISP2
eth2 - Local LAN

When the Internet traffic is changing from one ISP to the other the end user should not feel the difference both for internet traffic and VPN traffic.

Solution Please


ahraousAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

exploitedjCommented:
The bulk of this is a modified fwbuilder script I use on my lab host. It allows pings from everywhere, ssh from the all over to the firewall (even the outside, you may want to lock this down) and telnet, change telnet to vpn protocols for your case.
I am using eth0 192.168.0.1/24 (internal)
 eth1192.168.1.1/24 , eth2 192.168.2.1/24 (externals)
on my router/firewall box. My lab is not perfect because on the outside I am using a hub with virtual interfaces on the remote side but tethereal has the traffic going out and coming back over the right MACs
The last two lines might be all you need
( echo 1 > /proc/sys/net/ipv4/conf/eth1/arp_filter
echo 1 > /proc/sys/net/ipv4/conf/eth2/arp_filter )
but just in case you are wanting more:
This is everything I did, if you follow it step by step you should be in good shape.

Installed fedora core1 (Yarrow), no X, gnome, kde, but not base, I installed kernel packages, editors, text internet, and development not much else, feel free to add X or whatever you want.

went to ftp.kernel.org:/pub/linux/v.2.4/ and downloaded linux-2.4.24.tar.bz2

bunziped it into /usr/src/

cd /usr/src/

bunzip2 linux-2.4.24.tar.bz2

tar -xvf linux-2.4.24.tar

cd /usr/src/linux-2.4.24/

Download patch-2.4.24-ja1.diff patches from Julian Anastasov copy them into /usr/src/linux-2.4.24/

patch -p1 -b < patch-2.4.24-ja1.diff

Edit your top level Makefile add to EXTRAVERSION -9.1

make clean

make mrproper

make menuconfig - I took the config from

/usr/src/linux-2.4/configs/kernel-2.4.22-i586.config and loaded it, added the things from LVS/LVS-HOWTO/mini-HOWTO thatwere not checked.

make dep

make bzImage 2>comp_err

grep err compile_err

make modules 2>mod_err

grep err mod_err

cp /usr/src/linux-2.4.24/arch/i386/boot/bzImage /boot/vmlinuz-2.4.24-9.1

make modules_install

cp /usr/src/linux-2.4.24/System.map /boot/System-2.4.24-9.1

new-kernel-pkg --install --mkinitrd --depmod 2.4.24-

vi /etc/grub.conf changed my  kernel /vmlinuz-2.4.24-9.1 ro root=LABEL=/ to point to kernel /vmlinuz-2.4.24-9.1 ro root=/dev/hdd3
rebooted
Now that the basics are taken care of I took my old fwbuilder built output from another host and made some minor mods to it.
 Note not all the variables tie directly so you will have to find where I have my 192.168.0.0/24 and change those by hand or write in variables to correspond, best of luck (the rest is a script to be saved as file chmod +x and ran) :

#!/bin/sh
                                                                                                                           
log() {
  test -x "$LOGGER" && $LOGGER -p info "$1"
}
                                                                                                                           
va_num=1
add_addr() {
  addr=$1
  nm=$2
  dev=$3
                                                                                                                           
  type=""
  aadd=""
                                                                                                                           
  L=`$IP -4 link ls $dev | grep "$dev:"`
  if test -n "$L"; then
    OIFS=$IFS
    IFS=" /:,<"
    set $L
    type=$4
    IFS=$OIFS
    L=`$IP -4 addr ls $dev to $addr | grep " inet "`
    if test -n "$L"; then
      OIFS=$IFS
      IFS=" /"
      set $L
      aadd=$2
      IFS=$OIFS
    fi
  fi
  if test -z "$aadd"; then
    if test "$type" = "POINTOPOINT"; then
      $IP -4 addr add $addr dev $dev scope global label $dev:FWB${va_num}
      va_num=`expr $va_num + 1`
    fi
    if test "$type" = "BROADCAST"; then
      $IP -4 addr add $addr/$nm dev $dev brd + scope global label $dev:FWB${va_num}
      va_num=`expr $va_num + 1`
    fi
  fi
}
getaddr() {
  dev=$1
  name=$2
  L=`$IP -4 addr show dev $dev | grep inet`
  test -z "$L" && {
    eval "$name=''"
    return
  }
  OIFS=$IFS
  IFS=" /"
  set $L
  eval "$name=$2"
  IFS=$OIFS
}
getinterfaces() {
  NAME=$1
  $IP link show | grep -E "$NAME[^ ]*: "| while read L; do
    OIFS=$IFS
    IFS=" :"
    set $L
    IFS=$OIFS
    echo $2
  done
}
                                                                                                                           
LSMOD="/sbin/lsmod"
MODPROBE="/sbin/modprobe"
IPTABLES="/sbin/iptables"
IP="/sbin/ip"
LOGGER="/usr/bin/logger"
INTERFACES="eth0 eth1 eth2 lo "
for i in $INTERFACES ; do
  $IP link show "$i" > /dev/null 2>&1 || {
    echo Interface $i does not exist
    exit 1
  }
done
                                                                                                                           
$IP -4 neigh flush dev eth0 >/dev/null 2>&1
$IP -4 addr flush dev eth0 label "eth0:FWB*" >/dev/null 2>&1
$IP -4 neigh flush dev eth1 >/dev/null 2>&1
$IP -4 addr flush dev eth1 label "eth1:FWB*" >/dev/null 2>&1
$IP -4 neigh flush dev eth2 >/dev/null 2>&1
$IP -4 addr flush dev eth2 label "eth2:FWB*" >/dev/null 2>&1

add_addr 192.168.0.1 24 eth0
$IP link set eth0 up
add_addr 192.168.1.1 24 eth1
$IP link set eth1 up
add_addr 192.168.2.1 24 eth2
$IP link set eth2 up
add_addr 127.0.0.1 8 lo
$IP link set lo up

$IPTABLES -P OUTPUT  DROP
$IPTABLES -P INPUT   DROP
$IPTABLES -P FORWARD DROP

cat /proc/net/ip_tables_names | while read table; do
  $IPTABLES -t $table -L -n | while read c chain rest; do
      if test "X$c" = "XChain" ; then
        $IPTABLES -t $table -F $chain
      fi
  done
MODULE_DIR="/lib/modules/`uname -r`/kernel/net/ipv4/netfilter/"
MODULES=`(cd $MODULE_DIR; ls *_conntrack_*  *_nat_* | sed 's/\.o.*$//; s/\.ko$//')`
for module in $(echo $MODULES); do
  if $LSMOD | grep ${module} >/dev/null; then continue; fi
  $MODPROBE ${module} ||  exit 1
done
log "Activating firewall script"
#
#  Rule 0(NAT)
#
#
$IPTABLES -t nat -A POSTROUTING -o eth1  -s 192.168.0.0/24 -j SNAT --to-source 192.168.1.1
$IPTABLES -t nat -A POSTROUTING -o eth2  -s 192.168.0.0/24 -j SNAT --to-source 192.168.2.1
#
#  Rule 1(NAT)
#
#
$IPTABLES -t nat -A PREROUTING  -p tcp   -d 192.168.1.1 --destination-port 23 -j DNAT --to-destination 192.168.0.10:23
$IPTABLES -t nat -A PREROUTING  -p tcp   -d 192.168.2.1 --destination-port 23 -j DNAT --to-destination 192.168.0.10:23
#
#  Rule 2(NAT)
#
#
$IPTABLES -t nat -A PREROUTING   -j ACCEPT
$IPTABLES -t nat -A POSTROUTING   -j ACCEPT
#
#
$IPTABLES -A INPUT   -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -A OUTPUT  -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
                                                                                                                           
########## The following three lines are to test NAT ######################
                                                                                                                           
# $IPTABLES -A INPUT -s 0/0 -d 0/0 -j ACCEPT
# $IPTABLES -A OUTPUT -s 0/0 -d 0/0  -j ACCEPT
# $IPTABLES -A FORWARD -s 0/0 -d 0/0  -j ACCEPT
# When the previous three lines are not commented the rest doesn't matter #
#
# Rule Stateful

$IPTABLES -t filter -N keep_state
$IPTABLES -t filter -A keep_state -m state --state RELATED,ESTABLISHED -j ACCEPT
$IPTABLES -t filter -A keep_state -j RETURN
$IPTABLES -t nat -N keep_state
$IPTABLES -t nat -A keep_state -m state --state RELATED,ESTABLISHED -j ACCEPT
$IPTABLES -t nat -A keep_state -j RETURN
$IPTABLES -t nat -A PREROUTING -j keep_state
$IPTABLES -t nat -A POSTROUTING -j keep_state
$IPTABLES -t nat -A OUTPUT -j keep_state
$IPTABLES -t filter -A INPUT -j keep_state
$IPTABLES -t filter -A FORWARD -j keep_state
$IPTABLES -t filter -A OUTPUT -j keep_state
#
# Rule 0(global)
#
# ssh access to firewall
#
$IPTABLES -A OUTPUT -p tcp  -d 192.168.0.1  --destination-port 22  -m state --state NEW  -j ACCEPT
$IPTABLES -A OUTPUT -p tcp  -d 192.168.1.1  --destination-port 22  -m state --state NEW  -j ACCEPT
$IPTABLES -A OUTPUT -p tcp  -d 192.168.2.1  --destination-port 22  -m state --state NEW  -j ACCEPT
$IPTABLES -A INPUT -p tcp  -d 192.168.0.1  --destination-port 22  -m state --state NEW  -j ACCEPT
$IPTABLES -A INPUT -p tcp  -d 192.168.1.1  --destination-port 22  -m state --state NEW  -j ACCEPT
$IPTABLES -A INPUT -p tcp  -d 192.168.2.1  --destination-port 22  -m state --state NEW  -j ACCEPT
#
# Rule 1(global)
#
# permit telnet to 192.168.0.10
#
#
$IPTABLES -N RULE_1
$IPTABLES -A OUTPUT -p tcp  -d 192.168.2.1  --destination-port 23  -m state --state NEW  -j RULE_1
$IPTABLES -A OUTPUT -p tcp  -d 192.168.1.1  --destination-port 23  -m state --state NEW  -j RULE_1
$IPTABLES -A OUTPUT -p tcp  -d 192.168.0.10  --destination-port 23  -j RULE_1
$IPTABLES -A INPUT -p tcp  -d 192.168.2.1  --destination-port 23  -m state --state NEW  -j RULE_1
$IPTABLES -A INPUT -p tcp  -d 192.168.1.1  --destination-port 23  -m state --state NEW  -j RULE_1
$IPTABLES -A INPUT -p tcp  -d 192.168.0.10  --destination-port 23 -j RULE_1
$IPTABLES -A FORWARD -p tcp  -d 192.168.0.10  --destination-port 23 -j RULE_1
$IPTABLES -A RULE_1  -j LOG  --log-level info --log-prefix "RULE 1 -- ACCEPT "
$IPTABLES -A RULE_1  -j ACCEPT
#
# Rule 2(global)
#
#
#
$IPTABLES -N RULE_2
                                                                                                                           
$IPTABLES -A OUTPUT -p icmp  -s 0/0  -j RULE_2
$IPTABLES -A INPUT -p icmp  -s 0/0  -j RULE_2
$IPTABLES -A FORWARD -p icmp  -s 0/0  -j RULE_2
$IPTABLES -A OUTPUT -p icmp  -m state --state NEW  -j RULE_2
$IPTABLES -A INPUT -p icmp  -m state --state NEW  -j RULE_2
$IPTABLES -A FORWARD -p icmp  -m state --state NEW  -j RULE_2
$IPTABLES -A RULE_2  -j LOG  --log-level info --log-prefix "RULE 2 -- ACCEPT "
$IPTABLES -A RULE_2  -j ACCEPT
#
# Rule 3(global)
#
# firewall uses DNS server on Inet
#
$IPTABLES -A OUTPUT -p tcp  -s 192.168.0.0/24  --destination-port 53  -m state --state NEW  -j ACCEPT
$IPTABLES -A OUTPUT -p tcp  -s 192.168.1.1  --destination-port 53  -m state --state NEW  -j ACCEPT
$IPTABLES -A OUTPUT -p tcp  -s 192.168.2.1  --destination-port 53  -m state --state NEW  -j ACCEPT
$IPTABLES -A OUTPUT -p udp  -s 192.168.0.0/24  --destination-port 53  -m state --state NEW  -j ACCEPT
$IPTABLES -A OUTPUT -p udp  -s 192.168.1.1  --destination-port 53  -m state --state NEW  -j ACCEPT
$IPTABLES -A OUTPUT -p udp  -s 192.168.2.1  --destination-port 53  -m state --state NEW  -j ACCEPT
#
# Rule 4(global)
#
# 'masquerading' rule
#
$IPTABLES -A OUTPUT  -s 192.168.0.0/24  -m state --state NEW  -j ACCEPT
#
# Rule 5(global)
#
# 'catch all' rule
#
#
$IPTABLES -N RULE_5
$IPTABLES -A OUTPUT  -j RULE_5
$IPTABLES -A INPUT  -j RULE_5
$IPTABLES -A FORWARD  -j RULE_5
$IPTABLES -A RULE_5  -j LOG  --log-level info --log-prefix "RULE 5 -- DENY "
$IPTABLES -A RULE_5  -j DROP
#
#
echo 1 > /proc/sys/net/ipv4/ip_forward
echo 1 > /proc/sys/net/ipv4/conf/eth1/arp_filter
echo 1 > /proc/sys/net/ipv4/conf/eth2/arp_filter
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Linux Networking

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.