---
author: einar
categories:
- Linux
comments: true
date: "2015-01-02T20:11:40Z"
slug: policy-based-routing-for-single-ips-using-edgeos
tags:
- edgeos
- Linux
- routing
title: Policy-based routing for single IPs using EdgeOS
disable_share: true
wordpress_id: 1356
---

I've found myself in a situation where my ISP, notorious for having problems with certain online services (not to mention putting everyone under a permanent NAT) started misbehaving with Sony's Playstation Network: I was getting timeouts of all sorts with no reason (and reading online you see all sorts of attempts from people to work around the issue). When using my phone as hotspot, everything worked, as I went through my mobile operator's network.

But of course I couldn't do that, even so because I have a data cap. ;) Therefore, I decided to work around the issue. As I have access to a dedicated server (the one that runs this blog) I thought I could redirect traffic through it via OpenVPN.  On the other side (at home) I have a very nice piece of kit, Ubiquiti Networks' EdgeRouter Lite, which acts as router for my network.

The easy way would be to redirect _all_ traffic through the VPN, but this is not desirable, because in this case it's the EdgeRouter MIPS CPU to do the work, instead of its dedicated Cavium processor. What I could do, instead, was ensure that **only** the machine accessing the PSN (in my case, a PS4) would get rerouted.


## Setting things up


First of all, I needed an OpenVPN server set up. I won't go through that as there are plenty of guides around the net. I however needed to ensure that IPv4 forwarding was enabled on the server, and ensure that it was set up for forwarding packets around:


{{< highlight bash >}}
sysctl net.ipv4.ip_forward=1

iptables -A INPUT -i tun0 -j ACCEPT # tun0 is my VPN interface
iptables -A OUTPUT -o tun+ -j ACCEPT
iptables -A FORWARD -i tun0 -j ACCEPT
iptables -A FORWARD -i tun+ -o em1 -m state --state RELATED,ESTABLISHED -j ACCEPT # em1 is my server's network interface
iptables -A FORWARD -i em1 -o tun+ -m state --state RELATED,ESTABLISHED -j ACCEPT
# 192.168.10.0/24 is my home network
iptables -t nat -A POSTROUTING -s 192.168.10.0/24 -o tun0 -j MASQUERADE
{{< / highlight >}}


Afterwards, I set a static mapping on the DHCP server of the router to ensure that the PS4 would always get the same address.

I needed to set up two static routes: one for the LAN, which goes through the regular (ISP's) gateway, and one for the PS4, ensuring that the PS4 one gets evaluated **first** (otherwise it would match the one for the network). It was time to connect to the router and do some configuration, as the Web interface did not expose what was needed.

{{< highlight bash >}}

configure

# normal routing - ISP gateway
set protocols static table 1 route 0.0.0.0/0 next-hop 192.168.1.254
# VPN interface
set protocols static table 2 route 0.0.0.0/0 next-hop 10.8.1.1

set firewall modify VPN_IP rule 10 description "Host-specific route"
set firewall modify VPN_IP rule 10 source address 192.168.10.56
set firewall modify VPN_IP rule 10 modify table 2

# Since our IP is part of the subnet, we put the subnet (default)
# specific rule after this one

set firewall modify VPN_IP rule 20 description "Rest of network"
set firewall modify VPN_IP rule 20 source address 192.168.10.0/24
set firewall modify VPN_IP rule 20 modify table 1

# Apply changes to the internal interface (eth1)

set interfaces eth1 firewall in modify VPN_IP

commit
save

{{< / highlight >}}

Afterwards I logged on the Web interface and turned on the PS4: as expected, everything was going through the VPN. I may need to adjust things for fail-over, so that if the VPN is down, normal routing is done, but for now it should suffice.

I hope this could be useful for any of you in the same situation (where you need to route a single IP as opposed to a whole network).

## Addendum


I had one other VPN, this solution broke routing from the local network to that VPN (as the 192.168.10.0/24 route would match the default gateway). What I did was to set up an additional route only for the VPN:


{{< highlight bash >}}
set protocols static table 3 route 0.0.0.0/0 next-hop 10.8.0.2

set firewall modify VPN_IP rule 15 source address 192.168.10.0/24
set firewall modify VPN_IP rule 15 description "Routing for the additional VPN"
set firewall modify VPN_IP rule 15 destination address 10.8.0.0/24
set firewall modify VPN_IP rule 15 modify table 3
commit
save
{{< / highlight >}}

## Credits

Much of the information has come from [Ubiquiti's Wiki entry on Policy-Based Routing](http://wiki.ubnt.com/EdgePBR).. This post is an expanded version of [a thread I posted on Ubiquiti's community forums](http://community.ubnt.com/t5/EdgeMAX/Redirect-all-traffic-from-a-signle-IP-to-a-VPN-interface/m-p/1140025).
