Vyos Policy Based Routing
What is Policy Based Routing?
Normal ip packet routing only looks at the destination ip (v4 or v6) address to decide which outbound interface should send that packet. Policy based routing allows that interface selection process to use information other than the destination ip address. For example, you might want all TCP packets with destination port number 80 to exit via a particular interface.
In this particular case, we have two interfaces running a full BGP (IPv4) feed from a provider, and we also have a higher-speed consumer grade DSL line configured via DHCP. As long as the DSL link is up, we can use it for web browsing. If the link is down, we want to automatically fall back to the main data links.
Vyos
We add some stock Vyos commands to setup the policy based routing. Two interfaces and their BGP configuration are omitted here to simplify this, and to concentrate on the policy based issues.
The bulk-data port-group defines the TCP ports that we want to route over the DSL link. The source-route policy selects the packets to be routed via table 1. That policy is applied to the local ethernet interface, not the outgoing DSL link. The static protocol section defines the content of routing table 1, which forces those packets out thru the DSL link, rather than via the default BGP configured links.
firewall { group { port-group bulk-data { port 22 port 143 port 443 port 8000 port 80 } } } policy { route source-route { rule 10 { destination { group { port-group bulk-data } } protocol tcp set { table 1 } source { address 0.0.0.0/0 } } } } interfaces { ethernet eth0 { description "local network" policy { route source-route } } ethernet eth1 { address dhcp description "dsl link" } } protocols { static { table 1 { interface-route 0.0.0.0/0 { next-hop-interface eth1 { } } } } }
This all works as advertised, with the small exception of DHCP renewals. There are times when the DSL link may die (as in no traffic), but the Vyos router won't notice that until it tries to do a DHCP renewal many hours later. So we monitor the next hop by periodic pings, and when the link state changes, we force a 'renew dhcp interface eth1' command. If that renewal attempt fails, the default route in table 1 is removed, even though the Vyos configuration thinks it is still there. When the link comes back up, and the DHCP renewal succeeds, we need to reinstate that default route in table 1.
We also need to ensure that traffic from the vyos itself is properly natted out over that dhcp configured eth1. This is required to allow outside systems (IPv6 tunnelbroker.net) to ping the local IPv4 endpoint.
The following script in /etc/dhcp3/dhclient-exit-hooks.d/bgp handles those issues.
#!/bin/bash ( if [ -z "$reason" ]; then reason="NONE" fi case $reason in BOUND|RENEW|REBIND|REBOOT|NONE|EXPIRE|FAIL|RELEASE|STOP) # check if dhcp to verizon is up # dev=eth1 table=1 cmd="show ip route 0.0.0.0/0 exit " gwip=$( (echo "$cmd" | ssh -t -t vyos@localhost 2>/dev/null) | grep "via $dev" | rev | awk '{print $3}' | rev | cut -d, -f1 ) if [ "$gwip" != "" ]; then # link is up, replace the mangle table ip=$(ip addr list $dev | grep 'inet ' | awk '{print $2}' | cut -d/ -f1) iptables -t mangle -F OUTPUT # vyos source eth1 natted out eth1 iptables -t mangle -A OUTPUT -s $ip/32 -j MARK --set-mark 0x80000000 iptables -n -t mangle -L OUTPUT # link is up, check if table $table contains default route echo "dhcp $dev link is up at $(date)" cmd="ip route list table $table exit exit " ok=$( (echo "$cmd" | ssh -t -t vyos@localhost 2>/dev/null) | grep "default dev $dev") if [ "$ok" == "" ]; then # table $table does not contain the default route echo "route table $table has no default route at $(date)" cmd="configure delete protocols static table $table commit set protocols static table $table interface-route 0.0.0.0/0 next-hop-interface $dev commit save exit exit " echo "$cmd" | ssh -t -t vyos@localhost 2>/dev/null echo "remove/re-add protocols static table $table interface-route 0.0.0.0/0 next-hop-interface $dev $(date)" fi fi ;; PREINIT) ;; esac ) </dev/null >>/tmp/xxx 2>&1