Bypass VPN connections via specifics ports Kodibuntu - Ubuntu

Bypass VPN connections via specifics ports Kodibuntu – Ubuntu

Ok this is a little more advance topic. We will re-route some of the internet packets base on their port number. To do so, we will create 2 route table. One table will be our VPN connection and the other one will be our basic internet connection. We will redirect packets base on a mark that we will set with the help of a rule that will detect the packet destination or source port.

Before reading you might want to set up your openvpn. Here is a little guide to do so: Configure VPN with openvpn on Ubuntu and Kodibuntu

UPDATE KERNEL

First, especially for Kodibuntu users, you need to have a Linux Kernel greater than 3.16+. We need a specific kernel option to be enabled in order for this process to work. Ubuntu 14.10 has this kernel by default, but not 14.04+.
To check  your kernel version, simply type:
uname -r
It is very simple to update the kernel, but be sure you can access GRUB on boot before doing so. You want to be able to revert back to an older kernel if never the new one failed. You can check for newer kernel, but X64 users here is one stable kernel tested by my own for Kodibuntu:

wget http://kernel.ubuntu.com/~kernel-ppa/mainline/v3.16.7-utopic/linux-headers-3.16.7-031607-generic_3.16.7-031607.201410301735_amd64.deb wget http://kernel.ubuntu.com/~kernel-ppa/mainline/v3.16.7-utopic/linux-headers-3.16.7-031607_3.16.7-031607.201410301735_all.deb wget http://kernel.ubuntu.com/~kernel-ppa/mainline/v3.16.7-utopic/linux-image-3.16.7-031607-generic_3.16.7-031607.201410301735_amd64.deb sudo dpkg -i *3.16.7*deb sudo reboot

Here is the full list of Ubuntu kernels. There is a great chance they also work on Kodibuntu.
http://kernel.ubuntu.com/~kernel-ppa/mainline/

ENABLING KERNEL OPTIONS

Once you are on a Kernel 3.16+ you have to enable some kernel options. We need to change 3 main kernel variables:
rp_filter to 0
forwarding to 1
tcp_fwmark_accept to 1

  1. Get the list of your own variables with this:
    sysctl -a | grep \\.rp_filter && sysctl -a | grep \\.forwarding && sysctl -a | grep \\.tcp_fwmark_accept

    It will return something like this:
    net.ipv4.conf.all.rp_filter = 1
    net.ipv4.conf.default.rp_filter = 1
    ..
    net.ipv4.conf.all.forwarding = 1
    net.ipv4.conf.default.forwarding = 1
    ..
    net.ipv6.conf.all.forwarding = 1
    net.ipv6.conf.default.forwarding = 1
    net.ipv4.tcp_fwmark_accept = 1
  2. Change the values of all the variable returned, It should be something like this by default:
    sudo sysctl -w net.ipv4.conf.eth0.rp_filter=0 sudo sysctl -w net.ipv4.conf.tun0.rp_filter=0 sudo sysctl -w net.ipv4.conf.all.rp_filter=0 sudo sysctl -w net.ipv4.conf.default.rp_filter=0 sudo sysctl -w net.ipv4.conf.lo.rp_filter=0 sudo sysctl -w net.ipv4.conf.all.forwarding=1 sudo sysctl -w net.ipv4.conf.default.forwarding=1 sudo sysctl -w net.ipv4.conf.eth0.forwarding=1 sudo sysctl -w net.ipv4.conf.lo.forwarding=1 sudo sysctl -w net.ipv4.conf.tun0.forwarding=1 sudo sysctl -w net.ipv6.conf.all.forwarding=1 sudo sysctl -w net.ipv6.conf.default.forwarding=1 sudo sysctl -w net.ipv6.conf.eth0.forwarding=1 sudo sysctl -w net.ipv6.conf.lo.forwarding=1 sudo sysctl -w net.ipv6.conf.tun0.forwarding=1 sudo sysctl -w net.ipv4.tcp_fwmark_accept=1

ROUTE TABLES

Once you have the right the kernel, you can start setting your routing table.
HERE, BE CAREFULL OF WHAT YOU ARE DOING IF YOU ARE UNDER A REMOTE SSH.

  1. First off check what your main table looks like. ( BE SURE TO TURN OFF THE VPN BEFORE CHECKING THIS)
    sudo ip route show table main
    It will return something like this:
    default via 192.168.0.1 dev eth0 192.168.0.0/24 dev eth0 proto kernel scope link src 192.168.0.16 metric 1
  2. You have to copy the content this command returned to a new table by creating a new one numbered 101. Copy the content of main table to table 101 like so. To do so use
    ip route add table 101 *EACH LINES OF WHAT WAS RETURNED IN PREVIOUS STEP 1*
    In Exemple:
    ip route add table 101 default via 192.168.0.1 dev eth0 ip route add table 101 192.168.0.0/24 dev eth0 proto kernel scope link src 192.168.0.16 metric 1
  3. Now you have a new route table numbered 101. You can check it content via this command:
    sudo ip route show table 101
  4. To give a more human readable name to this table you can add line to rt_tables file:
    echo "101 vpnbypass"| sudo tee -a /etc/iproute2/rt_tables
  5. Now you should be able to show your table via this command instead:
    sudo ip route show table vpnbypass
  6. Now you should have a new route table. But it should disappear as soon as you reboot. You will have to run this via a script -> our VPN script is perfect for that check this post:
    CONFIGURE VPN WITH OPENVPN ON UBUNTU AND KODIBUNTU
    Otherewise we provide a script example here:
    Bypass VPN specific ports script

PACKET MARKING AND FOWARDING

HERE BE CAREFULL OF WHAT YOU ARE DOING IF YOU ARE UNDER A REMOTE SSH.

So now you should have two identical route table: table main (default) and table 101 (vpnbypass).  Now you can start your VPN via:
sudo /etc/init.d/openvpn
If you check your main table again, you will notice it has change. The main route table now has become the vpn route table. You should see some tun0 devices there:
sudo ip route show table main
Perfect, now by default all your connection packets will go directly into the main table (VPN). You now need to create some rule to redirect the packet you want to your table 101 (vpnbypass). We can do so by assigning a mark to some packets via a simple rule. You can mark packets by a specific port, or by a specific ip address or whatever rule iptables support.

  1. First off we need to create ip rule to redirect the packet marked with X number to our table 101. In this case we mark them with the number : 2
    sudo ip rule add fwmark 2 table 101
    This will tell any packets that is marked: 2 to go in our table 101 (vpnbypass). To check if it worked just type:
    sudo ip rule
    it should return rules that look like so
    32765:  from all fwmark 0x2 lookup vpnbypass
  2. Now you need to create the marking rule.
    We tell any TCP connections that is passing by port X to be marked with the number 2:
    # For Incoming Connections: # HTTP protocol TCP port 80: iptables -t mangle -A PREROUTING -p tcp --dport 80 -j MARK –set-mark 2 # DELUGE-WEB interface protocol TCP port 8112: iptables -t mangle -A PREROUTING -p tcp --dport 8112 -j MARK --set-mark 2 # --- # For Outgoing Connections: iptables --table nat --append POSTROUTING -o eth0 -j MASQUERADE # PLEX OUTGOING: iptables -t mangle -A OUTPUT -p tcp --sport 32400 -j MARK --set-mark 2

SCRIPT EXEMPLE:

HERE BE CAREFULL OF WHAT YOU ARE DOING IF YOU ARE UNDER A REMOTE SSH.

# ---ENABLING KERNEL OPTIONS sudo sysctl -w net.ipv4.conf.eth0.rp_filter=0 sudo sysctl -w net.ipv4.conf.tun0.rp_filter=0 sudo sysctl -w net.ipv4.conf.all.rp_filter=0 sudo sysctl -w net.ipv4.conf.default.rp_filter=0 sudo sysctl -w net.ipv4.conf.lo.rp_filter=0 sudo sysctl -w net.ipv4.conf.all.forwarding=1 sudo sysctl -w net.ipv4.conf.default.forwarding=1 sudo sysctl -w net.ipv4.conf.eth0.forwarding=1 sudo sysctl -w net.ipv4.conf.lo.forwarding=1 sudo sysctl -w net.ipv4.conf.tun0.forwarding=1 sudo sysctl -w net.ipv6.conf.all.forwarding=1 sudo sysctl -w net.ipv6.conf.default.forwarding=1 sudo sysctl -w net.ipv6.conf.eth0.forwarding=1 sudo sysctl -w net.ipv6.conf.lo.forwarding=1 sudo sysctl -w net.ipv6.conf.tun0.forwarding=1 sudo sysctl -w net.ipv4.tcp_fwmark_accept=1 # ---CLEAR ALL FIREWALL RULES iptables -F iptables -t mangle -F iptables -t nat -F # ---FLSUH EXISTING TABLE 101 + cache ip route flush table 101 ip route flush cache #--- DEL IF EXISTS AND ADD RULE ip rule del fwmark 2 table 2 ip rule add fwmark 2 table 2 #--- CREATE TABLE 101 ip route add table 101 default via 192.168.0.1 dev eth0 ip route add table 101 192.168.0.0/24 dev eth0 proto kernel scope link src 192.168.0.20 metric 1 #--- PORT FORWARD TO TABLE 101 # SETTING MASQUERADE FOR OUTPUT iptables --table nat --append POSTROUTING -o eth0 -j MASQUERADE # VPN BYPASS! # SSH THIS ONE IS THE MOST IMPORTANT iptables -t mangle -A PREROUTING -p tcp --dport 22 -j MARK --set-mark 2 # PLEX iptables -t mangle -A OUTPUT -p tcp --dport 32400 -j MARK --set-mark 2 iptables -t mangle -A PREROUTING -p tcp --dport 32400 -j MARK --set-mark 2 # HTTP S iptables -t mangle -A PREROUTING -p tcp --dport 80 -j MARK --set-mark 2 iptables -t mangle -A PREROUTING -p tcp --dport 443 -j MARK --set-mark 2 # FTP iptables -t mangle -A PREROUTING -p tcp --dport 21 -j MARK --set-mark 2 # YOU NEED TO SET UP MIN/MAX PORT IN VSFTPD iptables -t mangle -A PREROUTING -p tcp --dport 13000:13100 -j MARK --set-mark 2 iptables -t mangle -A OUTPUT -p tcp --sport 21 -j MARK --set-mark 2 #DELUGE LOCAL only from LOCAL NETWORK IPs iptables -t mangle -A PREROUTING -p tcp --dport 58846 -s 192.168.0.0/24 -j MARK --set-mark 2 # ----------- FIREWALL: THIS IS OPTIONAL BUT GIVE EXTRA SECURITY ----------- # REJECT ALL INCOMING CONNECTIONS iptables -P INPUT DROP iptables -P FORWARD DROP iptables -P OUTPUT ACCEPT # ALLOW LOCAL iptables -A INPUT -i lo -j ACCEPT iptables -A OUTPUT -o lo -j ACCEPT # ALLOW ALREADY ESTABLISHED CONNECTIONS iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # ALLOW PLEX iptables -I INPUT -p tcp --dport 32400 -j ACCEPT # ALLOW HTTPS iptables -I INPUT -p tcp --dport 443 -j ACCEPT # ALLOW SAMBA IN LOCAL NETWORK LOCALLY iptables -I INPUT -p tcp --dport 137 -s 192.168.0.0/24 -j ACCEPT iptables -I INPUT -p tcp --dport 138 -s 192.168.0.0/24 -j ACCEPT iptables -I INPUT -p tcp --dport 139 -s 192.168.0.0/24 -j ACCEPT iptables -I INPUT -p tcp --dport 445 -s 192.168.0.0/24 -j ACCEPT # ALLOW SAMBA LOCALLY iptables -I INPUT -p tcp --dport 58846 -s 192.168.0.0/24 -j ACCEPT # ALLOW SSH LOCAL NETWORK iptables -A INPUT -p tcp --dport 22 -s 192.168.0.0/24 -j ACCEPT # VSFTPD iptables -I INPUT -p tcp --dport 21 -j ACCEPT iptables -I INPUT -p tcp --dport 13000:13100 -j ACCEPT # ----------- END OF THE FIREWALL ----------- # AVOID DNS LEAK WITH GOOGLE DNS echo "nameserver 8.8.8.8 nameserver 8.8.4.4" | tee /etc/resolv.conf # START ANY PROGRAMS HERE /etc/init.d/deluged start /etc/init.d/deluge-web start

 


References:

http://www.linksysinfo.org/index.php?threads/route-only-specific-ports-through-vpn-openvpn.37240/